关于 cv::Mat 的矩形roi,特定行、列的访问已经在之前的博客中有所记录。本篇博文则用于记录 cv::Mat 掩膜操作的学习心得,并附上一种基于掩膜操作的多边形roi区域提取方法。
对与 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对象中。
需要注意:
这里提供一种基于 cv::Mat::copyTo 方法的多边形roi区域提取。
提取多边形roi的关键在于生成目标区域的mask,而opencv提供了绘制实心多边形函数:
void cv::polylines(InputOutputArray img, //被绘制的图像
InputArrayOfArrays pts, //多段线角点集合,类型可以是
//std::vector
bool isClosed, //所绘制的多段线是否闭合,
const Scalar & color, //所绘制线段的颜色
int thickness = 1, //绘制线段的粗细程度
int lineType = LINE_8, //绘制线段的类型
int hift = 0 //顶点坐标精度(小数点后位数)
)
利用 polylines+copyTo 获取多边形roi的方法如下:
std::vector<cv::Point> cornerList;
initial(cornerList); //求解出需要多边形的角点坐标
//srcImg为需要提取roi的目标图像
cv::Mat mask = cv::Mat::zeros(srcImg.size(), CV_8UC1);
//生成多边形mask
//参数thickness取为-1,则生成的多边形为实心多边形。
cv::polylines(mask, cornerList, true, cv::Scalar(255), -1);
//掩膜操作提取多边形roi到desImg
srcImg.copyTo(desImg, mask);
可以看到,提取非矩形roi的关键在于生成目标目标roi的mask。而多边形可以拟合任何一种形状。而对于非简单图形(如中间有孔洞,不连通等),也可以通过多边形mask的 &、|、~ 操作进行拟合。
以下提供几种常用的非矩形mask生成时可以用到的函数:
//圆形
void cv::circle(InputOutputArray img, //绘制的图形,用于提取roi时为mask
cv::Point center, //圆心
int radius, //半径
const cv::Scalar& color, //绘制边界的颜色
int thickness = 1, //绘制线段的粗细程度
int lineType = LINE_8, //绘制线段的类型
int hift = 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 hift = 0 //坐标精度(小数点后位数)
)
//绘制全椭圆时还有更简单的,利用RotatedRect代表椭圆的重载函数,
//参考opencv document