以下程序会给出鼠标左键单击的位置。
void onMouse(int evt, int x, int y, int flags, void* param) {
if(evt == CV_EVENT_LBUTTONDOWN) {
cv::Point* ptPtr = (cv::Point*)param;
ptPtr->x = x;
ptPtr->y = y;
}
}
int main() {
cv::Point2i pt(-1,-1);//assume initial point
cv::namedWindow("Output Window");
Mat frame = cv::imread("chhhha.png");
cv::setMouseCallback("Output Window", onMouse, (void*)&pt);
int X, Y;
while(1)
{
cv::imshow("Output Window", frame);
X=pt.x;
Y=pt.y;
cout<<"X and Y coordinates are given below"<<endl;
cout<<X<<'\t'<<Y<<endl;
waitKey(10);
}
getch();
}
我想绘制一条连接用户点击两点的线。我知道行可以通过函数绘制:
C++: void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0)
但问题是我必须为这个函数提供两点,但我之前的观点丢失了,如下面的代码所示:
void onMouse(int evt, int x, int y, int flags, void* param) {
if(evt == CV_EVENT_LBUTTONDOWN) {
cv::Point* ptPtr = (cv::Point*)param;
ptPtr->x = x;
ptPtr->y = y;
}
}
int main() {
cv::Point2i pt(-1,-1);
cv::namedWindow("Output Window");
Mat frame = cv::imread("chhhha.png");
cv::setMouseCallback("Output Window", onMouse, (void*)&pt);
int X, Y;
while(1)
{
cv::imshow("Output Window", frame);
X=pt.x;
Y=pt.y;
cout<<"X and Y coordinates are given below"<<endl;
cout<<X<<'\t'<<Y<<endl;
line(frame, pt1, pt2, 'r', 1, 8, 0); //here I am having only one point. This is the issue
waitKey(10);
}
getch();
}
修改
无论如何,存储用户点击的点的坐标。因此,让我们说用户点击图像上的两个点,我们将在X [0]和X [1]中存储两次点击的x坐标,对于y坐标,我们会同样存储Y [0]和Y [1] 。
然后我可以轻松地使用该功能绘制一条线。请帮助我朝着这个方向前进。
提前感谢您的建议。
我的最新代码
using namespace cv;
using namespace std;
void onMouse(int evt, int x, int y, int flags, void* param) {
if(evt == CV_EVENT_LBUTTONDOWN) {
std::vector<cv::Point>* ptPtr = (std::vector<cv::Point>*)param;
ptPtr->push_back(cv::Point(x,y));
}
}
int main()
{
std::vector<Point> points;
cv::namedWindow("Output Window");
Mat frame = cv::imread("chhha.png");
cv::setMouseCallback("Output Window", onMouse, (void*)&points);
int X=0, Y=0;
while(1)
{
cv::imshow("Output Window", frame);
X=points[0].x;
Y=points[0].y;
cout<<"First X and Y coordinates are given below"<<endl;
cout<<X<<'\t'<<Y<<endl;
waitKey(10);
}
getch();
}
这有两个主要问题:
1-这样编译得很好,但在运行时它会出现Debug Assertion Failed!
错误,
在以下行中:
X=points[0].x;
Y=points[0].y;
它进一步说:
表达式:矢量下标超出范围
2-如何走出while循环? 在其他类似的程序中,我注意到它永远存在于while循环中。
答案 0 :(得分:4)
我建议不要传递给cv::Point*
,而是传递std::vector<cv::Point>*
。由于cv::Point
具有复制构造函数,因此您可以通过push_back
存储点。
我的意思是代码:
std::vector<cv:Point> points;
cv::namedWindow("Output Window");
Mat frame = cv::imread("chhhha.png");
cv::setMouseCallback("Output Window", onMouse, (void*)&points);
int X, Y;
while(1)
{
cv::imshow("Output Window", frame);
if (points.size() > 2) //we have 2 points
{
for (auto it = points.begin(); it != points.end(); ++it)
{
cout<<"X and Y coordinates are given below"<<endl;
cout<<(*it).x<<'\t'<<(*it).y<<endl;
}
//draw points
}
...
并在回调中:
void onMouse(int evt, int x, int y, int flags, void* param) {
if(evt == CV_EVENT_LBUTTONDOWN) {
std::vector<cv::Point>* ptPtr = (std::vector<cv::Point>*)param;
ptPtr->push_back(cv::Point(x,y));
}
}
稍后,您可以使用points[0]
和points[1]
访问前2个点。
编辑:通过检查矢量大小更新代码。您应该注意,如果在不同的线程中执行鼠标回调,则此方法可能需要锁定。