From d517841154088e80b7b73b5c16b37e489c6688aa Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 30 Apr 2013 00:07:49 +0200 Subject: [PATCH 01/24] Cleaning code --- COPYING.libpabod | 2 +- TODO | 2 + src/readTypes.cpp | 8 ++-- tests/detectobj2.cpp | 2 +- tests/detectvid.cpp | 87 +++++--------------------------------------- 5 files changed, 19 insertions(+), 82 deletions(-) create mode 100644 TODO diff --git a/COPYING.libpabod b/COPYING.libpabod index 654fb38..cac84df 100644 --- a/COPYING.libpabod +++ b/COPYING.libpabod @@ -1,4 +1,4 @@ -Copyright (C) 2011 Daniel Rodriguez Molina and Manuel J. Marin-Jimenez +Copyright (C) 2011, 2012, 2013 Daniel Rodriguez Molina and Manuel J. Marin-Jimenez Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/TODO b/TODO new file mode 100644 index 0000000..bd531a5 --- /dev/null +++ b/TODO @@ -0,0 +1,2 @@ ++ Add a new method to load object models from XML file. This requires a M-script to create such XML model files. ++ Convert CvMat * variables to cv::Mat class. \ No newline at end of file diff --git a/src/readTypes.cpp b/src/readTypes.cpp index 3e11900..588d34d 100644 --- a/src/readTypes.cpp +++ b/src/readTypes.cpp @@ -18,7 +18,8 @@ char* readString (matvar_t *matVar, char* var, int pos) bool readLogical (matvar_t *matVar, char* var, int pos) { matvar_t *field; - int *auxInt = NULL; + //int *auxInt = NULL; + char *auxChar = NULL; bool flag = false; field = Mat_VarGetStructField (matVar, (char*) var, BY_NAME, pos); @@ -27,9 +28,10 @@ bool readLogical (matvar_t *matVar, char* var, int pos) { if ( field->data_type == MAT_T_UINT8 ) { - auxInt = (int*) field->data; + //auxInt = (int*) field->data; + auxChar = (char*) field->data; - if (*auxInt == 1) + if (*auxChar == 1) flag = true; } } diff --git a/tests/detectobj2.cpp b/tests/detectobj2.cpp index cc89792..dd2758e 100644 --- a/tests/detectobj2.cpp +++ b/tests/detectobj2.cpp @@ -116,7 +116,7 @@ int main ( int argc, char *argv[] ) if (argc < 5) { cout << " >> ERROR: the general form is:\n" - " ./detectobj -m -i [-t -n -o -d <0/1>]" << endl; + " ./detectobj2 -m -i [-t -n -o -d <0/1>]" << endl; return -1; } diff --git a/tests/detectvid.cpp b/tests/detectvid.cpp index d326373..a2fb055 100644 --- a/tests/detectvid.cpp +++ b/tests/detectvid.cpp @@ -40,64 +40,6 @@ string extractModelName (string modelPath) return name; } -void drawBoxes (IplImage *im, const CvPoint p1, const CvPoint p2, const string modelName, int i, - float maxScore, float minScore, float curScore) -{ - CvScalar color; - CvPoint bottomLeftCornerTag; - CvPoint topRightCornerTag; - CvPoint textPoint; - CvFont font; - CvSize textSize; - int textBase = 0; - char modelNameCh[1024]; //char modelNameCh[modelName.length()+4]; - float m, b; - int h; - - - sprintf (modelNameCh, "%s %d", modelName.c_str(), i); - - m = (-300) / (maxScore-minScore); - b = -(m * maxScore); - h = cvRound(m*curScore + b); - - color = cvScalar (h/2, 255, 255); - - cvCvtColor (im, im, CV_BGR2HSV); - - cvRectangle (im, p1, p2, color, 2); - - cvInitFont (&font, CV_FONT_HERSHEY_DUPLEX, 0.4, 0.6, 0, 1, CV_AA); - cvGetTextSize (modelNameCh, &font, &textSize, &textBase); - - bottomLeftCornerTag.x = min (p1.x, p2.x) -1; - bottomLeftCornerTag.y = min (p1.y, p2.y); - - topRightCornerTag.x = bottomLeftCornerTag.x + textSize.width + 2; - topRightCornerTag.y = bottomLeftCornerTag.y - textSize.height - 3; - - if (bottomLeftCornerTag.x < 0) - { - bottomLeftCornerTag.x = max (p1.x, p2.x) +1; - topRightCornerTag.x = bottomLeftCornerTag.x - textSize.width - 2; - } - - if (topRightCornerTag.y < 0) - { - bottomLeftCornerTag.y = max (p1.y, p2.y); - topRightCornerTag.y = bottomLeftCornerTag.y + textSize.height + 3; - } - - cvRectangle (im, bottomLeftCornerTag, topRightCornerTag, color, CV_FILLED); - - cvCvtColor (im, im, CV_HSV2BGR); - - textPoint.x = min (bottomLeftCornerTag.x, topRightCornerTag.x) + 1; - textPoint.y = max (bottomLeftCornerTag.y, topRightCornerTag.y) - 2; - - cvPutText (im, modelNameCh, textPoint, &font, cvScalarAll (255)); -} - string saveImage (const IplImage *im, string imgPath, int mode, const CvMat *results) { string name, path; @@ -167,7 +109,8 @@ int main ( int argc, char *argv[] ) int nDetected = 0; float usedThresh=NEGATIVE_INF, thresh = POSITIVE_INF; float minScore, maxScore; - bool savedata = false, display = true; + bool savedata = false, display = true; + double iouNms = 0.5; if (argc < 5) @@ -199,6 +142,9 @@ int main ( int argc, char *argv[] ) } else if (string(argv[i]) == "-t") { thresh = atof(argv[i + 1]); + } else if (string(argv[i]) == "-n") { + iouNms = atof(argv[i + 1]); + } else { cerr << ">> ERROR: Not enough or invalid arguments, please try again.\n"; @@ -273,7 +219,7 @@ int main ( int argc, char *argv[] ) GET_TIME(&t_ini); // Call to main function - usedThresh = detector.detect(im, thresh, &results); + usedThresh = detector.detect(im, thresh, iouNms, &results); if (results != NULL) nDetected = results->rows; @@ -341,29 +287,16 @@ int main ( int argc, char *argv[] ) } } - for (int i = nDetected - 1; i >= 0; i--) - { - drawBoxes ( - im, - cvPoint (cvGetReal2D(results, i, 0), cvGetReal2D(results, i, 1)), - cvPoint (cvGetReal2D(results, i, 2), cvGetReal2D(results, i, 3)), - extractModelName(modelfile), - i+1, - maxScore, - minScore, - cvGetReal2D (results, i, 4) - ); - - - } + // Draw detections + detector.drawDetections(im, results); for (int i = 0; i < nDetected; i++) cout << " - " << extractModelName(modelfile) << " " << i+1 << ", score = " << cvGetReal2D (results, i, 4) << endl; if (display) { - cvNamedWindow("Detected image", CV_WINDOW_AUTOSIZE); - cvShowImage ("Detected image", im); + cvNamedWindow("Detected objects", CV_WINDOW_AUTOSIZE); + cvShowImage ("Detected objects", im); cout << endl << "Push 't' key to save a copy of (t)agged image" << endl; From 0569de74d1c5c4a9ffb1a8b7f69e7fc1b681987c Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 1 May 2013 21:06:40 +0200 Subject: [PATCH 02/24] New interfaces use cv::Mat --- include/crossplatform.h | 5 +- include/makeDetection.h | 1 + include/pabod.h | 2 + src/makeDetection.cpp | 62 ++++++++++++++++++++ src/pabod.cpp | 39 +++++++++++++ tests/detectobj2.cpp | 122 +++++++++++++++++++++++++++++++++------- 6 files changed, 208 insertions(+), 23 deletions(-) diff --git a/include/crossplatform.h b/include/crossplatform.h index f2db0ac..24dbfa6 100644 --- a/include/crossplatform.h +++ b/include/crossplatform.h @@ -2,8 +2,9 @@ #include #include typedef time_t TIMER; - #define GET_TIME(var) time(var) - #define TIME_DIFF(tend, tini) difftime(tend, tini) + #include + #define GET_TIME(var) cv::getTickCount() //time(var) + #define TIME_DIFF(tend, tini) (((double)tend -tini)/cv::getTickFrequency()) //difftime(tend, tini) #if !defined _CRT_SECURE_NO_DEPRECATE && _MSC_VER > 1300 #define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio 2005 warnings */ diff --git a/include/makeDetection.h b/include/makeDetection.h index 9f968ba..e8efc16 100644 --- a/include/makeDetection.h +++ b/include/makeDetection.h @@ -38,6 +38,7 @@ PABOD_EXPORT float makeDetection (CvMat **results, IplImage *img, string modelTy \param iouNms - intersection-over-union threshold used during non-maxima supression. Default is 0.5 */ PABOD_EXPORT float makeDetection (CvMat **results, IplImage *img, Model * model, float thresh = POSITIVE_INF, double iouNms = 0.5); +PABOD_EXPORT float makeDetection (cv::Mat & results, cv::Mat & img, Model * model, float thresh = POSITIVE_INF, double iouNms = 0.5); #endif // MAKEDETECTION_H diff --git a/include/pabod.h b/include/pabod.h index be58646..2e5df86 100644 --- a/include/pabod.h +++ b/include/pabod.h @@ -42,6 +42,7 @@ class PABOD_EXPORT Pabod{ */ float detect(IplImage * img, float thr, CvMat ** detections); float detect(IplImage * img, float thr, double iouNms, CvMat ** detections); + float detect(cv::Mat & img, float thr, double iouNms, cv::Mat & detections); //! Most modern interface float detect(const char * imgfilename, float thr, CvMat ** detections); /** Draws all detections as rectangles on image. @@ -50,6 +51,7 @@ class PABOD_EXPORT Pabod{ \return Number of detections drawn into image */ int drawDetections(IplImage * img, CvMat * detections); + int drawDetections(cv::Mat & img, cv::Mat & detections); //! Most modern interface /** Gets the class registered in the model */ diff --git a/src/makeDetection.cpp b/src/makeDetection.cpp index f19f6fa..d0bac51 100644 --- a/src/makeDetection.cpp +++ b/src/makeDetection.cpp @@ -61,6 +61,68 @@ PABOD_EXPORT float makeDetection (CvMat **results, IplImage *img, Model * model, return thresh; } +/* +PABOD_EXPORT float makeDetection (cv::Mat & results, cv::Mat & img, Model * model, float thresh, double iouNms) +{ + + CvMat *dets = NULL; + CvMat *boxes = NULL; + CvMatND *info = NULL; + + if (thresh == POSITIVE_INF) + thresh = (float)model->getThresh(); + + bool found = imgDetect (img, model, thresh, NULL, NEGATIVE_INF, &dets, &boxes, &info); + + int detected = 0; + + if (found) + { + int *pick; + int pickDim; + + nms (&pick, &pickDim, dets, iouNms); + + (*results) = cvCreateMat (pickDim, 6, CV_32FC1); + + for (int i = 0; i < pickDim; i++) + { + cvSetReal2D ((*results), i, 0, cvGetReal2D (dets, pick[i], 0)); + cvSetReal2D ((*results), i, 1, cvGetReal2D (dets, pick[i], 1)); + cvSetReal2D ((*results), i, 2, cvGetReal2D (dets, pick[i], 2)); + cvSetReal2D ((*results), i, 3, cvGetReal2D (dets, pick[i], 3)); +//cout << cvGetReal2D (dets, pick[i], 4) << "+ " << cvGetReal2D (dets, pick[i], 5) << " |"; + cvSetReal2D ((*results), i, 4, cvGetReal2D (dets, pick[i], 5)); + cvSetReal2D ((*results), i, 5, cvGetReal2D (dets, pick[i], 4)); + } + + detected = pickDim; + + delete[] pick; + } + + else + (*results) = NULL; + + if (dets != NULL) + { + cvReleaseMat(&dets); + dets = NULL; + } + if (boxes != NULL) + { + cvReleaseMat(&boxes); + boxes = NULL; + } + if (info != NULL) + { + cvReleaseMatND(&info); + info = NULL; + } + + return thresh; +} +*/ PABOD_EXPORT float makeDetection (CvMat **results, IplImage *img, string modelType, float thresh) { diff --git a/src/pabod.cpp b/src/pabod.cpp index e6aefa4..91e729f 100644 --- a/src/pabod.cpp +++ b/src/pabod.cpp @@ -107,6 +107,45 @@ float Pabod::detect(IplImage * img, float thr, double iouNms, CvMat ** detection return usedThr; } +float Pabod::detect(cv::Mat & img, float thr, double iouNms, cv::Mat & detections) +{ + float usedThr = -999999; + if (!empty()) + { + CvMat * detections_ = NULL; + IplImage img_ = img; + // Call to main detection function + usedThr = makeDetection (&detections_, &img_, _model, thr, iouNms); + + detections = detections_; + } + else + cerr << "ERROR: model must be set before calling this method." << endl; + + return usedThr; +} + +int Pabod::drawDetections(cv::Mat & img, cv::Mat & detections) +{ + int ndetections = 0; + int i; + CvPoint p1, p2; + //srand(time(NULL)); + srand(123456); + IplImage img_ = img; + + ndetections = detections.rows; + for (i = 0; i < ndetections; i++) + { + p1 = cvPoint ((int)detections.at(i, 0), (int)detections.at(i, 1)); + p2 = cvPoint ((int)detections.at(i, 2), (int)detections.at(i, 3)); + + drawBB(&img_, p1, p2, cvScalar(int(rand()%256), int(rand()%256), int(rand()%256)), (float)detections.at(i, 4), detections.at(i, 5)); + } + + return ndetections; +} + int Pabod::drawDetections(IplImage * img, CvMat * detections) { int ndetections = 0; diff --git a/tests/detectobj2.cpp b/tests/detectobj2.cpp index dd2758e..3982d08 100644 --- a/tests/detectobj2.cpp +++ b/tests/detectobj2.cpp @@ -40,7 +40,7 @@ string extractModelName (string modelPath) return name; } - +/* string saveImage (const IplImage *im, string imgPath, int mode, const CvMat *results) { string name, path; @@ -98,6 +98,65 @@ string saveImage (const IplImage *im, string imgPath, int mode, const CvMat *res return path; } +*/ +string saveImage (const cv::Mat & im, string imgPath, int mode, const cv::Mat * results) +{ + string name, path; + size_t pos; + char imgNameCh[8]; + + int x, y, w, h; + + pos = imgPath.find_last_of ("/"); + path = imgPath.substr(0, pos); + + if (mode == TAGGED) + { + pos = imgPath.find_last_of("."); + + name = imgPath.substr (0, pos); + + name.append ("_tagged"); + name.append(imgPath.substr(pos)); + + cv::imwrite(name,im); + + } + + else if (mode == CUT) + { + for (int i = 0; i < results->rows; i++) + { + x = min (results->at(i, 0), results->at(i, 2)); + y = min (results->at(i, 1), results->at(i, 3)); + w = abs(results->at(i, 0) - results->at(i, 2)); + h = abs(results->at(i, 1) - results->at(i, 3)); + + cv::Mat cut2(cv::Size(w, h), cv::DataType>::type); + cout << im.channels() << endl; + + for (int m = x; m < w+x; m++) + for (int n = y; n < h+y; n++) + cut2.at(n-y, m-x) = im.at(n, m); + + + pos = imgPath.find_last_of("."); + + name = imgPath.substr (0, pos); + + sprintf (imgNameCh, "_cut%d", i+1); + + name.append (imgNameCh); + name.append(imgPath.substr(pos)); + + + cv::imwrite(name, cut2); + cut2.release(); + } + } + + return path; +} int main ( int argc, char *argv[] ) @@ -105,8 +164,10 @@ int main ( int argc, char *argv[] ) TIMER t_ini, t_fin; double secs=0; string modelfile(""), imName(""), aux, datafile; - IplImage *im = NULL, *copy = NULL; - CvMat *results = NULL; + //IplImage *im = NULL, *copy = NULL; + cv::Mat im, copy; + //CvMat *results = NULL; + cv::Mat results; int nDetected = 0; float usedThresh=NEGATIVE_INF, thresh = POSITIVE_INF; float minScore, maxScore; @@ -165,9 +226,12 @@ int main ( int argc, char *argv[] ) } // Load image - im = cvLoadImage (imName.c_str(), CV_LOAD_IMAGE_COLOR); + //im = cvLoadImage (imName.c_str(), CV_LOAD_IMAGE_COLOR); + im = cv::imread(imName.c_str(), CV_LOAD_IMAGE_COLOR); + - if (im == NULL) + //if (im == NULL) + if (im.empty()) { cerr << ">> ERROR: the image cannot be loaded" << endl; exit(-1); @@ -186,7 +250,8 @@ int main ( int argc, char *argv[] ) if (display) { cvNamedWindow("Input image", CV_WINDOW_AUTOSIZE); - cvShowImage ("Input image", im); + //cvShowImage ("Input image", im); + cv::imshow("Input image", im); cvWaitKey(250); } @@ -195,18 +260,20 @@ int main ( int argc, char *argv[] ) cout << " Searching for objects... This operation may take a few seconds" << endl << endl; // Get the current time before starting detection - GET_TIME(&t_ini); + t_ini = GET_TIME(&t_ini); // Call to main function - usedThresh = detector.detect(im, thresh, iouNms, &results); + //usedThresh = detector.detect(im, thresh, iouNms, &results); + usedThresh = detector.detect(im, thresh, iouNms, results); - if (results != NULL) - nDetected = results->rows; + if (results.data != NULL) + //nDetected = results->rows; + nDetected = results.rows; else nDetected = 0; // Get the current time after detection - GET_TIME(&t_fin); + t_fin = GET_TIME(&t_fin); // Number of secs taken to run detection secs = TIME_DIFF(t_fin, t_ini); @@ -223,16 +290,23 @@ int main ( int argc, char *argv[] ) for (int i = 0; i < nDetected; i++) { + /* if (cvGetReal2D(results, i, 4) < minScore) minScore = cvGetReal2D(results, i, 4); if (cvGetReal2D(results, i, 4) > maxScore) maxScore = cvGetReal2D(results, i, 4); + */ + if (results.at(i, 4) < minScore) + minScore = results.at(i, 4); + if (results.at(i, 4) > maxScore) + maxScore = results.at(i, 4); } if (maxScore == minScore) minScore = usedThresh; - copy = cvCloneImage (im); + //copy = cvCloneImage (im); + im.copyTo(copy); // Save data? if (savedata) @@ -249,10 +323,14 @@ int main ( int argc, char *argv[] ) fid << nDetected << endl; for (int i = nDetected - 1; i >= 0; i--) { - +/* fid << cvGetReal2D(results, i, 0) << " " << cvGetReal2D(results, i, 1) << " "; fid << cvGetReal2D(results, i, 2) << " " << cvGetReal2D(results, i, 3) << " "; fid << cvGetReal2D (results, i, 4) << endl; +*/ + fid << results.at(i, 0) << " " << results.at(i, 1) << " "; + fid << results.at(i, 2) << " " << results.at(i, 3) << " "; + fid << results.at(i, 4) << endl; } // Close file @@ -260,17 +338,17 @@ int main ( int argc, char *argv[] ) } } - //------------- NEW CODE ------------- - detector.drawDetections(im, results); - //------------------------------------ + // Draw detections + detector.drawDetections(im, results); for (int i = 0; i < nDetected; i++) - cout << " - " << extractModelName(modelfile) << " " << i+1 << ", score = " << cvGetReal2D (results, i, 4) << endl; + cout << " - " << extractModelName(modelfile) << " " << i+1 << ", score = " << results.at(i, 4) << endl; if (display) { cvNamedWindow("Detected image", CV_WINDOW_AUTOSIZE); - cvShowImage ("Detected image", im); + //cvShowImage ("Detected image", im); + cv::imshow("Detected image", im); cout << endl << "Push 't' key to save a copy of (t)agged image" << endl; @@ -285,6 +363,7 @@ int main ( int argc, char *argv[] ) if (c == 't' || c == 'T') { + //aux = saveImage (im, imName, TAGGED, NULL); aux = saveImage (im, imName, TAGGED, NULL); cout << " >> Tagged image saved on <" << aux << "> folder" << endl << endl; @@ -297,7 +376,8 @@ int main ( int argc, char *argv[] ) else if (c == 'c' || c == 'C') { - aux = saveImage (copy, imName, CUT, results); + // aux = saveImage (copy, imName, CUT, results); + aux = saveImage (copy, imName, CUT, &results); cout << " >> Cut images saved on <" << aux << "> folder" << endl << endl; c = 0; @@ -318,8 +398,8 @@ int main ( int argc, char *argv[] ) else cout << endl << " >> No objects found" << endl << endl; - cvReleaseImage (&im); - cvReleaseMat (&results); + //cvReleaseImage (&im); +// cvReleaseMat (&results); cout << "Running libPaBOD version " << PABOD_MAJOR_VERSION << "." << PABOD_MINOR_VERSION << "." << PABOD_PATCH_VERSION << endl; From d0e8650e6b49c9de2f362f4dea6d2eb353fe769d Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 2 May 2013 09:45:14 +0200 Subject: [PATCH 03/24] Developing a new Detection class --- include/detection.h | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 include/detection.h diff --git a/include/detection.h b/include/detection.h new file mode 100644 index 0000000..4834d2b --- /dev/null +++ b/include/detection.h @@ -0,0 +1,46 @@ +/** + \file detection.h + \author Manuel J. Marin-Jimenez +// (c) MJMJ/2013 +*/ + +#ifndef _DETECTION_H_ +#define _DETECTION_H_ + +#include "export.h" + +/** \class Detection + * This class represents a single detection returned by a Pabod detector. + */ +class PABOD_EXPORT Detection{ + public: + Detection(); + Detection(int x1, int y1, int x2, int y2, float score, int component) + { + _x1 = x1; + _x2 = x2; + _y1 = y1; + _y2 = y2; + _score = score; + _component = component; + }; + ~Detection(); + + int getX1(void){return _x1;}; + int getX2(void){return _x2;}; + int getY1(void){return _y1;}; + int getY2(void){return _y2;}; + int getW(void){return (_x2-_x1+1);}; + int getH(void){return (_y2-_y1+1);}; + + private: + int _x1; + int _y1; + int _x2; + int _y2; + float _score; //! Detection score + int _component; //! Component that fired +}; + +#endif + \ No newline at end of file From d55b108053d1a85be87ce72975ba074e1a38fbd5 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 2 May 2013 11:55:57 +0200 Subject: [PATCH 04/24] Developing a new Detection class --- .gitignore | 8 +++++- include/detection.h | 33 ++++++++++++++++++--- include/makeDetection.h | 2 ++ include/pabod.h | 5 +++- src/makeDetection.cpp | 64 +++++++++++++++++++++++++++++++++++++++++ src/pabod.cpp | 39 +++++++++++++++++++++++++ tests/detectobj2.cpp | 26 +++++++++++++---- 7 files changed, 166 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index ed5d66c..f19a904 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,10 @@ Thumbs.db ########## *.aux *.bbl -*.blg \ No newline at end of file +*.blg +*.html +*.map +*.md5 +*.png +*.gch +*.css diff --git a/include/detection.h b/include/detection.h index 4834d2b..8065f7f 100644 --- a/include/detection.h +++ b/include/detection.h @@ -7,14 +7,23 @@ #ifndef _DETECTION_H_ #define _DETECTION_H_ +#include #include "export.h" + +#define LOWESTSCORE -999999 /** \class Detection * This class represents a single detection returned by a Pabod detector. */ class PABOD_EXPORT Detection{ public: - Detection(); + Detection() + { + _x1 = _x2 = _y1 = _y2 = -1; + _component = -1; + _score = LOWESTSCORE; + }; + Detection(int x1, int y1, int x2, int y2, float score, int component) { _x1 = x1; @@ -24,7 +33,13 @@ class PABOD_EXPORT Detection{ _score = score; _component = component; }; - ~Detection(); + /** Creates a new Detection from the given parameters. + \param x1, y1, x2, y2 are the coordinates of the bounding-box + \param score the higher the better + \param component index of the component fired by the detector + */ + + //~Detection(); int getX1(void){return _x1;}; int getX2(void){return _x2;}; @@ -32,6 +47,15 @@ class PABOD_EXPORT Detection{ int getY2(void){return _y2;}; int getW(void){return (_x2-_x1+1);}; int getH(void){return (_y2-_y1+1);}; + int getComponent(void){return _component;}; + + float getScore(void){return _score;}; + /** Returns the detection score + */ + + bool empty(void){return (_component == -1) && (_score == LOWESTSCORE);}; + /** Checks if object has not been initialized yet + */ private: int _x1; @@ -41,6 +65,7 @@ class PABOD_EXPORT Detection{ float _score; //! Detection score int _component; //! Component that fired }; - + +typedef std::vector LDetections; //! List of detections + #endif - \ No newline at end of file diff --git a/include/makeDetection.h b/include/makeDetection.h index e8efc16..fa843de 100644 --- a/include/makeDetection.h +++ b/include/makeDetection.h @@ -4,6 +4,7 @@ #include #include #include +#include /** \file @@ -39,6 +40,7 @@ PABOD_EXPORT float makeDetection (CvMat **results, IplImage *img, string modelTy */ PABOD_EXPORT float makeDetection (CvMat **results, IplImage *img, Model * model, float thresh = POSITIVE_INF, double iouNms = 0.5); PABOD_EXPORT float makeDetection (cv::Mat & results, cv::Mat & img, Model * model, float thresh = POSITIVE_INF, double iouNms = 0.5); +PABOD_EXPORT float makeDetection (LDetections & D, IplImage *img, Model * model, float thresh, double iouNms); #endif // MAKEDETECTION_H diff --git a/include/pabod.h b/include/pabod.h index 2e5df86..e4b993c 100644 --- a/include/pabod.h +++ b/include/pabod.h @@ -10,7 +10,8 @@ #include #include "export.h" #include "model.h" - +#include "detection.h" + /** \class Pabod * This class implements a part-based object detector. */ @@ -43,6 +44,7 @@ class PABOD_EXPORT Pabod{ float detect(IplImage * img, float thr, CvMat ** detections); float detect(IplImage * img, float thr, double iouNms, CvMat ** detections); float detect(cv::Mat & img, float thr, double iouNms, cv::Mat & detections); //! Most modern interface + float detect(cv::Mat & img, float thr, double iouNms, LDetections & detections); //! Most modern interface float detect(const char * imgfilename, float thr, CvMat ** detections); /** Draws all detections as rectangles on image. @@ -52,6 +54,7 @@ class PABOD_EXPORT Pabod{ */ int drawDetections(IplImage * img, CvMat * detections); int drawDetections(cv::Mat & img, cv::Mat & detections); //! Most modern interface + int drawDetections(cv::Mat & img, LDetections & detections); /** Gets the class registered in the model */ diff --git a/src/makeDetection.cpp b/src/makeDetection.cpp index d0bac51..526360a 100644 --- a/src/makeDetection.cpp +++ b/src/makeDetection.cpp @@ -1,6 +1,69 @@ #include +PABOD_EXPORT float makeDetection (LDetections & D, IplImage *img, Model * model, float thresh, double iouNms) +{ + + CvMat *dets = NULL; + CvMat *boxes = NULL; + CvMatND *info = NULL; + + if (thresh == POSITIVE_INF) + thresh = (float)model->getThresh(); + + bool found = imgDetect (img, model, thresh, NULL, NEGATIVE_INF, &dets, &boxes, &info); + + int detected = 0; + + if (found) + { + int *pick; + int pickDim; + + nms (&pick, &pickDim, dets, iouNms); + +// (*results) = cvCreateMat (pickDim, 6, CV_32FC1); + + for (int i = 0; i < pickDim; i++) + { + D.push_back(Detection(cvGetReal2D(dets,pick[i],0), cvGetReal2D(dets,pick[i],1), cvGetReal2D(dets,pick[i],2), cvGetReal2D(dets,pick[i],3), cvGetReal2D(dets,pick[i],5), cvGetReal2D(dets,pick[i],4))); +/* cvSetReal2D ((*results), i, 0, cvGetReal2D (dets, pick[i], 0)); + cvSetReal2D ((*results), i, 1, cvGetReal2D (dets, pick[i], 1)); + cvSetReal2D ((*results), i, 2, cvGetReal2D (dets, pick[i], 2)); + cvSetReal2D ((*results), i, 3, cvGetReal2D (dets, pick[i], 3)); +//cout << cvGetReal2D (dets, pick[i], 4) << "+ " << cvGetReal2D (dets, pick[i], 5) << " |"; + cvSetReal2D ((*results), i, 4, cvGetReal2D (dets, pick[i], 5)); + cvSetReal2D ((*results), i, 5, cvGetReal2D (dets, pick[i], 4)); + */ + } + + detected = pickDim; + + delete[] pick; + } +/* + else + (*results) = NULL; +*/ + if (dets != NULL) + { + cvReleaseMat(&dets); + dets = NULL; + } + if (boxes != NULL) + { + cvReleaseMat(&boxes); + boxes = NULL; + } + if (info != NULL) + { + cvReleaseMatND(&info); + info = NULL; + } + + return thresh; +} + PABOD_EXPORT float makeDetection (CvMat **results, IplImage *img, Model * model, float thresh, double iouNms) { @@ -61,6 +124,7 @@ PABOD_EXPORT float makeDetection (CvMat **results, IplImage *img, Model * model, return thresh; } + /* PABOD_EXPORT float makeDetection (cv::Mat & results, cv::Mat & img, Model * model, float thresh, double iouNms) { diff --git a/src/pabod.cpp b/src/pabod.cpp index 91e729f..59eec4a 100644 --- a/src/pabod.cpp +++ b/src/pabod.cpp @@ -125,6 +125,45 @@ float Pabod::detect(cv::Mat & img, float thr, double iouNms, cv::Mat & detection return usedThr; } +float Pabod::detect(cv::Mat & img, float thr, double iouNms, LDetections & detections) +{ + float usedThr = -999999; + if (!empty()) + { + //CvMat * detections_ = NULL; + IplImage img_ = img; + // Call to main detection function + usedThr = makeDetection (detections, &img_, _model, thr, iouNms); + + //detections = detections_; + } + else + cerr << "ERROR: model must be set before calling this method." << endl; + + return usedThr; +} + +int Pabod::drawDetections(cv::Mat & img, LDetections & detections) +{ + int ndetections = 0; + int i; + CvPoint p1, p2; + //srand(time(NULL)); + srand(123456); + IplImage img_ = img; + + ndetections = detections.size(); + for (i = 0; i < ndetections; i++) + { + p1 = cvPoint (detections[i].getX1(), detections[i].getY1()); + p2 = cvPoint (detections[i].getX2(), detections[i].getY2()); + + drawBB(&img_, p1, p2, cvScalar(int(rand()%256), int(rand()%256), int(rand()%256)), detections[i].getScore(), detections[i].getComponent()); + } + + return ndetections; +} + int Pabod::drawDetections(cv::Mat & img, cv::Mat & detections) { int ndetections = 0; diff --git a/tests/detectobj2.cpp b/tests/detectobj2.cpp index 3982d08..f878568 100644 --- a/tests/detectobj2.cpp +++ b/tests/detectobj2.cpp @@ -167,7 +167,8 @@ int main ( int argc, char *argv[] ) //IplImage *im = NULL, *copy = NULL; cv::Mat im, copy; //CvMat *results = NULL; - cv::Mat results; + //cv::Mat results; + LDetections results; int nDetected = 0; float usedThresh=NEGATIVE_INF, thresh = POSITIVE_INF; float minScore, maxScore; @@ -266,11 +267,14 @@ int main ( int argc, char *argv[] ) //usedThresh = detector.detect(im, thresh, iouNms, &results); usedThresh = detector.detect(im, thresh, iouNms, results); + nDetected = results.size(); + /* if (results.data != NULL) //nDetected = results->rows; - nDetected = results.rows; + nDetected = results.rows; else nDetected = 0; + */ // Get the current time after detection t_fin = GET_TIME(&t_fin); @@ -296,10 +300,17 @@ int main ( int argc, char *argv[] ) if (cvGetReal2D(results, i, 4) > maxScore) maxScore = cvGetReal2D(results, i, 4); */ + /* if (results.at(i, 4) < minScore) minScore = results.at(i, 4); if (results.at(i, 4) > maxScore) maxScore = results.at(i, 4); + */ + if (results[i].getScore() < minScore) + minScore = results[i].getScore(); + + if (results[i].getScore() < maxScore) + maxScore = results[i].getScore(); } if (maxScore == minScore) @@ -328,9 +339,14 @@ int main ( int argc, char *argv[] ) fid << cvGetReal2D(results, i, 2) << " " << cvGetReal2D(results, i, 3) << " "; fid << cvGetReal2D (results, i, 4) << endl; */ +/* fid << results.at(i, 0) << " " << results.at(i, 1) << " "; fid << results.at(i, 2) << " " << results.at(i, 3) << " "; fid << results.at(i, 4) << endl; +*/ + fid << results[i].getX1() << " " << results[i].getY1() << " "; + fid << results[i].getX2() << " " << results[i].getY2() << " "; + fid << results[i].getScore() << endl; } // Close file @@ -342,7 +358,7 @@ int main ( int argc, char *argv[] ) detector.drawDetections(im, results); for (int i = 0; i < nDetected; i++) - cout << " - " << extractModelName(modelfile) << " " << i+1 << ", score = " << results.at(i, 4) << endl; + cout << " - " << extractModelName(modelfile) << " " << i+1 << ", score = " << results[i].getScore() << endl; if (display) { @@ -364,7 +380,7 @@ int main ( int argc, char *argv[] ) if (c == 't' || c == 'T') { //aux = saveImage (im, imName, TAGGED, NULL); - aux = saveImage (im, imName, TAGGED, NULL); +//To update aux = saveImage (im, imName, TAGGED, NULL); cout << " >> Tagged image saved on <" << aux << "> folder" << endl << endl; c = 0; @@ -377,7 +393,7 @@ int main ( int argc, char *argv[] ) else if (c == 'c' || c == 'C') { // aux = saveImage (copy, imName, CUT, results); - aux = saveImage (copy, imName, CUT, &results); +//To update aux = saveImage (copy, imName, CUT, &results); cout << " >> Cut images saved on <" << aux << "> folder" << endl << endl; c = 0; From d377f1bd034af140dd8e91892ab63e514eec6baa Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 2 May 2013 20:43:27 +0200 Subject: [PATCH 05/24] Developing a new Detection class detectobj2 and detectvid use the new interface --- TODO | 1 + include/detection.h | 20 ++++---- tests/detectobj2.cpp | 63 ++++++++++++++++++++++- tests/detectvid.cpp | 116 +++++++++++++++++++++++++++++++++++-------- 4 files changed, 168 insertions(+), 32 deletions(-) diff --git a/TODO b/TODO index bd531a5..ccdb22b 100644 --- a/TODO +++ b/TODO @@ -1,2 +1,3 @@ ++ Some memory leaks still to be fixed. + Add a new method to load object models from XML file. This requires a M-script to create such XML model files. + Convert CvMat * variables to cv::Mat class. \ No newline at end of file diff --git a/include/detection.h b/include/detection.h index 8065f7f..36a5e2b 100644 --- a/include/detection.h +++ b/include/detection.h @@ -1,7 +1,7 @@ /** \file detection.h \author Manuel J. Marin-Jimenez -// (c) MJMJ/2013 + \date May 2013 */ #ifndef _DETECTION_H_ @@ -41,19 +41,19 @@ class PABOD_EXPORT Detection{ //~Detection(); - int getX1(void){return _x1;}; - int getX2(void){return _x2;}; - int getY1(void){return _y1;}; - int getY2(void){return _y2;}; - int getW(void){return (_x2-_x1+1);}; - int getH(void){return (_y2-_y1+1);}; - int getComponent(void){return _component;}; + int getX1(void) const {return _x1;}; + int getX2(void) const {return _x2;}; + int getY1(void) const {return _y1;}; + int getY2(void) const {return _y2;}; + int getW(void) const {return (_x2-_x1+1);}; //! Width of BB + int getH(void) const {return (_y2-_y1+1);}; //! Height of BB + int getComponent(void) const {return _component;}; - float getScore(void){return _score;}; + float getScore(void) const {return _score;}; /** Returns the detection score */ - bool empty(void){return (_component == -1) && (_score == LOWESTSCORE);}; + bool empty(void) const {return (_component == -1) && (_score == LOWESTSCORE);}; /** Checks if object has not been initialized yet */ diff --git a/tests/detectobj2.cpp b/tests/detectobj2.cpp index f878568..0690df1 100644 --- a/tests/detectobj2.cpp +++ b/tests/detectobj2.cpp @@ -99,6 +99,7 @@ string saveImage (const IplImage *im, string imgPath, int mode, const CvMat *res return path; } */ +/* string saveImage (const cv::Mat & im, string imgPath, int mode, const cv::Mat * results) { string name, path; @@ -157,6 +158,65 @@ string saveImage (const cv::Mat & im, string imgPath, int mode, const cv::Mat * return path; } +*/ +string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetections & results) +{ + string name, path; + size_t pos; + char imgNameCh[8]; + + int x, y, w, h; + + pos = imgPath.find_last_of ("/"); + path = imgPath.substr(0, pos); + + if (mode == TAGGED) + { + pos = imgPath.find_last_of("."); + + name = imgPath.substr (0, pos); + + name.append ("_tagged"); + name.append(imgPath.substr(pos)); + + cv::imwrite(name,im); + + } + + else if (mode == CUT) + { + for (int i = 0; i < results.size(); i++) + { + x = min (results[i].getX1(), results[i].getX2()); + y = min (results[i].getY1(), results[i].getY2()); + w = abs(results[i].getW()); + h = abs(results[i].getH()); + + cv::Mat cut2(cv::Size(w, h), cv::DataType>::type); + cout << im.channels() << endl; + + for (int m = x; m < w+x; m++) + for (int n = y; n < h+y; n++) + cut2.at(n-y, m-x) = im.at(n, m); + + + pos = imgPath.find_last_of("."); + + name = imgPath.substr (0, pos); + + sprintf (imgNameCh, "_cut%d", i+1); + + name.append (imgNameCh); + name.append(imgPath.substr(pos)); + + + cv::imwrite(name, cut2); + cut2.release(); + } + } + + return path; +} int main ( int argc, char *argv[] ) @@ -381,6 +441,7 @@ int main ( int argc, char *argv[] ) { //aux = saveImage (im, imName, TAGGED, NULL); //To update aux = saveImage (im, imName, TAGGED, NULL); + aux = saveImage (im, imName, TAGGED, results); cout << " >> Tagged image saved on <" << aux << "> folder" << endl << endl; c = 0; @@ -393,7 +454,7 @@ int main ( int argc, char *argv[] ) else if (c == 'c' || c == 'C') { // aux = saveImage (copy, imName, CUT, results); -//To update aux = saveImage (copy, imName, CUT, &results); + aux = saveImage (copy, imName, CUT, results); cout << " >> Cut images saved on <" << aux << "> folder" << endl << endl; c = 0; diff --git a/tests/detectvid.cpp b/tests/detectvid.cpp index a2fb055..2e8b5b6 100644 --- a/tests/detectvid.cpp +++ b/tests/detectvid.cpp @@ -98,14 +98,74 @@ string saveImage (const IplImage *im, string imgPath, int mode, const CvMat *res return path; } +string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetections & results) +{ + string name, path; + size_t pos; + char imgNameCh[8]; + + int x, y, w, h; + + pos = imgPath.find_last_of ("/"); + path = imgPath.substr(0, pos); + + if (mode == TAGGED) + { + pos = imgPath.find_last_of("."); + + name = imgPath.substr (0, pos); + + name.append ("_tagged"); + name.append(imgPath.substr(pos)); + + cv::imwrite(name,im); + + } + + else if (mode == CUT) + { + for (int i = 0; i < results.size(); i++) + { + x = min (results[i].getX1(), results[i].getX2()); + y = min (results[i].getY1(), results[i].getY2()); + w = abs(results[i].getW()); + h = abs(results[i].getH()); + + cv::Mat cut2(cv::Size(w, h), cv::DataType>::type); + cout << im.channels() << endl; + + for (int m = x; m < w+x; m++) + for (int n = y; n < h+y; n++) + cut2.at(n-y, m-x) = im.at(n, m); + + + pos = imgPath.find_last_of("."); + + name = imgPath.substr (0, pos); + + sprintf (imgNameCh, "_cut%d", i+1); + + name.append (imgNameCh); + name.append(imgPath.substr(pos)); + + + cv::imwrite(name, cut2); + cut2.release(); + } + } + + return path; +} int main ( int argc, char *argv[] ) { TIMER t_ini, t_fin; double secs=0; string modelfile(""), vidName(""), imName(""), aux, datafile; - IplImage *im = NULL, *copy = NULL, *frame= NULL; - CvMat *results = NULL; + //IplImage *im = NULL, *copy = NULL, *frame= NULL; + cv::Mat im, copy, frame; + //CvMat *results = NULL; + LDetections results; int nDetected = 0; float usedThresh=NEGATIVE_INF, thresh = POSITIVE_INF; float minScore, maxScore; @@ -183,7 +243,7 @@ int main ( int argc, char *argv[] ) frame = cvQueryFrame( vid); // Check if frame is read - if (frame == NULL) + if (frame.empty()) { break; // No more frames } @@ -195,7 +255,8 @@ int main ( int argc, char *argv[] ) frix++; } - im = cvCloneImage(frame); + im = frame.clone(); + //im = cvCloneImage(frame); cout << endl << endl << endl << endl; cout << " Model: " << modelfile << endl; @@ -208,26 +269,30 @@ int main ( int argc, char *argv[] ) if (display) { - cvNamedWindow("Input image", CV_WINDOW_AUTOSIZE); - cvShowImage ("Input image", im); + cvNamedWindow("Input frame", CV_WINDOW_AUTOSIZE); + //cvShowImage ("Input image", im); + cv::imshow("Input frame", im); cvWaitKey(250); } cout << "Searching for objects... This operation may take a few seconds" << endl << endl; // Get the current time before starting detection - GET_TIME(&t_ini); + t_ini = GET_TIME(&t_ini); // Call to main function - usedThresh = detector.detect(im, thresh, iouNms, &results); + usedThresh = detector.detect(im, thresh, iouNms, results); + /* if (results != NULL) nDetected = results->rows; else nDetected = 0; + */ + nDetected = results.size(); // Get the current time after detection - GET_TIME(&t_fin); + t_fin = GET_TIME(&t_fin); // Number of secs taken to run detection secs = TIME_DIFF(t_fin, t_ini); @@ -245,16 +310,19 @@ int main ( int argc, char *argv[] ) for (int i = 0; i < nDetected; i++) { - if (cvGetReal2D(results, i, 4) < minScore) - minScore = cvGetReal2D(results, i, 4); - if (cvGetReal2D(results, i, 4) > maxScore) - maxScore = cvGetReal2D(results, i, 4); + + if (results[i].getScore() < minScore) + minScore = results[i].getScore(); + + if (results[i].getScore() < maxScore) + maxScore = results[i].getScore(); } if (maxScore == minScore) minScore = usedThresh; - copy = cvCloneImage (im); + //copy = cvCloneImage (im); + copy = im.clone(); // Save data? if (savedata) @@ -276,10 +344,14 @@ int main ( int argc, char *argv[] ) fid << nDetected << endl; for (int i = nDetected - 1; i >= 0; i--) { - + /* fid << cvGetReal2D(results, i, 0) << " " << cvGetReal2D(results, i, 1) << " "; fid << cvGetReal2D(results, i, 2) << " " << cvGetReal2D(results, i, 3) << " "; fid << cvGetReal2D (results, i, 4) << endl; + */ + fid << results[i].getX1() << " " << results[i].getY1() << " "; + fid << results[i].getX2() << " " << results[i].getY2() << " "; + fid << results[i].getScore() << endl; } // Close file @@ -291,12 +363,13 @@ int main ( int argc, char *argv[] ) detector.drawDetections(im, results); for (int i = 0; i < nDetected; i++) - cout << " - " << extractModelName(modelfile) << " " << i+1 << ", score = " << cvGetReal2D (results, i, 4) << endl; + cout << " - " << extractModelName(modelfile) << " " << i+1 << ", score = " << results[i].getScore() << endl; if (display) { cvNamedWindow("Detected objects", CV_WINDOW_AUTOSIZE); - cvShowImage ("Detected objects", im); + //cvShowImage ("Detected objects", im); + cv::imshow("Detected objects", im); cout << endl << "Push 't' key to save a copy of (t)agged image" << endl; @@ -311,7 +384,7 @@ int main ( int argc, char *argv[] ) if (c == 't' || c == 'T') { - aux = saveImage (im, imName, TAGGED, NULL); + aux = saveImage (im, imName, TAGGED, results); cout << " >> Tagged image saved on <" << aux << "> folder" << endl << endl; c = 0; @@ -344,9 +417,10 @@ int main ( int argc, char *argv[] ) else cout << endl << " >> No objects found" << endl << endl; - - cvReleaseMat (&results); - cvReleaseImage (&im); + results.clear(); + //cvReleaseMat (&results); + im.release(); + //cvReleaseImage (&im); } // while-doProcessing From 07c7036728c2e6c567e82cc2eed02d9a5e7f0e10 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 6 May 2013 00:28:31 +0200 Subject: [PATCH 06/24] Improving memory usage --- TODO | 3 +- doc/quickstart.tex | 16 ++++++++++ include/crossplatform.h | 13 ++++++-- include/custom.h | 6 +++- include/export.h | 6 +++- include/handlerOpenCVStructs.h | 2 +- include/model.h | 12 ++++++++ src/cell.cpp | 4 +-- src/fconvThreads.cpp | 3 ++ src/featPyramid.cpp | 6 ++-- src/gdetect.cpp | 29 +++++++++++++----- src/makeDetection.cpp | 6 ++++ src/model.cpp | 54 +++++++++++++++++++++++++++++----- src/modelSort.cpp | 4 +++ src/pabod.cpp | 2 +- tests/detectobj2.cpp | 1 - 16 files changed, 139 insertions(+), 28 deletions(-) diff --git a/TODO b/TODO index ccdb22b..d4eddb7 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,4 @@ -+ Some memory leaks still to be fixed. ++ Some memory leaks still to be fixed: + - Possible ones: Model, Cell + Add a new method to load object models from XML file. This requires a M-script to create such XML model files. + Convert CvMat * variables to cv::Mat class. \ No newline at end of file diff --git a/doc/quickstart.tex b/doc/quickstart.tex index 81026a1..6b0ea6c 100644 --- a/doc/quickstart.tex +++ b/doc/quickstart.tex @@ -35,6 +35,22 @@ \section{Easy detection with LibPaBOD} \noindent So easy! +\section{Using the OpenCV C++ interface} + +\begin{verbatim} + LDetections detections; + + cv::Mat img = cv::imread("my_image.jpg", CV_LOAD_IMAGE_COLOR); + + Pabod detector("data/models/person_v6.mat"); + + detector.detect(img, POSITIVE_INF, 0.5, detections); + + detector.drawDetections(img, detections); + + cv::imwrite("my_image_dets.jpg", img); +\end{verbatim} + \begin{thebibliography}{} \bibitem{felzenszwalb2010} P. Felzenszwalb, R. Girshick, D. McAllester, D. Ramanan. ``Object Detection with Discriminatively Trained Part Based Models''. IEEE Transactions on Pattern Analysis and Machine Intelligence, Vol. 32, No. 9, September 2010. diff --git a/include/crossplatform.h b/include/crossplatform.h index 24dbfa6..50d3b6a 100644 --- a/include/crossplatform.h +++ b/include/crossplatform.h @@ -10,12 +10,21 @@ #define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio 2005 warnings */ #endif +#ifdef _DEBUG + #define _CRTDBG_MAP_ALLOC + #include + #include +#ifndef DBG_NEW + #define DBG_NEW new ( _NORMAL_BLOCK , __FILE__ , __LINE__ ) + #define new DBG_NEW +#endif +#endif // _DEBUG + #else #include typedef struct timeval TIMER; #define GET_TIME(var) gettimeofday(var, NULL) #define TIME_DIFF(tend, tini) ((double)(tend.tv_sec + (double)tend.tv_usec/1000000.0) - (double)(tini.tv_sec + (double)tini.tv_usec/1000000.0)) - - #define PABOD_EXPORT + #endif diff --git a/include/custom.h b/include/custom.h index 6011dc1..9019ae6 100644 --- a/include/custom.h +++ b/include/custom.h @@ -3,12 +3,16 @@ #undef USE_OPENMP +#if _DEBUG #undef USE_PTHREADS +#else +#define USE_PTHREADS 1 +#endif #define PABOD_MAJOR_VERSION 0 #define PABOD_MINOR_VERSION 2 -#define PABOD_PATCH_VERSION 7 +#define PABOD_PATCH_VERSION 8 #endif diff --git a/include/export.h b/include/export.h index ad60c2a..05fc143 100644 --- a/include/export.h +++ b/include/export.h @@ -5,7 +5,11 @@ */ #if defined _WIN32 - #define PABOD_EXPORT __declspec(dllexport) + #ifdef _DEBUG + #define PABOD_EXPORT //__declspec(dllexport) + #else + #define PABOD_EXPORT __declspec(dllexport) + #endif #if !defined _CRT_SECURE_NO_DEPRECATE && _MSC_VER > 1300 #define _CRT_SECURE_NO_DEPRECATE /* to avoid multiple Visual Studio 2005 warnings */ diff --git a/include/handlerOpenCVStructs.h b/include/handlerOpenCVStructs.h index b72eed1..a1032f7 100644 --- a/include/handlerOpenCVStructs.h +++ b/include/handlerOpenCVStructs.h @@ -3,7 +3,7 @@ #include #include - +#include /** \file * The file contains a wide variety of different handling matrixes and diff --git a/include/model.h b/include/model.h index 140db77..ddd29c6 100644 --- a/include/model.h +++ b/include/model.h @@ -883,6 +883,13 @@ class Model */ void destroyModel (); + /** Releases temporal memory from a previous detection. + * Model definition is not modified. Then, same model + * is ready for a new detection. + */ + + void resetModel(); + /** Allocates dinamic memory for the private vector variable * _scoretpt. This function is necessary because the vector * is initialized element by element, so the memory must be @@ -995,6 +1002,11 @@ class Model CvMat** _scoretpt; int _scoretptDim; + + // Private methods + void _releaseSymbols(void); //! Release memory allocated during a detection + + void _releaseScores(void); //! Release memory allocated during a detection }; diff --git a/src/cell.cpp b/src/cell.cpp index 81760e2..a0f0a45 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -332,7 +332,7 @@ void Cell::setRhs (int *rhs) { assert (getRhsDim() > 0); - _rhs = new int [getRhsDim()]; + _rhs = new int [getRhsDim()]; // Suspicious assert (_rhs != NULL); @@ -358,7 +358,7 @@ void Cell::setAnchor (anchor *a) { assert (getAnchorDim() > 0); - _anchor = new anchor [getAnchorDim()]; + _anchor = new anchor [getAnchorDim()]; // Suspicious assert (_anchor != NULL); diff --git a/src/fconvThreads.cpp b/src/fconvThreads.cpp index faad63c..2612163 100644 --- a/src/fconvThreads.cpp +++ b/src/fconvThreads.cpp @@ -1,6 +1,7 @@ // Customized by mjmarin #include +#include #ifdef USE_PTHREADS CvMat** fconv (CvMatND* features, CvMatND** filters, int a, int filtersDim) @@ -183,6 +184,7 @@ CvMat** fconv (CvMatND* features, CvMatND** filters, int a, int filtersDim) int height; int width; + for (int i = 0; i < len; i++) { mxB = filters[i+start]; @@ -231,6 +233,7 @@ CvMat** fconv (CvMatND* features, CvMatND** filters, int a, int filtersDim) delete[] td; // delete[] ts; + return result; } diff --git a/src/featPyramid.cpp b/src/featPyramid.cpp index ca1c8d6..8625d04 100644 --- a/src/featPyramid.cpp +++ b/src/featPyramid.cpp @@ -579,9 +579,9 @@ void FeatPyramid::featpyramid (const IplImage *im, const Model *model, int padX, setDim (int(maxScale + interval)); assert (getDim() > 0); - _feat = new CvMatND* [getDim()]; + _feat = new CvMatND* [getDim()]; // Suspicious assert (_feat != NULL); - _scales = new float [getDim()]; + _scales = new float [getDim()]; // Suspicious assert (_scales != NULL); // Field imsize is setted @@ -698,7 +698,7 @@ void FeatPyramid::destroyFeatPyramid() void FeatPyramid::setImSize(int *imSize) { - _imSize = new int [PAIR]; + _imSize = new int [PAIR]; // Suspicious assert (imSize[0] > 0); assert (imSize[1] > 0); diff --git a/src/gdetect.cpp b/src/gdetect.cpp index 8c00909..8051f08 100644 --- a/src/gdetect.cpp +++ b/src/gdetect.cpp @@ -1,4 +1,5 @@ #include +#include void gdetect (CvMat **dets, CvMat **boxes, CvMatND **info, @@ -23,10 +24,14 @@ void gdetect (CvMat **dets, CvMat **boxes, CvMatND **info, if ( overlap == NEGATIVE_INF ) overlap = 0.7; + _CrtMemState s1, s2, s3; + + // Cache filter response filterResponses (model, pyra, latent, bbox, overlap); // Compute parse scores + LStructure* L = new LStructure; assert (L != NULL); L = modelSort (model, L); // mjmarin: uses def params --> i=-1, V=NULL @@ -42,6 +47,7 @@ void gdetect (CvMat **dets, CvMat **boxes, CvMatND **info, delete[] L; + // Find scores above threshold int *X = NULL; int XDim = 0; @@ -66,6 +72,8 @@ void gdetect (CvMat **dets, CvMat **boxes, CvMatND **info, int *tmpL; double *tmpS; + + for (int level = model->getInterval() + 1; level < pyra.getDim(); level++) { CvMat* score = model->getSymbols()[(int) model->getStart()].score[level]; @@ -402,6 +410,9 @@ void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, int dim = 0; int spadX, spadY; + _CrtMemState s1, s2, s3; + _CrtMemCheckpoint( &s1 ); + // Firstable the function has to count how many elements there will be for (int s = 0; s < model->getSymbolsDim(); s++) { @@ -412,21 +423,21 @@ void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, // Gather filters for computing match quality responses assert (i > 0); - CvMatND **filters = new CvMatND* [i]; + CvMatND **filters = new CvMatND* [i]; // Suspicious assert (filters != NULL); int filtersDim = i; - int *filtersDimF = new int [i]; + int *filtersDimF = new int [i]; // Suspicious assert (filtersDimF != NULL); - int *filtersDimC = new int [i]; + int *filtersDimC = new int [i]; // Suspicious assert (filtersDimC != NULL); - int *filtersDimA = new int [i]; + int *filtersDimA = new int [i]; // Suspicious assert (filtersDimA != NULL); - int *filter_to_symbol = new int [i]; + int *filter_to_symbol = new int [i]; // Suspicious assert (filter_to_symbol != NULL); i = 0; @@ -463,7 +474,7 @@ void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, for (int i = 0; i < rDim; i++) { model->getSymbols()[filter_to_symbol[i]].dimScore = dim; - model->getSymbols()[filter_to_symbol[i]].score = new CvMat* [dim]; + model->getSymbols()[filter_to_symbol[i]].score = new CvMat* [dim]; // Suspicious --> to be tracked } int s[2]; @@ -505,7 +516,9 @@ void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, cvReleaseMat(&r[i]); // Release old memory r[i] = newArray; + _CrtMemCheckpoint( &s1 ); model->getSymbols()[filter_to_symbol[i]].score[levels[j]] = r[i]; + } assert (s[0] > 0); @@ -522,12 +535,14 @@ void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, delete [] r; } + delete[] filters; delete[] filtersDimF; delete[] filtersDimC; delete[] filtersDimA; delete[] filter_to_symbol; delete[] levels; + } @@ -542,7 +557,7 @@ int* validateLevels (const Model *model, const FeatPyramid &pyra, { assert (pyra.getDim() > 0); - levels = new int [pyra.getDim()]; + levels = new int [pyra.getDim()]; // Suspicious assert (levels != NULL); diff --git a/src/makeDetection.cpp b/src/makeDetection.cpp index 526360a..d78dcfe 100644 --- a/src/makeDetection.cpp +++ b/src/makeDetection.cpp @@ -61,6 +61,9 @@ PABOD_EXPORT float makeDetection (LDetections & D, IplImage *img, Model * model, info = NULL; } + // Release extra memory from detection + model->resetModel(); + return thresh; } @@ -122,6 +125,9 @@ PABOD_EXPORT float makeDetection (CvMat **results, IplImage *img, Model * model, info = NULL; } + // Release extra memory from detection + model->resetModel(); + return thresh; } diff --git a/src/model.cpp b/src/model.cpp index 9af3274..32b265d 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -76,6 +76,7 @@ void Model::destroyModel () _rules = NULL; } + // filterResponses() fills it if (_symbols != NULL) { for (int i = 0; i < getSymbolsDim(); i++) @@ -184,7 +185,7 @@ void Model::destroyModel () delete[] _bboxpred; _bboxpred = NULL; } - + // filterResponses() fills it if (_scoretpt != NULL) { for (int i = 0; i < getScoretptDim(); i++) @@ -1002,7 +1003,7 @@ void Model::setFilters (filters *f) { assert (getFiltersDim() > 0); - _filters = new filters [getFiltersDim()]; + _filters = new filters [getFiltersDim()]; // Suspicious assert (_filters != NULL); @@ -1020,7 +1021,7 @@ void Model::setRules (rules *r) { assert (getRulesDim() > 0); - _rules = new rules [getRulesDim()]; + _rules = new rules [getRulesDim()]; // Suspicious assert (_rules != NULL); @@ -1038,7 +1039,7 @@ void Model::setSymbols (symbols *s) { assert (getSymbolsDim() > 0); - _symbols = new symbols [getSymbolsDim()]; + _symbols = new symbols [getSymbolsDim()]; // Suspicious assert (_symbols != NULL); @@ -1147,7 +1148,7 @@ void Model::setLowerbounds (lowerbounds *l) { assert (getLowerboundsDim() > 0); - _lowerbounds = new lowerbounds [getLowerboundsDim()]; + _lowerbounds = new lowerbounds [getLowerboundsDim()]; // Suspicious assert (_lowerbounds != NULL); @@ -1208,7 +1209,7 @@ void Model::setScoretpt (CvMat **scoretpt) if (scoretpt != NULL) assert (getScoretptDim() > 0); - _scoretpt = new CvMat* [getScoretptDim()]; + _scoretpt = new CvMat* [getScoretptDim()]; // Suspicious assert (_scoretpt != NULL); @@ -1318,7 +1319,7 @@ void Model::initializeRules (matvar_t *rulesStructure) { /* Allocate memory for a scalar element, the field structure of r[i] variable (Cell*) and calls the constructor of Cell */ - r[i].structure = new Cell(field); + r[i].structure = new Cell(field); // Suspicious assert (r[i].structure != NULL); } @@ -1327,7 +1328,7 @@ void Model::initializeRules (matvar_t *rulesStructure) { /* Allocate memory for an array element, the field structure of r[i] variable (Cell*) */ - r[i].structure = new Cell [lengthField]; + r[i].structure = new Cell [lengthField]; // Suspicious assert (r[i].structure != NULL); // Calls the Cell constructor for each element of the r[i] array @@ -1521,4 +1522,41 @@ ostream & operator<<(ostream & co, const Model & m) return co; } +void Model::resetModel() +{ + //_releaseSymbols(); + _releaseScores(); +} +// Private methods +void Model::_releaseSymbols(void) + { + symbols * sym = this->getSymbols(); + if (sym != NULL) + { + for (int i = 0; i < this->getSymbolsDim(); i++) + { + CvMat ** score = sym[i].score; + for (int j = 0; j < sym[i].dimScore; j++) + cvReleaseMat(&(score[j])); + delete [] score; + } + delete [] sym; + _symbols = NULL; + } + } + + void Model::_releaseScores(void) + { + CvMat** scorept = this->getScoretpt() ; + if (scorept != NULL) + { + + for (int i = 0; i < this->getScoretptDim(); i++) + { + cvReleaseMat(&(scorept[i])); + } + delete [] scorept; + _scoretpt = NULL; + } + } diff --git a/src/modelSort.cpp b/src/modelSort.cpp index d952b5f..0a15c8e 100644 --- a/src/modelSort.cpp +++ b/src/modelSort.cpp @@ -64,6 +64,10 @@ LStructure *modelSort (const Model *m, LStructure* L, int i, int* V) auxL[L->LDim] = i; + // Added by mjmarin + if (L->L != NULL) + delete [] L->L; + L->L = auxL; (L->LDim)++; diff --git a/src/pabod.cpp b/src/pabod.cpp index 59eec4a..a3d40cf 100644 --- a/src/pabod.cpp +++ b/src/pabod.cpp @@ -32,7 +32,7 @@ Pabod::Pabod(const char * modelfile) Pabod::Pabod(string modelfile) { - _model = new Model(modelfile); + _model = new Model(modelfile); _isCopied = false; } diff --git a/tests/detectobj2.cpp b/tests/detectobj2.cpp index 0690df1..3d4a11f 100644 --- a/tests/detectobj2.cpp +++ b/tests/detectobj2.cpp @@ -15,7 +15,6 @@ #include #include - #define TAGGED 0 #define CUT 1 From 10c7d1974e73eefcf4059bf02d30dc4ff83c7eec Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 May 2013 01:09:42 +0200 Subject: [PATCH 07/24] Improving memory usage detectvid still uses lot of memory :( --- include/cell.h | 10 +++++ include/model.h | 29 +++++++++++++ src/cell.cpp | 76 ++++++++++++++++++++++++++++++++- src/model.cpp | 111 +++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 215 insertions(+), 11 deletions(-) diff --git a/include/cell.h b/include/cell.h index 0c0ef88..8efb1fd 100644 --- a/include/cell.h +++ b/include/cell.h @@ -70,6 +70,12 @@ typedef struct anchor { int* array; int dim; + + anchor() + { + dim = 0; + array = NULL; + } } anchor; @@ -152,6 +158,10 @@ class Cell */ void destroyCell (); + void releaseScore(void); + void releaseIxIy(void); + + /////////////////////////////// ///// LOAD FILE FUNCTIONS ///// diff --git a/include/model.h b/include/model.h index ddd29c6..628f2bb 100644 --- a/include/model.h +++ b/include/model.h @@ -55,6 +55,13 @@ typedef struct rules { int n; Cell *structure; + + rules() + { + n=0; + structure = NULL; + } + } rules; /////////////////////////////// @@ -73,6 +80,13 @@ typedef struct symbols int filter; CvMat **score; int dimScore; + + symbols() + { + score = NULL; + dimScore = 0; + } + } symbols; /////////////////////////////////// @@ -89,6 +103,12 @@ typedef struct lowerbounds float *v; int f; int c; + + lowerbounds() + { + v = NULL; + } + } lowerbounds; //////////////////////////////// @@ -107,6 +127,11 @@ typedef struct bboxpred float *x2; float *y2; int dim; + + bboxpred() + { + dim = 0; + } } bboxpred; @@ -1004,6 +1029,10 @@ class Model int _scoretptDim; // Private methods + void initPtrs(void); + + void _releaseRules(bool full=false); //! Release memory allocated during a detection + void _releaseSymbols(void); //! Release memory allocated during a detection void _releaseScores(void); //! Release memory allocated during a detection diff --git a/src/cell.cpp b/src/cell.cpp index a0f0a45..9c8c9d3 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -111,6 +111,60 @@ void Cell::destroyCell () } +void Cell::releaseScore(void) +{ + if (_score != NULL) + { + for (int i = 0; i < getScoreDim(); i++) + { + if (_score[i] != NULL) + { + cvReleaseMat (&_score[i]); + _score[i] = NULL; + } + } + + delete[] _score; + _score = NULL; + } + +} + +void Cell::releaseIxIy(void) +{ + + if (_Ix != NULL) + { + for (int i = 0; i < getIxDim(); i++) + { + if (_Ix[i] != NULL) + { + cvReleaseMat (&_Ix[i]); + _Ix[i] = NULL; + } + } + + delete[] _Ix; + _Ix = NULL; + } + + if (_Iy != NULL) + { + for (int i = 0; i < getIyDim(); i++) + { + if (_Iy[i] != NULL) + { + cvReleaseMat (&_Iy[i]); + _Iy[i] = NULL; + } + } + + delete[]_Iy; + _Iy = NULL; + } +} + + /////////////////////////////// ///// LOAD FILE FUNCTIONS ///// /////////////////////////////// @@ -156,6 +210,8 @@ void Cell::loadEmptyCell () void Cell::loadCell (matvar_t *matVar, int i) { + loadEmptyCell (); // Initialize all members + loadType (matVar, i); loadLhs (matVar, i); loadDetwindow (matVar, i); @@ -332,7 +388,10 @@ void Cell::setRhs (int *rhs) { assert (getRhsDim() > 0); - _rhs = new int [getRhsDim()]; // Suspicious + if (_rhs != NULL) + delete [] _rhs; + + _rhs = new int [getRhsDim()]; assert (_rhs != NULL); @@ -345,6 +404,9 @@ void Cell::setDetwindow (double *d) { assert (getDetwindowDim() > 0); + if (_detwindow != NULL) + delete [] _detwindow; + _detwindow = new int [getDetwindowDim()]; assert (_detwindow != NULL); @@ -358,6 +420,9 @@ void Cell::setAnchor (anchor *a) { assert (getAnchorDim() > 0); + if (_anchor != NULL) + delete [] _anchor; + _anchor = new anchor [getAnchorDim()]; // Suspicious assert (_anchor != NULL); @@ -371,6 +436,9 @@ void Cell::setScore (CvMat **score) { assert (getScoreDim() > 0); + if (_score != NULL) + delete [] _score; + _score = new CvMat* [getScoreDim()]; assert (_score != NULL); @@ -384,6 +452,9 @@ void Cell::setIx (CvMat **Ix) { assert (getIxDim() > 0); + if (_Ix != NULL) + delete [] _Ix; + _Ix = new CvMat* [getIxDim()]; assert (_Ix != NULL); @@ -397,6 +468,9 @@ void Cell::setIy (CvMat **Iy) { assert (getIyDim() > 0); + if (_Iy != NULL) + delete [] _Iy; + _Iy = new CvMat* [getIyDim()]; assert (_Iy != NULL); diff --git a/src/model.cpp b/src/model.cpp index 32b265d..b22b28a 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -8,14 +8,20 @@ Model::Model () : _filters(0) , _scoretpt(0) + , _rules(0) + , _symbols(0) { + initPtrs(); loadEmptyModel(); } Model::Model (string fileName) : _filters(0) , _scoretpt(0) -{ + , _rules(0) + , _symbols(0) +{ + initPtrs(); loadFile (fileName); } @@ -25,6 +31,22 @@ Model::~Model () destroyModel(); } +void Model::initPtrs(void) +{ + _filters = NULL; + _scoretpt = NULL; + _rules = NULL; + _symbols = NULL; + _bboxpred = NULL; + _fusage = NULL; + _lowerbounds = NULL; + _learnmult = NULL; + _regmult = NULL; + _minSize = NULL; + _maxSize = NULL; + _blockSizes = NULL; +} + void Model::destroyModel () { if (_filters != NULL) @@ -1003,7 +1025,10 @@ void Model::setFilters (filters *f) { assert (getFiltersDim() > 0); - _filters = new filters [getFiltersDim()]; // Suspicious + if (_filters != NULL) + delete [] _filters; + + _filters = new filters [getFiltersDim()]; assert (_filters != NULL); @@ -1020,8 +1045,10 @@ void Model::setRules (rules *r) if (r != NULL) { assert (getRulesDim() > 0); + if (_rules != NULL) + delete [] _rules; - _rules = new rules [getRulesDim()]; // Suspicious + _rules = new rules [getRulesDim()]; assert (_rules != NULL); @@ -1038,8 +1065,10 @@ void Model::setSymbols (symbols *s) if (s != NULL) { assert (getSymbolsDim() > 0); + if (_symbols != NULL) + delete [] _symbols; - _symbols = new symbols [getSymbolsDim()]; // Suspicious + _symbols = new symbols [getSymbolsDim()]; assert (_symbols != NULL); @@ -1058,6 +1087,8 @@ void Model::setBlockSizes (int *d) { assert (getBlockSizesDim() > 0); + if ( _blockSizes != NULL) + delete [] _blockSizes; _blockSizes = new int [getBlockSizesDim()]; assert (_blockSizes != NULL); @@ -1076,6 +1107,9 @@ void Model::setMaxSize (int *d) { assert (getMaxSizeDim() > 0); + if (_maxSize != NULL) + delete [] _maxSize; + _maxSize = new int [getMaxSizeDim()]; assert (_maxSize != NULL); @@ -1094,6 +1128,8 @@ void Model::setMinSize (int *d) { assert (getMinSizeDim() > 0); + if (_minSize != NULL) + delete [] _minSize; _minSize = new int [getMinSizeDim()]; assert (_minSize != NULL); @@ -1148,7 +1184,9 @@ void Model::setLowerbounds (lowerbounds *l) { assert (getLowerboundsDim() > 0); - _lowerbounds = new lowerbounds [getLowerboundsDim()]; // Suspicious + if ( _lowerbounds != NULL) + delete [] _lowerbounds; + _lowerbounds = new lowerbounds [getLowerboundsDim()]; assert (_lowerbounds != NULL); @@ -1209,6 +1247,9 @@ void Model::setScoretpt (CvMat **scoretpt) if (scoretpt != NULL) assert (getScoretptDim() > 0); + if (_scoretpt != NULL) // To be improved: loop over CvMat's + delete [] _scoretpt; + _scoretpt = new CvMat* [getScoretptDim()]; // Suspicious assert (_scoretpt != NULL); @@ -1319,7 +1360,10 @@ void Model::initializeRules (matvar_t *rulesStructure) { /* Allocate memory for a scalar element, the field structure of r[i] variable (Cell*) and calls the constructor of Cell */ - r[i].structure = new Cell(field); // Suspicious + if (r[i].structure != NULL) + delete r[i].structure; + + r[i].structure = new Cell(field); assert (r[i].structure != NULL); } @@ -1328,7 +1372,10 @@ void Model::initializeRules (matvar_t *rulesStructure) { /* Allocate memory for an array element, the field structure of r[i] variable (Cell*) */ - r[i].structure = new Cell [lengthField]; // Suspicious + if (r[i].structure != NULL) + delete [] r[i].structure; + + r[i].structure = new Cell [lengthField]; assert (r[i].structure != NULL); // Calls the Cell constructor for each element of the r[i] array @@ -1524,11 +1571,51 @@ ostream & operator<<(ostream & co, const Model & m) void Model::resetModel() { - //_releaseSymbols(); + _releaseSymbols(); + _releaseRules(false); _releaseScores(); + } // Private methods +// --------------------------------------------------------------- +void Model::_releaseRules(bool full) +{ + if (_rules != NULL) + { + // Release some data + for (int i = 0; i < _rulesDim; i++) + { + Cell * c = _rules[i].structure; + for (int j = 0; j < _rules[i].n; j++) + { + // Release score + c[j].releaseScore(); + + // Release Ix and Iy + c[j].releaseIxIy(); + } + /* // Do not delete this + if (_rules[i].n > 1) + delete [] _rules[i].structure; + else + delete _rules[i].structure; + _rules[i].structure = NULL; + _rules[i].n = 0; + */ + } + + // Release remaining data + if (full) + { + // TO DO + _rules = NULL; + _rulesDim = 0; + } + } + +} + void Model::_releaseSymbols(void) { symbols * sym = this->getSymbols(); @@ -1537,12 +1624,16 @@ void Model::_releaseSymbols(void) for (int i = 0; i < this->getSymbolsDim(); i++) { CvMat ** score = sym[i].score; + /* Do not release score, it is shared by Rules */ + /* for (int j = 0; j < sym[i].dimScore; j++) cvReleaseMat(&(score[j])); + */ delete [] score; } - delete [] sym; - _symbols = NULL; + /* Do not delete member _symbols, it is part of the model definition */ + //delete [] sym; + //_symbols = NULL; } } From 41e37950555c08364b641a5d269d5b4c24307b27 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 8 May 2013 21:33:13 +0200 Subject: [PATCH 08/24] After each detection call, extra mem is released But not all yet :( --- src/model.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/model.cpp b/src/model.cpp index b22b28a..d81eb87 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -103,22 +103,20 @@ void Model::destroyModel () { for (int i = 0; i < getSymbolsDim(); i++) { - for (int j = 0; j < getSymbols()[i].dimScore; j++) - { - if (getSymbols()[i].score[j] != NULL) - { - cvReleaseMat(&(getSymbols()[i].score[j])); - getSymbols()[i].score[j] = NULL; - } - } + if (getSymbols()[i].score != NULL) + { + for (int j = 0; j < getSymbols()[i].dimScore; j++) + { + if (getSymbols()[i].score[j] != NULL) + { + cvReleaseMat(&(getSymbols()[i].score[j])); + getSymbols()[i].score[j] = NULL; + } + } - /*delete[] getSymbols()[i].score; - getSymbols()[i].score = NULL;*/ - if (getSymbols()[i].score != NULL) - { - delete [] getSymbols()[i].score; - getSymbols()[i].score = NULL; - } + delete [] getSymbols()[i].score; + getSymbols()[i].score = NULL; + } } delete[] _symbols; @@ -1630,6 +1628,7 @@ void Model::_releaseSymbols(void) cvReleaseMat(&(score[j])); */ delete [] score; + this->_symbols[i].score = NULL; } /* Do not delete member _symbols, it is part of the model definition */ //delete [] sym; From bace6d59ba5926b5d3274aa8039d931a1eb22701 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 9 May 2013 00:44:54 +0200 Subject: [PATCH 09/24] Dealing with memory leaks --- include/cell.h | 21 +++++++++++++++------ src/cell.cpp | 29 ++++++++++++++++++++++++++++- src/gdetect.cpp | 6 +++--- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/include/cell.h b/include/cell.h index 8efb1fd..d24cc15 100644 --- a/include/cell.h +++ b/include/cell.h @@ -1,21 +1,22 @@ #ifndef _CELL_H_ #define _CELL_H_ +#include #include #include -/** \file - * This file contains the definition of Model class. This class is used to - * load a the model structure stored on a .mat file. - */ - /** \file * This file contains the definition of Cell class. This class is * an auxiliar part of class Model, and is used to load the * field rules of .mat model file */ +/** \typedef vectorMat + Vector of OpenCV Mat + */ +typedef std::vector vectorMat; + /** \def INVALID_STR * This define is used to indicate a structure is invalid, which means their @@ -485,6 +486,7 @@ class Cell * \sa _scoreDim */ CvMat** getScore () const {return _score;} + //const vectorMat & getScore () const {return _score;} /** Set the value of private variable _score to score. @@ -493,6 +495,7 @@ class Cell * \sa _scoreDim */ void setScore (CvMat **score); + //void setScore (vectorMat & score); /** Returns the value of private variable _scoreDim @@ -521,6 +524,7 @@ class Cell * \sa _IxDim */ CvMat** getIx () const {return _Ix;} + //const vectorMat & getIx () const {return _Ix;} /** Set the value of private variable _Ix to Ix. @@ -529,7 +533,7 @@ class Cell * \sa _IxDim */ void setIx (CvMat **Ix); - + //void setIx (vectorMat &Ix); /** Returns the value of private variable _IxDim * \return The int value _IxDim, which indicates _Ix @@ -558,6 +562,7 @@ class Cell * \sa _IyDim */ CvMat** getIy () const {return _Iy;} + //const vectorMat & getIy () const {return _Iy;} /** Set the value of private variable _Iy to Iy. @@ -566,6 +571,7 @@ class Cell * \sa _IyDim */ void setIy (CvMat **Iy); + //void setIy (vectorMat & Iy); /** Returns the value of private variable _IyDim @@ -697,6 +703,7 @@ class Cell * \sa _scoreDim */ CvMat** _score; + //vectorMat _score; /** Is an int private variable. Indicates the size of @@ -710,6 +717,7 @@ class Cell * \sa _IxDim */ CvMat** _Ix; + //vectorMat _Ix; /** Is an int private variable. Indicates the size of @@ -723,6 +731,7 @@ class Cell * \sa _IyDim */ CvMat** _Iy; + //vectorMat _Iy; /** Is an int private variable. Indicates the size of diff --git a/src/cell.cpp b/src/cell.cpp index 9c8c9d3..3c53e0c 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -60,8 +60,10 @@ void Cell::destroyCell () _anchor = NULL; } - if (_score != NULL) + if (_score != NULL) + //if (_score.size() > 0) { + for (int i = 0; i < getScoreDim(); i++) { if (_score[i] != NULL) @@ -73,11 +75,16 @@ void Cell::destroyCell () delete[] _score; _score = NULL; + + // _score.clear(); } + } if (_Ix != NULL) + //if(_Ix.size() > 0) { + for (int i = 0; i < getIxDim(); i++) { if (_Ix[i] != NULL) @@ -89,10 +96,14 @@ void Cell::destroyCell () delete[] _Ix; _Ix = NULL; + + //_Ix.clear(); } if (_Iy != NULL) + //if (_Iy.size() > 0) { + for (int i = 0; i < getIyDim(); i++) { if (_Iy[i] != NULL) @@ -104,7 +115,11 @@ void Cell::destroyCell () delete[]_Iy; _Iy = NULL; + + //_Iy.clear(); } + + } setFlagStr (INVALID_STR); @@ -437,7 +452,11 @@ void Cell::setScore (CvMat **score) assert (getScoreDim() > 0); if (_score != NULL) + { + for (int i = 0; i < getScoreDim(); i++) + cvReleaseMat(&_score[i]); delete [] _score; + } _score = new CvMat* [getScoreDim()]; @@ -453,7 +472,11 @@ void Cell::setIx (CvMat **Ix) assert (getIxDim() > 0); if (_Ix != NULL) + { + for (int i = 0; i < getIxDim(); i++) + cvReleaseMat(&_Ix[i]); delete [] _Ix; + } _Ix = new CvMat* [getIxDim()]; @@ -469,7 +492,11 @@ void Cell::setIy (CvMat **Iy) assert (getIyDim() > 0); if (_Iy != NULL) + { + for (int i = 0; i < getIyDim(); i++) + cvReleaseMat(&_Iy[i]); delete [] _Iy; + } _Iy = new CvMat* [getIyDim()]; diff --git a/src/gdetect.cpp b/src/gdetect.cpp index 8051f08..8c7e7c5 100644 --- a/src/gdetect.cpp +++ b/src/gdetect.cpp @@ -24,7 +24,7 @@ void gdetect (CvMat **dets, CvMat **boxes, CvMatND **info, if ( overlap == NEGATIVE_INF ) overlap = 0.7; - _CrtMemState s1, s2, s3; +// _CrtMemState s1, s2, s3; // Cache filter response @@ -410,8 +410,8 @@ void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, int dim = 0; int spadX, spadY; - _CrtMemState s1, s2, s3; - _CrtMemCheckpoint( &s1 ); +// _CrtMemState s1, s2, s3; +// _CrtMemCheckpoint( &s1 ); // Firstable the function has to count how many elements there will be for (int s = 0; s < model->getSymbolsDim(); s++) From 0f0e435b0a6438860b6cfccdf765289e99706364 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 9 May 2013 12:49:20 +0200 Subject: [PATCH 10/24] Moving CvMat to cv::Mat Starting --- include/cell.h | 42 ++++--- src/cell.cpp | 82 ++++++++----- src/gdetect.cpp | 268 +++++++++++++++++++++++++++++++++++++++++- src/getDetections.cpp | 21 +++- 4 files changed, 359 insertions(+), 54 deletions(-) diff --git a/include/cell.h b/include/cell.h index d24cc15..f2728a5 100644 --- a/include/cell.h +++ b/include/cell.h @@ -485,8 +485,8 @@ class Cell * \sa _score * \sa _scoreDim */ - CvMat** getScore () const {return _score;} - //const vectorMat & getScore () const {return _score;} + //CvMat** getScore () const {return _score;} + const vectorMat & getScore () const {return _score;} /** Set the value of private variable _score to score. @@ -494,8 +494,8 @@ class Cell * \sa _score * \sa _scoreDim */ - void setScore (CvMat **score); - //void setScore (vectorMat & score); + //void setScore (CvMat **score); + void setScore (vectorMat & score); /** Returns the value of private variable _scoreDim @@ -523,8 +523,8 @@ class Cell * \sa _Ix * \sa _IxDim */ - CvMat** getIx () const {return _Ix;} - //const vectorMat & getIx () const {return _Ix;} + //CvMat** getIx () const {return _Ix;} + const vectorMat & getIx () const {return _Ix;} /** Set the value of private variable _Ix to Ix. @@ -532,8 +532,14 @@ class Cell * \sa _Ix * \sa _IxDim */ - void setIx (CvMat **Ix); - //void setIx (vectorMat &Ix); + //void setIx (CvMat **Ix); + void setIx (vectorMat &Ix); + + void addIxItem(cv::Mat &Ix){_Ix.push_back(Ix);}; + void addIyItem(cv::Mat &Iy){_Iy.push_back(Iy);}; + + void addIxItem(CvMat * Ix){_Ix.push_back(Ix);}; + void addIyItem(CvMat * Iy){_Iy.push_back(Iy);}; /** Returns the value of private variable _IxDim * \return The int value _IxDim, which indicates _Ix @@ -561,8 +567,8 @@ class Cell * \sa _Iy * \sa _IyDim */ - CvMat** getIy () const {return _Iy;} - //const vectorMat & getIy () const {return _Iy;} + //CvMat** getIy () const {return _Iy;} + const vectorMat & getIy () const {return _Iy;} /** Set the value of private variable _Iy to Iy. @@ -570,8 +576,8 @@ class Cell * \sa _Iy * \sa _IyDim */ - void setIy (CvMat **Iy); - //void setIy (vectorMat & Iy); + //void setIy (CvMat **Iy); + void setIy (vectorMat & Iy); /** Returns the value of private variable _IyDim @@ -702,8 +708,8 @@ class Cell /** Is a CvMat* array private variable. * \sa _scoreDim */ - CvMat** _score; - //vectorMat _score; + //CvMat** _score; + vectorMat _score; /** Is an int private variable. Indicates the size of @@ -716,8 +722,8 @@ class Cell /** Is a CvMat* array private variable. * \sa _IxDim */ - CvMat** _Ix; - //vectorMat _Ix; + //CvMat** _Ix; + vectorMat _Ix; /** Is an int private variable. Indicates the size of @@ -730,8 +736,8 @@ class Cell /** Is a CvMat* array private variable. * \sa _IyDim */ - CvMat** _Iy; - //vectorMat _Iy; + //CvMat** _Iy; + vectorMat _Iy; /** Is an int private variable. Indicates the size of diff --git a/src/cell.cpp b/src/cell.cpp index 3c53e0c..31f8ebe 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -60,10 +60,10 @@ void Cell::destroyCell () _anchor = NULL; } - if (_score != NULL) - //if (_score.size() > 0) + //if (_score != NULL) + if (_score.size() > 0) { - + /* for (int i = 0; i < getScoreDim(); i++) { if (_score[i] != NULL) @@ -75,16 +75,16 @@ void Cell::destroyCell () delete[] _score; _score = NULL; - - // _score.clear(); + */ + _score.clear(); } } - if (_Ix != NULL) - //if(_Ix.size() > 0) + //if (_Ix != NULL) + if(_Ix.size() > 0) { - + /* for (int i = 0; i < getIxDim(); i++) { if (_Ix[i] != NULL) @@ -96,14 +96,14 @@ void Cell::destroyCell () delete[] _Ix; _Ix = NULL; - - //_Ix.clear(); + */ + _Ix.clear(); } - if (_Iy != NULL) - //if (_Iy.size() > 0) + //if (_Iy != NULL) + if (_Iy.size() > 0) { - + /* for (int i = 0; i < getIyDim(); i++) { if (_Iy[i] != NULL) @@ -115,8 +115,8 @@ void Cell::destroyCell () delete[]_Iy; _Iy = NULL; - - //_Iy.clear(); + */ + _Iy.clear(); } @@ -128,8 +128,10 @@ void Cell::destroyCell () void Cell::releaseScore(void) { - if (_score != NULL) + //if (_score != NULL) + if(!_score.empty()) { + /* for (int i = 0; i < getScoreDim(); i++) { if (_score[i] != NULL) @@ -141,6 +143,8 @@ void Cell::releaseScore(void) delete[] _score; _score = NULL; + */ + _score.clear(); } } @@ -148,8 +152,10 @@ void Cell::releaseScore(void) void Cell::releaseIxIy(void) { - if (_Ix != NULL) + //if (_Ix != NULL) + if(!_Ix.empty()) { + /* for (int i = 0; i < getIxDim(); i++) { if (_Ix[i] != NULL) @@ -161,10 +167,14 @@ void Cell::releaseIxIy(void) delete[] _Ix; _Ix = NULL; + */ + _Ix.clear(); } - if (_Iy != NULL) + //if (_Iy != NULL) + if (!_Iy.empty()) { + /* for (int i = 0; i < getIyDim(); i++) { if (_Iy[i] != NULL) @@ -176,6 +186,8 @@ void Cell::releaseIxIy(void) delete[]_Iy; _Iy = NULL; + */ + _Iy.clear(); } } @@ -213,13 +225,13 @@ void Cell::loadEmptyCell () getDef().symmetric = 0; _scoreDim = -1; - _score = NULL; +// _score = NULL; _IxDim = -1; - _Ix = NULL; +// _Ix = NULL; _IyDim = -1; - _Iy = NULL; +// _Iy = NULL; } @@ -250,13 +262,13 @@ void Cell::loadCell (matvar_t *matVar, int i) } _IxDim = -1; - _Ix = NULL; +// _Ix = NULL; _IyDim = -1; - _Iy = NULL; +// _Iy = NULL; _scoreDim = -1; - _score = NULL; +// _score = NULL; } @@ -446,7 +458,7 @@ void Cell::setAnchor (anchor *a) _anchor[i] = a[i]; } - +/* void Cell::setScore (CvMat **score) { assert (getScoreDim() > 0); @@ -465,8 +477,13 @@ void Cell::setScore (CvMat **score) for (int i = 0; i < getScoreDim(); i++) _score[i] = score[i]; } +*/ +void Cell::setScore (vectorMat &score) +{ + _score = score; +} - +/* void Cell::setIx (CvMat **Ix) { assert (getIxDim() > 0); @@ -485,8 +502,15 @@ void Cell::setIx (CvMat **Ix) for (int i = 0; i < getIxDim(); i++) _Ix[i] = Ix[i]; } +*/ + +void Cell::setIx (vectorMat &Ix) +{ + _Ix = Ix; +} +/* void Cell::setIy (CvMat **Iy) { assert (getIyDim() > 0); @@ -505,7 +529,11 @@ void Cell::setIy (CvMat **Iy) for (int i = 0; i < getIyDim(); i++) _Iy[i] = Iy[i]; } - +*/ +void Cell::setIy (vectorMat &Iy) +{ + _Iy = Iy; +} //////////////////////// ///// INITIALIZERS ///// diff --git a/src/gdetect.cpp b/src/gdetect.cpp index 8c7e7c5..8615b58 100644 --- a/src/gdetect.cpp +++ b/src/gdetect.cpp @@ -154,7 +154,7 @@ void gdetect (CvMat **dets, CvMat **boxes, CvMatND **info, } - +/* void symbolScore (Model *model, int s, bool latent, const FeatPyramid &pyra, double *bbox, double overlap) { @@ -177,6 +177,36 @@ void symbolScore (Model *model, int s, bool latent, const FeatPyramid &pyra, model->getSymbols()[s].dimScore = r.structure[0].getScoreDim(); model->getSymbols()[s].score = sc; } +*/ + +void symbolScore (Model *model, int s, bool latent, const FeatPyramid &pyra, + double *bbox, double overlap) +{ + // Take pointwise max over scores for each rule with s as the lhs + rules r = model->getRules()[s]; + //CvMat **score = r.structure[0].getScore(); + vectorMat score = r.structure[0].getScore(); + + CvMat **sc = new CvMat* [r.structure[0].getScoreDim()]; + + assert (sc != NULL); + + for (int i = 0; i < r.structure[0].getScoreDim(); i++) + { + CvMat tmpMat = score[i]; + sc[i] = cvCloneMat (&tmpMat); + } + + for (int j = 1; j < r.n; j++) + for (int i = 0; i < r.structure[j].getScoreDim(); i++) + { + CvMat tmpMat = r.structure[j].getScore()[i]; + cvMax (sc[i], &tmpMat, sc[i]); + } + + model->getSymbols()[s].dimScore = r.structure[0].getScoreDim(); + model->getSymbols()[s].score = sc; +} @@ -190,7 +220,7 @@ void applyRule (Model *model, const Cell &r, int padY, int padX) } - +/* void applyStructuralRule (Model *model, const Cell &r, int padY, int padX) { // Structural rule -> shift and sum scores from rhs symbols @@ -362,9 +392,190 @@ void applyStructuralRule (Model *model, const Cell &r, int padY, int padX) model->getRules()[(int) r.getLhs()].structure [(int) r.getI()].setScore(score); } +*/ + +void applyStructuralRule (Model *model, const Cell &r, int padY, int padX) +{ + // Structural rule -> shift and sum scores from rhs symbols + // Prepare score for this rule + //CvMat** score = new CvMat* [model->getScoretptDim()]; + vectorMat score; + score.reserve(model->getScoretptDim()); + //assert (score != NULL); + + int scoreDims[2]; + + for (int i = 0; i < model->getScoretptDim(); i++) + { + scoreDims[0] = model->getScoretpt()[i]->rows; + scoreDims[1] = model->getScoretpt()[i]->cols; + + cv::Mat tmpMat(scoreDims[0], scoreDims[1], model->getScoretpt()[i]->type); + //tmpMat.setTo(0); + //createMatrix (2, scoreDims, model->getScoretpt()[i]->type, &(score[i])); + + //assert (score[i] != NULL); + + //fillMat (score[i], r.getOffset().w); + tmpMat.setTo(r.getOffset().w); + score.push_back(tmpMat); + } + + + int *iy; + int *ix; + CvMat *sp; + CvMat *sTmp; + int sz[2]; + + double ax; + double ay; + double ds; + + int step; + + int virtPadY; + int virtPadX; + + int startY; + int startX; + + int startLevel; + + int level; + int iter = 0; + + int endY; + int endX; + + int iyDim; + int oy; + + int ixDim; + int ox; + + int sTmpDims[2]; + + // Sum scores from rhs (with appropriate shift and down sample) + for (int j = 0; j < r.getRhsDim(); j++) + { + ax = r.getAnchor()[j].array[0]; + ay = r.getAnchor()[j].array[1]; + ds = r.getAnchor()[j].array[2]; + + // Step size for down sampling + step = int(pow (2, ds)); + + // Amount of (virtual) padding to halucinate + virtPadY = (step-1) * padY; + virtPadX = (step-1) * padX; + + // Starting points (simulates additional padding at finer scales) + startY = int(ay - virtPadY); + startX = int(ax - virtPadX); + + // Starting level + startLevel = int( (model->getInterval() + 1) * ds); + + // Score table to shift and down sample + CvMat** s = model->getSymbols()[(int) r.getRhs()[j]].score; + assert (s != NULL); + + for (int i = startLevel; + i < (int) (model->getSymbols()[(int)r.getRhs()[j]].dimScore); + i++) + { + level = i - int( (model->getInterval() + 1) * ds); + + // Ending points + endY = min ((int) s[level]->rows, (int) (startY + + (step * (score[i].rows))) ); + endX = min ((int) s[level]->cols, (int) (startX + + (step * (score[i].cols))) ); + + // Y sample points + assert ( (endY-startY) > 0); + assert ( step > 0); + + iyDim = round((float)(endY-startY)/step); + iy = new int [iyDim]; + assert (iy != NULL); + + iter = 0; + + for (int k = startY; k < endY; k += step) + { + iy[iter] = k; + iter++; + } + + oy = countElementsWhich (LOWER, 0, &iy, iyDim, true); + + iyDim = iyDim - oy; + assert (iyDim > 0); + + // X sample points + assert ( (endX-startX) > 0); + assert (step > 0); + + ixDim = round((float)(endX-startX)/step); + ix = new int [ixDim]; + assert (ix != NULL); + + iter = 0; + + for (int k = startX; k < endX; k += step) + { + ix[iter] = k; + iter++; + } + + ox = countElementsWhich (LOWER, 0, &ix, ixDim, true); + + ixDim = ixDim - ox; + assert (ixDim > 0); + + // Sample scores + sp = subMat (s[level], iy, iyDim, ix, ixDim); + assert (sp != NULL); + getDimensions (sp, sz); + // Sum with correct offset + assert (score[i]->rows > 0); + assert (score[i]->cols > 0); + + sTmpDims[0] = score[i].rows; + sTmpDims[1] = score[i].cols; + + createMatrix (2, sTmpDims, CV_64FC1, &sTmp); + + assert (sTmp != NULL); + + fillMat (sTmp, NEGATIVE_INF); + + for (int j = oy; j < oy+sz[0]; j++) + for (int k = ox; k < ox+sz[1]; k++) + cvSetReal2D (sTmp, j, k, cvGetReal2D (sp, j-oy, k-ox)); + + cv::Mat sTmp2 = sTmp; + //cvAdd (score[i], sTmp, score[i]); + add (score[i], sTmp2, score[i]); + + delete[] iy; + delete[] ix; + cvReleaseMat (&sp); + cvReleaseMat (&sTmp); + } + } + + model->getRules()[(int) r.getLhs()].structure + [(int) r.getI()].setScoreDim(model->getScoretptDim()); + model->getRules()[(int) r.getLhs()].structure + [(int) r.getI()].setScore(score); +} +/* void applyDeformationRule (Model *model, const Cell &r) { // Deformation rule -> apply distance transform @@ -400,8 +611,50 @@ void applyDeformationRule (Model *model, const Cell &r) model->getRules()[(int) r.getLhs()].structure[(int) r.getI()] .setIy(Iy); } +*/ + +void applyDeformationRule (Model *model, const Cell &r) +{ + // Deformation rule -> apply distance transform + double *d = r.getDef().w; + int dim = model->getSymbols()[(int) r.getRhs()[0]].dimScore; + CvMat** score = model->getSymbols()[(int) r.getRhs()[0]].score; + + //CvMat **Ix = new CvMat* [dim]; + //assert (Ix != NULL); + + //CvMat **Iy = new CvMat* [dim]; + //assert (Iy != NULL); + + for (int i = 0; i < dim; i++) + { + // Note: dt has been changed so it is not necesarry to pass in -score[i] + CvMat * tmpIx, * tmpIy; + //dt (score[i], d[0], d[1], d[2], d[3], &score[i], &Ix[i], &Iy[i]); + dt (score[i], d[0], d[1], d[2], d[3], &score[i], &tmpIx, &tmpIy); + model->getRules()[(int) r.getLhs()].structure[(int) r.getI()].addIxItem(tmpIx); + model->getRules()[(int) r.getLhs()].structure[(int) r.getI()].addIyItem(tmpIy); + cvAddS (score[i], cvRealScalar(r.getOffset().w), score[i]); + } + + model->getRules()[(int) r.getLhs()].structure[(int) r.getI()] + .setScoreDim(dim); + vectorMat scoreTmp; + scoreTmp.reserve(dim); + for (int i =0; i < dim; i++) + scoreTmp.push_back(score[i]); + model->getRules()[(int) r.getLhs()].structure[(int) r.getI()].setScore(scoreTmp); + //.setScore(score); + model->getRules()[(int) r.getLhs()].structure[(int) r.getI()] + .setIxDim(dim); + // model->getRules()[(int) r.getLhs()].structure[(int) r.getI()].setIx(Ix); + + model->getRules()[(int) r.getLhs()].structure[(int) r.getI()] + .setIyDim(dim); + //model->getRules()[(int) r.getLhs()].structure[(int) r.getI()].setIy(Iy); +} void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, double *bbox, double overlap) @@ -474,7 +727,10 @@ void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, for (int i = 0; i < rDim; i++) { model->getSymbols()[filter_to_symbol[i]].dimScore = dim; - model->getSymbols()[filter_to_symbol[i]].score = new CvMat* [dim]; // Suspicious --> to be tracked + model->getSymbols()[filter_to_symbol[i]].score = new CvMat* [dim]; + // Init ptrs so can be safely deleted if needed + for (int j = 0; j < dim; j++) + model->getSymbols()[filter_to_symbol[i]].score[j] = NULL; } int s[2]; @@ -516,7 +772,11 @@ void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, cvReleaseMat(&r[i]); // Release old memory r[i] = newArray; - _CrtMemCheckpoint( &s1 ); + // _CrtMemCheckpoint( &s1 ); + if (model->getSymbols()[filter_to_symbol[i]].score[levels[j]] != NULL) + { + cvReleaseMat(&model->getSymbols()[filter_to_symbol[i]].score[levels[j]]); + } model->getSymbols()[filter_to_symbol[i]].score[levels[j]] = r[i]; } diff --git a/src/getDetections.cpp b/src/getDetections.cpp index a987a07..95dd206 100644 --- a/src/getDetections.cpp +++ b/src/getDetections.cpp @@ -179,14 +179,17 @@ static void trace(int padX, int padY, const float *scales, int sx, int sy, success = false; symRules = rul[n.symbol]; rulesDim = symRules.n; - r = 0; + - for (; r < rulesDim; r++) + for (r = 0; r < rulesDim; r++) { // probe location = symbol location minus virtual padding probeY = n.y - virtpadding(padY, n.ds); probeX = n.x - virtpadding(padX, n.ds); - mxScore = symRules.structure[r].getScore()[n.l]; + cv::Mat tmpScore; + tmpScore = symRules.structure[r].getScore()[n.l]; + CvMat mxScore2 = tmpScore; + mxScore = &mxScore2; score = new double [mxScore->rows * mxScore->cols]; getMatData (mxScore, score); getDimensions(mxScore, sz); @@ -269,8 +272,16 @@ static void trace(int padX, int padY, const float *scales, int sx, int sy, else { // Deformation rule (only 1 rhs symbol) - mxIx = symRules.structure[r].getIx()[n.l]; - mxIy = symRules.structure[r].getIy()[n.l]; + cv::Mat tmpMxIx; + tmpMxIx = symRules.structure[r].getIx()[n.l]; + CvMat mxIx2 = tmpMxIx; + mxIx = &mxIx2; + + cv::Mat tmpMxIy; + tmpMxIy = symRules.structure[r].getIy()[n.l]; + CvMat mxIy2 = tmpMxIy; + mxIy = &mxIy2; + Ix = new int [mxIx->rows * mxIx->cols]; getMatData (mxIx, Ix); Iy = new int [mxIy->rows * mxIy->cols]; From 1722f1b50be01789d0455b03b0669035d153f1d1 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 9 May 2013 19:46:31 +0200 Subject: [PATCH 11/24] Moving CvMat to cv::Mat --- CMakeLists.txt | 2 +- README.txt | 2 + include/cell.h | 6 -- include/custom.h | 6 +- include/featPyramid.h | 19 +++- include/handlerOpenCVStructs.h | 73 ++++++++++++++++ include/nms.h | 3 + src/featPyramid.cpp | 72 +++++++++------ src/gdetect.cpp | 7 +- src/makeDetection.cpp | 12 ++- src/nms.cpp | 154 +++++++++++++++++++++++++++++++++ 11 files changed, 309 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 899d2ab..9181124 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(pabod) -set(PROJECT_VERSION "0.2.7") +set(PROJECT_VERSION "0.2.9") string(REGEX MATCHALL "[0-9]" PROJECT_VERSION_PARTS "${PROJECT_VERSION}") list(GET PROJECT_VERSION_PARTS 0 PROJECT_VERSION_MAJOR) list(GET PROJECT_VERSION_PARTS 1 PROJECT_VERSION_MINOR) diff --git a/README.txt b/README.txt index 7372682..da19dd9 100644 --- a/README.txt +++ b/README.txt @@ -89,6 +89,8 @@ URL: http://people.cs.uchicago.edu/~pff/latent/ Version history: ================ + - v0.2.9: moving CvMat to cv::Mat + - v0.2.8: new class Detection - v0.2.7: memory leaks found by github/yokox solved. Thanks! - v0.2.6: new file 'export.h' for properly exporting functions to dll's. - v0.2.5: updated CMake files and other minor improvements for Windows compatibility. diff --git a/include/cell.h b/include/cell.h index f2728a5..d7e3fb8 100644 --- a/include/cell.h +++ b/include/cell.h @@ -12,12 +12,6 @@ * field rules of .mat model file */ -/** \typedef vectorMat - Vector of OpenCV Mat - */ -typedef std::vector vectorMat; - - /** \def INVALID_STR * This define is used to indicate a structure is invalid, which means their * fields are not considered. diff --git a/include/custom.h b/include/custom.h index 9019ae6..b37546f 100644 --- a/include/custom.h +++ b/include/custom.h @@ -3,16 +3,12 @@ #undef USE_OPENMP -#if _DEBUG -#undef USE_PTHREADS -#else #define USE_PTHREADS 1 -#endif #define PABOD_MAJOR_VERSION 0 #define PABOD_MINOR_VERSION 2 -#define PABOD_PATCH_VERSION 8 +#define PABOD_PATCH_VERSION 9 #endif diff --git a/include/featPyramid.h b/include/featPyramid.h index 9e6ea83..8ede71f 100644 --- a/include/featPyramid.h +++ b/include/featPyramid.h @@ -198,7 +198,8 @@ class FeatPyramid * _feat * \note Inline function */ - CvMatND** getFeat() const {return _feat;} + //CvMatND** getFeat() const {return _feat;} + vectorMat const & getFeat(void) const {return _feat;} /** Sets the value of private variable _feat to @@ -206,12 +207,25 @@ class FeatPyramid * \param feat - new value for the variable _feat * \note Inline function */ + /* void setFeat (CvMatND** feat) { if (feat != NULL) _feat = feat; } +*/ + void setFeat (vectorMat & feat) + { + if (!_feat.empty()) + _feat.clear(); + _feat = feat; + } + + void addFeatItem(cv::Mat & f) + { + _feat.push_back(f); + } /** Sets the value of element i of private vector variable * _feat to feat. @@ -329,7 +343,8 @@ class FeatPyramid private: - CvMatND **_feat; + //CvMatND **_feat; + vectorMat _feat; //! Computed features float *_scales; diff --git a/include/handlerOpenCVStructs.h b/include/handlerOpenCVStructs.h index a1032f7..66f746c 100644 --- a/include/handlerOpenCVStructs.h +++ b/include/handlerOpenCVStructs.h @@ -3,6 +3,7 @@ #include #include +#include #include /** \file @@ -14,6 +15,11 @@ * uses library \e OpenCV, arrays and matrixes */ +/** \typedef vectorMat + Vector of OpenCV Mat + */ +typedef std::vector vectorMat; + /** \def PAIR * Is used in some vectors which stores a pair of values. @@ -764,6 +770,73 @@ void removeIndexes (Type **original, int dimOr, const int *indexes, int dimIdx) (*original) = NULL; } +template +bool greaterThan (Type i, Type j) { return (i > j); } + +//! Remove from original elements at locations defined by indexes +template +void removeIndexes (Type **original, int dimOr, std::vector &indexes) +{ + Type *aux = (*original); + //int *sortedIdx = (int*) indexes; + std::vector sortedIdx = indexes; + int dimIdx = indexes.size(); + + if (dimOr - dimIdx > 0) + { + (*original) = new Type [dimOr - dimIdx]; + + //shellSort (sortedIdx, dimIdx, DESCEND); + std::sort(sortedIdx.begin(), sortedIdx.end(), greaterThan); + + for (int i = 0; i < dimIdx; i++) + for (int j = 0; j < dimOr - sortedIdx[i]; j++) + aux[sortedIdx[i] + j] = aux[sortedIdx[i] + j + 1]; + + for (int i = 0; i < dimOr - dimIdx; i++) + (*original)[i] = aux[i]; + } + + else + (*original) = NULL; +} + + +template +void removeIndexes (std::vector & original, int dimOr, const int *indexes, int dimIdx) +{ + //Type *aux = (*original); + std::vector aux = original; + int *sortedIdx = (int*) indexes; + int siz = dimOr - dimIdx; + + if (siz > 0) + { + //(*original) = new Type [dimOr - dimIdx]; + original.clear(); + original.reserve(siz); + for (int i = 0; i < siz; i++) + original.push_back(0); + + shellSort (sortedIdx, dimIdx, DESCEND); + + for (int i = 0; i < dimIdx; i++) + for (int j = 0; j < dimOr - sortedIdx[i]; j++) + //aux[sortedIdx[i] + j] = aux[sortedIdx[i] + j + 1]; + aux[sortedIdx[i] + j] = aux[sortedIdx[i] + j + 1]; + + /* + for (int i = 0; i < dimOr - dimIdx; i++) + (*original)[i] = aux[i]; + */ + original = aux; + } + + else + //(*original) = NULL; + original.clear(); +} + template void shellSort (Type *v, int n, int mode, int **idx) diff --git a/include/nms.h b/include/nms.h index aecb14d..c52b6ed 100644 --- a/include/nms.h +++ b/include/nms.h @@ -26,4 +26,7 @@ void nms (int** pick, int *pickDim, CvMat *dets = NULL, double overlap = POSITIVE_INF); +void nms2 (std::vector & pick, + CvMat *dets, double overlap); + #endif diff --git a/src/featPyramid.cpp b/src/featPyramid.cpp index 8625d04..ca6ce82 100644 --- a/src/featPyramid.cpp +++ b/src/featPyramid.cpp @@ -41,7 +41,7 @@ float vv[9] = FeatPyramid::FeatPyramid () { - _feat = NULL; +// _feat = NULL; _scales = NULL; _dim = -1; _imSize = NULL; @@ -579,8 +579,12 @@ void FeatPyramid::featpyramid (const IplImage *im, const Model *model, int padX, setDim (int(maxScale + interval)); assert (getDim() > 0); - _feat = new CvMatND* [getDim()]; // Suspicious - assert (_feat != NULL); +// _feat = new CvMatND* [getDim()]; // Suspicious + _feat.reserve(getDim()); + for (int i = 0; i < getDim(); i++) // Pre-allocate memory + _feat.push_back(cv::Mat()); +// assert (_feat != NULL); + assert(!_feat.empty()); _scales = new float [getDim()]; // Suspicious assert (_scales != NULL); @@ -620,39 +624,51 @@ void FeatPyramid::featpyramid (const IplImage *im, const Model *model, int padX, // mjmarin: more release needed for imAux cvReleaseImage(&imAux); } - //cout << "Antes de bucle2 featpyramid" << endl; + // Second loop for (int i = 0; i < getDim(); i++ ) { // Add 1 to padding because feature generation deletes a 1-cell // Wide border around the feature map pad[0] = padY + 1; pad[1] = padX + 1; - pad[2] = 0; - - // mjmarin: TODO memory leak? - //setFeat (padArray (getFeat()[i], pad, 0), i); - CvMatND* tmpfeat = getFeat()[i]; - CvMatND* tmppad = padArray (tmpfeat, pad, 0); + pad[2] = 0; + + //CvMatND* tmpfeat = getFeat()[i]; + cv::Mat tmpfeat = getFeat()[i]; + CvMatND tmpND = tmpfeat; + //CvMatND* tmppad = padArray (tmpfeat, pad, 0); + CvMatND* tmppad = padArray (&tmpND, pad, 0); setFeat (tmppad, i); - cvReleaseMatND(&tmpfeat); - // end of fix + //cvReleaseMatND(&tmpfeat); // mjmarin: commented out since it should be auto released with use of cv::Mat + // Write boundary occlusion feature + cv::Mat fMat = getFeat()[i]; for (int j = 0; j <= padY; j++) - for (int k = 0; k < getFeat()[i]->dim[1].size; k++) - cvSetReal3D (getFeat()[i], j, k, 31, 1); - - for (int j = getFeat()[i]->dim[0].size - padY -1; j < getFeat()[i]->dim[0].size; j++) - for (int k = 0; k < getFeat()[i]->dim[1].size; k++) - cvSetReal3D (getFeat()[i], j, k, 31, 1); - - for (int j = 0; j < getFeat()[i]->dim[0].size; j++) + //for (int k = 0; k < getFeat()[i]->dim[1].size; k++) + for (int k = 0; k < fMat.size.p[1]; k++) + //cvSetReal3D (getFeat()[i], j, k, 31, 1); + fMat.at(j, k, 31) = 1; + + //for (int j = getFeat()[i]->dim[0].size - padY -1; j < getFeat()[i]->dim[0].size; j++) + for (int j = fMat.size.p[0] - padY -1; j < fMat.size.p[0]; j++) + //for (int k = 0; k < getFeat()[i]->dim[1].size; k++) + for (int k = 0; k < fMat.size.p[1]; k++) + //cvSetReal3D (getFeat()[i], j, k, 31, 1); + fMat.at(j, k, 31) = 1; + + //for (int j = 0; j < getFeat()[i]->dim[0].size; j++) + for (int j = 0; j < fMat.size.p[0]; j++) for (int k = 0; k <= padX; k++) - cvSetReal3D (getFeat()[i], j, k, 31, 1); - - for (int j = 0; j < getFeat()[i]->dim[0].size; j++) - for (int k = getFeat()[i]->dim[1].size - padX - 1; k < getFeat()[i]->dim[1].size; k++) - cvSetReal3D (getFeat()[i], j, k, 31, 1); + //cvSetReal3D (getFeat()[i], j, k, 31, 1); + fMat.at(j, k, 31) = 1; + + //for (int j = 0; j < getFeat()[i]->dim[0].size; j++) + for (int j = 0; j < fMat.size.p[0]; j++) + //for (int k = getFeat()[i]->dim[1].size - padX - 1; k < getFeat()[i]->dim[1].size; k++) + for (int k = fMat.size.p[1] - padX - 1; k < fMat.size.p[1]; k++) + //cvSetReal3D (getFeat()[i], j, k, 31, 1); + fMat.at(j, k, 31) = 1; } setPadX (padX); @@ -663,8 +679,10 @@ void FeatPyramid::featpyramid (const IplImage *im, const Model *model, int padX, void FeatPyramid::destroyFeatPyramid() { - if (_feat != NULL) + //if (_feat != NULL) + if (!_feat.empty()) { + /* for (int i = 0; i < getDim(); i++) { if (_feat[i] != NULL) @@ -676,6 +694,8 @@ void FeatPyramid::destroyFeatPyramid() delete[] _feat; _feat = NULL; + */ + _feat.clear(); } if (_scales != NULL) diff --git a/src/gdetect.cpp b/src/gdetect.cpp index 8615b58..ed42e0d 100644 --- a/src/gdetect.cpp +++ b/src/gdetect.cpp @@ -541,8 +541,8 @@ void applyStructuralRule (Model *model, const Cell &r, int padY, int padX) getDimensions (sp, sz); // Sum with correct offset - assert (score[i]->rows > 0); - assert (score[i]->cols > 0); + assert (score[i].rows > 0); + assert (score[i].cols > 0); sTmpDims[0] = score[i].rows; sTmpDims[1] = score[i].cols; @@ -739,7 +739,8 @@ void filterResponses (Model *model, const FeatPyramid &pyra, bool latent, for (int j = 0; j < dim; j++) { // Compute filter response for all filters at this level - r = fconv (pyra.getFeat()[levels[j]], filters, 1, filtersDim); + CvMatND tmpF = pyra.getFeat()[levels[j]]; + r = fconv (&tmpF, filters, 1, filtersDim); // Find max response array size for this level s[0] = NEGATIVE_INF_INT; // mjmarin fix diff --git a/src/makeDetection.cpp b/src/makeDetection.cpp index d78dcfe..3375615 100644 --- a/src/makeDetection.cpp +++ b/src/makeDetection.cpp @@ -17,10 +17,13 @@ PABOD_EXPORT float makeDetection (LDetections & D, IplImage *img, Model * model, if (found) { - int *pick; - int pickDim; + //int *pick; + std::vector pick; + - nms (&pick, &pickDim, dets, iouNms); + //nms (&pick, &pickDim, dets, iouNms); + nms2(pick, dets, iouNms); + int pickDim = pick.size(); // (*results) = cvCreateMat (pickDim, 6, CV_32FC1); @@ -39,7 +42,8 @@ PABOD_EXPORT float makeDetection (LDetections & D, IplImage *img, Model * model, detected = pickDim; - delete[] pick; + //delete[] pick; + pick.clear(); } /* else diff --git a/src/nms.cpp b/src/nms.cpp index 3d56330..5267d36 100644 --- a/src/nms.cpp +++ b/src/nms.cpp @@ -145,3 +145,157 @@ void nms (int** pick, int *pickDim, } } +void nms2 (std::vector & pick, + CvMat *dets, double overlap) +{ +#ifdef _DEBUG + std::cout << "debug: using nms2" << std::endl; +#endif + //int pickDim = 0; + if (dets == NULL) + { + //*pick = NULL; + pick.clear(); + //*pickDim = 0; + } + + else + { + //*pick = NULL; + pick.clear(); + //*pickDim = 0; + + int *rows = new int [dets->rows]; + for (int i = 0; i < dets->rows; i++) + rows[i] = i; + + int col; + col = 0; + CvMat *x1 = subMat (dets, rows, dets->rows, &col, 1); + double *x1Ptr = new double [x1->rows * x1->cols]; + getMatData (x1, x1Ptr); + + col = 1; + CvMat *y1 = subMat (dets, rows, dets->rows, &col, 1); + double *y1Ptr = new double [y1->rows * y1->cols]; + getMatData (y1, y1Ptr); + + col = 2; + CvMat *x2 = subMat (dets, rows, dets->rows, &col, 1); + double *x2Ptr = new double [x2->rows * x2->cols]; + getMatData (x2, x2Ptr); + + col = 3; + CvMat *y2 = subMat (dets, rows, dets->rows, &col, 1); + double *y2Ptr = new double [y2->rows * y2->cols]; + getMatData (y2, y2Ptr); + + col = 5; + CvMat *s = subMat (dets, rows, dets->rows, &col, 1); + double *sPtr = new double [s->rows * s->cols]; + getMatData (s, sPtr); + + int areaDims[2] = {dets->rows, 1}; + + CvMat *area; + createMatrix (2, areaDims, CV_64FC1, &area); + CvMat *p1, *p2; + p1 = cvCloneMat (x1); + p2 = cvCloneMat (y1); + cvSub (x2, x1, p1); + cvAddS (p1, cvScalar(1), p1); + cvSub (y2, y1, p2); + cvAddS (p2, cvScalar(1), p2); + cvMul (p1, p2, area); + + double *areaPtr = new double [area->rows * area->cols]; + getMatData (area, areaPtr); + + cvReleaseMat (&x1); + cvReleaseMat (&y1); + cvReleaseMat (&x2); + cvReleaseMat (&y2); + cvReleaseMat (&x1); + cvReleaseMat (&s); + cvReleaseMat (&area); + cvReleaseMat (&p1); + cvReleaseMat (&p2); + delete[] rows; + + int idxDim = dets->rows; + int *idx = new int [idxDim]; + + shellSort (sPtr, dets->rows, ASCEND, &idx); + + int last; + int i; + //int *suppress = NULL; + //int suppressDim = 0; + std::vector suppress; + + int j; + + double xx1; + double yy1; + double xx2; + double yy2; + double w; + double h; + + double o; + + while (idxDim > 0) + { + last = idxDim-1; + i = idx[last]; + //appendArray (pick, (*pickDim), &i, 1); + pick.push_back(i); + //(*pickDim)++; + + //suppress = NULL; + //suppressDim = 0; + //appendArray (&suppress, suppressDim, &last, 1); + //suppressDim++; + suppress.push_back(last); + + for (int pos = 0; pos < last; pos++) + { + j = idx[pos]; + + xx1 = max (x1Ptr[i], x1Ptr[j]); + yy1 = max (y1Ptr[i], y1Ptr[j]); + xx2 = min (x2Ptr[i], x2Ptr[j]); + yy2 = min (y2Ptr[i], y2Ptr[j]); + w = xx2 - xx1 + 1; + h = yy2 - yy1 + 1; + + if (w > 0 && h > 0) + { + // Compute overlap + o = (w * h) / areaPtr[j]; + + if (o > overlap) + { + //appendArray (&suppress, suppressDim, &pos, 1); + suppress.push_back(pos); + //suppressDim++; + } + } + } + + removeIndexes(&idx, idxDim, suppress); + idxDim -= suppress.size(); + + //delete[] suppress; + suppress.clear(); + } + + delete[] x1Ptr; + delete[] y1Ptr; + delete[] x2Ptr; + delete[] y2Ptr; + delete[] sPtr; + delete[] areaPtr; + delete[] idx; + } +} From 480e641589b7c0413cbc277a7a9c91fc9c36eb8b Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 21 May 2013 19:50:36 +0200 Subject: [PATCH 12/24] Moving CvMat to cv::Mat See new process2() --- include/featPyramid.h | 8 + include/handlerOpenCVStructs.h | 61 +++++++ include/nms.h | 2 + src/featPyramid.cpp | 302 ++++++++++++++++++++++++++++++++- 4 files changed, 368 insertions(+), 5 deletions(-) diff --git a/include/featPyramid.h b/include/featPyramid.h index 8ede71f..fbf1618 100644 --- a/include/featPyramid.h +++ b/include/featPyramid.h @@ -154,6 +154,8 @@ class FeatPyramid */ CvMatND *process(const IplImage *mximage, const float mxsbin); + cv::Mat FeatPyramid::process2( const IplImage *mximage, const float mxsbin ); + /** The function pad the mat array with so many values val * like indicates the vector dimPad. Each element means * one dimension. @@ -239,6 +241,12 @@ class FeatPyramid _feat[i] = feat; } + void setFeat (const cv::Mat & feat, int i) + { + assert (i < getDim()); + _feat[i] = feat; + } + /** Returns the value of private variable _scales. * \return The float vector, which is the value of diff --git a/include/handlerOpenCVStructs.h b/include/handlerOpenCVStructs.h index 66f746c..6cfaeb6 100644 --- a/include/handlerOpenCVStructs.h +++ b/include/handlerOpenCVStructs.h @@ -645,6 +645,42 @@ Type* getMatNData (const CvMatND *mat) return v; } +template +Type* getMatNData (const cv::Mat & mat_) +{ + Type *v; + CvMatND mat__ = mat_; + CvMatND * mat = &mat__; + + int counter = 0; + unsigned int dim0 = mat->dim[0].size; + unsigned int dim1 = mat->dim[1].size; + unsigned int dim2 = mat->dim[2].size; + + assert (dim2 > 0); + assert (dim1 > 0); + assert (dim0 > 0); + + v = new Type [dim2 * dim1 * dim0]; + + assert (v != NULL); + + for (unsigned int i = 0; i < dim2; i++) + { + for (unsigned int j = 0; j < dim1; j++) + { + for (unsigned int k = 0; k < dim0; k++) + { + v[counter] = (Type) cvGetReal3D (mat, k, j, i); + counter++; + } + + } + } + + return v; +} + template void setMatNData (CvMatND *mat, const Type *v) @@ -669,6 +705,31 @@ void setMatNData (CvMatND *mat, const Type *v) } +template +void setMatNData (cv::Mat & mat_, const Type *v) +{ + CvMatND mat = mat_; // Intermediate var + + int counter = 0; + unsigned int dim0 = mat.dim[0].size; + unsigned int dim1 = mat.dim[1].size; + unsigned int dim2 = mat.dim[2].size; + + for (unsigned int i = 0; i < dim2; i++) + { + for (unsigned int j = 0; j < dim1; j++) + { + for (unsigned int k = 0; k < dim0; k++) + { + cvSetReal3D (&mat, k, j, i, v[counter]); + counter++; + } + + } + } +} + + template CvMat* padArray (const CvMat *mat, int dimPad[2], Type val, int mode) { diff --git a/include/nms.h b/include/nms.h index c52b6ed..36498d6 100644 --- a/include/nms.h +++ b/include/nms.h @@ -26,6 +26,8 @@ void nms (int** pick, int *pickDim, CvMat *dets = NULL, double overlap = POSITIVE_INF); + +//! This version uses std::vector void nms2 (std::vector & pick, CvMat *dets, double overlap); diff --git a/src/featPyramid.cpp b/src/featPyramid.cpp index ca6ce82..b0b9466 100644 --- a/src/featPyramid.cpp +++ b/src/featPyramid.cpp @@ -499,6 +499,295 @@ CvMatND* FeatPyramid::process ( const IplImage *mximage, const float mxsbin ) return mxfeat; } +// mjmarin: this version works with cv::Mat +cv::Mat FeatPyramid::process2( const IplImage *mximage, const float mxsbin ) +{ +//cout << "Init process pyramid" << endl; + float *im = getImgData (mximage); + int dims[3]; + getDimensions (mximage, dims); + + if (dims[2] != 3) + cout << "Invalid input" << endl; + + int sbin = (int) mxsbin; + + // memory for caching orientation histograms & their norms + int blocks[2]; + blocks[0] = (int)round((float)dims[0]/(float)sbin); + blocks[1] = (int)round((float)dims[1]/(float)sbin); + + assert (blocks[0] > 0); + assert (blocks[1] > 0); + + float *hist = new float [blocks[0]*blocks[1]*18]; + + for (int i = 0; i < blocks[0]*blocks[1]*18; i++) + hist[i] = 0; + + float *norm = new float [blocks[0]*blocks[1]]; + + for (int i = 0; i < blocks[0]*blocks[1]; i++) + norm[i] = 0; + + // memory for HOG features + int out[3]; + + out[0] = max(blocks[0]-2, 0); + out[1] = max(blocks[1]-2, 0); + out[2] = 27+4+1; + + //CvMatND *mxfeat; + cv::Mat mxfeat; +//cout << "POS" << endl; + if (out[0] == 0 && out[1] == 0 ) + mxfeat = NULL; + + else + { + assert (out[0] > 0); + assert (out[1] > 0); + + //mxfeat = createNDMatrix (3, out, CV_64FC1); + //createMatrix (3, out, CV_64FC1, &mxfeat); + mxfeat.create(3, out, CV_64FC1); + //assert (mxfeat != NULL); + assert (!mxfeat.empty()); +//cout << "POS" << endl; + //double *feat = new double [out[0] * out[1] * out[2]]; + //float *feat = getMatNData (mxfeat); + float *feat = new float [out[0] * out[1] * out[2]]; + assert (feat != NULL); +//cout << "POS" << endl; + int visible[2]; + visible[0] = blocks[0]*sbin; + visible[1] = blocks[1]*sbin; + + float *s; + float dy, dx; + float v; + + float dy2, dx2; + float v2; + + float dy3, dx3; + float v3; + + float best_dot = 0; + int best_o = 0; + + float dot; + + float xp, yp; + + int ixp, iyp; + float vx0, vy0, vx1, vy1; + + float *src1, *src2; + float *dst, *end; + + float *dst2; + float *src, *p, n1, n2, n3, n4; + + float t1 = 0; + float t2 = 0; + float t3 = 0; + float t4 = 0; + + double h1, h2, h3, h4; +// +// +// + float sum = 0;// +// + for (int x = 1; x < visible[1]-1; x++) + { + for (int y = 1; y < visible[0]-1; y++) + { + // first color channel + s = im + min(x, dims[1]-2)*dims[0] + min(y, dims[0]-2); + dy = *(s+1) - *(s-1); + dx = *(s+dims[0]) - *(s-dims[0]); + v = dx*dx + dy*dy; + + // second color channel + s += dims[0]*dims[1]; + dy2 = *(s+1) - *(s-1); + dx2 = *(s+dims[0]) - *(s-dims[0]); + v2 = dx2*dx2 + dy2*dy2; + + // third color channel + s += dims[0]*dims[1]; + dy3 = *(s+1) - *(s-1); + dx3 = *(s+dims[0]) - *(s-dims[0]); + v3 = dx3*dx3 + dy3*dy3; + + // pick channel with strongest gradient + if (v2 > v) + { + v = v2; + dx = dx2; + dy = dy2; + } + + if (v3 > v) + { + v = v3; + dx = dx3; + dy = dy3; + } + + // snap to one of 18 orientations + best_dot = 0; + best_o = 0; + + for (int o = 0; o < 9; o++) + { + dot = uu[o]*dx + vv[o]*dy; + if (dot > best_dot) + { + best_dot = dot; + best_o = o; + } + + else if (-dot > best_dot) + { + best_dot = -dot; + best_o = o+9; + } + } + + // add to 4 histograms around pixel using linear interpolation + xp = ((float)x+0.5)/(float)sbin - 0.5; + yp = ((float)y+0.5)/(float)sbin - 0.5; + + ixp = (int)floor(xp); + iyp = (int)floor(yp); + vx0 = xp-ixp; + vy0 = yp-iyp; + vx1 = 1.0-vx0; + vy1 = 1.0-vy0; + v = sqrt(v); +//cout << "POS" << endl; + if (ixp >= 0 && iyp >= 0) + { + *(hist + ixp*blocks[0] + iyp + best_o*blocks[0]*blocks[1]) += vx1*vy1*v; + } + + if (ixp+1 < blocks[1] && iyp >= 0) + { + *(hist + (ixp+1)*blocks[0] + iyp + best_o*blocks[0]*blocks[1]) += vx0*vy1*v; + } + + if (ixp >= 0 && iyp+1 < blocks[0]) + { + *(hist + ixp*blocks[0] + (iyp+1) + best_o*blocks[0]*blocks[1]) += vx1*vy0*v; + } + + if (ixp+1 < blocks[1] && iyp+1 < blocks[0]) + { + *(hist + (ixp+1)*blocks[0] + (iyp+1) + best_o*blocks[0]*blocks[1]) += vx0*vy0*v; + } + } + } +//cout << "POS" << endl; + // compute energy in each block by summing over orientations + for (int o = 0; o < 9; o++) + { + src1 = hist + o*blocks[0]*blocks[1]; + src2 = hist + (o+9)*blocks[0]*blocks[1]; + dst = norm; + end = norm + blocks[1]*blocks[0]; + + while (dst < end) + { + *(dst++) += (*src1 + *src2) * (*src1 + *src2); + src1++; + src2++; + } + } +//cout << "POS" << endl; + // compute features + for (int x = 0; x < out[1]; x++) + { + for (int y = 0; y < out[0]; y++) + { + dst2 = feat + x*out[0] + y; + + p = norm + (x+1)*blocks[0] + y+1; + n1 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps); + p = norm + (x+1)*blocks[0] + y; + n2 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps); + p = norm + x*blocks[0] + y+1; + n3 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps); + p = norm + x*blocks[0] + y; + n4 = 1.0 / sqrt(*p + *(p+1) + *(p+blocks[0]) + *(p+blocks[0]+1) + eps); + + t1 = 0; + t2 = 0; + t3 = 0; + t4 = 0; + + // contrast-sensitive features + src = hist + (x+1)*blocks[0] + (y+1); + + for (int o = 0; o < 18; o++) + { + h1 = min(*src * n1, 0.2); + h2 = min(*src * n2, 0.2); + h3 = min(*src * n3, 0.2); + h4 = min(*src * n4, 0.2); + *dst2 = 0.5 * (h1 + h2 + h3 + h4); + t1 += h1; + t2 += h2; + t3 += h3; + t4 += h4; + dst2 += out[0]*out[1]; + src += blocks[0]*blocks[1]; + } + + // contrast-insensitive features + src = hist + (x+1)*blocks[0] + (y+1); + + for (int o = 0; o < 9; o++) + { + sum = *src + *(src + 9*blocks[0]*blocks[1]); + h1 = min(sum * n1, 0.2); + h2 = min(sum * n2, 0.2); + h3 = min(sum * n3, 0.2); + h4 = min(sum * n4, 0.2); + *dst2 = 0.5 * (h1 + h2 + h3 + h4); + dst2 += out[0]*out[1]; + src += blocks[0]*blocks[1]; + } + + // texture features + *dst2 = 0.2357 * t1; + dst2 += out[0]*out[1]; + *dst2 = 0.2357 * t2; + dst2 += out[0]*out[1]; + *dst2 = 0.2357 * t3; + dst2 += out[0]*out[1]; + *dst2 = 0.2357 * t4; + + // truncation feature + dst2 += out[0]*out[1]; + *dst2 = 0; + } + } + + delete[] hist; + delete[] norm; +// + setMatNData (mxfeat, feat); + + delete[] feat; + } +// + delete[] im; +// + return mxfeat; +} CvMatND* FeatPyramid::padArray (CvMatND *mat, int dimPad[3], float val) { @@ -562,8 +851,8 @@ void FeatPyramid::featpyramid (const IplImage *im, const Model *model, int padX, padY = getPaddingY(model); } - sbin = model->getSbin(); - interval = model->getInterval()+1; + sbin = (float)model->getSbin(); + interval = (float) model->getInterval()+1.0; sc = pow (2, 1/(interval)); imsize[0] = im->height; imsize[1] = im->width; @@ -600,11 +889,13 @@ void FeatPyramid::featpyramid (const IplImage *im, const Model *model, int padX, imAux = resize (im, (1/pow(sc, i))); // "First" 2x interval - setFeat(process(imAux, sbin/2), i); + //setFeat(process(imAux, sbin/2), i); + setFeat(process2(imAux, sbin/2), i); setScales(2/pow(sc, i), i); // "Second" 2x interval - setFeat (process (imAux, sbin), (int)(i+interval)); + //setFeat (process (imAux, sbin), (int)(i+interval)); + setFeat (process2 (imAux, sbin), (int)(i+interval)); setScales (1/pow(sc, i), (int)(i+interval)); // Remaining intervals @@ -617,7 +908,8 @@ void FeatPyramid::featpyramid (const IplImage *im, const Model *model, int padX, cvReleaseImage(&imAux); imAux = imAux2; - setFeat (process (imAux, sbin), (int)(j+interval)); + //setFeat (process (imAux, sbin), (int)(j+interval)); + setFeat (process2 (imAux, sbin), (int)(j+interval)); setScales ((float)(0.5 * getScales()[j]), (int)(j+interval)); } From fe41e44de4c386150d5482bc98fe7758e28b1d80 Mon Sep 17 00:00:00 2001 From: Manuel Date: Tue, 21 May 2013 20:09:33 +0200 Subject: [PATCH 13/24] New file README.md Testing how it works --- README.md | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..20920bb --- /dev/null +++ b/README.md @@ -0,0 +1,115 @@ +============================================================================== +libpabod: Library for PArt-Based Object Detection in C++ +============================================================================== +Daniel Rodriguez Molina and Manuel J. Marin-Jimenez + +This software implements the object detection system described in Felzenszwalb et al. [1]. +-------------------------------------------------------------------------------- + + Source-Code: https://github.com/mjmarin/libpabod + +-------------------------------------------------------------------------------- +Contents of the package: +-------------------------------------------------------------------------------- +- bin - the executable file will be created here +- data: + - models - contains all the object model files + - testimages - a set of images to test the software +- doc - folder where the documentation will be generated +- include - contains all the software header files +- libs - folder where the library will be generated +- obj - folder where the object files will be generated during the compilation +- src - contains all the software source files +- tests - contains some programs to test the library +- makefile - used to compile the library, the documentation and the test program + +-------------------------------------------------------------------------------- +Requirements: +-------------------------------------------------------------------------------- +This software has been tested on Ubuntu 10.10 (Maverick Meerkat) with the following libraries: + - libmatio-dev - v1.3.4-2 (required) + - libcv-dev - v2.1.0-2 (required) + - libhighgui-dev - v2.1.0-2 (required) + - doxygen - v1.7.1-1 (optional; used to generate the documentation) + - graphviz - v2.26.3-4 (optional; used to generate figures for the documentation) + +-------------------------------------------------------------------------------- +Quick start: +-------------------------------------------------------------------------------- + +A) Classic installation (obsolete --> CMake is highly recommended): + 1. Unpack in + 2. cd + 3.1. Generating the library + > make + 3.2. Creating the test programs + > make alltests + 3.3. Generating the documentation + > make docum + 3.4. Recompiling all + > make cleanobj + > make + +Tip: use 'make all' to generate both the library and the test programs. + +B) Installing with CMake: + Please, follow the steps described in the file named INSTALL. + +C) Testing the library: + (assuming test program has been already generated) + 1. cd + 2. ./bin/detectobj -m -i [-t ] [-o ] [-d <0/1>] + Example: + > ./bin/detectobj -m data/models/person_v6.mat -i data/testimages/2008_007537.jpg -t -0.3 -o detections.txt + +If the program has finished correctly, you will find a text file named 'detections.txt' with the following structure: + + +where are the pairs of coordinates of the i-th bounding box and is its corresponding detection score. + +Tip: object detection can be performed directly on video frames (e.g. avi file) with the test program named 'detectvid'. + +-------------------------------------------------------------------------------- +Citation: +-------------------------------------------------------------------------------- +If you use this library for your publications, please cite it as: +@misc{libpabod, + author = {Rodriguez-Molina, Daniel and Marin-Jimenez, Manuel J.}, + title = {{LibPaBOD}: A Library for Part-Based Object Detection in {C++}}, + year = {2011}, + note = {Software available at \url{http://www.uco.es/~in1majim/}} +} + +-------------------------------------------------------------------------------- +Contact the authors: +-------------------------------------------------------------------------------- +Daniel Rodriguez Molina (developer) - i72romod@uco.es / daniel.rodriguez.molina@gmail.com +Manuel J. Marin-Jimenez (advisor) - mjmarin@uco.es + +-------------------------------------------------------------------------------- +References: +-------------------------------------------------------------------------------- +[1] P. Felzenszwalb, R. Girshick, D. McAllester, D. Ramanan. "Object Detection with Discriminatively Trained Part Based Models." IEEE Transactions on Pattern Analysis and Machine Intelligence, Vol. 32, No. 9, September 2010. +URL: http://people.cs.uchicago.edu/~pff/latent/ + +-------------------------------------------------------------------------------- +Version history: +-------------------------------------------------------------------------------- + - v0.2.9: moving CvMat to cv::Mat + - v0.2.8: new class Detection + - v0.2.7: memory leaks found by github/yokox solved. Thanks! + - v0.2.6: new file 'export.h' for properly exporting functions to dll's. + - v0.2.5: updated CMake files and other minor improvements for Windows compatibility. + - v0.2.4: CMake and code updated to properly manage libmatio on Windows (thanks to Eric Sommerlade for his invaluable contributions). See new file 'INSTALL.windows'. libmatio 1.5.x is supported. + - v0.2.2: detector component is now included in detections matrix. Other minor improvements. + - v0.2.1: OpenMP is now optional via CMake. Selection of OpenMP overrides pthread's choice. + - v0.2: new class Pabod. It encapsulates the class model and detection process. New demo file 'detectobj2.cpp' uses Pabod class. pthread is now optional via CMake. New 'quickstart.pdf' in directory 'doc'. + - v0.1.7: fixed bugs (i.e. memory leaks) reported by . + - v0.1.6: fixed documentation option for CMake (thanks to eichnerm). Use 'cmake .. -DINSTALL_DOC=ON" to generate the library documentation. + - v0.1.5: CMake is supported (thanks to rmsalinas@uco.es). By default, the library is built in shared mode (non-static). + - v0.1.4: added an alternative 'makeDetection' function. Updated makefile. Now 'make all' builds both the library and the test programs. + - v0.1.3: added 'detectvid' program. It performs detection on video sequences (e.g. avi). Use 'make test3' to generate it. Use 'make alltests' to generate all test programs. + - v0.1.2: small fixes in code. + - v0.1.1: added 'detectobj' program. It can save detections to disk. Use 'make test2' to generate it. + - v0.1: first release. + From 1f7b8b1568fe72a4eeafcc59bb40760e363c3f1f Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 22 May 2013 16:21:33 +0200 Subject: [PATCH 14/24] Fix for *nix versions cv::Mat is not found in some *nix systems --- include/crossplatform.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/crossplatform.h b/include/crossplatform.h index 50d3b6a..1f99ce3 100644 --- a/include/crossplatform.h +++ b/include/crossplatform.h @@ -26,5 +26,10 @@ #define GET_TIME(var) gettimeofday(var, NULL) #define TIME_DIFF(tend, tini) ((double)(tend.tv_sec + (double)tend.tv_usec/1000000.0) - (double)(tini.tv_sec + (double)tini.tv_usec/1000000.0)) + + #if (CV_MAJOR_VERSION >= 2) && (CV_MINOR_VERSION >= 3) + #include + #endif + #endif From 4fca7bb8f4e8cb9ad6361f822dbf708c75595e22 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 31 May 2013 10:17:47 +0200 Subject: [PATCH 15/24] Option -O added to detectobj2 -O : save image with detections to --- tests/detectobj2.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/tests/detectobj2.cpp b/tests/detectobj2.cpp index 3d4a11f..318d1d3 100644 --- a/tests/detectobj2.cpp +++ b/tests/detectobj2.cpp @@ -169,8 +169,10 @@ string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetection pos = imgPath.find_last_of ("/"); path = imgPath.substr(0, pos); - if (mode == TAGGED) + switch (mode) { + case TAGGED: + pos = imgPath.find_last_of("."); name = imgPath.substr (0, pos); @@ -180,10 +182,10 @@ string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetection cv::imwrite(name,im); - } + break; - else if (mode == CUT) - { + case CUT: + for (int i = 0; i < results.size(); i++) { x = min (results[i].getX1(), results[i].getX2()); @@ -212,6 +214,9 @@ string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetection cv::imwrite(name, cut2); cut2.release(); } + break; + default: + cv::imwrite(imgPath, im); } return path; @@ -231,13 +236,14 @@ int main ( int argc, char *argv[] ) int nDetected = 0; float usedThresh=NEGATIVE_INF, thresh = POSITIVE_INF; float minScore, maxScore; - bool savedata = false, display = true; + bool savedata = false, display = true, saveOutputImg = false; + string outputimg(""); double iouNms = 0.5; if (argc < 5) { cout << " >> ERROR: the general form is:\n" - " ./detectobj2 -m -i [-t -n -o -d <0/1>]" << endl; + " ./detectobj2 -m -i [-t -n -o -O -d <0/1>]" << endl; return -1; } @@ -258,8 +264,11 @@ int main ( int argc, char *argv[] ) datafile = argv[i + 1]; savedata = true; } else if (string(argv[i]) == "-d") { // Display images? - display = atoi(argv[i+1]); + display = atoi(argv[i + 1]) > 0; + } else if (string(argv[i]) == "-O") { // Automatically save image with detections? + outputimg = argv[i + 1]; //atoi(argv[i + 1]) > 0; + saveOutputImg = true; } else if (string(argv[i]) == "-t") { thresh = atof(argv[i + 1]); @@ -419,6 +428,12 @@ int main ( int argc, char *argv[] ) for (int i = 0; i < nDetected; i++) cout << " - " << extractModelName(modelfile) << " " << i+1 << ", score = " << results[i].getScore() << endl; + if (saveOutputImg) // Save image with detections to disk? + { + // Save tagged with given name + aux = saveImage (im, outputimg, 999, results); + } + if (display) { cvNamedWindow("Detected image", CV_WINDOW_AUTOSIZE); From cbae818953b0f3c09247cf6dc17098d9c80fdaf7 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 13 Jan 2014 15:43:20 +0100 Subject: [PATCH 16/24] Compiled on Ubuntu 12.04 64 bits --- include/featPyramid.h | 2 +- src/featPyramid.cpp | 2 +- tests/detectobj2.cpp | 6 +++--- tests/detectvid.cpp | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/featPyramid.h b/include/featPyramid.h index fbf1618..1554e5b 100644 --- a/include/featPyramid.h +++ b/include/featPyramid.h @@ -154,7 +154,7 @@ class FeatPyramid */ CvMatND *process(const IplImage *mximage, const float mxsbin); - cv::Mat FeatPyramid::process2( const IplImage *mximage, const float mxsbin ); + cv::Mat process2( const IplImage *mximage, const float mxsbin ); /** The function pad the mat array with so many values val * like indicates the vector dimPad. Each element means diff --git a/src/featPyramid.cpp b/src/featPyramid.cpp index b0b9466..edb9c17 100644 --- a/src/featPyramid.cpp +++ b/src/featPyramid.cpp @@ -541,7 +541,7 @@ cv::Mat FeatPyramid::process2( const IplImage *mximage, const float mxsbin ) cv::Mat mxfeat; //cout << "POS" << endl; if (out[0] == 0 && out[1] == 0 ) - mxfeat = NULL; + cout << "Empty matrix" << endl; else { diff --git a/tests/detectobj2.cpp b/tests/detectobj2.cpp index 318d1d3..0c7bef8 100644 --- a/tests/detectobj2.cpp +++ b/tests/detectobj2.cpp @@ -193,7 +193,7 @@ string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetection w = abs(results[i].getW()); h = abs(results[i].getH()); - cv::Mat cut2(cv::Size(w, h), cv::DataType>::type); + cv::Mat cut2(cv::Size(w, h), cv::DataType< cv::Vec >::type); cout << im.channels() << endl; for (int m = x; m < w+x; m++) @@ -329,7 +329,7 @@ int main ( int argc, char *argv[] ) cout << " Searching for objects... This operation may take a few seconds" << endl << endl; // Get the current time before starting detection - t_ini = GET_TIME(&t_ini); + GET_TIME(&t_ini); // Call to main function //usedThresh = detector.detect(im, thresh, iouNms, &results); @@ -345,7 +345,7 @@ int main ( int argc, char *argv[] ) */ // Get the current time after detection - t_fin = GET_TIME(&t_fin); + GET_TIME(&t_fin); // Number of secs taken to run detection secs = TIME_DIFF(t_fin, t_ini); diff --git a/tests/detectvid.cpp b/tests/detectvid.cpp index 2e8b5b6..1055778 100644 --- a/tests/detectvid.cpp +++ b/tests/detectvid.cpp @@ -131,7 +131,7 @@ string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetection w = abs(results[i].getW()); h = abs(results[i].getH()); - cv::Mat cut2(cv::Size(w, h), cv::DataType>::type); + cv::Mat cut2(cv::Size(w, h), cv::DataType >::type); cout << im.channels() << endl; for (int m = x; m < w+x; m++) @@ -278,7 +278,7 @@ int main ( int argc, char *argv[] ) cout << "Searching for objects... This operation may take a few seconds" << endl << endl; // Get the current time before starting detection - t_ini = GET_TIME(&t_ini); + GET_TIME(&t_ini); // Call to main function usedThresh = detector.detect(im, thresh, iouNms, results); @@ -292,7 +292,7 @@ int main ( int argc, char *argv[] ) nDetected = results.size(); // Get the current time after detection - t_fin = GET_TIME(&t_fin); + GET_TIME(&t_fin); // Number of secs taken to run detection secs = TIME_DIFF(t_fin, t_ini); From 22edfdba2f68adb1caccc57c7feab80a55d7fc4b Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 13 Jan 2014 17:45:00 +0100 Subject: [PATCH 17/24] New option to draw only top N detections --- include/pabod.h | 5 +++-- makefile | 2 +- src/pabod.cpp | 10 ++++++++-- tests/detectobj2.cpp | 9 ++++++--- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/pabod.h b/include/pabod.h index e4b993c..f32e305 100644 --- a/include/pabod.h +++ b/include/pabod.h @@ -50,11 +50,12 @@ class PABOD_EXPORT Pabod{ /** Draws all detections as rectangles on image. \param img Target image \param detections As returned by method detect + \param topN Shows only top N detections \return Number of detections drawn into image */ int drawDetections(IplImage * img, CvMat * detections); - int drawDetections(cv::Mat & img, cv::Mat & detections); //! Most modern interface - int drawDetections(cv::Mat & img, LDetections & detections); + int drawDetections(cv::Mat & img, cv::Mat & detections, int topN = -1); //! Most modern interface + int drawDetections(cv::Mat & img, LDetections & detections, int topN = -1); /** Gets the class registered in the model */ diff --git a/makefile b/makefile index c4cee92..6a2ecaf 100644 --- a/makefile +++ b/makefile @@ -18,7 +18,7 @@ INCLUDE = -I$(HEADERS) LIBRARY = -L$(LIBS) CPP_OBJS = $(OBJS)makeDetection.o $(OBJS)pabod.o $(OBJS)model.o $(OBJS)cell.o $(OBJS)readTypes.o $(OBJS)imgdetect.o $(OBJS)featPyramid.o $(OBJS)handlerOpenCVStructs.o $(OBJS)gdetect.o $(OBJS)fconvThreads.o $(OBJS)modelSort.o $(OBJS)dt.o $(OBJS)getDetections.o $(OBJS)nms.o CPP_TEST = $(TESTS)mainTest.cpp -CPP_TEST2 = $(TESTS)detectobj.cpp +CPP_TEST2 = $(TESTS)detectobj2.cpp CPP_TEST3 = $(TESTS)detectvid.cpp LIBA = $(LIBS)libpabod.a DOXYFILE = $(DOC)Doxyfile diff --git a/src/pabod.cpp b/src/pabod.cpp index a3d40cf..197e262 100644 --- a/src/pabod.cpp +++ b/src/pabod.cpp @@ -143,7 +143,7 @@ float Pabod::detect(cv::Mat & img, float thr, double iouNms, LDetections & detec return usedThr; } -int Pabod::drawDetections(cv::Mat & img, LDetections & detections) +int Pabod::drawDetections(cv::Mat & img, LDetections & detections, int topN) { int ndetections = 0; int i; @@ -153,6 +153,9 @@ int Pabod::drawDetections(cv::Mat & img, LDetections & detections) IplImage img_ = img; ndetections = detections.size(); + if (topN > 0 && topN < ndetections) + ndetections = topN; + for (i = 0; i < ndetections; i++) { p1 = cvPoint (detections[i].getX1(), detections[i].getY1()); @@ -164,7 +167,7 @@ int Pabod::drawDetections(cv::Mat & img, LDetections & detections) return ndetections; } -int Pabod::drawDetections(cv::Mat & img, cv::Mat & detections) +int Pabod::drawDetections(cv::Mat & img, cv::Mat & detections, int topN) { int ndetections = 0; int i; @@ -174,6 +177,9 @@ int Pabod::drawDetections(cv::Mat & img, cv::Mat & detections) IplImage img_ = img; ndetections = detections.rows; + if (topN > 0 && topN < ndetections) + ndetections = topN; + for (i = 0; i < ndetections; i++) { p1 = cvPoint ((int)detections.at(i, 0), (int)detections.at(i, 1)); diff --git a/tests/detectobj2.cpp b/tests/detectobj2.cpp index 0c7bef8..21ace2d 100644 --- a/tests/detectobj2.cpp +++ b/tests/detectobj2.cpp @@ -233,7 +233,7 @@ int main ( int argc, char *argv[] ) //CvMat *results = NULL; //cv::Mat results; LDetections results; - int nDetected = 0; + int nDetected = 0, nTopShow = -1; float usedThresh=NEGATIVE_INF, thresh = POSITIVE_INF; float minScore, maxScore; bool savedata = false, display = true, saveOutputImg = false; @@ -243,7 +243,7 @@ int main ( int argc, char *argv[] ) if (argc < 5) { cout << " >> ERROR: the general form is:\n" - " ./detectobj2 -m -i [-t -n -o -O -d <0/1>]" << endl; + " ./detectobj2 -m -i [-t -n -o -O -d <0/1> -k ]" << endl; return -1; } @@ -272,6 +272,9 @@ int main ( int argc, char *argv[] ) } else if (string(argv[i]) == "-t") { thresh = atof(argv[i + 1]); + } else if (string(argv[i]) == "-k") { + nTopShow = atoi(argv[i + 1]); + } else if (string(argv[i]) == "-n") { iouNms = atof(argv[i + 1]); @@ -423,7 +426,7 @@ int main ( int argc, char *argv[] ) } // Draw detections - detector.drawDetections(im, results); + detector.drawDetections(im, results, nTopShow); for (int i = 0; i < nDetected; i++) cout << " - " << extractModelName(modelfile) << " " << i+1 << ", score = " << results[i].getScore() << endl; From faf3cb72cdc82682ad930cdd49088070f492d066 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 13 Jan 2014 18:36:19 +0100 Subject: [PATCH 18/24] Updated to version 0.2.10 --- CMakeLists.txt | 7 ++++--- README.md | 1 + include/custom.h | 7 +++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9181124..3c050b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,11 +5,12 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(pabod) -set(PROJECT_VERSION "0.2.9") +set(PROJECT_VERSION "0.2.10") string(REGEX MATCHALL "[0-9]" PROJECT_VERSION_PARTS "${PROJECT_VERSION}") list(GET PROJECT_VERSION_PARTS 0 PROJECT_VERSION_MAJOR) list(GET PROJECT_VERSION_PARTS 1 PROJECT_VERSION_MINOR) list(GET PROJECT_VERSION_PARTS 2 PROJECT_VERSION_PATCH) +list(GET PROJECT_VERSION_PARTS 3 PROJECT_VERSION_PATCH2) set(PROJECT_SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}") @@ -29,7 +30,7 @@ MESSAGE(STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") if(WIN32) # Postfix of DLLs: - SET(PROJECT_DLLVERSION "${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR}${PROJECT_VERSION_PATCH}") + SET(PROJECT_DLLVERSION "${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR}${PROJECT_VERSION_PATCH}${PROJECT_VERSION_PATCH2}") SET(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}") SET(RUNTIME_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin CACHE PATH "Directory for dlls and binaries") SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin CACHE PATH "Directory for binaries") @@ -127,7 +128,7 @@ endif() # ADDING PROJECT VERSION file(APPEND ${CUSTOM_H} "\n#define PABOD_MAJOR_VERSION ${PROJECT_VERSION_MAJOR}\n") file(APPEND ${CUSTOM_H} "\n#define PABOD_MINOR_VERSION ${PROJECT_VERSION_MINOR}\n") -file(APPEND ${CUSTOM_H} "\n#define PABOD_PATCH_VERSION ${PROJECT_VERSION_PATCH}\n") +file(APPEND ${CUSTOM_H} "\n#define PABOD_PATCH_VERSION ${PROJECT_VERSION_PATCH}${PROJECT_VERSION_PATCH2}\n") # DEALING WITH MATIO VERSIONS IF(WIN32) diff --git a/README.md b/README.md index 20920bb..2733703 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ URL: http://people.cs.uchicago.edu/~pff/latent/ -------------------------------------------------------------------------------- Version history: -------------------------------------------------------------------------------- + - v0.2.10: new option '-k' added to 'detectobj2' to show only K top detections - v0.2.9: moving CvMat to cv::Mat - v0.2.8: new class Detection - v0.2.7: memory leaks found by github/yokox solved. Thanks! diff --git a/include/custom.h b/include/custom.h index b37546f..996c8f9 100644 --- a/include/custom.h +++ b/include/custom.h @@ -1,14 +1,13 @@ #ifndef _CUSTOM_H_ #define _CUSTOM_H_ 1 -#undef USE_OPENMP - -#define USE_PTHREADS 1 +#define USE_OPENMP 1 +#undef USE_PTHREADS #define PABOD_MAJOR_VERSION 0 #define PABOD_MINOR_VERSION 2 -#define PABOD_PATCH_VERSION 9 +#define PABOD_PATCH_VERSION 10 #endif From e7bc05467989ded09a6d4efcf4ef84450b235cf5 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 13 Jan 2014 18:39:53 +0100 Subject: [PATCH 19/24] Updated to version 0.2.10 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f19a904..e6110d0 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,4 @@ Thumbs.db *.png *.gch *.css +*~ From 3cedc7adb5d257d50aa46665d54d3332e7ba163a Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 15 Jan 2014 13:01:02 +0100 Subject: [PATCH 20/24] Compiled on Windows 32 Minor fix --- include/crossplatform.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/crossplatform.h b/include/crossplatform.h index 1f99ce3..9d3487c 100644 --- a/include/crossplatform.h +++ b/include/crossplatform.h @@ -3,7 +3,7 @@ #include typedef time_t TIMER; #include - #define GET_TIME(var) cv::getTickCount() //time(var) + #define GET_TIME(var) (*var = cv::getTickCount()) //time(var) #define TIME_DIFF(tend, tini) (((double)tend -tini)/cv::getTickFrequency()) //difftime(tend, tini) #if !defined _CRT_SECURE_NO_DEPRECATE && _MSC_VER > 1300 From d57b57baa9f1845508a4607b3dd889fdb67c3317 Mon Sep 17 00:00:00 2001 From: Manuel Date: Fri, 14 Mar 2014 23:45:32 +0100 Subject: [PATCH 21/24] Minor fixes Further control of memory --- include/cell.h | 10 +++ src/cell.cpp | 3 +- src/gdetect.cpp | 170 +++++++++++++++++++++++++----------------------- 3 files changed, 99 insertions(+), 84 deletions(-) diff --git a/include/cell.h b/include/cell.h index d7e3fb8..f943a8b 100644 --- a/include/cell.h +++ b/include/cell.h @@ -89,6 +89,16 @@ typedef struct def int blocklabel; bool flip; char symmetric; + + //! Constructor + def() + { + w[0]=w[1]=w[2]=w[3] = 0; + blocklabel = 0; + flip = 0; + symmetric = 'N'; + } + } def; diff --git a/src/cell.cpp b/src/cell.cpp index 31f8ebe..e48545c 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -400,7 +400,8 @@ void Cell::loadDef (matvar_t *matVar, int i) field = Mat_VarGetStructField (matVar, (char*) variable, BY_NAME, i); - initializeDef (field); + if (field != NULL) + initializeDef (field); delete[] variable; } diff --git a/src/gdetect.cpp b/src/gdetect.cpp index ed42e0d..bc93c85 100644 --- a/src/gdetect.cpp +++ b/src/gdetect.cpp @@ -456,118 +456,122 @@ void applyStructuralRule (Model *model, const Cell &r, int padY, int padX) int sTmpDims[2]; - // Sum scores from rhs (with appropriate shift and down sample) - for (int j = 0; j < r.getRhsDim(); j++) + anchor *anc; + anc = r.getAnchor(); + if (anc != NULL) { - ax = r.getAnchor()[j].array[0]; - ay = r.getAnchor()[j].array[1]; - ds = r.getAnchor()[j].array[2]; + // Sum scores from rhs (with appropriate shift and down sample) + for (int j = 0; j < r.getRhsDim(); j++) + { + ax = anc[j].array[0]; //r.getAnchor()[j].array[0]; + ay = anc[j].array[1]; //r.getAnchor()[j].array[1]; + ds = anc[j].array[2]; //r.getAnchor()[j].array[2]; - // Step size for down sampling - step = int(pow (2, ds)); + // Step size for down sampling + step = int(pow (2, ds)); - // Amount of (virtual) padding to halucinate - virtPadY = (step-1) * padY; - virtPadX = (step-1) * padX; + // Amount of (virtual) padding to halucinate + virtPadY = (step-1) * padY; + virtPadX = (step-1) * padX; - // Starting points (simulates additional padding at finer scales) - startY = int(ay - virtPadY); - startX = int(ax - virtPadX); + // Starting points (simulates additional padding at finer scales) + startY = int(ay - virtPadY); + startX = int(ax - virtPadX); - // Starting level - startLevel = int( (model->getInterval() + 1) * ds); + // Starting level + startLevel = int( (model->getInterval() + 1) * ds); - // Score table to shift and down sample - CvMat** s = model->getSymbols()[(int) r.getRhs()[j]].score; - assert (s != NULL); + // Score table to shift and down sample + CvMat** s = model->getSymbols()[(int) r.getRhs()[j]].score; + assert (s != NULL); - for (int i = startLevel; - i < (int) (model->getSymbols()[(int)r.getRhs()[j]].dimScore); - i++) - { - level = i - int( (model->getInterval() + 1) * ds); + for (int i = startLevel; + i < (int) (model->getSymbols()[(int)r.getRhs()[j]].dimScore); + i++) + { + level = i - int( (model->getInterval() + 1) * ds); - // Ending points - endY = min ((int) s[level]->rows, (int) (startY + - (step * (score[i].rows))) ); - endX = min ((int) s[level]->cols, (int) (startX + - (step * (score[i].cols))) ); - - // Y sample points - assert ( (endY-startY) > 0); - assert ( step > 0); + // Ending points + endY = min ((int) s[level]->rows, (int) (startY + + (step * (score[i].rows))) ); + endX = min ((int) s[level]->cols, (int) (startX + + (step * (score[i].cols))) ); - iyDim = round((float)(endY-startY)/step); - iy = new int [iyDim]; - assert (iy != NULL); + // Y sample points + assert ( (endY-startY) > 0); + assert ( step > 0); - iter = 0; + iyDim = round((float)(endY-startY)/step); + iy = new int [iyDim]; + assert (iy != NULL); - for (int k = startY; k < endY; k += step) - { - iy[iter] = k; - iter++; - } + iter = 0; - oy = countElementsWhich (LOWER, 0, &iy, iyDim, true); + for (int k = startY; k < endY; k += step) + { + iy[iter] = k; + iter++; + } - iyDim = iyDim - oy; - assert (iyDim > 0); + oy = countElementsWhich (LOWER, 0, &iy, iyDim, true); - // X sample points - assert ( (endX-startX) > 0); - assert (step > 0); + iyDim = iyDim - oy; + assert (iyDim > 0); - ixDim = round((float)(endX-startX)/step); - ix = new int [ixDim]; - assert (ix != NULL); + // X sample points + assert ( (endX-startX) > 0); + assert (step > 0); - iter = 0; + ixDim = round((float)(endX-startX)/step); + ix = new int [ixDim]; + assert (ix != NULL); - for (int k = startX; k < endX; k += step) - { - ix[iter] = k; - iter++; - } + iter = 0; - ox = countElementsWhich (LOWER, 0, &ix, ixDim, true); + for (int k = startX; k < endX; k += step) + { + ix[iter] = k; + iter++; + } - ixDim = ixDim - ox; - assert (ixDim > 0); + ox = countElementsWhich (LOWER, 0, &ix, ixDim, true); - // Sample scores - sp = subMat (s[level], iy, iyDim, ix, ixDim); - assert (sp != NULL); - getDimensions (sp, sz); + ixDim = ixDim - ox; + assert (ixDim > 0); - // Sum with correct offset - assert (score[i].rows > 0); - assert (score[i].cols > 0); + // Sample scores + sp = subMat (s[level], iy, iyDim, ix, ixDim); + assert (sp != NULL); + getDimensions (sp, sz); - sTmpDims[0] = score[i].rows; - sTmpDims[1] = score[i].cols; + // Sum with correct offset + assert (score[i].rows > 0); + assert (score[i].cols > 0); - createMatrix (2, sTmpDims, CV_64FC1, &sTmp); + sTmpDims[0] = score[i].rows; + sTmpDims[1] = score[i].cols; - assert (sTmp != NULL); + createMatrix (2, sTmpDims, CV_64FC1, &sTmp); - fillMat (sTmp, NEGATIVE_INF); + assert (sTmp != NULL); - for (int j = oy; j < oy+sz[0]; j++) - for (int k = ox; k < ox+sz[1]; k++) - cvSetReal2D (sTmp, j, k, cvGetReal2D (sp, j-oy, k-ox)); + fillMat (sTmp, NEGATIVE_INF); - cv::Mat sTmp2 = sTmp; - //cvAdd (score[i], sTmp, score[i]); - add (score[i], sTmp2, score[i]); + for (int j = oy; j < oy+sz[0]; j++) + for (int k = ox; k < ox+sz[1]; k++) + cvSetReal2D (sTmp, j, k, cvGetReal2D (sp, j-oy, k-ox)); - delete[] iy; - delete[] ix; - cvReleaseMat (&sp); - cvReleaseMat (&sTmp); - } - } + cv::Mat sTmp2 = sTmp; + //cvAdd (score[i], sTmp, score[i]); + add (score[i], sTmp2, score[i]); + delete[] iy; + delete[] ix; + cvReleaseMat (&sp); + cvReleaseMat (&sTmp); + } + } + } // if model->getRules()[(int) r.getLhs()].structure [(int) r.getI()].setScoreDim(model->getScoretptDim()); model->getRules()[(int) r.getLhs()].structure From ad9a446436edceb3bec5256576d990c7097afa2c Mon Sep 17 00:00:00 2001 From: Manuel Date: Sat, 15 Mar 2014 00:20:31 +0100 Subject: [PATCH 22/24] Some esom's changes applied --- CMakeLists.txt | 2 +- include/pabod.h | 2 +- include/readTypes.h | 6 ++++++ src/cell.cpp | 16 ++++++++++++---- src/featPyramid.cpp | 4 +++- src/gdetect.cpp | 10 +++++++--- src/model.cpp | 2 +- src/readTypes.cpp | 3 +++ 8 files changed, 34 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c050b3..0bd8f71 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,7 @@ ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/c # ---------------------------------------------------------------------------- # create configuration file from .in file (If you use windows take care with paths) # ---------------------------------------------------------------------------- - +set(CMAKE_INCLUDE_DIRS_CONFIGCMAKE ${CMAKE_CURRENT_SOURCE_DIR}/include) CONFIGURE_FILE("${PROJECT_SOURCE_DIR}/config.cmake.in" "${PROJECT_BINARY_DIR}/Find${PROJECT_NAME}.cmake") INSTALL(FILES "${PROJECT_BINARY_DIR}/Find${PROJECT_NAME}.cmake" DESTINATION lib/cmake/ ) diff --git a/include/pabod.h b/include/pabod.h index f32e305..27de6d9 100644 --- a/include/pabod.h +++ b/include/pabod.h @@ -6,7 +6,7 @@ #ifndef _PABOD_H_ #define _PABOD_H_ -#include +#include #include #include "export.h" #include "model.h" diff --git a/include/readTypes.h b/include/readTypes.h index 84a2a25..08c2ad9 100644 --- a/include/readTypes.h +++ b/include/readTypes.h @@ -91,6 +91,12 @@ void readNumber (matvar_t *matVar, char* var, Type **number, int* dim, int pos) matvar_t *field; double* auxNumb = NULL; + if (!matVar ) + { + *dim = 0; + return; + } + // If the variable is a Struct if ( matVar->data_type == MAT_T_STRUCT ) field = Mat_VarGetStructField (matVar, (char*) var, BY_NAME, pos); diff --git a/src/cell.cpp b/src/cell.cpp index e48545c..c936e2f 100644 --- a/src/cell.cpp +++ b/src/cell.cpp @@ -605,16 +605,24 @@ void Cell::initializeDef (matvar_t *defStructure) strcpy (variable, "blocklabel"); readNumber (defStructure, variable, &el, &dim); - d.blocklabel = el[0]; - + //d.blocklabel = el[0]; + if (el) + d.blocklabel = el[0]; + else + d.blocklabel = 0; + delete[] el; strcpy (variable, "flip"); d.flip = readLogical (defStructure, variable); strcpy (variable, "symmetric"); - d.symmetric = readString (defStructure, variable)[0]; - + //d.symmetric = readString (defStructure, variable)[0]; + if ( defStructure ) + d.symmetric = readString (defStructure, variable)[0]; + else + d.symmetric = 0; + setDef (d); delete[] variable; diff --git a/src/featPyramid.cpp b/src/featPyramid.cpp index edb9c17..3b71c1a 100644 --- a/src/featPyramid.cpp +++ b/src/featPyramid.cpp @@ -541,8 +541,10 @@ cv::Mat FeatPyramid::process2( const IplImage *mximage, const float mxsbin ) cv::Mat mxfeat; //cout << "POS" << endl; if (out[0] == 0 && out[1] == 0 ) + { cout << "Empty matrix" << endl; - + mxfeat = 0.0; + } else { assert (out[0] > 0); diff --git a/src/gdetect.cpp b/src/gdetect.cpp index bc93c85..da394a4 100644 --- a/src/gdetect.cpp +++ b/src/gdetect.cpp @@ -36,11 +36,15 @@ void gdetect (CvMat **dets, CvMat **boxes, CvMatND **info, assert (L != NULL); L = modelSort (model, L); // mjmarin: uses def params --> i=-1, V=NULL + rules* rules = model->getRules(); for (int s = 0; s < L->LDim; s++) { - for (int r = 0; r < model->getRules()[L->L[s]].n; r++) - applyRule (model, model->getRules()[L->L[s]].structure[r], - pyra.getPadY(), pyra.getPadX()); + if (rules) + { + for (int r = 0; r < rules[L->L[s]].n; r++) + applyRule(model, rules[L->L[s]].structure[r], + pyra.getPadY(), pyra.getPadX()); + } symbolScore (model, L->L[s], latent, pyra, bbox, overlap); } diff --git a/src/model.cpp b/src/model.cpp index d81eb87..10e8fa3 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -1553,7 +1553,7 @@ bool Model::existField (matvar_t *matVar, char* var) field = Mat_VarGetStructField (matVar, (char*) var, BY_NAME, 0); - if ( field != NULL ) + if ( field != NULL && field->data_size > 0) flag = true; return flag; diff --git a/src/readTypes.cpp b/src/readTypes.cpp index 588d34d..8e65e9f 100644 --- a/src/readTypes.cpp +++ b/src/readTypes.cpp @@ -22,6 +22,9 @@ bool readLogical (matvar_t *matVar, char* var, int pos) char *auxChar = NULL; bool flag = false; + if (!matVar) + return false; + field = Mat_VarGetStructField (matVar, (char*) var, BY_NAME, pos); if ( field != NULL ) From 3045bbba726d2351f11794f9d9fafd63e362a798 Mon Sep 17 00:00:00 2001 From: Manuel Date: Sat, 15 Mar 2014 10:34:22 +0100 Subject: [PATCH 23/24] Added default constructor to structs --- include/cell.h | 12 +++++++++--- include/crossplatform.h | 3 +++ include/featPyramid.h | 6 ++++++ include/model.h | 18 ++++++++++++++++++ src/pabod.cpp | 2 +- 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/include/cell.h b/include/cell.h index f943a8b..9251b2a 100644 --- a/include/cell.h +++ b/include/cell.h @@ -49,6 +49,12 @@ typedef struct offset { float w; int blocklabel; + + offset() + { + w = 0.0; + blocklabel = 0; + } } offset; @@ -93,10 +99,10 @@ typedef struct def //! Constructor def() { - w[0]=w[1]=w[2]=w[3] = 0; + w[0]=w[1]=w[2]=w[3] = 0.0; blocklabel = 0; - flip = 0; - symmetric = 'N'; + flip = false; + symmetric = '\0'; } } def; diff --git a/include/crossplatform.h b/include/crossplatform.h index 9d3487c..7559f1a 100644 --- a/include/crossplatform.h +++ b/include/crossplatform.h @@ -1,3 +1,6 @@ +//! \file crossplatform.h +//! \author Manuel J. Marin-Jimenez + #if defined _WIN32 #include #include diff --git a/include/featPyramid.h b/include/featPyramid.h index 1554e5b..37ca252 100644 --- a/include/featPyramid.h +++ b/include/featPyramid.h @@ -34,6 +34,12 @@ struct alphainfo int si; int di; float alpha; + + alphainfo() + { + si = di = 0; + alpha = 0.0; + } }; diff --git a/include/model.h b/include/model.h index 628f2bb..02561dc 100644 --- a/include/model.h +++ b/include/model.h @@ -38,6 +38,18 @@ typedef struct filters int sizeDim; bool flip; int symbol; + + filters() + { + w = NULL; + blocklabel = 0; + symmetric = '\0'; + size = NULL; + sizeDim = 0; + flip = false; + symbol = 0; + } + } filters; ///////////////////////////// @@ -83,6 +95,9 @@ typedef struct symbols symbols() { + type = '\0'; + i = 0; + filter = 0; score = NULL; dimScore = 0; } @@ -107,6 +122,8 @@ typedef struct lowerbounds lowerbounds() { v = NULL; + f = 0; + c = 0; } } lowerbounds; @@ -130,6 +147,7 @@ typedef struct bboxpred bboxpred() { + x1 = x2 = y1 = y2 = NULL; dim = 0; } } bboxpred; diff --git a/src/pabod.cpp b/src/pabod.cpp index 197e262..3546673 100644 --- a/src/pabod.cpp +++ b/src/pabod.cpp @@ -185,7 +185,7 @@ int Pabod::drawDetections(cv::Mat & img, cv::Mat & detections, int topN) p1 = cvPoint ((int)detections.at(i, 0), (int)detections.at(i, 1)); p2 = cvPoint ((int)detections.at(i, 2), (int)detections.at(i, 3)); - drawBB(&img_, p1, p2, cvScalar(int(rand()%256), int(rand()%256), int(rand()%256)), (float)detections.at(i, 4), detections.at(i, 5)); + drawBB(&img_, p1, p2, cvScalar(int(rand()%256), int(rand()%256), int(rand()%256)), (float)detections.at(i, 4), (int)detections.at(i, 5)); } return ndetections; From 268af9079a698693fc66f495034f3a3492bf4bb5 Mon Sep 17 00:00:00 2001 From: Manuel Date: Sat, 15 Mar 2014 11:11:25 +0100 Subject: [PATCH 24/24] Code cleaning --- tests/detectobj2.cpp | 124 ++----------------------------------------- tests/detectvid.cpp | 5 +- 2 files changed, 6 insertions(+), 123 deletions(-) diff --git a/tests/detectobj2.cpp b/tests/detectobj2.cpp index 21ace2d..93db199 100644 --- a/tests/detectobj2.cpp +++ b/tests/detectobj2.cpp @@ -39,131 +39,13 @@ string extractModelName (string modelPath) return name; } -/* -string saveImage (const IplImage *im, string imgPath, int mode, const CvMat *results) -{ - string name, path; - size_t pos; - char imgNameCh[8]; - IplImage *cut = NULL; - int x, y, w, h; - - pos = imgPath.find_last_of ("/"); - path = imgPath.substr(0, pos); - - if (mode == TAGGED) - { - pos = imgPath.find_last_of("."); - - name = imgPath.substr (0, pos); - - name.append ("_tagged"); - name.append(imgPath.substr(pos)); - - cvSaveImage (name.c_str(), im); - } - - else if (mode == CUT) - { - for (int i = 0; i < results->rows; i++) - { - x = min (cvGetReal2D (results, i, 0), cvGetReal2D (results, i, 2)); - y = min (cvGetReal2D (results, i, 1), cvGetReal2D (results, i, 3)); - w = abs(cvGetReal2D (results, i, 0) - cvGetReal2D (results, i, 2)); - h = abs(cvGetReal2D (results, i, 1) - cvGetReal2D (results, i, 3)); - - cut = cvCreateImage (cvSize (w, h), im->depth, im->nChannels); - - for (int m = x; m < w+x; m++) - for (int n = y; n < h+y; n++) - cvSet2D (cut, n-y, m-x, cvGet2D(im, n, m)); - - - pos = imgPath.find_last_of("."); - - name = imgPath.substr (0, pos); - - sprintf (imgNameCh, "_cut%d", i+1); - - name.append (imgNameCh); - name.append(imgPath.substr(pos)); - - cvSaveImage (name.c_str(), cut); - cvReleaseImage (&cut); - cut = NULL; - } - } - - return path; -} -*/ -/* -string saveImage (const cv::Mat & im, string imgPath, int mode, const cv::Mat * results) -{ - string name, path; - size_t pos; - char imgNameCh[8]; - - int x, y, w, h; - - pos = imgPath.find_last_of ("/"); - path = imgPath.substr(0, pos); - - if (mode == TAGGED) - { - pos = imgPath.find_last_of("."); - - name = imgPath.substr (0, pos); - - name.append ("_tagged"); - name.append(imgPath.substr(pos)); - - cv::imwrite(name,im); - - } - - else if (mode == CUT) - { - for (int i = 0; i < results->rows; i++) - { - x = min (results->at(i, 0), results->at(i, 2)); - y = min (results->at(i, 1), results->at(i, 3)); - w = abs(results->at(i, 0) - results->at(i, 2)); - h = abs(results->at(i, 1) - results->at(i, 3)); - - cv::Mat cut2(cv::Size(w, h), cv::DataType>::type); - cout << im.channels() << endl; - - for (int m = x; m < w+x; m++) - for (int n = y; n < h+y; n++) - cut2.at(n-y, m-x) = im.at(n, m); - - - pos = imgPath.find_last_of("."); - - name = imgPath.substr (0, pos); - - sprintf (imgNameCh, "_cut%d", i+1); - - name.append (imgNameCh); - name.append(imgPath.substr(pos)); - - - cv::imwrite(name, cut2); - cut2.release(); - } - } - - return path; -} -*/ string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetections & results) { string name, path; size_t pos; char imgNameCh[8]; - + int nresults; int x, y, w, h; pos = imgPath.find_last_of ("/"); @@ -185,8 +67,8 @@ string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetection break; case CUT: - - for (int i = 0; i < results.size(); i++) + nresults = (int) results.size(); + for (int i = 0; i < nresults; i++) { x = min (results[i].getX1(), results[i].getX2()); y = min (results[i].getY1(), results[i].getY2()); diff --git a/tests/detectvid.cpp b/tests/detectvid.cpp index 1055778..d04a5e2 100644 --- a/tests/detectvid.cpp +++ b/tests/detectvid.cpp @@ -103,7 +103,7 @@ string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetection string name, path; size_t pos; char imgNameCh[8]; - + int nresults; int x, y, w, h; pos = imgPath.find_last_of ("/"); @@ -124,7 +124,8 @@ string saveImage (const cv::Mat & im, string imgPath, int mode, const LDetection else if (mode == CUT) { - for (int i = 0; i < results.size(); i++) + nresults = (int) results.size(); + for (int i = 0; i < nresults; i++) { x = min (results[i].getX1(), results[i].getX2()); y = min (results[i].getY1(), results[i].getY2());