前言
1.在图像处理中,会用鼠标选择一个感兴趣的区域进行相关的操作,我这里演示如何用鼠标选择任何形状的ROI,就你Ps的抠图一样,使用鼠标左键选择一个任何形状的区域,生成新的图像。
2.我演示的代码环境是,IDE是VS2015,使用的是OpenCV3.30这个版本。
选择任何形状的ROI
#include <iostream>
#include<opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
//定义全局坐标系
Point prev_pt = Point(-1, -1);
Mat src, background_img, foreground_img;
void on_mouse(int event, int x, int y, int flags, void*)
{
//松开鼠标左键或不是按住左键拖拽的动作时,把坐标还原
if (event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))
{
prev_pt = Point(-1, -1);
}
//按下左键
else if (event == CV_EVENT_LBUTTONDOWN)
{
prev_pt = Point(x, y);
}
//移动鼠标并按住左键拖拽
else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))
{
Point pt = Point(x, y);
//前景模板上划线
line(foreground_img, prev_pt, pt, Scalar(255), 2, 8, 0);
//原图上划线 Scalar::all(255)意思就是BGR通道像素值全为255
line(src, prev_pt, pt, Scalar::all(255), 2, 8, 0);
//起点等于终点,说明曲线要比
prev_pt = pt;
imshow("原图", src);
}
//点击右键,截取所选区域
if (event == CV_EVENT_RBUTTONUP)
{
Mat dst;
//画线闭合区域被白色填充显示在原始图像上
floodFill(foreground_img, Point(x, y), Scalar(255));
// img中被FG_mask掩盖后的图像附到FG中显示
src.copyTo(dst, foreground_img);
namedWindow("ROI", 0);
imshow("ROI", dst);
}
}
int main()
{
Mat image = imread("4.jpg");
//初始化前景和背景模板
foreground_img = Mat(image.size(), CV_8UC1, Scalar(0));
image.copyTo(src);
//显示原图
namedWindow("原图", 0);
imshow("原图", src);
cvSetMouseCallback("原图", on_mouse, 0);
waitKey(0);
return 0;
}
结果
1.运行之后,按下鼠标左键,对着要选择的区域拖动鼠标描边,闭合之后松开左键,点击右键,得到ROI区域。
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0DMX5EMRhEZoFjMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLyUDNyMTOzMjMxEjNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
2.如果不闭合,按漫水填充的算法,会得到整张图像。