漫水填充加模板实现截图。
**实现思路:**创建一个原图大小相同的单通道白色模板,在原图上通过鼠标圈出抠图区域,
并在模板上相同区域使用黑色线条画出对应区域,再将模板进行漫水填充,模板所选区域外全为黑色,区域内为白色。最后,使用copyTo()将模板上不为0的区域像素拷贝出来。
//FloodFill漫水函数原型
int floodFill(InputOutputArray image, InputOutputArray mask,
Point seedPoint, Scalar newVal, Rect* rect=0,
Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 );
InputOutputArray:输入和输出图像。
mask: 输入的掩码图像。
seedPoint: 进行填充的起始点。
newVal: 图像中所有被算法选中的点,都用这个数值来填充。
rect: 最小包围矩阵。
loDiff: 最大的低亮度之间的差异。
upDiff: 最大的高亮度之间的差异。
flag: 选择算法连接方式。
// copyTo函数
src.copyTo(dst, mask);
src拷贝原图,dst结果图,mask模板。
mask不存在时将src拷贝给dst,存在时将mask像素不为0的区域拷贝给dst。
Mat dst = src;浅复制,共享同一块内存;copyto深复制,各自拥有内存。
//初始化及回调函数的调用
bool g_bDrawingBox = false;//记录鼠标左键是否按下
Rect g_rectangle; //画矩形所用rect
Point2i roi_p;//路径上的点 //画任意线条
image_mask.create(roi_image1.rows, roi_image1.cols, CV_8U);
image_mask.setTo(Scalar(255));
setMouseCallback("裁剪图", mouse, (void*)&roi_image1);
while (1)
{
if (waitKey(10) == 27) { break; }//esc键,程序退出
imshow("裁剪图", roi_image1);
}
//回调函数
void mouse(int event, int x, int y, int flags, void* param) {
Mat& image = *(Mat*)param;
switch (event){
case EVENT_LBUTTONDOWN: {
cout << "EVENT_LBUTTONDOWN" << endl;
g_bDrawingBox = true;
g_rectangle = Rect(x, y, 0, 0);
roi_p.x = x;
roi_p.y = y;
}
break;
case EVENT_MOUSEMOVE: {
if (g_bDrawingBox) {
g_rectangle.width = x - g_rectangle.x;
g_rectangle.height = y - g_rectangle.y;
line(image, roi_p, Point2i(x,y), Scalar(0, 0, 255), 1, CV_AA);
line(image_mask, roi_p, Point2i(x, y), Scalar(0), 3, 8);
roi_p.x = x;
roi_p.y = y;
}
}
break;
case EVENT_LBUTTONUP: {
// 可以将起点和终点的矩形画出来
cout << "EVENT_LBUTTONUP" << endl;
g_bDrawingBox = false;
if (g_rectangle.width < 0) {
g_rectangle.x += g_rectangle.width;
g_rectangle.width *= -1;
}
if (g_rectangle.height < 0) {
g_rectangle.y += g_rectangle.height;
g_rectangle.height *= -1;
}
rectangle(image, g_rectangle, Scalar(0, 0, 255));
}
break;
case EVENT_RBUTTONUP: {
floodFill(image_mask, Point(100, 100), Scalar(0, 0, 0));//漫水填充
image.copyTo(dst, image_mask);//抠图
}
}
}