OpenCV - 如何对 RGB 图像使用 floodFill?

Had*_*had 5 c++ python opencv image-processing flood-fill

我正在尝试使用floodFill像下面这样的图像来提取天空:

在此处输入图片说明

但即使我设置了loDiff=Scalar(0,0,0)upDiff=Scalar(255,255,255)结果也只是显示了种子点并且不会变大(绿点):

在此处输入图片说明

代码:

Mat flood;
Point seed = Point(180, 80);
flood = imread("D:/Project/data/1.jpeg");
cv::floodFill(flood, seed, Scalar(0, 0, 255), NULL, Scalar(0, 0, 0), Scalar(255, 255, 255));
circle(flood, seed, 2, Scalar(0, 255, 0), CV_FILLED, CV_AA);
Run Code Online (Sandbox Code Playgroud)

这是结果(红点是种子):

在此处输入图片说明

如何设置功能以获得更大的区域(如整个天空)?

nat*_*ncy 8

如果您希望洪水填充的轮廓尽可能接近图像中的对比元素,您可以做的另一件事是执行 Kmeans 颜色量化以将图像分割为指定数量的簇。由于天空和山脉/树木有明显的色差,我们可以将图像分割成仅三种颜色,这样可以更好地分离物体。

例如clusters=3

输入图像->Kmeans颜色分割

洪水填埋结果呈绿色

请注意分割后,只有三种颜色定义图像。这样,洪水填充物将更好地沿着山脉/树木轮廓

代码

import cv2
import numpy as np

# Kmeans color segmentation
def kmeans_color_quantization(image, clusters=8, rounds=1):
    h, w = image.shape[:2]
    samples = np.zeros([h*w,3], dtype=np.float32)
    count = 0

    for x in range(h):
        for y in range(w):
            samples[count] = image[x][y]
            count += 1

    compactness, labels, centers = cv2.kmeans(samples,
            clusters, 
            None,
            (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10000, 0.0001), 
            rounds, 
            cv2.KMEANS_RANDOM_CENTERS)

    centers = np.uint8(centers)
    res = centers[labels.flatten()]
    return res.reshape((image.shape))

# Load image and perform kmeans
image = cv2.imread('1.jpg')
kmeans = kmeans_color_quantization(image, clusters=3)
result = kmeans.copy()

# Floodfill
seed_point = (150, 50)
cv2.floodFill(result, None, seedPoint=seed_point, newVal=(36, 255, 12), loDiff=(0, 0, 0, 0), upDiff=(0, 0, 0, 0))

cv2.imshow('image', image)
cv2.imshow('kmeans', kmeans)
cv2.imshow('result', result)
cv2.waitKey()     
Run Code Online (Sandbox Code Playgroud)


Rot*_*tem 4

您需要正确设置loDiffupDiff参数。

\n\n

请参阅洪水填充文档

\n\n
\n

loDiff \xe2\x80\x93 当前观察到的像素与其属于该组件的相邻像素之一或添加到该组件的种子像素之间的最大较低亮度/色差。
\n upDiff \xe2\x80\x93 当前观察到的像素与其属于该组件的邻居之一或添加到该组件的种子像素之间的最大上部亮度/色差。

\n
\n\n

这是一个 Python 代码示例:

\n\n
import cv2\nflood = cv2.imread("1.jpeg");\n\nseed = (180, 80)\n\ncv2.floodFill(flood, None, seedPoint=seed, newVal=(0, 0, 255), loDiff=(5, 5, 5, 5), upDiff=(5, 5, 5, 5))\ncv2.circle(flood, seed, 2, (0, 255, 0), cv2.FILLED, cv2.LINE_AA);\n\ncv2.imshow(\'flood\', flood)\ncv2.waitKey(0)\ncv2.destroyAllWindows()\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

结果:
\n地面

\n