我对此进行了一些尝试——它可能不是最干净的代码,但应该会给你一些想法。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
// Globals
bool finished=false;
Mat img,ROI;
vector<Point> vertices;
void
CallBackFunc(int event,int x,int y,int flags,void* userdata)
{
if(event==EVENT_RBUTTONDOWN){
cout << "Right mouse button clicked at (" << x << ", " << y << ")" << endl;
if(vertices.size()<2){
cout << "You need a minimum of three points!" << endl;
return;
}
// Close polygon
line(img,vertices[vertices.size()-1],vertices[0],Scalar(0,0,0));
// Mask is black with white where our ROI is
Mat mask= Mat::zeros(img.rows,img.cols,CV_8UC1);
vector<vector<Point>> pts{vertices};
fillPoly(mask,pts,Scalar(255,255,255));
img.copyTo(ROI,mask);
finished=true;
return;
}
if(event==EVENT_LBUTTONDOWN){
cout << "Left mouse button clicked at (" << x << ", " << y << ")" << endl;
if(vertices.size()==0){
// First click - just draw point
img.at<Vec3b>(x,y)=Vec3b(255,0,0);
} else {
// Second, or later click, draw line to previous vertex
line(img,Point(x,y),vertices[vertices.size()-1],Scalar(0,0,0));
}
vertices.push_back(Point(x,y));
return;
}
}
int main()
{
// Read image from file
img=imread("demo.jpg");
// Check it loaded
if(img.empty())
{
cout << "Error loading the image" << endl;
exit(1);
}
//Create a window
namedWindow("ImageDisplay",1);
// Register a mouse callback
setMouseCallback("ImageDisplay",CallBackFunc,nullptr);
// Main loop
while(!finished){
imshow("ImageDisplay",img);
waitKey(50);
}
// Show results
namedWindow("Result",1);
imshow("Result",ROI);
waitKey(5000);
}
回调说明
在main()的开头我这样做:
setMouseCallback("ImageDisplay",CallBackFunc,nullptr);
这告诉 OpenCV 在鼠标移动或点击时为我们调用函数CallBackFunc()。
CallBackFunc() 和其他函数一样只是一个普通函数。然而,我们从来没有自己调用它 - OpenCV 为我们异步调用它(当我们不期望它时)。因此,我们看不到函数的任何返回值——因为我们从未调用过它——这就是为什么它被声明为:
void CallBackFunc(...)
因为它什么也没有返回,或者是一个虚无,或者一个肮脏的虚无。
好的,让我们继续讨论调用它的参数。基本上,当 OpenCV 的设计者编写 setMouseCallback() 函数时,他们不知道我想将什么作为参数传递给它——也许我想传递一个文件名,也许我想想要在单击鼠标时传递一个文本字符串以在图像上绘制,也许我想传递一个我想用鼠标位置更新的变量。它可以是任何东西。所以,正如他们不知道的那样,他们决定说它是一个“指向任何东西的指针”,我可以将它用于我喜欢的任何事情。好吧,什么都不是,所以指向 void 的指针可以指向任何东西。因此,他们说只需将指针传递给您知道其含义的 void。然后,在 CallBackFunc() 中,您可以将指针转换为您传递的任何内容,因为您知道它是什么。
因此,总而言之,指向 void 的指针只是指向某物的指针的位置标记,您可以在 OpenCV 设计者需要知道的情况下决定该物是什么。
希望有帮助!