opencv3.0 截取任意形状封闭图形

截取任意图形是抠图的一个基本操作,在opencv 下也可以实现了。
漫水填充加模板实现截图。

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:           选择算法连接方式。
简单的说,就是选中点seedPoint,然后选取出它周围和它色彩差异不大的点,并将它们的值改为newVal。如果被选取的点,遇到mask掩码,则放弃对该方向的
蔓延填充。
#include "stdafx.h"
#include "iostream"
#include <iostream>  
#include <vector>  
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;

CvPoint prev_pt = { -1, -1 };//
Mat img;
Mat img_mask;
Mat dst;
void on_mouse(int event, int x, int y, int flags, void*)
{
    if (!img.data)
        return;
    if (event == CV_EVENT_RBUTTONUP)//注意在选中的区域外按下**右键**鼠标并释放后将产生填充
    {

        floodFill(img_mask, Point(x, y), Scalar(0));//在选中点的位置进行漫水填充抠图模板  
        img.copyTo(dst, img_mask);
        imshow("dst", dst);
    }
    //注意下面不要用 else if,否则动作需要连续,画完封闭图,立即使用右键操作
    if (event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))  //判断事件为松开鼠标左键或者不是左拖拽  
    {
        prev_pt = cvPoint(-1, -1);
    }
    else if (event == CV_EVENT_LBUTTONDOWN)  //判断为按下左键  
    {
        prev_pt = cvPoint(x, y);
    }
    else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))  //判断移动鼠标并且左拖拽  
    {
        CvPoint pt = cvPoint(x, y);
        if (prev_pt.x < 0)
        {
            prev_pt = pt; 
        }
        line(img_mask, prev_pt, pt, Scalar(0), 2, 8, 0); //在模板连接上次的点和这次的点,并画直线。 
        line(img, prev_pt, pt, Scalar::all(255), 2, 8, 0);          //原图上画直线  
        prev_pt = pt;
        imshow("image", img);
    }
}

int main()
{

    Mat image_base = imread("d:\\betty.jpg");
    image_base.copyTo(img);

    //将模板设置成白色  
    img_mask.create(img.rows, img.cols, CV_8U);
    img_mask.setTo(Scalar(255));
    //显示原图用于选取任意封闭图形  
    imshow("image", img);

    //设置鼠标回调函数  
    cvSetMouseCallback("image", on_mouse, 0);
    while (true)
    {
        if (waitKey(1) == 27)//只能按 ESC 键退出程序
            break;
    }
    return 0;
}

在原图上截取一个封闭图形
截图后的效果

目前还有个问题,就是一旦使用了右键后,后面的选取就不再会去截图了。

参考了如下博客
OpenCV通过MASK来实现抠图
http://blog.csdn.net/qiek/article/details/51045813
opencv FloodFill(漫水填充)和物体选取
http://blog.csdn.net/u011630458/article/details/44260119
opencv的鼠标以及键值使用
http://blog.csdn.net/u011630458/article/details/44081561

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值