如何在OpenCV中用另一个RGB值替换所有特定RGB值的像素

12

我需要在OpenCV中将所有具有特定RGB值的像素替换为另一种颜色。

我尝试了一些解决方案,但都没有奏效。

如何以最佳方式实现这一目标?


尝试更新问题并附上你所尝试的内容。 - Imanpal Singh
链接已失效。 - Imanpal Singh
我知道,大约15分钟前还能用。我想它暂时挂了。 - SJS
如果您有多个需要替换的颜色,LUT 是一种高效的方法。 - Micka
2个回答

25

TLDR; 使用Numpy将所有绿色像素变为白色:

import numpy as np

pixels[np.all(pixels == (0, 255, 0), axis=-1)] = (255,255,255)

我在这里提供了一些其他改变颜色的方法示例。首先,我将涵盖像你在问题中提到的那样精确的RGB值,使用这张图片。左侧有三个完全红色、完全绿色和完全蓝色的大块,右侧有这些颜色之间的三个逐渐过渡:

enter image description here

以下是原始答案:

#!/usr/bin/env python3

import cv2
import numpy as np

# Load image
im = cv2.imread('image.png')

# Make all perfectly green pixels white
im[np.all(im == (0, 255, 0), axis=-1)] = (255,255,255)

# Save result
cv2.imwrite('result1.png',im)

enter image description here


这一次,我定义了颜色名称,以提高可读性和可维护性。最后一行是重点:

# Define some colours for readability - these are in OpenCV **BGR** order - reverse them for PIL
red   = [0,0,255]
green = [0,255,0]
blue  = [255,0,0]
white = [255,255,255]
black = [0,0,0]

# Make all perfectly green pixels white
im[np.all(im == green, axis=-1)] = white

同样的结果。


这次我制作了一个可重复使用的红色像素掩码,可以在后续操作中使用。现在,赋值语句im[Rmask] = black非常容易阅读:

# Define some colours for readability - these are in OpenCV **BGR** order - reverse them for PIL
red   = [0,0,255]
green = [0,255,0]
blue  = [255,0,0]
white = [255,255,255]
black = [0,0,0]

# Make mask of all perfectly red pixels
Rmask = np.all(im == red, axis=-1)

# Make all red pixels black
im[Rmask] = black

enter image description here


这次我将红色和蓝色像素的掩码合并起来,以展示掩码的威力。最后一行是重点:
# Define some colours for readability - these are in OpenCV **BGR** order - reverse them for PIL
red   = [0,0,255]
green = [0,255,0]
blue  = [255,0,0]
white = [255,255,255]
black = [0,0,0]

# Make mask of all perfectly red pixels and all perfectly blue pixels
Rmask = np.all(im == red,  axis=-1)
Bmask = np.all(im == blue, axis=-1)

# Make all red or blue pixels black
im[Rmask | Bmask] = black

enter image description here


这一次,我将所有非红色像素变成黑色 - 希望你现在已经意识到了掩膜的强大。最后一行是重点:

# Define some colours for readability - these are in OpenCV **BGR** order - reverse them for PIL
red   = [0,0,255]
green = [0,255,0]
blue  = [255,0,0]
white = [255,255,255]
black = [0,0,0]

# Make mask of all perfectly red pixels
Rmask = np.all(im == red,  axis=-1)

# Make all non-red pixels black
im[~Rmask] = black

enter image description here


到目前为止,我们只是将一些像素选择成单个新颜色。如果我们想在一次操作中使一些像素成为一种颜色,而所有其他像素成为另一种颜色呢?最后一行是关键点:

# Define some colours for readability - these are in OpenCV **BGR** order - reverse them for PIL
red   = [0,0,255]
green = [0,255,0]
blue  = [255,0,0]
white = [255,255,255]
black = [0,0,0]

# Make mask of all perfectly red pixels
Rmask = np.all(im == red,  axis=-1)

# Make all red pixels white AND at same time everything else black
im = np.where(np.all(im == red, axis=-1, keepdims=True), white, black)

enter image description here


如果你想影响整个颜色范围,而不是特定的RGB值,请看这里这里
关键词:图像处理,Python,素数,改变颜色。

谢谢!我能用一系列颜色来做到这个吗?所以,不是绿色,我可以替换所有接近绿色的颜色吗? - SJS
当然可以。在这里看一下。它以PIL开头,但实际上并没有影响 - 技术是相同的。我会在未来的一两天内让这个答案更加全面。https://dev59.com/ZK7la4cB1Zd3GeqPYipH#52183666 - Mark Setchell
谢谢!这不是我计划做的事情,但遮罩似乎是一个不错的方法。 - SJS

0
假设您需要更改的“特定”像素具有以下RGB值:[r,g,b],即像素的颜色值为R = r,G = g和B = b。
首先,您需要创建与图像大小相同的2D掩码。让大小为(X,Y)。掩码应该:
  1. 如果图像中对应的像素具有RGB通道== [r,g,b],则在索引(x1,y1)处具有值1或True
  2. 如果图像中对应的像素具有RGB通道!= [r,g,b],则在索引(x2,y2)处具有值0或False
要创建此掩码:
old_color = [r,g,b]
new_color = [r2,g2,b2]

height, width, channels = numpy.shape(image)
mask = numpy.zeros((height,width))
# iterate over all pixels in the image and assign 0 to the mask(x,y) if image(x,y) has channels==old_color
mask= [[1 if np.all(channels==[old_color]) else 0 for channels in row ] for row in image ] 


然后找到掩模中所有1的坐标,这些是需要在图像中分配新颜色的坐标。只需使用np.where()查找坐标即可。

mask = numpy.array(mask) # make sure that mask is a numpy array not a list of lists
# numpy.where would not work otherwise
coords_x, coord_y = np.where(mask>0)

最后,在图像的这些坐标上,将RGB值更改为新的RGB值。
img_cp = image.copy()
img_cp[coords_x,coord_y,:]=new_color

您选择的图像像素现在具有新的颜色。 您可以使用matplotlib.pyplot.imshow(img_cp)进行检查。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接