mirror of
https://github.com/opencv/opencv.git
synced 2024-12-18 03:18:01 +08:00
5fb3869775
* Fixed clang -Wnewline-eof warnings * Fixed all trivial clang -Wextra-semi and -Wc++98-compat-extra-semi warnings * Removed trailing semi from various macros * Fixed various -Wunused-macros warnings * Fixed some trivial -Wdocumentation warnings * Fixed some -Wdocumentation-deprecated-sync warnings * Fixed incorrect indentation * Suppressed some clang warnings in 3rd party code * Fixed QRCodeEncoder::Params documentation. --------- Co-authored-by: Alexander Smorkalov <alexander.smorkalov@xperience.ai>
222 lines
7.5 KiB
C++
222 lines
7.5 KiB
C++
// This file is part of OpenCV project.
|
|
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
|
// of this distribution and at http://opencv.org/license.html.
|
|
|
|
#include "precomp.hpp"
|
|
#include <opencv2/imgproc.hpp>
|
|
#include <algorithm>
|
|
|
|
using namespace cv;
|
|
|
|
namespace
|
|
{
|
|
class ROISelector
|
|
{
|
|
public:
|
|
Rect select(const String &windowName, Mat img, bool showCrossair = true, bool fromCenter = true, bool printNotice = true)
|
|
{
|
|
if(printNotice)
|
|
{
|
|
// show notice to user
|
|
printf("Select a ROI and then press SPACE or ENTER button!\n");
|
|
printf("Cancel the selection process by pressing c button!\n");
|
|
}
|
|
|
|
key = 0;
|
|
imageSize = img.size();
|
|
|
|
// 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*)this);
|
|
|
|
// end selection process on SPACE (32) ESC (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 bounding box
|
|
imshow(windowName, selectorParams.image);
|
|
|
|
// reset the image
|
|
selectorParams.image = img.clone();
|
|
|
|
// get keyboard event
|
|
key = waitKey(30);
|
|
|
|
if (key == 'c' || key == 'C')//cancel selection
|
|
{
|
|
selectorParams.box = Rect();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//cleanup callback
|
|
setMouseCallback(windowName, emptyMouseHandler, NULL);
|
|
|
|
return selectorParams.box;
|
|
}
|
|
|
|
void select(const String &windowName, Mat img, std::vector<Rect> &boundingBoxes,
|
|
bool showCrosshair = true, bool fromCenter = true, bool printNotice = true)
|
|
{
|
|
if(printNotice)
|
|
{
|
|
printf("Finish the selection process by pressing ESC button!\n");
|
|
}
|
|
boundingBoxes.clear();
|
|
key = 0;
|
|
|
|
// while key is not ESC (27)
|
|
for (;;)
|
|
{
|
|
Rect temp = select(windowName, img, showCrosshair, fromCenter, printNotice);
|
|
if (key == 27)
|
|
break;
|
|
if (temp.width > 0 && temp.height > 0)
|
|
boundingBoxes.push_back(temp);
|
|
}
|
|
}
|
|
|
|
struct handlerT
|
|
{
|
|
// basic parameters
|
|
bool isDrawing;
|
|
Rect2d box;
|
|
Mat image;
|
|
Point2f startPos;
|
|
|
|
// parameters for drawing from the center
|
|
bool drawFromCenter;
|
|
|
|
// initializer list
|
|
handlerT() : isDrawing(false), drawFromCenter(true){}
|
|
} selectorParams;
|
|
|
|
private:
|
|
static void emptyMouseHandler(int, int, int, int, void*)
|
|
{
|
|
}
|
|
|
|
static void mouseHandler(int event, int x, int y, int flags, void *param)
|
|
{
|
|
ROISelector *self = static_cast<ROISelector *>(param);
|
|
self->opencv_mouse_callback(event, x, y, flags);
|
|
}
|
|
|
|
void opencv_mouse_callback(int event, int x, int y, int)
|
|
{
|
|
switch (event)
|
|
{
|
|
// update the selected bounding box
|
|
case EVENT_MOUSEMOVE:
|
|
if (selectorParams.isDrawing)
|
|
{
|
|
if (selectorParams.drawFromCenter)
|
|
{
|
|
// limit half extends to imageSize
|
|
float halfWidth = std::min(std::min(
|
|
std::abs(x - selectorParams.startPos.x),
|
|
selectorParams.startPos.x),
|
|
imageSize.width - selectorParams.startPos.x);
|
|
float halfHeight = std::min(std::min(
|
|
std::abs(y - selectorParams.startPos.y),
|
|
selectorParams.startPos.y),
|
|
imageSize.height - selectorParams.startPos.y);
|
|
|
|
selectorParams.box.width = halfWidth * 2;
|
|
selectorParams.box.height = halfHeight * 2;
|
|
selectorParams.box.x = selectorParams.startPos.x - halfWidth;
|
|
selectorParams.box.y = selectorParams.startPos.y - halfHeight;
|
|
|
|
}
|
|
else
|
|
{
|
|
// limit x and y to imageSize
|
|
int lx = std::min(std::max(x, 0), imageSize.width);
|
|
int by = std::min(std::max(y, 0), imageSize.height);
|
|
selectorParams.box.width = std::abs(lx - selectorParams.startPos.x);
|
|
selectorParams.box.height = std::abs(by - selectorParams.startPos.y);
|
|
selectorParams.box.x = std::min((float)lx, selectorParams.startPos.x);
|
|
selectorParams.box.y = std::min((float)by, selectorParams.startPos.y);
|
|
}
|
|
}
|
|
break;
|
|
|
|
// start to select the bounding box
|
|
case EVENT_LBUTTONDOWN:
|
|
selectorParams.isDrawing = true;
|
|
selectorParams.box = Rect2d(x, y, 0, 0);
|
|
selectorParams.startPos = Point2f((float)x, (float)y);
|
|
break;
|
|
|
|
// cleaning up the selected bounding box
|
|
case EVENT_LBUTTONUP:
|
|
selectorParams.isDrawing = false;
|
|
if (selectorParams.box.width < 0)
|
|
{
|
|
selectorParams.box.x += selectorParams.box.width;
|
|
selectorParams.box.width *= -1;
|
|
}
|
|
if (selectorParams.box.height < 0)
|
|
{
|
|
selectorParams.box.y += selectorParams.box.height;
|
|
selectorParams.box.height *= -1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// save the keypressed character
|
|
int key;
|
|
Size imageSize;
|
|
};
|
|
}
|
|
|
|
Rect cv::selectROI(InputArray img, bool showCrosshair, bool fromCenter, bool printNotice)
|
|
{
|
|
ROISelector selector;
|
|
return selector.select("ROI selector", img.getMat(), showCrosshair, fromCenter, printNotice);
|
|
}
|
|
|
|
Rect cv::selectROI(const String& windowName, InputArray img, bool showCrosshair, bool fromCenter, bool printNotice)
|
|
{
|
|
ROISelector selector;
|
|
return selector.select(windowName, img.getMat(), showCrosshair, fromCenter, printNotice);
|
|
}
|
|
|
|
void cv::selectROIs(const String& windowName, InputArray img,
|
|
std::vector<Rect>& boundingBox, bool showCrosshair, bool fromCenter, bool printNotice)
|
|
{
|
|
ROISelector selector;
|
|
selector.select(windowName, img.getMat(), boundingBox, showCrosshair, fromCenter, printNotice);
|
|
}
|