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對象中。
需要注意:
- mask.type()一般爲CV_8U型,mask.size()必須與當前對象的size一致。
- 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