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

末尾註:以上爲作者學習過程中自己認識的記錄,如有問題,敬請指正。

發佈了8 篇原創文章 · 獲贊 1 · 訪問量 1418
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章