如何在OpenCV中扩展过滤蒙版以覆盖感兴趣区域的更多像素?

zpgglvta  于 2023-02-13  发布在  其他
关注(0)|答案(1)|浏览(157)

看一下this图像。我想把这张卡变成蓝色。
我使用Python和OpenCV来执行图像处理。

我现在是这么做的

import cv2
import numpy as np

# Load the image
image = cv2.imread("input.jpg")

# Convert the image to the HSV color space
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# Threshold the HSV image to get only the red colors
# Bitwise OR unites Hue value 170-179 and 0-10.
mask = cv2.bitwise_or(
    cv2.inRange(hsv_image, np.array([0, 120, 100]), np.array([10, 255, 255])),
    cv2.inRange(hsv_image, np.array([170, 120, 100]), np.array([180, 255, 255]))
)

# Perform median blurring
mask = cv2.medianBlur(mask, 5)

# Define a kernel for the morphological operations
kernel = np.ones((5, 5), np.uint8)

# Perform an opening operation to remove small objects
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=2)

# Perform a closing operation to fill small holes
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=2)

# Perform a gradient operation to extract object boundaries
gradient_mask = cv2.morphologyEx(mask, cv2.MORPH_GRADIENT, kernel)

# Modify hue value of every masked pixel
hsv_image[:, :, 0][mask != 0] = (hsv_image[:, :, 0][mask != 0].astype(int, copy=False) + 120) % 180

# Convert the HSV image back to BGR color space
result = cv2.cvtColor(hsv_image, cv2.COLOR_HSV2BGR)

# Display the result
cv2.namedWindow("output", cv2.WINDOW_NORMAL)
cv2.imshow("output", result)

# Save images of the mask, result and gradient
cv2.imwrite('mask.jpg', mask)
cv2.imwrite('result.jpg', result)
cv2.imwrite('gradient.jpg', gradient_mask)

# Wait for the window to close
while cv2.getWindowProperty('output', 0) >= 0:
    cv2.waitKey(50)

cv2.destroyAllWindows()

效果很好。The resultThe filtering mask
但如果你仔细观察就会发现问题:linklink

**一些红色像素仍然在这里,原因如下。**它们不在红色的过滤范围内:170〈=色相〈= 10,饱和度〉= 120,明度〉= 100。它们的HSV颜色接近(178,32,60)。因此,饱和度和明度落在滤镜范围之外。
**为什么我不能降低饱和度和明度的范围?**这是因为在这种情况下,在另一个具有更多颜色的背景上会有太多的噪声。这种情况下的噪声即使使用多次迭代的开形态学操作也很难避免。

我在图像处理和使用OpenCV方面没有太多经验,所以我的想法可能远远不是最好的解决方案,如果你提出另一种方法也没关系。

**可能的解决方案。**是否可以在过滤遮罩上执行扩张形态操作(扩展过滤蒙版),但仅限于落入另一个更宽红色范围的像素(饱和度和取值范围等于10,色调范围保持相同)。从而使得落入红色的较宽范围中且与现有掩模的像素相邻的所有红色像素(这样就不会添加背景像素来产生噪点)。如果这是个好主意,我该如何实现它,尤其是只对红色范围内的像素进行放大的部分?也许OpenCV已经实现了,只是我不知道而已。

我也很乐意听到任何建议或推荐。我是一名学生,我想了解更多。提前感谢!

r8xiu3jd

r8xiu3jd1#

我找到了自己该怎么做,但它仍然不是最好的面具。我创建了一个更广泛的面具如下:

broader_mask = cv2.bitwise_or(
    cv2.inRange(hsv_image, np.array([0, 30, 30]), np.array([20, 255, 255])),
    cv2.inRange(hsv_image, np.array([160, 30, 30]), np.array([180, 255, 255]))
)

并对扩大的主掩模和更宽的掩模应用逐位AND以获得结果掩模:

mask = cv2.bitwise_and(cv2.dilate(mask, kernel, iterations=2), broader_mask)

效果好多了,但现在面具在某些情况下可能比我想要的要大。例如:

这完全取决于膨胀操作的内核和迭代次数。我不认为这是最好的解决方案,因为对于不同的图像大小,内核和迭代次数可能不同,我仍在寻找更好的解决方案。

相关问题