class GCApplication
{
public:
enum { NOT_SET = 0, IN_PROCESS = 1, SET = 2 };
void reset();
void setImageAndWinName(const cv::Mat& _image, const std::string& _winName);
void showImage() const;
void mouseClick(int event, int x, int y, int flags, void* param);
private:
const std::string* winName; //图像窗口指针
const cv::Mat* image; //图像指针
uchar rectState; //绘制状态标识
cv::Rect rect; //绘制矩形
};
重置绘制状态
void GCApplication::reset()
{
rectState = NOT_SET; //未开启绘制
}
显示图像与绘制的矩形ROI
void GCApplication::setImageAndWinName(const cv::Mat& _image, const std::string& _winName)
{
if (_image.empty() || _winName.empty())
return;
image = &_image; //将内存地址传递给image
winName = &_winName;
reset();
}
下面简单的介绍下“&”的作用
显示图像与绘制的矩形ROI
void GCApplication::showImage() const
{
if (image->empty() || winName->empty())
return;
cv::Mat res;
image->copyTo(res); //图像拷贝到res中
if (rectState == IN_PROCESS || rectState == SET)
rectangle(res, cv::Point(rect.x, rect.y), cv::Point(rect.x + rect.width, rect.y + rect.height), GREEN, 2);
imshow(*winName, res);
}
定义绘制事件所执行的内容
void GCApplication::mouseClick(int event, int x, int y, int flags, void*)
{
// 鼠标回调事件
switch (event)
{
case cv::EVENT_LBUTTONDOWN: // 鼠标左键按下事件
{
//程序启动时,rectState已被设置为NOT_SET
//鼠标左键按下时,设置rectState的状态为IN_PROCESS
//并将此时鼠标的位置设定为rect的起始点
if (rectState == NOT_SET)
{
rectState = IN_PROCESS;
rect = cv::Rect(x, y, 1, 1);
}
}
break;
case cv::EVENT_LBUTTONUP: //鼠标左键抬起事件
//当鼠标左键抬起时,如果rectState不处于在绘制的状态,则不做任何处理
//如rectState==IN_PROCESS时,则执行rect的绘制与显示,将当前鼠标位置作为
//矩形的右下顶点最终坐标,同时,要调用showImage,来实时显示绘制效果
if (rectState == IN_PROCESS)
{
if (rect.x == x || rect.y == y) {
rectState = NOT_SET;
}
else {
rect = cv::Rect(cv::Point(rect.x, rect.y), cv::Point(x, y));
rectState = SET;
}
showImage();
}
break;
case cv::EVENT_MOUSEMOVE: //鼠标移动事件
//当鼠标移动,且左键按下时,开始绘制
if (rectState == IN_PROCESS)
{
rect = cv::Rect(cv::Point(rect.x, rect.y), cv::Point(x, y));
showImage();
}
break;
}
}
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include
const cv::Scalar GREEN = cv::Scalar(0, 255, 0); //定义一个颜色常量
GCApplication gcapp; //声明GCApplication的全局变量,以便调用相关函数
static void on_mouse(int event, int x, int y, int flags, void* param)
{
gcapp.mouseClick(event, x, y, flags, param);
}
int main(int argc, char** argv)
{
//1.读取图像
cv::Mat image = cv::imread("messi5.jpg", cv::IMREAD_COLOR);
if (image.empty())
{
std::cout << "\n Durn, couldn't read image filename " << std::endl;
return 1;
}
//2.创建显示窗口
const std::string winName = "image";
cv::namedWindow(winName, cv::WINDOW_AUTOSIZE);
//3.创建鼠标回调
cv::setMouseCallback(winName, on_mouse, 0);
//4.将image和winName传递给GCApplication类的成员变量
gcapp.setImageAndWinName(image, winName);
//5.通过showImage函数显示图像与ROI区域
gcapp.showImage();
//6.设定一个循环函数,来执行键盘上一些按键的操作
for (;;)
{
char c = (char)cv::waitKey(0);
switch (c)
{
case '\x1b': //Esc退出
std::cout << "Exiting ..." << std::endl;
goto exit_main;
case 'r': //R 重置
std::cout << std::endl;
gcapp.reset();
gcapp.showImage();
break;
}
}
exit_main:
cv::destroyWindow(winName); //退出时销毁窗体
return 0;
}
备注:为甚要定义一个静态on_mouse函数呢?