获得多边形ROI

opencv函数

  • polylines   作用:绘制多条多边形曲线 
void cv::polylines(
InputOutputArray img,
const Point* const* pts,
const int* npts,
int ncontours,
bool isClosed,
const Scalar& color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0 
)
void cv::polylines(	
InputOutputArray img, //输入图像
InputArrayOfArrays pts, //多边形曲线点
bool isClosed, //指示绘制的多段线是否闭合的标志。如果它们是闭合的,则函数将从每条曲线的最后一个顶点到其第一个顶点绘制一条线。
const Scalar& color, //折线颜色
int thickness = 1, //多段线边缘的厚度
int lineType = LINE_8, //线段的线型类型
int shift = 0 //缩放比例(0是不缩放,4是1/4)
)
  •  fillPoly 填充由多个多边形轮廓界定的区域
void cv::fillPoly(InputOutputArray 	img,
const Point** 	pts,
const int* 	npts,
int ncontours,
const Scalar& color,
int lineType = LINE_8,
int shift = 0,
Point offset = Point())
void cv::fillPoly(
InputOutputArray img, //输入图像
InputArrayOfArrays pts, //多边形数组,其中每个多边形表示为点数组
const Scalar& color, //多边形颜色
int lineType = LINE_8, //多边形边界的类型
int shift = 0, //缩放比例(0是不缩放,4是1/4)
Point offset = Point() //轮廓所有点的偏移
)

 测试代码

Mat src = imread("test.jpg");	
imshow("src", src);

//方式一
//Point root_points[1][5];
//root_points[0][0] = Point(93, 146);
//root_points[0][1] = Point(243, 57);
//root_points[0][2] = Point(290, 190);
//root_points[0][3] = Point(239, 259);
//root_points[0][4] = Point(155, 240);

//const Point* ppt[1] = { root_points[0] };
//int npt[] = { 5 };
//polylines(src, ppt, npt, 1, 1, Scalar(255), 3);
//fillPoly(src, ppt, npt, 1, Scalar(0, 0, 255));

//方式二
vector<Point> pt0 = { Point(93, 146), Point(243, 57), Point(290, 190), Point(239, 259), Point(155, 240) };
vector<vector<Point>> pt1;
pt1.push_back(pt0);
polylines(src, pt1, true, Scalar(255), 3);
fillPoly(src, pt1, Scalar(0, 0, 255));

imshow("dst", src);

Mat src = imread("test.jpg");	
imshow("src", src);

Point root_points[1][5];
root_points[0][0] = Point(93, 146);
root_points[0][1] = Point(243, 57);
root_points[0][2] = Point(290, 190);
root_points[0][3] = Point(239, 259);
root_points[0][4] = Point(155, 240);

const Point* ppt[1] = { root_points[0] };
int npt[] = { 5 };
polylines(src, ppt, npt, 1, 1, Scalar(0, 255, 0), 3);
imshow("poly", src);

Mat mask, dst;
src.copyTo(mask);
mask.setTo(Scalar::all(0));

fillPoly(mask, ppt, npt, 1, Scalar(255, 255, 255));
imshow("mask", mask);

src.copyTo(dst, mask);
imshow("dst", dst);

#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

using namespace std;
using namespace cv;

Mat src, img1, mask, final;

Point point;
vector<Point> pts;

int drag = 0;
int var = 0;
int flag = 0;

void mouseHandler(int, int, int, int, void*);

void mouseHandler(int event, int x, int y, int, void*)
{
    // 左键按下
    if (event == EVENT_LBUTTONDOWN && !drag)
    {
        if (flag == 0)  // 标记是否生成掩码
        {
            // 第一次进入备份原图像
            if (var == 0) 
                img1 = src.clone();

            // 记录当前左键按下的点
            point = Point(x, y);

            // 在图像上将这个点用圆绘制出来,实心圆
            circle(img1, point, 2, Scalar(0, 0, 255), -1, 8, 0);
    
            // 点入vector
            pts.push_back(point);

            // 点的数量加1
            var++;

            // 表示已经有了一个点了
            drag = 1;  
            
            // 如果点的数量大于1,则绘制上一个点于当前点的直线
            if (var > 1)
                line(img1, pts[var - 2], point, Scalar(0, 0, 255), 2, 8, 0);

            // 刷新图像
            imshow("Source", img1);
        }
    }

    // 左键松起
    if (event == EVENT_LBUTTONUP && drag)
    {
        // 显示图像
        imshow("Source", img1);

        drag = 0;
    }
    // 右键按下
    if (event == EVENT_RBUTTONDOWN)
    {
        // 表示右键
        flag = 1;

        // 备份图像
        img1 = src.clone();

        // 如果左键点击的得到的点数不为0,则绘制多边形
        if (var != 0)
        {
            polylines(img1, pts, 1, Scalar(0, 0, 0), 2, 8, 0);
        }

        // 显示图像
        imshow("Source", img1);
    }

    // 右键松起
    if (event == EVENT_RBUTTONUP)
    {
        flag = var;

        // 创建全为0的彩色图像
        final = Mat::zeros(src.size(), CV_8UC3);

        // 创建掩码图像
        mask = Mat::zeros(src.size(), CV_8UC1);

        vector<vector<Point> > vpts;

        // 如果点集为孔,则什么都不做
        if (pts.size() == 0)
        {
            return;
        }
        vpts.push_back(pts);

        // 用白色填充多边形(掩码图像)
        fillPoly(mask, vpts, Scalar(255, 255, 255), 8, 0);

        // 对原图像每一个像素进行与操作,使用mask掩码
        bitwise_and(src, src, final, mask);

        // 显示掩码图像
        imshow("Mask", mask);

        // 显示结果图像
        imshow("Result", final);

        // 显示原图像
        imshow("Source", img1);
    }

    // 指示按下鼠标中间按钮,清除所有标记
    if (event == EVENT_MBUTTONDOWN)
    {
        pts.clear();
        var = 0;
        drag = 0;
        flag = 0;
        imshow("Source", src);
    }
}
int main(int argc, char **argv)
{
    // 载入图像
    src = imread("lena.png");

    // 图像是否为孔
    if (src.empty())
    {
        printf("Error open image !\n");
        return 0;
    }

    // 创建窗口
    namedWindow("Source", WINDOW_AUTOSIZE);

    // 调用鼠标回调函数
    setMouseCallback("Source", mouseHandler, NULL);

    // 显示图像
    imshow("Source", src);

    waitKey(0);
    return 0;
}

参考:

https://www.jianshu.com/p/4bd302ff91a3

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值