- 操作系統:ubuntu22.04
- OpenCV版本:OpenCV4.9
- IDE:Visual Studio Code
- 編程語言:C++11
功能描述
? ? ? ? ffloodFill函數是OpenCV庫中用于圖像處理的一個功能,它用于填充與種子點顏色相近的連通區域。這個函數在很多場景下都非常有用,比如圖像分割、對象填充或改變圖像中某個區域的顏色等。
? ? ? ? 連通性的判斷基于鄰近像素的顏色或亮度接近程度。如果像素位于(x,y)處被認為屬于要重新上色的連通域,需滿足以下條件:
- 對于灰度圖像和浮動范圍的情況:
src ( x ′ , y ′ ) ? loDiff ≤ src ( x , y ) ≤ src ( x ′ , y ′ ) + upDiff \texttt{src} (x',y')- \texttt{loDiff} \leq \texttt{src} (x,y) \leq \texttt{src} (x',y')+ \texttt{upDiff} src(x′,y′)?loDiff≤src(x,y)≤src(x′,y′)+upDiff - 對于灰度圖像和固定范圍的情況:
src ( seedPoint . x , seedPoint . y ) ? loDiff ≤ src ( x , y ) ≤ src ( seedPoint . x , seedPoint . y ) + upDiff \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)- \texttt{loDiff} \leq \texttt{src} (x,y) \leq \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)+ \texttt{upDiff} src(seedPoint.x,seedPoint.y)?loDiff≤src(x,y)≤src(seedPoint.x,seedPoint.y)+upDiff - 對于彩色圖像和浮動范圍的情況:
src ( x ′ , y ′ ) r ? loDiff r ≤ src ( x , y ) r ≤ src ( x ′ , y ′ ) r + upDiff r , \texttt{src} (x',y')_r- \texttt{loDiff} _r \leq \texttt{src} (x,y)_r \leq \texttt{src} (x',y')_r+ \texttt{upDiff} _r, src(x′,y′)r??loDiffr?≤src(x,y)r?≤src(x′,y′)r?+upDiffr?, src ( x ′ , y ′ ) g ? loDiff g ≤ src ( x , y ) g ≤ src ( x ′ , y ′ ) g + upDiff g \texttt{src} (x',y')_g- \texttt{loDiff} _g \leq \texttt{src} (x,y)_g \leq \texttt{src} (x',y')_g+ \texttt{upDiff} _g src(x′,y′)g??loDiffg?≤src(x,y)g?≤src(x′,y′)g?+upDiffg?
并且:
src ( x ′ , y ′ ) b ? loDiff b ≤ src ( x , y ) b ≤ src ( x ′ , y ′ ) b + upDiff b \texttt{src} (x',y')_b- \texttt{loDiff} _b \leq \texttt{src} (x,y)_b \leq \texttt{src} (x',y')_b+ \texttt{upDiff} _b src(x′,y′)b??loDiffb?≤src(x,y)b?≤src(x′,y′)b?+upDiffb? - 對于彩色圖像和固定范圍的情況:
src ( seedPoint . x , seedPoint . y ) r ? loDiff r ≤ src ( x , y ) r ≤ src ( seedPoint . x , seedPoint . y ) r + upDiff r , \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_r- \texttt{loDiff} _r \leq \texttt{src} (x,y)_r \leq \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_r+ \texttt{upDiff} _r, src(seedPoint.x,seedPoint.y)r??loDiffr?≤src(x,y)r?≤src(seedPoint.x,seedPoint.y)r?+upDiffr?, src ( seedPoint . x , seedPoint . y ) g ? loDiff g ≤ src ( x , y ) g ≤ src ( seedPoint . x , seedPoint . y ) g + upDiff g \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_g- \texttt{loDiff} _g \leq \texttt{src} (x,y)_g \leq \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_g+ \texttt{upDiff} _g src(seedPoint.x,seedPoint.y)g??loDiffg?≤src(x,y)g?≤src(seedPoint.x,seedPoint.y)g?+upDiffg?
并且:
src ( seedPoint . x , seedPoint . y ) b ? loDiff b ≤ src ( x , y ) b ≤ src ( seedPoint . x , seedPoint . y ) b + upDiff b \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_b- \texttt{loDiff} _b \leq \texttt{src} (x,y)_b \leq \texttt{src} ( \texttt{seedPoint} .x, \texttt{seedPoint} .y)_b+ \texttt{upDiff} _b src(seedPoint.x,seedPoint.y)b??loDiffb?≤src(x,y)b?≤src(seedPoint.x,seedPoint.y)b?+upDiffb?
其中 s r c ( x ′ , y ′ ) src(x',y') src(x′,y′)是已經被判定屬于該連通組件的某個鄰居像素的值。要被添加到連通組件中,像素的顏色或亮度應該足夠接近: - 如果使用浮動范圍,它應該接近其一個已經屬于連通組件的鄰居的顏色或亮度。
- 如果使用固定范圍,它應該接近種子點的顏色或亮度。
這些函數可用于以下操作:
- 直接在原圖上用指定的顏色標記一個連通組件。
- 構建一個掩模,然后提取輪廓。
- 復制區域到另一個圖像,等等。
函數原型1
int cv::floodFill
(InputOutputArray image,InputOutputArray mask,Point seedPoint,Scalar newVal,Rect * rect = 0,Scalar loDiff = Scalar(),Scalar upDiff = Scalar(),int flags = 4
)
參數1
- 參數image:輸入/輸出的1-或3-通道、8位或浮點圖像。除非在函數的第二個變體中設置了FLOODFILL_MASK_ONLY標志,否則該圖像將被函數修改。詳情請見下方說明。
- 參數mask:操作掩模,應當是一個比圖像寬2像素、高2像素的單通道8位圖像。如果傳遞空的Mat對象,它將被自動創建。由于這是一個輸入和輸出參數,你必須負責初始化它。洪水填充不會跨越輸入掩模中非零像素。例如,邊緣檢測的輸出可以用作掩模,以在邊緣處停止填充。輸出時,掩模中對應于圖像中填充像素的像素將被設置為1或在flags中指定的值,如下文所述。此外,函數會在掩模的邊界填充1,以簡化內部處理。因此,可以在多次調用函數時使用同一掩模,以確保填充的區域不會重疊。
- 參數seedPoint:填充的起始點。
- 參數newVal:重繪區域像素的新值。
- 參數loDiff:當前觀察像素與其屬于同一連通組件的鄰居像素,或加入連通組件的種子像素之間的最大下限亮度/顏色差異。
- 參數upDiff:當前觀察像素與其屬于同一連通組件的鄰居像素,或加入連通組件的種子像素之間的最大上限亮度/顏色差異。
- 參數rect:可選的輸出參數,由函數設置為重繪區域的最小邊界矩形。
- 參數flags:操作標志。前8位包含連通性值。默認值4意味著僅考慮四個最近鄰像素(那些共享邊緣的像素)。連通性值8意味著將考慮八個最近鄰像素(那些共享角落的像素)。接下來的8位(8-16位)包含一個1到255之間的值,用于填充掩模(默認值是1)。例如,4 | ( 255 << 8 )將考慮四個最近鄰并用255填充掩模。以下附加選項占據更高位,因此可以使用按位或(|)與連通性和掩模填充值進一步組合,請參閱FloodFillFlags。
注釋:
???????由于掩模比填充的圖像大,圖像中的像素(x,y)對應于掩模中的像素(x+1,y+1)。
另見:
findContours:查找輪廓的函數。
函數原型2
int cv::floodFill
(InputOutputArray image,Point seedPoint,Scalar newVal,Rect * rect = 0,Scalar loDiff = Scalar(),Scalar upDiff = Scalar(),int flags = 4
)
參數2
比原型1少了個mask參數,其他參數都一樣。
代碼示例
include <iostream>
#include <opencv2/opencv.hpp>int main()
{cv::Mat img = cv::imread( "/media/dingxin/data/study/OpenCV/sources/images/hawk.jpg" );if ( img.empty() ){std::cout << "Could not read the image" << std::endl;return -1;}cv::Point seedPoint( 359, 578 ); // 假設種子點為(359, 578)cv::Scalar newVal( 255, 0, 0 ); // 新的顏色值為藍色cv::Rect roi;int flags = 8;// 進行填充cv::floodFill( img, seedPoint, newVal, &roi, cv::Scalar( 1, 1, 1 ), cv::Scalar( 40, 40, 40 ), 8 );// 顯示結果cv::imshow( "Flood Fill Result", img );cv::waitKey();return 0;
}
運行結果
原圖:
運算之后的圖:
藍色部分就是填充的部分,參數loDiff為Scalar(1, 1, 1),upDiff為Scalar(40, 40, 40),表示當前觀測點的像素X與周圍已被填充的像素點數值Y,需滿足X-Y<10,且Y-X<1,才被填充。