ドキュメント OpenCVのフラッドフィル機能の状態:
この関数はマスクを使用および更新するため、ユーザーはマスクコンテンツを初期化する必要があります。塗りつぶしは、マスク内のゼロ以外のピクセルを超えることはできません。たとえば、エッジ検出器の出力をマスクとして使用して、エッジでの塗りつぶしを停止できます。関数の複数の呼び出しで同じマスクを使用して、塗りつぶされた領域が重ならないようにすることができます。
関数はどのようにマスクを更新しますか?フラッドフィル内のすべてのピクセルをゼロ以外の値に設定しますか?
マスクのシードポイントと同じ接続コンポーネント内のすべてのゼロ値ピクセルは、指定した値に置き換えられます。この値は、8ビット左にシフトされたflags
パラメーターに追加する必要があります。
uchar fillValue = 128;
cv::floodFill(img, mask, seed, cv::Scalar(255) ,0, cv::Scalar(), cv::Scalar(), 4 | cv::FLOODFILL_MASK_ONLY | (fillValue << 8));
簡単ですが、おそらく啓発的な例を次に示します。次のような画像を作成します。
//Create simple input image
cv::Point seed(4,4);
cv::Mat img = cv::Mat::zeros(100,100,CV_8UC1);
cv::circle(img, seed, 20, cv::Scalar(128),3);
この画像の結果:
次に、マスクを作成して塗りつぶします。
//Create a mask from edges in the original image
cv::Mat mask;
cv::Canny(img, mask, 100, 200);
cv::copyMakeBorder(mask, mask, 1, 1, 1, 1, cv::BORDER_REPLICATE);
//Fill mask with value 128
uchar fillValue = 128;
cv::floodFill(img, mask, seed, cv::Scalar(255) ,0, cv::Scalar(), cv::Scalar(), 4 | cv::FLOODFILL_MASK_ONLY | (fillValue << 8));
この結果を与えます:
マスク内の白いピクセルはエッジ検出の結果であり、グレーのピクセルは塗りつぶしの結果です。
PDATE:コメントへの応答で、フラグ値4
は、色値の差を比較するピクセル近傍を指定します。ドキュメントから:
下位ビットには、関数内で使用される接続値4(デフォルト)または8が含まれます。接続性は、ピクセルのどの近傍を考慮するかを決定します。
cv::FLOODFILL_MASK_ONLY
フラグは渡されません。both画像とマスクは更新されますが、塗りつぶしはゼロ以外のマスク値で停止します。
そしてpythonバージョン
im = cv2.imread("seagull.jpg")
h,w,chn = im.shape
seed = (w/2,h/2)
mask = np.zeros((h+2,w+2),np.uint8)
floodflags = 4
floodflags |= cv2.FLOODFILL_MASK_ONLY
floodflags |= (255 << 8)
num,im,mask,rect = cv2.floodFill(im, mask, seed, (255,0,0), (10,)*3, (10,)*3, floodflags)
cv2.imwrite("seagull_flood.png", mask)
(ウィキメディアのシーガル画像: https://commons.wikimedia.org/wiki/Commons:Quality_images#/media/File:Gull_portrait_ca_usa.jpg )
結果:
アウレリウスの答えによると、マスクはゼロにする必要があります。
ソース内のコメントを確認すると、
これは入力パラメーターと出力パラメーターの両方であるため、初期化の責任を負う必要があります。塗りつぶしは、入力マスク内のゼロ以外のピクセルを超えることはできません。
マスクは結果に影響するため、使用する前にゼロにする必要があります。
cv::Mat mask;
mask = cv::Mat::zeros(img.rows + 2, img.cols + 2, CV_8UC1);