Path: blob/master/modules/highgui/src/roiSelector.cpp
16337 views
// This file is part of OpenCV project.1// It is subject to the license terms in the LICENSE file found in the top-level directory2// of this distribution and at http://opencv.org/license.html.34#include "precomp.hpp"5#include <opencv2/imgproc.hpp>6#include <algorithm>78using namespace cv;910namespace11{12class ROISelector13{14public:15Rect select(const String &windowName, Mat img, bool showCrossair = true, bool fromCenter = true)16{17// show notice to user18printf("Select a ROI and then press SPACE or ENTER button!\n");19printf("Cancel the selection process by pressing c button!\n");2021key = 0;22imageSize = img.size();2324// set the drawing mode25selectorParams.drawFromCenter = fromCenter;2627// show the image and give feedback to user28imshow(windowName, img);2930// copy the data, rectangle should be drawn in the fresh image31selectorParams.image = img.clone();3233// select the object34setMouseCallback(windowName, mouseHandler, (void*)this);3536// end selection process on SPACE (32) ESC (27) or ENTER (13)37while (!(key == 32 || key == 27 || key == 13))38{39// draw the selected object40rectangle(selectorParams.image, selectorParams.box, Scalar(255, 0, 0), 2, 1);4142// draw cross air in the middle of bounding box43if (showCrossair)44{45// horizontal line46line(selectorParams.image,47Point((int)selectorParams.box.x,48(int)(selectorParams.box.y + selectorParams.box.height / 2)),49Point((int)(selectorParams.box.x + selectorParams.box.width),50(int)(selectorParams.box.y + selectorParams.box.height / 2)),51Scalar(255, 0, 0), 2, 1);5253// vertical line54line(selectorParams.image,55Point((int)(selectorParams.box.x + selectorParams.box.width / 2),56(int)selectorParams.box.y),57Point((int)(selectorParams.box.x + selectorParams.box.width / 2),58(int)(selectorParams.box.y + selectorParams.box.height)),59Scalar(255, 0, 0), 2, 1);60}6162// show the image bounding box63imshow(windowName, selectorParams.image);6465// reset the image66selectorParams.image = img.clone();6768// get keyboard event69key = waitKey(30);7071if (key == 'c' || key == 'C')//cancel selection72{73selectorParams.box = Rect();74break;75}76}7778//cleanup callback79setMouseCallback(windowName, emptyMouseHandler, NULL);8081return selectorParams.box;82}8384void select(const String &windowName, Mat img, std::vector<Rect> &boundingBoxes,85bool showCrosshair = true, bool fromCenter = true)86{87printf("Finish the selection process by pressing ESC button!\n");88boundingBoxes.clear();89key = 0;9091// while key is not ESC (27)92for (;;)93{94Rect temp = select(windowName, img, showCrosshair, fromCenter);95if (key == 27)96break;97if (temp.width > 0 && temp.height > 0)98boundingBoxes.push_back(temp);99}100}101102struct handlerT103{104// basic parameters105bool isDrawing;106Rect2d box;107Mat image;108109// parameters for drawing from the center110bool drawFromCenter;111Point2f center;112113// initializer list114handlerT() : isDrawing(false), drawFromCenter(true){};115} selectorParams;116117private:118static void emptyMouseHandler(int, int, int, int, void*)119{120}121122static void mouseHandler(int event, int x, int y, int flags, void *param)123{124ROISelector *self = static_cast<ROISelector *>(param);125self->opencv_mouse_callback(event, x, y, flags);126}127128void opencv_mouse_callback(int event, int x, int y, int)129{130switch (event)131{132// update the selected bounding box133case EVENT_MOUSEMOVE:134if (selectorParams.isDrawing)135{136if (selectorParams.drawFromCenter)137{138selectorParams.box.width = 2 * (x - selectorParams.center.x);139selectorParams.box.height = 2 * (y - selectorParams.center.y);140selectorParams.box.x = std::min(141std::max(selectorParams.center.x - selectorParams.box.width / 2.0, 0.), (double)imageSize.width);142selectorParams.box.y = std::min(143std::max(selectorParams.center.y - selectorParams.box.height / 2.0, 0.), (double)imageSize.height);144}145else146{147selectorParams.box.width = std::max(148std::min(x - selectorParams.box.x, (double)imageSize.width - selectorParams.box.x), - selectorParams.box.x);149selectorParams.box.height = std::max(150std::min(y - selectorParams.box.y, (double)imageSize.height - selectorParams.box.y), - selectorParams.box.y);151}152}153break;154155// start to select the bounding box156case EVENT_LBUTTONDOWN:157selectorParams.isDrawing = true;158selectorParams.box = Rect2d(x, y, 0, 0);159selectorParams.center = Point2f((float)x, (float)y);160break;161162// cleaning up the selected bounding box163case EVENT_LBUTTONUP:164selectorParams.isDrawing = false;165if (selectorParams.box.width < 0)166{167selectorParams.box.x += selectorParams.box.width;168selectorParams.box.width *= -1;169}170if (selectorParams.box.height < 0)171{172selectorParams.box.y += selectorParams.box.height;173selectorParams.box.height *= -1;174}175break;176}177}178179// save the keypressed character180int key;181Size imageSize;182};183}184185Rect cv::selectROI(InputArray img, bool showCrosshair, bool fromCenter)186{187ROISelector selector;188return selector.select("ROI selector", img.getMat(), showCrosshair, fromCenter);189}190191Rect cv::selectROI(const String& windowName, InputArray img, bool showCrosshair, bool fromCenter)192{193ROISelector selector;194return selector.select(windowName, img.getMat(), showCrosshair, fromCenter);195}196197void cv::selectROIs(const String& windowName, InputArray img,198std::vector<Rect>& boundingBox, bool showCrosshair, bool fromCenter)199{200ROISelector selector;201selector.select(windowName, img.getMat(), boundingBox, showCrosshair, fromCenter);202}203204205