From 194455a4bd5fba4867e90bea369217059b46c072 Mon Sep 17 00:00:00 2001 From: Kurnianggoro Date: Thu, 23 Jul 2015 10:51:22 +0900 Subject: [PATCH] Add: roi selector --- modules/tracking/doc/diagrams.markdown | 2 - .../include/opencv2/tracking/tracker.hpp | 35 ++++ modules/tracking/samples/multitracker.cpp | 163 +--------------- modules/tracking/src/roiSelector.cpp | 184 ++++++++++++++++++ 4 files changed, 221 insertions(+), 163 deletions(-) create mode 100644 modules/tracking/src/roiSelector.cpp diff --git a/modules/tracking/doc/diagrams.markdown b/modules/tracking/doc/diagrams.markdown index 1efd47b5c..32abd2e0d 100644 --- a/modules/tracking/doc/diagrams.markdown +++ b/modules/tracking/doc/diagrams.markdown @@ -237,7 +237,6 @@ MultiTracker diagram @enduml @startuml{multi_tracker_uml.png} - package "MultiTracker class" #DDDDDD { class MultiTracker{ MultiTracker(const String& trackerType = "" ); @@ -254,5 +253,4 @@ MultiTracker diagram } - } @enduml diff --git a/modules/tracking/include/opencv2/tracking/tracker.hpp b/modules/tracking/include/opencv2/tracking/tracker.hpp index 6d6248d2c..4e53b438f 100644 --- a/modules/tracking/include/opencv2/tracking/tracker.hpp +++ b/modules/tracking/include/opencv2/tracking/tracker.hpp @@ -1322,6 +1322,41 @@ class CV_EXPORTS_W MultiTracker String defaultAlgorithm; }; +class ROISelector { +public: + Rect2d select(Mat img, bool fromCenter = true); + Rect2d select(const std::string& windowName, Mat img, bool showCrossair = true, bool fromCenter = true); + void select(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter = true); + + struct handlerT{ + // basic parameters + bool isDrawing; + Rect2d box; + Mat image; + + // parameters for drawing from the center + bool drawFromCenter; + Point2f center; + + // initializer list + handlerT(): isDrawing(false), drawFromCenter(true) {}; + }selectorParams; + + // to store the tracked objects + std::vector objects; + +private: + static void mouseHandler(int event, int x, int y, int flags, void *param); + void opencv_mouse_callback( int event, int x, int y, int , void *param ); + + // save the keypressed characted + int key; +}; + +Rect2d CV_EXPORTS_W selectROI(Mat img, bool fromCenter = true); +Rect2d CV_EXPORTS_W selectROI(const std::string& windowName, Mat img, bool showCrossair = true, bool fromCenter = true); +void CV_EXPORTS_W selectROI(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter = true); + } /* namespace cv */ #endif diff --git a/modules/tracking/samples/multitracker.cpp b/modules/tracking/samples/multitracker.cpp index a86d2c971..fe6bdf99c 100644 --- a/modules/tracking/samples/multitracker.cpp +++ b/modules/tracking/samples/multitracker.cpp @@ -36,37 +36,6 @@ using namespace std; using namespace cv; -class BoxExtractor { -public: - Rect2d selectROI(Mat img, bool fromCenter = true); - Rect2d selectROI(const std::string& windowName, Mat img, bool showCrossair = true, bool fromCenter = true); - void selectROI(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter = true); - - struct handlerT{ - // basic parameters - bool isDrawing; - Rect2d box; - Mat image; - - // parameters for drawing from the center - bool drawFromCenter; - Point2f center; - - // initializer list - handlerT(): isDrawing(false), drawFromCenter(true) {}; - }params; - - // to store the tracked objects - vector objects; - -private: - static void mouseHandler(int event, int x, int y, int flags, void *param); - void opencv_mouse_callback( int event, int x, int y, int , void *param ); - - // save the keypressed characted - int key; -}; - int main( int argc, char** argv ){ // show help if(argc<2){ @@ -95,9 +64,6 @@ int main( int argc, char** argv ){ std::string text; char buffer [50]; - // ROI selector - BoxExtractor box; - // set the default tracking algorithm std::string trackingAlg = "KCF"; @@ -119,7 +85,7 @@ int main( int argc, char** argv ){ // get bounding box cap >> frame; - box.selectROI("tracker",frame,objects); + selectROI("tracker",frame,objects); //quit when the tracked object(s) is not provided if(objects.size()<1) @@ -162,7 +128,7 @@ int main( int argc, char** argv ){ // draw the tracked object for(unsigned i=0;i(param); - self->opencv_mouse_callback(event,x,y,flags,param); -} - -void BoxExtractor::opencv_mouse_callback( int event, int x, int y, int , void *param ){ - handlerT * data = (handlerT*)param; - switch( event ){ - // update the selected bounding box - case EVENT_MOUSEMOVE: - if( data->isDrawing ){ - if(data->drawFromCenter){ - data->box.width = 2*(x-data->center.x)/*data->box.x*/; - data->box.height = 2*(y-data->center.y)/*data->box.y*/; - data->box.x = data->center.x-data->box.width/2.0; - data->box.y = data->center.y-data->box.height/2.0; - }else{ - data->box.width = x-data->box.x; - data->box.height = y-data->box.y; - } - } - break; - - // start to select the bounding box - case EVENT_LBUTTONDOWN: - data->isDrawing = true; - data->box = cvRect( x, y, 0, 0 ); - data->center = Point2f((float)x,(float)y); - break; - - // cleaning up the selected bounding box - case EVENT_LBUTTONUP: - data->isDrawing = false; - if( data->box.width < 0 ){ - data->box.x += data->box.width; - data->box.width *= -1; - } - if( data->box.height < 0 ){ - data->box.y += data->box.height; - data->box.height *= -1; - } - break; - } -} - -Rect2d BoxExtractor::selectROI(Mat img, bool fromCenter){ - return selectROI("Bounding Box Extractor", img, fromCenter); -} - -Rect2d BoxExtractor::selectROI(const std::string& windowName, Mat img, bool showCrossair, bool fromCenter){ - - key=0; - - // set the drawing mode - params.drawFromCenter = fromCenter; - - // show the image and give feedback to user - imshow(windowName,img); - - // copy the data, rectangle should be drawn in the fresh image - params.image=img.clone(); - - // select the object - setMouseCallback( windowName, mouseHandler, (void *)¶ms ); - - // end selection process on SPACE (32) BACKSPACE (27) or ENTER (13) - while(!(key==32 || key==27 || key==13)){ - // draw the selected object - rectangle( - params.image, - params.box, - Scalar(255,0,0),2,1 - ); - - // draw cross air in the middle of bounding box - if(showCrossair){ - // horizontal line - line( - params.image, - Point((int)params.box.x,(int)(params.box.y+params.box.height/2)), - Point((int)(params.box.x+params.box.width),(int)(params.box.y+params.box.height/2)), - Scalar(255,0,0),2,1 - ); - - // vertical line - line( - params.image, - Point((int)(params.box.x+params.box.width/2),(int)params.box.y), - Point((int)(params.box.x+params.box.width/2),(int)(params.box.y+params.box.height)), - Scalar(255,0,0),2,1 - ); - } - - // show the image bouding box - imshow(windowName,params.image); - - // reset the image - params.image=img.clone(); - - //get keyboard event - key=waitKey(1); - } - - - return params.box; -} - -void BoxExtractor::selectROI(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter){ - vector box; - Rect2d temp; - key=0; - - // show notice to user - printf(RED "Select an object to track and then press SPACE or ENTER button!\n" RESET); - printf(RED "Finish the selection process by pressing BACKSPACE button!\n" RESET); - - // while key is not Backspace - while(key!=27){ - temp=selectROI(windowName, img, true, fromCenter); - if(temp.width>0 && temp.height>0) - box.push_back(temp); - } - boundingBox=box; -} \ No newline at end of file diff --git a/modules/tracking/src/roiSelector.cpp b/modules/tracking/src/roiSelector.cpp new file mode 100644 index 000000000..67dc545b8 --- /dev/null +++ b/modules/tracking/src/roiSelector.cpp @@ -0,0 +1,184 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// + // + // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. + // + // By downloading, copying, installing or using the software you agree to this license. + // If you do not agree to this license, do not download, install, + // copy or use the software. + // + // + // License Agreement + // For Open Source Computer Vision Library + // + // Copyright (C) 2013, OpenCV Foundation, all rights reserved. + // Third party copyrights are property of their respective owners. + // + // Redistribution and use in source and binary forms, with or without modification, + // are permitted provided that the following conditions are met: + // + // * Redistribution's of source code must retain the above copyright notice, + // this list of conditions and the following disclaimer. + // + // * Redistribution's in binary form must reproduce the above copyright notice, + // this list of conditions and the following disclaimer in the documentation + // and/or other materials provided with the distribution. + // + // * The name of the copyright holders may not be used to endorse or promote products + // derived from this software without specific prior written permission. + // + // This software is provided by the copyright holders and contributors "as is" and + // any express or implied warranties, including, but not limited to, the implied + // warranties of merchantability and fitness for a particular purpose are disclaimed. + // In no event shall the Intel Corporation or contributors be liable for any direct, + // indirect, incidental, special, exemplary, or consequential damages + // (including, but not limited to, procurement of substitute goods or services; + // loss of use, data, or profits; or business interruption) however caused + // and on any theory of liability, whether in contract, strict liability, + // or tort (including negligence or otherwise) arising in any way out of + // the use of this software, even if advised of the possibility of such damage. + // + //M*/ + +#include "precomp.hpp" + +namespace cv { + void ROISelector::mouseHandler(int event, int x, int y, int flags, void *param){ + ROISelector *self =static_cast(param); + self->opencv_mouse_callback(event,x,y,flags,param); + } + + void ROISelector::opencv_mouse_callback( int event, int x, int y, int , void *param ){ + handlerT * data = (handlerT*)param; + switch( event ){ + // update the selected bounding box + case EVENT_MOUSEMOVE: + if( data->isDrawing ){ + if(data->drawFromCenter){ + data->box.width = 2*(x-data->center.x)/*data->box.x*/; + data->box.height = 2*(y-data->center.y)/*data->box.y*/; + data->box.x = data->center.x-data->box.width/2.0; + data->box.y = data->center.y-data->box.height/2.0; + }else{ + data->box.width = x-data->box.x; + data->box.height = y-data->box.y; + } + } + break; + + // start to select the bounding box + case EVENT_LBUTTONDOWN: + data->isDrawing = true; + data->box = cvRect( x, y, 0, 0 ); + data->center = Point2f((float)x,(float)y); + break; + + // cleaning up the selected bounding box + case EVENT_LBUTTONUP: + data->isDrawing = false; + if( data->box.width < 0 ){ + data->box.x += data->box.width; + data->box.width *= -1; + } + if( data->box.height < 0 ){ + data->box.y += data->box.height; + data->box.height *= -1; + } + break; + } + } + + Rect2d ROISelector::select(Mat img, bool fromCenter){ + return select("ROI selector", img, fromCenter); + } + + Rect2d ROISelector::select(const std::string& windowName, Mat img, bool showCrossair, bool fromCenter){ + + key=0; + + // set the drawing mode + selectorParams.drawFromCenter = fromCenter; + + // show the image and give feedback to user + imshow(windowName,img); + + // copy the data, rectangle should be drawn in the fresh image + selectorParams.image=img.clone(); + + // select the object + setMouseCallback( windowName, mouseHandler, (void *)&selectorParams ); + + // end selection process on SPACE (32) BACKSPACE (27) or ENTER (13) + while(!(key==32 || key==27 || key==13)){ + // draw the selected object + rectangle( + selectorParams.image, + selectorParams.box, + Scalar(255,0,0),2,1 + ); + + // draw cross air in the middle of bounding box + if(showCrossair){ + // horizontal line + line( + selectorParams.image, + Point((int)selectorParams.box.x,(int)(selectorParams.box.y+selectorParams.box.height/2)), + Point((int)(selectorParams.box.x+selectorParams.box.width),(int)(selectorParams.box.y+selectorParams.box.height/2)), + Scalar(255,0,0),2,1 + ); + + // vertical line + line( + selectorParams.image, + Point((int)(selectorParams.box.x+selectorParams.box.width/2),(int)selectorParams.box.y), + Point((int)(selectorParams.box.x+selectorParams.box.width/2),(int)(selectorParams.box.y+selectorParams.box.height)), + Scalar(255,0,0),2,1 + ); + } + + // show the image bouding box + imshow(windowName,selectorParams.image); + + // reset the image + selectorParams.image=img.clone(); + + //get keyboard event + key=waitKey(1); + } + + + return selectorParams.box; + } + + void ROISelector::select(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter){ + std::vector box; + Rect2d temp; + key=0; + + // show notice to user + printf("Select an object to track and then press SPACE or ENTER button!\n" ); + printf("Finish the selection process by pressing BACKSPACE button!\n" ); + + // while key is not Backspace + while(key!=27){ + temp=select(windowName, img, true, fromCenter); + if(temp.width>0 && temp.height>0) + box.push_back(temp); + } + boundingBox=box; + } + + ROISelector _selector; + Rect2d selectROI(Mat img, bool fromCenter){ + return _selector.select("ROI selector", img, true, fromCenter); + }; + + Rect2d selectROI(const std::string& windowName, Mat img, bool showCrossair, bool fromCenter){ + printf("Select an object to track and then press SPACE or ENTER button!\n" ); + return _selector.select(windowName,img, showCrossair, fromCenter); + }; + + void selectROI(const std::string& windowName, Mat img, std::vector & boundingBox, bool fromCenter){ + return _selector.select(windowName, img, boundingBox, fromCenter); + } + +} /* namespace cv */ \ No newline at end of file