OpenCV (iOS)中的漫水填充(12)

一個蘿蔔壹個坑發表於2018-01-03

漫水填充的定義

漫水填充是一種用特定的顏色填充連通區域,通過設定可連通畫素的上下限以及連通方式達到不同的填充效果的方法。漫水填充經常用來標記或者是分離影象的一部分,以便對其進行進一步處理貨分析,也可以用來從輸入影象獲取掩碼區域,掩碼會加速處理過程,或者只處理指定的畫素點,操作的結果總是某個連續的區域。

實現漫水填充演算法:floodFill函式

foodFill函式有兩個版本,一個不帶掩碼的mask的版本,一個是帶有mask的版本

第一個版本

floodFill( InputOutputArray image,

               Point seedPoint, 

               Scalar newVal, 

               CV_OUT Rect* rect = 0,

               Scalar loDiff = Scalar(), 

               Scalar upDiff = Scalar(),

               int flags = 4 

               );

第二個版本

floodFill( InputOutputArray image, 

              InputOutputArray mask,

              Point seedPoint,

               Scalar newVal,

               CV_OUT Rect* rect=0,

                Scalar loDiff = Scalar(),

                Scalar upDiff = Scalar(),

                int flags = 4 

            );

第一個引數,InputOutputArray型別的image, 輸入/輸出1通道或3通道,8位或浮點影象,具體引數由之後的引數具體指明。

第二個引數, InputOutputArray型別的mask,這是第二個版本的floodFill獨享的引數,表示操作掩模,。它應該為單通道、8位、長和寬上都比輸入影象 image 大兩個畫素點的影象。第二個版本的floodFill需要使用以及更新掩膜,所以這個mask引數我們一定要將其準備好並填在此處。需要注意的是,漫水填充不會填充掩膜mask的非零畫素區域。例如,一個邊緣檢測運算元的輸出可以用來作為掩膜,以防止填充到邊緣。同樣的,也可以在多次的函式呼叫中使用同一個掩膜,以保證填充的區域不會重疊。另外需要注意的是,掩膜mask會比需填充的影象大,所以 mask 中與輸入影象(x,y)畫素點相對應的點的座標為(x+1,y+1)。

第三個引數,Point型別的seedPoint,漫水填充演算法的起始點。

第四個引數,Scalar型別的newVal,畫素點被染色的值,即在重繪區域畫素的新值。

第五個引數,Rect*型別的rect,有預設值0,一個可選的引數,用於設定floodFill函式將要重繪區域的最小邊界矩形區域。

第六個引數,Scalar型別的loDiff,有預設值Scalar( ),表示當前觀察畫素值與其部件鄰域畫素值或者待加入該部件的種子畫素之間的亮度或顏色之負差(lower brightness/color difference)的最大值。

第七個引數,Scalar型別的upDiff,有預設值Scalar( ),表示當前觀察畫素值與其部件鄰域畫素值或者待加入該部件的種子畫素之間的亮度或顏色之正差(lower brightness/color difference)的最大值。

第八個引數,int型別的flags,操作標誌符,此引數包含三個部分,比較複雜,我們一起詳細看看。

低八位(第0~7位)用於控制演算法的連通性,可取4 (4為預設值) 或者 8。如果設為4,表示填充演算法只考慮當前畫素水平方向和垂直方向的相鄰點;如果設為 8,除上述相鄰點外,還會包含對角線方向的相鄰點。

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

FLOODFILL_FIXED_RANGE- 如果設定為這個識別符號的話,就會考慮當前畫素與種子畫素之間的差,否則就考慮當前畫素與其相鄰畫素的差。也就是說,這個範圍是浮動的。

FLOODFILL_MASK_ONLY- 如果設定為這個識別符號的話,函式不會去填充改變原始影象 (也就是忽略第三個引數newVal), 而是去填充掩模影象(mask)。這個識別符號只對第二個版本的floodFill有用,因第一個版本里面壓根就沒有mask引數。

中間八位部分,上面關於高八位FLOODFILL_MASK_ONLY識別符號中已經說的很明顯,需要輸入符合要求的掩碼。Floodfill的flags引數的中間八位的值就是用於指定填充掩碼影象的值的。但如果flags中間八位的值為0,則掩碼會用1來填充。

而所有flags可以用or操作符連線起來,即“|”。例如,如果想用8鄰域填充,並填充固定畫素值範圍,填充掩碼而不是填充源影象,以及設填充值為38,那麼輸入的引數是這樣:

flags=8 | FLOODFILL_MASK_ONLY | FLOODFILL_FIXED_RANGE | (38<<8)

程式碼實現:

NSString *image = @"words.jpg";

UIImage *image1 = [UIImage imageNamed:image];

Mat im;

UIImageToMat(image1, im);

if (im.empty()) {

return;

}

cvtColor(im, dst, CV_BGRA2BGR,3);// 將拿到的圖片轉換為我們能夠使用的圖片,使用floodFill必須是1通道或者是三通道的圖片,這個函式的使用方法參照openCV中顏色空間轉換cvtColor()

cv::Rect ccomp;

cv::floodFill(dst, cv::Point(100,100), Scalar(50,0,150),&ccomp,Scalar(20,20,20),Scalar(20,20,20));

self.secondImageView.image = MatToUIImage(dst);

實現效果


OpenCV (iOS)中的漫水填充(12)

參考資料:

學習程式碼

相關文章