日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV学习笔记(九): 漫水填充:floodFill()

發布時間:2024/7/23 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV学习笔记(九): 漫水填充:floodFill() 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OpenCV學習筆記(九): 漫水填充:floodFill()

定義:
漫水填充法是一種用特定的顏色填充聯通區域(自動選中了和種子點相連的區域,接著將該區域替換成指定的顏色)通過設置可連通像素的上下限以及連通方式來達到不同的填充效果的方法。
使用:
1)經常被用來標記或分離圖像的一部分,以便對其進行進一步處理或分析。
2)從輸入圖像獲取掩碼區域(掩碼會加速處理過程,或只處理掩碼指定的像素點,操作的結果總是某個連續的區域)
算子:

int floodFill( InputOutputArray image, // 1.輸入/輸出圖像 InputOutputArray mask, // 2.這是第二個版本的floodFill獨享的參數,表示操作掩模(它應該為單通道、8位、長和寬上都比輸入圖像 image 大兩個像素點的圖像) Point seedPoint, // 3.漫水填充算法的起始點 Scalar newVal, // 4.在重繪區域像素點被染色的新值 Rect* rect=0, // 5.一個可選的參數,將要重繪區域的最小邊界矩形區域 Scalar loDiff=Scalar(), // 6.loDiff 負差最大值(當前像素與領域像素或種子像素顏色或亮度的) Scalar upDiff=Scalar(), // 7.upDiff 正差最大值(當前像素與領域像素或種子像素顏色或亮度的) int flags=4 // 8.操作標志符 )

// PS:
1、漫水填充不會填充掩膜mask的非零像素區域。例如,一個邊緣檢測算子的輸出可以用來作為掩膜,以防止填充到邊緣。同樣的,也可以在多次的函數調用中使用同一個掩膜,以保證填充的區域不會重疊。另外需要注意的是,
掩膜mask會比需填充的圖像大,所以 mask 中與輸入圖像(x,y)像素點相對應的點的坐標為(x+1,y+1)。
2、
1)低八位(第0~7位)用于控制算法的連通性,可取4 (4為缺省值) 或者 8。

如果設為4,表示填充算法只考慮當前像素水平方向和垂直方向的相鄰點; 如果設為 8,除上述相鄰點外,還會包含對角線方向的相鄰點。

2)高八位部分(16~23位)可以為0 或者如下兩種選項標識符的組合:

FLOODFILL_FIXED_RANGE - 如果設置為這個標識符的話,就會考慮當前像素與種子像素之間的差, 否則就考慮當前像素與其相鄰像素的差。也就是說,這個范圍是浮動的。 FLOODFILL_MASK_ONLY - 如果設置為這個標識符的話,函數不會去填充改變原始圖像 (也就是忽略第三個參數newVal), 而是去填充掩模圖像(mask)。

3)中間八位部分,上面關于高八位FLOODFILL_MASK_ONLY標識符中已經說的很明顯,需要輸入符合要求的掩碼。Floodfill的flags參數的中間八位的值就是用于指定填充掩碼圖像的值的。但如果flags中間八位的值為0,則掩碼會用1來填充。

//如果想用8鄰域填充,并填充固定像素值范圍,填充掩碼而不是填充源圖像,以及設填充值為38 flags=8 | FLOODFILL_MASK_ONLY | FLOODFILL_FIXED_RANGE |38<<8

示例代碼:

#include <opencv2/opencv.hpp>using namespace cv; using namespace std;Mat g_srcImage, g_dstImage, g_grayImage, g_maskImage; //定義原始圖、目標圖、灰度圖、掩模圖 int g_nFillMode = 1; //漫水填充的模式 int g_nLowDifference = 20, g_nUpDifference = 20; //負差最大值、正差最大值 int g_nConnectivity = 4; //表示floodFill函數標識符低八位的連通值 bool g_bIsColor = true; //是否為彩色圖的標識 bool g_bUseMask = false; //是否顯示掩膜窗口的標識 int g_nNewMaskVal = 255; //新的重新繪制的像素值int main() {//顯示幫助文字ShowHelpText();// 1、載入原圖g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/2.jpg", 1);if( !g_srcImage.data ){printf("讀取圖片image0錯誤~! \n");return false;}// 2、拷貝源圖到目標圖g_srcImage.copyTo(g_dstImage);// 3、轉換三通道的image0到灰度圖cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);// 4、利用image0的尺寸來初始化掩膜maskg_maskImage.create(g_srcImage.rows+2, g_srcImage.cols+2, CV_8UC1);// 5、創建TrackbarnamedWindow( "效果圖",WINDOW_AUTOSIZE );createTrackbar( "負差最大值", "效果圖", &g_nLowDifference, 255, 0 ); // 無滑動條事件,只改變滑動條值(0~255)createTrackbar( "正差最大值" ,"效果圖", &g_nUpDifference, 255, 0 ); // 無滑動條事件,只改變滑動條值(0~255)// 6、鼠標回調函數(鼠標點擊便觸發)// 將mask所有元素設置為0(背景設為黑色)g_maskImage = Scalar::all(0); setMouseCallback( "效果圖", onMouse, 0 );// 7、循環輪詢按鍵while(1){//先顯示效果圖imshow("效果圖", g_bIsColor ? g_dstImage : g_grayImage);//獲取鍵盤按鍵int c = waitKey(0);//判斷ESC是否按下,若按下便退出if( (c & 255) == 27 ){cout << "程序退出...........\n";break;}//根據按鍵的不同,進行各種操作switch( (char)c ){//如果鍵盤“1”被按下,效果圖在在灰度圖,彩色圖之間互換case '1':if( g_bIsColor )//若原來為彩色,轉為灰度圖,并且將掩膜mask所有元素設置為0{cout << "鍵盤“1”被按下,切換彩色/灰度模式,當前操作為將【彩色模式】切換為【灰度模式】\n";cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);g_maskImage = Scalar::all(0); //將mask所有元素設置為0g_bIsColor = false; //將標識符置為false,表示當前圖像不為彩色,而是灰度}else//若原來為灰度圖,便將原來的彩圖image0再次拷貝給image,并且將掩膜mask所有元素設置為0{cout << "鍵盤“1”被按下,切換彩色/灰度模式,當前操作為將【彩色模式】切換為【灰度模式】\n";g_srcImage.copyTo(g_dstImage);g_maskImage = Scalar::all(0);g_bIsColor = true; //將標識符置為true,表示當前圖像模式為彩色}break;//如果鍵盤按鍵“2”被按下,顯示/隱藏掩膜窗口case '2':if( g_bUseMask ){destroyWindow( "mask" );g_bUseMask = false;}else{namedWindow( "mask", 0 );//g_maskImage = Scalar::all(0); // 清空置零imshow("mask", g_maskImage);g_bUseMask = true;}break;//如果鍵盤按鍵“3”被按下,恢復原始圖像case '3':cout << "按鍵“3”被按下,恢復原始圖像\n";g_srcImage.copyTo(g_dstImage);cvtColor(g_dstImage, g_grayImage, COLOR_BGR2GRAY);g_maskImage = Scalar::all(0);break;// 改變”漫水填充“操作標識:// 1、如果鍵盤按鍵“4”被按下,使用空范圍的漫水填充case '4':cout << "按鍵“4”被按下,使用空范圍的漫水填充\n";g_nFillMode = 0;break;// 2、如果鍵盤按鍵“5”被按下,使用漸變、固定范圍的漫水填充case '5':cout << "按鍵“5”被按下,使用漸變、固定范圍的漫水填充\n";g_nFillMode = 1;break;// 3、如果鍵盤按鍵“6”被按下,使用漸變、浮動范圍的漫水填充case '6':cout << "按鍵“6”被按下,使用漸變、浮動范圍的漫水填充\n";g_nFillMode = 2;break;// 4、如果鍵盤按鍵“7”被按下,操作標志符的低八位使用4位的連接模式case '7':cout << "按鍵“7”被按下,操作標志符的低八位使用4位的連接模式\n";g_nConnectivity = 4;break;// 5、如果鍵盤按鍵“8”被按下,操作標志符的低八位使用8位的連接模式case '8':cout << "按鍵“8”被按下,操作標志符的低八位使用8位的連接模式\n";g_nConnectivity = 8;break;}} }

輸出一些幫助信息

static void ShowHelpText() {printf("\n\n\t漫水填充示例程序~");printf("\n\n\t根據鼠標選取的點搜索圖像中與之顏色相近的點,并用不同顏色標注。");printf("\n\n\t按鍵操作說明: \n\n""\t\t鼠標點擊圖中區域- 進行漫水填充操作\n""\t\t鍵盤按鍵【ESC】- 退出程序\n""\t\t鍵盤按鍵【1】- 切換彩色圖/灰度圖模式\n""\t\t鍵盤按鍵【2】- 顯示/隱藏掩膜窗口\n""\t\t鍵盤按鍵【3】- 恢復原始圖像\n""\t\t鍵盤按鍵【4】- 使用空范圍的漫水填充\n""\t\t鍵盤按鍵【5】- 使用漸變、固定范圍的漫水填充\n""\t\t鍵盤按鍵【6】- 使用漸變、浮動范圍的漫水填充\n""\t\t鍵盤按鍵【7】- 操作標志符的低八位使用4位的連接模式\n""\t\t鍵盤按鍵【8】- 操作標志符的低八位使用8位的連接模式\n\n"); }

鼠標消息onMouse回調

static void onMouse(int event, int x, int y, int, void*) {if (event != EVENT_LBUTTONDOWN)return;// 1、調用floodFill函數之前的參數準備部分Point seed = Point(x, y); // 鼠標點擊獲取起始點位置int LowDifference = g_nFillMode == 0 ? 0 : g_nLowDifference; //空范圍的漫水填充,此值設為0,否則設為全局的g_nLowDifferenceint UpDifference = g_nFillMode == 0 ? 0 : g_nUpDifference; //空范圍的漫水填充,此值設為0,否則設為全局的g_nUpDifference// 1.1、floodFill()函數第八個參數值:flags=低八位+中八位+高八位int flags = g_nConnectivity + (g_nNewMaskVal << 8) + (g_nFillMode == 1 ? FLOODFILL_FIXED_RANGE : 0); // FLOODFILL_FIXED_RANGE// 1.2、隨機生成bgr值int b = (unsigned)theRNG() & 255;//隨機返回一個0~255之間的值int g = (unsigned)theRNG() & 255;//隨機返回一個0~255之間的值int r = (unsigned)theRNG() & 255;//隨機返回一個0~255之間的值Rect ccomp;//定義重繪區域的最小邊界矩形區域// 1.3、在重繪區域像素的新值,若是彩色圖模式,取Scalar(b, g, r);若是灰度圖模式,取Scalar(r*0.299 + g*0.587 + b*0.114)Scalar newVal = g_bIsColor ? Scalar(b, g, r) : Scalar(r*0.299 + g*0.587 + b*0.114);Mat dst = g_bIsColor ? g_dstImage : g_grayImage;//目標圖的賦值// 2、正式調用floodFill函數threshold(g_maskImage, g_maskImage, 1, 128, THRESH_BINARY);// 帶掩碼輸出的 floodFill()int area = floodFill(dst, g_maskImage, seed, newVal, &ccomp, Scalar(LowDifference, LowDifference, LowDifference),Scalar(UpDifference, UpDifference, UpDifference), flags);// 3、關閉或顯示掩碼窗口if (g_bUseMask){imshow("mask", g_maskImage);} // else // { // // 不帶掩碼輸出的 floodFill() // area = floodFill(dst, seed, newVal, &ccomp, Scalar(LowDifference, LowDifference, LowDifference), // Scalar(UpDifference, UpDifference, UpDifference), flags); // }imshow("效果圖", dst);cout << area << " 個像素被重繪\n"; }

結果:

總結

以上是生活随笔為你收集整理的OpenCV学习笔记(九): 漫水填充:floodFill()的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。