使用 opencv 将不匹配特定颜色的颜色更改为白色

Change colors that do not match specific color(s) to white using opencv

我正在尝试使用 opencv 从图像中抓取特定元素。到目前为止,我所做的是减少图像中的颜色数量,并获得带有颜色计数的颜色字典。我现在想要做的是将所有与该特定颜色不匹配的颜色替换为白色,以便我可以遍历图像并创建不同的图像,其中每个图像只有一个特定颜色的对象。

这是我目前所做的:

def showOnlyOneColor(img, rgb_key):
    print("Getting only one color")
    rgb_key = rgb_key.split("-")
    r = int(rgb_key[0])
    g = int(rgb_key[1])
    b = int(rgb_key[2])

    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    rgb_low = np.array([r,g,b])
    rgb_high = np.array([r,g,b])
    mask = cv2.inRange(hsv, rgb_low, rgb_high)
    contours = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    cv2.fillPoly(mask, contours, (255, 255, 255))
    result = cv2.bitwise_and(img,img,mask=mask)


    return result

第二次尝试:

def showOnlyOneColor(img, rgb_key):
    print("Getting only one color")
    rgb_key = rgb_key.split("-")
    r = int(rgb_key[0])
    g = int(rgb_key[1])
    b = int(rgb_key[2])

    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    rgb_low = np.array([r,g,b])
    rgb_high = np.array([r,g,b])
    mask = cv2.inRange(hsv, rgb_low, rgb_high)

    img[mask!=255] = (255, 255, 255)

    return img

这会为所有迭代生成白色图像

这是我用来减少图像中颜色数量的方法:

def reduceNumberOfColors(img):
    div = 128
    return img // div * div + div // 2

最近一次尝试:

def showOnlyOneColor(img, rgb_key):
    print("Getting only one color")
    rgb_key = rgb_key.split("-")
    r = int(rgb_key[0])
    g = int(rgb_key[1])
    b = int(rgb_key[2])
    hsv_color = colorsys.rgb_to_hsv(r,g,b)

    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    rgb_low = np.array(hsv_color)
    rgb_high = np.array(hsv_color)
    mask = cv2.inRange(hsv, rgb_low, rgb_high)

    img[mask!=255] = (255, 255, 255)

    return img

其中一张生成的图像显示了一些东西,其余图像是白色的

我如何组织 rgb:

def getColorCount(img):
    color_dict = {}
    print("Getting color count")
    for i in tqdm(range(img.shape[0])):
        for j in range(img.shape[1]):
            color = img[i,j]
            r = color[0]
            g = color[1]
            b = color[2]
            rgb_askey = str(r)+"-"+str(g)+"-"+str(b)
            if rgb_askey not in color_dict.keys():
                color_dict[rgb_askey] = 1
            else:
                color_dict[rgb_askey] += 1
    return color_dict

OpenCV 中的颜色顺序为 B,G,R。

所以在 Python/OpenCV 试试这个。

def showOnlyOneColor(img, bgr_key):
    print("Getting only one color")
    bgr_key = bgr_key.split("-")
    b = int(bgr_key[0])
    g = int(bgr_key[1])
    r = int(bgr_key[2])
    bgr_low = np.array((b,g,r))
    bgr_high = np.array((b,g,r))
    mask = cv2.inRange(img, bgr_low, bgr_high)

    img[mask!=255] = (255, 255, 255)

    return img

加法

我认为您的问题在于您假设在使用 colorsys 将 RGB 转换为 HSV 时具有 RGB 颜色。您的颜色实际上是 B、G、R。因此,要使用 colorsys,您需要先将图像转换为 RGB,或者在使用 colorsys 之前,最好反转从 B、G、R 提取到 R、G、B 的颜色顺序。

您的词典颜色实际上是 B、G、R,而不是 R、G、B。因此请反转它们或稍后在使用 colorsys 时反转它们。

这对我 Python/OpenCV 有用。请注意,OpenCV 颜色的顺序为 B、G、R。

import cv2
import numpy as np

# read image
img = cv2.imread('corn.jpg')

# threshold on yellow color
lower=(0,170,215)
upper=(70,255,255)
mask = cv2.inRange(img, lower, upper)

# change all non-yellow to white
result = img.copy()
result[mask!=255] = (255, 255, 255)

# save results
cv2.imwrite('corn_yellow.jpg',result)

# display result
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

这是在 Python/OpenCV 中执行您想要的操作的一种方法。注意颜色顺序为 B、G、R。

输入:

import cv2
import numpy as np

# read image
img = cv2.imread('corn.jpg')

# do simple color reduction
imgcopy = img.copy()
div = 128
imgcopy = div * ( imgcopy // div ) + div // 2

# get list of unique colors
list_bgr_colors = np.unique(imgcopy.reshape(-1, imgcopy.shape[2]), axis=0)
print(list_bgr_colors)
print(list_bgr_colors[1])

# save reduced color image
cv2.imwrite("corn_reduced_colors.png", imgcopy)

# display reduced color image
cv2.imshow("reduced_colors", imgcopy)
cv2.waitKey(0)   

# loop over colors in list and change all non-specified colors to white
i = 1
for color in list_bgr_colors:

    # threshold on the specified color
    lower=np.array((color))
    upper=np.array((color))
    mask = cv2.inRange(imgcopy, lower, upper)

    # change all non-specified color to white
    result = imgcopy.copy()
    result[mask!=255] = (255, 255, 255)

    # save results
    cv2.imwrite("corn_color_{0}.png".format(i), result)

    # display result
    cv2.imshow("result", result)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
    # increment
    i += 1

减少的颜色列表:

[[ 64  64  64]
 [ 64  64 192]
 [ 64 192  64]
 [ 64 192 192]
 [192 192 192]]

缩小的彩色图像:

个人彩色图像: