diff --git a/include/MatioModel.hpp b/include/MatioModel.hpp new file mode 100644 index 0000000..fbab6cd --- /dev/null +++ b/include/MatioModel.hpp @@ -0,0 +1,60 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * File: MatlabIOModel.hpp + * Author: Tim Sheerman-Chase + * Created: Apr 1, 2013 + */ + +#ifndef MATIOMODEL_HPP_ +#define MATIOMODEL_HPP_ + +#include "Model.hpp" +#include "types.hpp" + +/*! @class MatlabIOModel + * @brief Model implementation with Matlab .Mat file deserialization + */ +class MatioModel: public Model +{ +public: + MatioModel() {} + virtual ~MatioModel() {} + bool deserialize(const std::string& filename); + bool serialize(const std::string& filename) const; + +protected: + bool readModelData(struct mat_t *matfp, struct matvar_t *model); +}; + +#endif /* MATIOMODEL_HPP_ */ diff --git a/matlab/modelTransfer.m b/matlab/modelTransfer.m index bfc6d43..96a2d67 100644 --- a/matlab/modelTransfer.m +++ b/matlab/modelTransfer.m @@ -228,4 +228,4 @@ end model.components{i} = parts; end -end \ No newline at end of file +end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 53d8009..7ac8a1f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,17 @@ if (cvmatio_FOUND) ) endif() +if (1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWITH_MATIO") + set(SRC_FILES ${SRC_FILES} MatioModel.cpp) + set(LIBS ${LIBS} ${ZLIB_LIBRARIES} "-lmatio") + add_executable(ModelTransfer ModelTransfer.cpp FileStorageModel.cpp MatioModel.cpp) + target_link_libraries(ModelTransfer ${LIBS}) + install(TARGETS ModelTransfer + RUNTIME DESTINATION ${PROJECT_SOURCE_DIR}/bin + ) +endif() + # as a library (always) add_library(${PROJECT_NAME}_lib SHARED ${SRC_FILES}) target_link_libraries(${PROJECT_NAME}_lib ${LIBS}) diff --git a/src/FileStorageModel.cpp b/src/FileStorageModel.cpp index 235ad81..b09f256 100644 --- a/src/FileStorageModel.cpp +++ b/src/FileStorageModel.cpp @@ -37,7 +37,6 @@ */ #include -#include #include #include "FileStorageModel.hpp" diff --git a/src/MatioModel.cpp b/src/MatioModel.cpp new file mode 100644 index 0000000..c49954f --- /dev/null +++ b/src/MatioModel.cpp @@ -0,0 +1,312 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * File: MatlabIOModel.cpp + * Author: Tim Sheerman-Chase + * Created: Apr 1, 2013 + */ + +#include +#include +#include +#include +#include +#include "MatioModel.hpp" +using namespace std; + +//************ Utility Functions **************************** + +//! convert a vector of integers from Matlab 1-based indexing to C++ 0-based indexing +static inline void zeroIndex(vectori& idx) { + for (unsigned int n = 0; n < idx.size(); ++n) idx[n] -= 1; +} + +//! convert an integer from Matlab 1-based indexing to C++ 0-based indexing +static inline void zeroIndex(int& idx) { + idx -= 1; +} + +//! convert a vector of Point from Matlab 1-based indexing to C++ 0-based indexing +static inline void zeroIndex(vectorPoint& pt) { + cv::Point one(1,1); + for (unsigned int n = 0; n < pt.size(); ++n) pt[n] = pt[n] - one; +} + +template mytype Matio2DToVec(matvar_t *m) +{ + assert(m->data_type==MAT_T_DOUBLE); + assert(m->rank==2); + + double arr[m->dims[0]*m->dims[1]]; + int start[] = {0,0}; + int stride[] = {1,1}; + int *edge = m->dims; + int ret = Mat_VarReadData(m->fp, m, arr, start, stride, edge); + assert(ret==0); + mytype out; + for(unsigned int i=0;idims[0]*m->dims[1];i++) + out.push_back(arr[i]); + return out; +} + +//************* Main Class ************************************************************ + +bool MatioModel::readModelData(mat_t *matfp, matvar_t *model) +{ + matvar_t *filters = Mat_VarGetStructField(model, (void *)"filters", BY_NAME, 0); + if(filters==NULL) {cout << "Model filters not found" << endl;} + + matvar_t *components = Mat_VarGetStructField(model, (void *)"components", BY_NAME, 0); + if(components==NULL) {cout << "Model components not found" << endl;} + + matvar_t *defs = Mat_VarGetStructField(model, (void *)"defs", BY_NAME, 0); + if(defs==NULL) {cout << "Model filters not found" << endl;} + + matvar_t *bias = Mat_VarGetStructField(model, (void *)"bias", BY_NAME, 0); + if(bias==NULL) {cout << "Model bias not found" << endl;} + + //Return if something is missing + if(filters==NULL || components==NULL || defs==NULL || bias == NULL) + { + if(filters!=NULL) Mat_VarFree(filters); + if(components!=NULL) Mat_VarFree(components); + if(defs!=NULL) Mat_VarFree(defs); + if(bias!=NULL) Mat_VarFree(bias); + return false; + } + + matvar_t *intervalField = Mat_VarGetStructField(model, (void *)"interval", BY_NAME, 0); + assert(intervalField!=NULL); + this->nscales_ = *(double *)intervalField->data; + + matvar_t *threshField = Mat_VarGetStructField(model, (void *)"thresh", BY_NAME, 0); + assert(threshField!=NULL); + this->thresh_ = *(double *)threshField->data; + + matvar_t *sbinField = Mat_VarGetStructField(model, (void *)"sbin", BY_NAME, 0); + assert(sbinField!=NULL); + this->binsize_ = *(double *)sbinField->data; + + this->norient_ = 18; + + assert(filters->data_type==MAT_T_STRUCT); + //cout << filters->rank << "," << filters->dims[0] <<"," << filters->dims[1] << endl; + + for(int structInd = 0; structInd < filters->dims[1]; structInd++) + { + //Get filteri values + //matvar_t *filtersi = Mat_VarGetStructField(filters, (void *)"i", BY_NAME, structInd); + //if(filtersi==NULL) {cout << "Model filtersi not found" << endl;} + //assert(filtersi->data_type==MAT_T_DOUBLE); + + //Get filterw values + matvar_t *filtersw = Mat_VarGetStructField(filters, (void *)"w", BY_NAME, structInd); + if(filtersw==NULL) {cout << "Model filtersw not found" << endl;} + assert(filtersw->data_type==MAT_T_DOUBLE); + assert(filtersw->rank==3); + + //cout <data_type<< "," << filtersw->dims[0] <<"," << filtersw->dims[1]<<"," << filtersw->dims[2] << endl; + + int C = filtersw->dims[2]; + this->flen_ = C; + cv::Mat filter_flat(cv::Size(C, 1), cv::DataType::type); + + double *buff = new double[filtersw->dims[0]*filtersw->dims[1]*filtersw->dims[2]]; + int start[] = {0,0,0}; + int stride[] = {1,1,1}; + int edge[] = {filtersw->dims[0],filtersw->dims[1],filtersw->dims[2]}; + int ret = Mat_VarReadData(matfp, filtersw, buff, start, stride, edge); + assert(ret==0); + for(int c=0; c(c,1) = buff[c]; + delete buff; + + this->filtersw_.push_back(filter_flat); + } + + //Copy components into memory + assert(components->data_type==MAT_T_CELL); + //cout <data_type<< "," << components->dims[0] <<"," << components->dims[1]<<"," << components->dims[2] << endl; + biasid_.resize(components->dims[1]); + filterid_.resize(components->dims[1]); + defid_.resize(components->dims[1]); + parentid_.resize(components->dims[1]); + + for(int cellInd = 0; cellInd < components->dims[1]; cellInd++) + { + matvar_t *cell = Mat_VarGetCell(components, cellInd); + assert(cell!=NULL); + assert(cell->data_type==MAT_T_STRUCT); + biasid_[cellInd].resize(cell->dims[1]); + filterid_[cellInd].resize(cell->dims[1]); + defid_[cellInd].resize(cell->dims[1]); + parentid_[cellInd].resize(cell->dims[1]); + + for(int structInd = 0; structInd < cell->dims[1]; structInd++) + { + matvar_t *defid = Mat_VarGetStructField(cell, (void *)"defid", BY_NAME, structInd); + matvar_t *filterid = Mat_VarGetStructField(cell, (void *)"filterid", BY_NAME, structInd); + matvar_t *parent = Mat_VarGetStructField(cell, (void *)"parent", BY_NAME, structInd); + matvar_t *biasid = Mat_VarGetStructField(cell, (void *)"biasid", BY_NAME, structInd); + assert(defid!=NULL && filterid != NULL && parent != NULL && biasid != NULL); + + this->biasid_[cellInd][structInd] = Matio2DToVec(biasid); + this->parentid_[cellInd][structInd] = *(double *)parent->data; + this->filterid_[cellInd][structInd] = Matio2DToVec(filterid); + this->defid_[cellInd][structInd] = Matio2DToVec(biasid); + + //re-index from zero (Matlab uses 1-based indexing) + zeroIndex(this->biasid_[cellInd][structInd]); + zeroIndex(this->parentid_[cellInd][structInd]); + zeroIndex(this->filterid_[cellInd][structInd]); + zeroIndex(this->defid_[cellInd][structInd]); + } + } + + //Copy defs to memory + for(int structInd = 0; structInd < defs->dims[1]; structInd++) + { + matvar_t *defsw = Mat_VarGetStructField(defs, (void *)"w", BY_NAME, structInd); + matvar_t *defsanchor = Mat_VarGetStructField(defs, (void *)"anchor", BY_NAME, structInd); + assert(defsw!=NULL && defsanchor!=NULL); + + vector wv = Matio2DToVec(defsw); + this->defw_.push_back(wv); + + assert(defsanchor->data_type==MAT_T_DOUBLE); + double p[defsanchor->dims[0]*defsanchor->dims[1]]; + int start2[] = {0,0}; + int stride2[] = {1,1}; + int *edge2 = defsanchor->dims; + int ret = Mat_VarReadData(matfp, defsanchor, p, start2, stride2, edge2); + assert(ret==0); + this->anchors_.push_back(cv::Point(p[0], p[1])); + } + zeroIndex(this->anchors_); + + //Read bias into memory + for(int structInd = 0; structInd < bias->dims[1]; structInd++) + { + matvar_t *biasw = Mat_VarGetStructField(bias, (void *)"w", BY_NAME, structInd); + assert(biasw!=NULL); + assert(biasw->data_type==MAT_T_DOUBLE); + this->biasw_.push_back(*(double *)biasw->data); + } + + //if(filters!=NULL) Mat_VarFree(filters); + //if(components!=NULL) Mat_VarFree(components); + //if(defs!=NULL) Mat_VarFree(defs); + //if(bias!=NULL) Mat_VarFree(bias); + return true; +} + +/*! @brief deserialize a Matlab .Mat file into memory + * + * deserialize a valid version 5 .Mat file using the underlying + * matio parser, and populate the model fields. If any of the fields + * do not exist, or a bad type cast is attempted, an exception will be thrown + * + * @param filename the path to the model file + * @return true if the file was found, opened and verified to be a valid Matlab + * version 5 file + * @throws boost::bad_any_cast, exception + */ +bool MatioModel::deserialize(const std::string& filename) +{ + //Open output file for reading via matio + mat_t *matfp = Mat_Open(filename.c_str(),MAT_ACC_RDWR); + if ( NULL == matfp ) { + return false; + } + + //Read struct container + matvar_t *cont1 = Mat_VarReadNext(matfp); + if(cont1==NULL) {Mat_Close(matfp); return false;} + + //Read struct members + matvar_t *model = Mat_VarGetStructField(cont1, (void *)"model", BY_NAME, 0); + if(model==NULL) {cout << "Model data not found" << endl;} + + matvar_t *name = Mat_VarGetStructField(cont1, (void *)"name", BY_NAME, 0); + if(name==NULL) {cout << "Model name not found" << endl;} + + //matvar_t *pa = Mat_VarGetStructField(cont1, (void *)"pa", BY_NAME, 0); + //if(pa==NULL) {cout << "Model pa not found" << endl;} + + matvar_t *sbin = Mat_VarGetStructField(cont1, (void *)"sbin", BY_NAME, 0); + if(sbin==NULL) {cout << "Model sbin not found" << endl;} + + //Return if something is missing + if(model==NULL || name==NULL || sbin==NULL) //|| pa==NULL + { + if(model!=NULL) Mat_VarFree(model); + if(name!=NULL) Mat_VarFree(name); + //if(pa!=NULL) Mat_VarFree(pa); + if(sbin!=NULL) Mat_VarFree(sbin); + Mat_VarFree(cont1); + } + + //cout << (name->data_type == MAT_T_UINT8) << "," << name->data_size << endl; + //cout << (model->data_type == MAT_T_STRUCT) << "," << model->data_size << endl; + this->name_ = (char *)name->data; + + //assert(pa->data_type==MAT_T_DOUBLE); + //assert(sizeof(double) == pa->data_size); + //double *paVal = (double *)pa->data; + + assert(sbin->data_type==MAT_T_DOUBLE); + assert(sizeof(double) == sbin->data_size); + double *sbinVal = (double *)sbin->data; + this->binsize_ = *sbinVal; + + bool ret = this->readModelData(matfp, model); + + //Clear matio objects + //if(model!=NULL) Mat_VarFree(model); + //if(name!=NULL) Mat_VarFree(name); + //if(pa!=NULL) Mat_VarFree(pa); + //if(sbin!=NULL) Mat_VarFree(sbin); + Mat_VarFree(cont1); + Mat_Close(matfp); + return ret; +} + + +bool MatioModel::serialize(const std::string& filename) const +{ + /* TODO: implement */ + filename[0]; + return false; +} + + diff --git a/src/ModelTransfer.cpp b/src/ModelTransfer.cpp index bb59051..1ce6e7b 100644 --- a/src/ModelTransfer.cpp +++ b/src/ModelTransfer.cpp @@ -37,7 +37,11 @@ */ #include +#ifdef WITH_MATLABIO #include "MatlabIOModel.hpp" +#elif defined WITH_MATIO +#include "MatioModel.hpp" +#endif #include "FileStorageModel.hpp" using namespace std; @@ -49,7 +53,12 @@ int main(int argc, char** argv) { exit(-1); } // allocate two models +#ifdef WITH_MATLABIO Model* matlab = new MatlabIOModel; +#elif defined WITH_MATIO + Model* matlab = new MatioModel; +#endif + Model* cv = new FileStorageModel; // deserialize the Matlab model, cast sideways and serialize @@ -59,13 +68,20 @@ int main(int argc, char** argv) { cout << "-------------------------------" << endl; cout << "" << endl; cout << "deserializing Matlab (.mat) model..." << endl; - matlab->deserialize(argv[1]); - cout << "converting..." << endl; - (*cv) = (*matlab); - cout << "serializing to OpenCV (.xml) model..." << endl; - cv->serialize(argv[2]); - cout << "Conversion complete" << endl; - cout << "-------------------------------" << endl; + bool ret = matlab->deserialize(argv[1]); + if(ret == false) + { + cout << "Error reading input " << argv[1] << endl; + } + else + { + cout << "converting..." << endl; + (*cv) = (*matlab); + cout << "serializing to OpenCV (.xml) model..." << endl; + cv->serialize(argv[2]); + cout << "Conversion complete" << endl; + cout << "-------------------------------" << endl; + } // cleanup delete matlab; diff --git a/src/Visualize.cpp b/src/Visualize.cpp index 20574db..87b9375 100644 --- a/src/Visualize.cpp +++ b/src/Visualize.cpp @@ -64,7 +64,7 @@ void Visualize::candidates(const Mat& im, const vectorCandidate& candidates, uns const unsigned int ncolors = candidates[0].parts().size(); vector colors; for (unsigned int n = 0; n < ncolors; ++n) { - Mat color(Size(1,1), CV_32FC3); + Mat color(Size(1,3), CV_32FC3); // Hue is in degrees, not radians (because consistency is over-rated) color.at(0) = (360) / ncolors * n; color.at(1) = 1.0; diff --git a/src/demo.cpp b/src/demo.cpp index ead9e60..7f52302 100644 --- a/src/demo.cpp +++ b/src/demo.cpp @@ -47,6 +47,8 @@ #include "FileStorageModel.hpp" #ifdef WITH_MATLABIO #include "MatlabIOModel.hpp" +#elif defined WITH_MATIO + #include "MatioModel.hpp" #endif #include "Visualize.hpp" #include "types.hpp" @@ -74,6 +76,10 @@ int main(int argc, char** argv) { else if (ext.compare(".mat") == 0) { model.reset(new MatlabIOModel); } +#elif defined WITH_MATIO + else if (ext.compare(".mat") == 0) { + model.reset(new MatioModel); + } #endif else { printf("Unsupported model format: %s\n", ext.c_str()); @@ -115,10 +121,14 @@ int main(int argc, char** argv) { Mat canvas; if (candidates.size() > 0) { Candidate::sort(candidates); - //Candidate::nonMaximaSuppression(im, candidates, 0.2); + Candidate::nonMaximaSuppression(im, candidates, 0.2); visualize.candidates(im, candidates, canvas, true); visualize.image(canvas); waitKey(); } + int *test = new int[5]; + test[0] = 1; + test[0]; + delete [] test; return 0; }