OpenCV - 如何对 RGB 图像使用 floodFill?
OpenCV - How to use floodFill with RGB image?
我正尝试在下面的图像上使用 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);
这是结果(红点是种子):
如何设置函数以获得更大的区域(如整个天空)?
您需要正确设置 loDiff
和 upDiff
参数。
loDiff – Maximal lower brightness/color difference between the currently observed pixel and one of its neighbors belonging to the component, or a seed pixel being added to the component.
upDiff – Maximal upper brightness/color difference between the currently observed pixel and one of its neighbors belonging to the component, or a seed pixel being added to the component.
这是一个 Python 代码示例:
import cv2
flood = cv2.imread("1.jpeg");
seed = (180, 80)
cv2.floodFill(flood, None, seedPoint=seed, newVal=(0, 0, 255), loDiff=(5, 5, 5, 5), upDiff=(5, 5, 5, 5))
cv2.circle(flood, seed, 2, (0, 255, 0), cv2.FILLED, cv2.LINE_AA);
cv2.imshow('flood', flood)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
如果您希望填充轮廓尽可能接近图像中的对比元素,您可以做的另一件事是执行 Kmeans 颜色量化以将图像分割成指定数量的簇。由于天空和 mountains/trees 有明显的色差,我们可以将图像分割成三种颜色,这样可以更好地分离物体。
例如 clusters=3
:
输入图像->
Kmeans颜色分割
Floodfill 结果为绿色
注意分割后如何只有三种颜色定义图像。这样,填充物将沿着mountains/trees更好
等高线
代码
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()
我正尝试在下面的图像上使用 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);
这是结果(红点是种子):
如何设置函数以获得更大的区域(如整个天空)?
您需要正确设置 loDiff
和 upDiff
参数。
loDiff – Maximal lower brightness/color difference between the currently observed pixel and one of its neighbors belonging to the component, or a seed pixel being added to the component.
upDiff – Maximal upper brightness/color difference between the currently observed pixel and one of its neighbors belonging to the component, or a seed pixel being added to the component.
这是一个 Python 代码示例:
import cv2
flood = cv2.imread("1.jpeg");
seed = (180, 80)
cv2.floodFill(flood, None, seedPoint=seed, newVal=(0, 0, 255), loDiff=(5, 5, 5, 5), upDiff=(5, 5, 5, 5))
cv2.circle(flood, seed, 2, (0, 255, 0), cv2.FILLED, cv2.LINE_AA);
cv2.imshow('flood', flood)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
如果您希望填充轮廓尽可能接近图像中的对比元素,您可以做的另一件事是执行 Kmeans 颜色量化以将图像分割成指定数量的簇。由于天空和 mountains/trees 有明显的色差,我们可以将图像分割成三种颜色,这样可以更好地分离物体。
例如 clusters=3
:
输入图像->
Kmeans颜色分割
Floodfill 结果为绿色
注意分割后如何只有三种颜色定义图像。这样,填充物将沿着mountains/trees更好
等高线代码
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()