OpenCV3.4.0学习笔记(四)——cv::Mat掩膜操作与多边形roi区域的提取

cv::Mat掩膜操作与多边形roi区域的提取

关于 cv::Mat 的矩形roi,特定行、列的访问已经在之前的博客中有所记录。本篇博文则用于记录 cv::Mat 掩膜操作的学习心得,并附上一种基于掩膜操作的多边形roi区域提取方法。

cv::Mat 的掩膜操作(mask)

对与 cv::Mat 中不规则区域的访问,除了指针+循环的基本访问方式外,opencv还提供了常用的掩膜操作。这里先介绍cv::Mat常用的两个掩膜操作方法:

//函数声明
void cv::Mat::setTo(InputArray value, InputArray mask=noArray());
void cv::Mat::copyTo(inputArray array, InputArray mask=noArray()) const;

其中,成员函数 setTo 将当前cv::Mat对象中mask对应的值改为value。
而成员函数 copyTo 则是将当前cv::Mat对象中mask对应的值复制到array对象中。

需要注意:

  1. mask.type()一般为CV_8U型,mask.size()必须与当前对象的size一致。
  2. mask在执行过程中被二值化,mask非0像素标志着该点为目标点。相应,mask的0像素点则代表着非目标点。

多边形roi区域的提取

这里提供一种基于 cv::Mat::copyTo 方法的多边形roi区域提取。

提取多边形roi的关键在于生成目标区域的mask,而opencv提供了绘制实心多边形函数:

void fillPoly(InputOutputArray img, //被绘制的图片
	InputArrayOfArrays pts, //多边形角点点列,一般为vector<vector<Point>>
	const Scalar& color,  //绘制的实心多边形颜色
	int lineType = LINE_8, //绘制边缘类型
	int shift = 0, //坐标精度(小数点后位数)
	Point offset = Point() //角点坐标总体偏移
);

利用 fillPoly+copyTo 获取多边形roi的方法如下:

std::vector<std::vector<cv::Point>> cornerList; 
//可以绘制一次绘制多个实心多边形,若只需要绘制一个,仅赋值cornerList[0]
initial(cornerList); //求解出需要多边形的角点坐标

//srcImg为需要提取roi的目标图像
cv::Mat mask = cv::Mat::zeros(srcImg.size(), CV_8UC1); 

//生成多边形mask
//生成多边形为实心多边形。非实心多边形参见polylines
cv::fillPoly(mask, cornerList, cv::Scalar(255));

//掩膜操作提取多边形roi到desImg
srcImg.copyTo(desImg, mask);

可以看到,提取非矩形roi的关键在于生成目标目标roi的mask。而多边形可以拟合任何一种形状。而对于非简单图形(如中间有孔洞,不连通等),也可以通过多边形mask的 &、|、~ 操作进行拟合。

以下提供几种常用的非矩形mask生成时可以用到的函数:

//绘制实心目标时,一般将thickness设为-1即可
//圆形
void cv::circle(InputOutputArray img, //绘制的图形,用于提取roi时为mask
	cv::Point center, //圆心
	int radius, //半径
	const cv::Scalar& color, //绘制边界的颜色
	int thickness = 1,  //绘制线段的粗细程度
	int lineType = LINE_8,  //绘制线段的类型
	int shift = 0  //坐标精度(小数点后位数)
	)
//椭圆
void cv::ellipse(InputOutputArray img, //绘制的图形,用于提取roi时为mask
 cv::Point center, //椭圆中心
 cv::Size axes, //半长轴a * 半短轴b
 double angle, //椭圆旋转角度
 double startAngle, //绘制椭圆的起始角度,若绘制全椭圆,此为0
 double endAngle, //绘制椭圆的终止角度,若绘制全椭圆,此为360
 const cv::Scalar& color,  //绘制边界的颜色
 int thickness = 1,  //绘制线段的粗细程度
 int lineType = LINE_8,  //绘制线段的类型
 int shift = 0  //坐标精度(小数点后位数)
 )
//绘制全椭圆时还有更简单的,利用RotatedRect代表椭圆的重载函数,
//参考opencv document

末尾注:以上为作者学习过程中自己认识的记录,如有问题,敬请指正。

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值