目錄
第6章? 圖像分割
6.1?Grabcut實(shí)現(xiàn)
6.1.1 定義前景和背景
6.1.2???cv::grabCut()
6.1.3?cv::compare()
6.1.4 算法實(shí)現(xiàn)
???????
Github代碼地址:GitHub - Qinong/OpenCV
第6章? 圖像分割
????????Opencv提供了一種常用的圖像分割算法Grabcut。Grabcut算法比較復(fù)雜,計算量也很大,但有很高的精確度。
6.1?Grabcut實(shí)現(xiàn)
6.1.1 定義前景和背景
????????cv::grabCut函數(shù)的用法非常簡單,只需要在輸入圖像做上 “屬于背景”或“屬于前最” 的標(biāo)記即可。根據(jù)這個局部標(biāo)記,算法將計算出整幅圖像的前景/背景分割線。
? ? ? ? 可以通過定義矩形指定輸人圖像局部前景/背景標(biāo)簽的。
// 定義一個帶邊框的矩形
// 矩形外部的像素會被標(biāo)記為背景
cv::Rect rectangle(100,120,650,350);
?
6.1.2???cv::grabCut()
????????GrabCut算法的工作原理是:參考文章
接受輸入圖像與任一(1)的邊界框,我們想段或(2)所涉及的圖像中指定的對象的位置掩模即近似分割
?
? ? ? ? 反復(fù)執(zhí)行以下步驟:
? ? ? ? 步驟1:通過高斯混合模型(GMM)估算前景和背景的顏色分布
? ? ? ? 步驟2:在像素標(biāo)簽上構(gòu)造一個馬爾可夫隨機(jī)場(即,前景與背景)
? ? ? ? 步驟3:應(yīng)用圖割優(yōu)化以進(jìn)行最終細(xì)分
? ? ? ? ?GrabCut是Graph Cut的改進(jìn)版,是迭代的Graph Cut。OpenCV中的GrabCut算法是依據(jù)《"GrabCut" - Interactive Foreground Extraction using Iterated Graph Cuts》這篇文章來實(shí)現(xiàn)的。該算法利用了圖像中的紋理(顏色)信息和邊界(反差)信息,只要少量的用戶交互操作即可得到比較好的分割結(jié)果。與Graph cut指定兩個頂點(diǎn)不同,grabcut只需指定一個粗略的能將目標(biāo)框住的邊框就可以完成良好的分割。
? ? ? ? 雖然神經(jīng)網(wǎng)絡(luò)的分割已經(jīng)占據(jù)了主流,但是再很多情況下并不需要如此大力氣的訓(xùn)練,所以GrabCut也是可選項(xiàng)之一。
void grabCut( InputArray img,
InputOutputArray mask,
Rect rect, ? ? ? ? ? ? ? ? ? ? ? ?
InputOutputArray bgdModel,
InputOutputArray fgdModel,
int iterCount,
int mode = GC_EVAL );
- img:輸入圖像
- mask:得到掩碼矩陣,其值為以下四種
? ? ? ? ? ? ?cv::GC_BGD ?== 0//表示是背景
? ? ? ? ? ? ?cv::GC_FGD ?== 1//表示是前景
? ? ? ? ? ? ? cv::GC_PR_BGD ?== 2//表示可能是背景
? ? ? ? ? ? ? cv::GC_PR_FGD ?== 3//表示可能是前景
- rect:指定的包含目標(biāo)對象的矩陣
- bdgModel:背景模型,如果為null,函數(shù)內(nèi)部會自動創(chuàng)建一個bgdModel;bgdModel必須是單通道浮點(diǎn)型(CV_32FC1)圖像,且行數(shù)只能為1,列數(shù)只能為13*5
- fgdModel:前景模型,如果為null,函數(shù)內(nèi)部會自動創(chuàng)建一個fgdModel;fgdModel必須是單通道浮點(diǎn)型(CV_32FC1)圖像,且行數(shù)只能為1,列數(shù)只能為13x5;(bgdModel , fgdModel可以在 cv::GC_INIT_WITH_MASK下使用,可以在以往迭代的基礎(chǔ)上用它們保存的信息繼續(xù)迭代)
- iterCount:指定迭代次數(shù)
- mode:有三個值可用
? ? ? ? ? cv::GC_INIT_WITH_RECT//用矩陣初始化grabCut
? ? ? ? ? cv::GC_INIT_WITH_MASK//用掩碼初始化grabCut
? ? ? ? ? cv::GC_EVAL//執(zhí)行分割
6.1.3?cv::compare()
????????cv::compare()主要用于兩個圖像之間進(jìn)行逐像素的比較,并輸出比較的結(jié)果。具體用法如下:
bool cv::compare(cv::InputArray src1, // 輸入數(shù)組1
?? ? cv::InputArray src2, // 輸入數(shù)組2
?? ? cv::OutputArray dst, // 輸出數(shù)組
?? ?int cmpop // 比較操作子,見注釋?
- ? ? cmpop:比較操作子
? ? ? ? cv::CMP_EQ ? ?src==src1
? ? ? ? cv::CMP_GT ? ?src>src1
? ? ? ? cv::CMP_GE ? ?src>=src1
? ? ? ? cv::CMP_LT ? ?src<src1
? ? ? ? cv::CMP_LE ? ?src<=src1
? ? ? ? cv::CMP_NE ? ?src!=src1
6.1.4 算法實(shí)現(xiàn)
int main()
{
cv::Mat image= cv::imread("Ferrar_F8.png");
if (!image.data)
return 0;
cv::namedWindow("Image");
cv::imshow("Image",image);
// 定義邊框矩形
cv::Rect rectangle(100,120,650,350);
// 定義前景、背景和分割結(jié)果
cv::Mat bgModel,fgModel,result;
// GrabCut分割
cv::grabCut(image,
result,
rectangle,
bgModel,
fgModel,
5,
cv::GC_INIT_WITH_RECT); // use rectangle
// 標(biāo)記可能屬于前景的區(qū)域
cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);
// or:
// result= result&1;
// 創(chuàng)建前景圖像
cv::Mat foreground(image.size(), CV_8UC3, cv::Scalar(255, 255, 255));
image.copyTo(foreground,result); // 復(fù)制前景圖像
// 在原圖像繪制矩形區(qū)域
cv::rectangle(image, rectangle, cv::Scalar(200,0,200),4);
cv::namedWindow("Rectangle");
cv::imshow("Rectangle",image);
cv::namedWindow("Foreground");
cv::imshow("Foreground",foreground);
cv::waitKey();
return 0;
}
文章來源:http://www.zghlxwxcb.cn/news/detail-726920.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-726920.html
到了這里,關(guān)于OpenCV - C++實(shí)戰(zhàn)(06) — Grabcut圖像分割的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!