opencv如何通过鼠标事件不规则地选择图像区域?C/C ++ [英] opencv how can I select a region of image irregularly with mouse event? c/c++

查看:56
本文介绍了opencv如何通过鼠标事件不规则地选择图像区域?C/C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近正在学习opencv.有没有一种方法可以使用鼠标事件来选择图像区域?我已经尝试过三角形了.如果我想选择特定区域而不是三角形,该怎么办?谢谢!

I'm learning opencv recently. Is there a way to select a region of image using mouse event? I already try out the triangle one. What if I want to choose a specific region but not a triangle shape? Thank you!

推荐答案

我对此做了一点尝试-它可能不是最干净的代码,但是应该给您一些想法.

I had a little attempt at this - it is probably not the cleanest code, but should give you some ideas.

#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().

and that tells OpenCV to call the function CallBackFunc() for us whenever the mouse moves or is clicked.

CallBackFunc()就像其他函数一样,只是一个普通函数.但是,我们永远不会自己调用它- OpenCV 异步地为我们调用它(当我们不期望它时).因此,我们从函数中看不到任何返回的值-因为我们从未调用过它-这就是为什么将其声明为:

CallBackFunc() is just a normal function like any other function. However, we don't ever call it ourselves - OpenCV calls it for us asynchronously (when we aren't expecting it). Because of that, we can't see any returned value from the function - since we never called it - and that is why it is declared as:

void CallBackFunc(...)

因为它什么也不返回,或者返回一个空,或者一个虚无的肮脏的巨大空.

because it returns nothing, or a void, or a dirty great void of nothingness.

好吧,让我们继续调用它的参数.基本上,当 OpenCV 的设计人员编写了 setMouseCallback()函数时,他们不知道我想要将什么作为参数传递给它-也许我想传递文件名,也许我想传递一个文本字符串以在单击鼠标时在图像上绘制,也许我想传递一个我想用鼠标位置更新的变量.可能是任何东西.因此,正如他们所不知道的,他们决定说这是指向任何东西的指针" ,我可以将其用于任何我喜欢的东西.好吧,什么都不是什么,所以指向void的指针可以指向任何东西.因此,他们说只要传递一个指向void的指针,就可以知道它的含义.然后,在 CallBackFunc()内部,您可以将指针强制转换为所传递的指针,因为您知道它是什么.

Ok, let's move on to the parameters it is called with. Basically, when the designers of OpenCV wrote the setMouseCallback() function, they couldn't know what I would want to pass to it as a parameter - maybe I would want to pass a filename, maybe I would want to pass a text string to draw on the image when the mouse is clicked, maybe I would want to pass a variable that I wanted updated with the mouse position. It could be anything. So, as they didn't know, they decided to say it is a "pointer to anything" and I can use it for whatever I like. Well, nothing is anything, so a pointer to void can point to anything. So, they say just pass a pointer to void that you know the meaning of. Then, inside CallBackFunc() you can just cast the pointer to whatever it was you passed since you know what it is.

因此,总而言之,指向void的指针仅是指向某事物的指针的位置标记,您可以确定该事物是什么,而无需 OpenCV 设计人员知道.

So, in summary a pointer to void is just a place-marker for a pointer to something and you can decide what that something is without the OpenCV designers needing to know.

希望有帮助!

这篇关于opencv如何通过鼠标事件不规则地选择图像区域?C/C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆