如何更改与黑色接触的像素颜色集
How to change the set of pixel colors in contatc with black color
考虑这张图片:
我想用红色更改与黑色像素接触的白色像素集,这样:
我尝试在 python
中使用此代码:
import numpy as np
from PIL import Image
im = Image.open('image.png')
data = np.array(im)
r1, g1, b1 = 255, 255, 255 # Original value
r2, g2, b2 = 0, 0, 255 # Value that we want to replace it with
red, green, blue = data[:,:,0], data[:,:,1], data[:,:,2]
mask = (red == r1) & (green == g1) & (blue == b1)
data[:,:,:3][mask] = [r2, g2, b2]
im = Image.fromarray(data)
但是我把所有的白色像素都换成了红色。但也可能是一个 UNIX
方法建议。
请 post 输入图像的无损版本。有损图像会修改像素值,从而产生影响处理的伪像。我重新创建了您的图像并将其保存为 lossless PNF file。
我正在使用 OpenCV 来获得您想要的结果。我用您原始输入的 non-zero 元素创建了一个遮罩。然后,我使用 Flood-fill 用你想要的颜色填充外部形状。如果您 AND
两张图片都可以获得最终图像。
让我们看看代码:
# import opencv:
import cv2
# image path
path = "D://opencvImages//"
fileName = "rectsLossless.png"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Grayscale image:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# Get non-zero mask:
binaryThresh = 1
_, binaryMask = cv2.threshold(grayscaleImage, binaryThresh, 255, cv2.THRESH_BINARY)
此位创建 non-zero 像素掩码:
这将有助于将所有 non-white 的元素归零。该图像是掩码的第一部分。现在,让我们用红色填充外部形状。这是通过三个步骤实现的:
# Get image dimensions:
(imageHeight, imageWidth) = inputImage.shape[:2]
# Get image center:
xCenter = int(0.5 * imageWidth)
yCenter = int(0.5 * imageHeight)
# Get flood-fill target color
floodColor = inputImage[yCenter, xCenter]
print("Flood Color: %s" % floodColor)
# numpy array to tuple
floodColor = (int(floodColor[0]), int(floodColor[1]), int(floodColor[2]))
第一步获取实际填充颜色。我想红色或多或少位于图像的中心。然后,第二步涉及用白色填充所有“前景”像素。让我们在左上角播种:
# Flood fill at top left corner:
leftCorner = (1, 1)
whiteColor = (255, 255, 255)
cv2.floodFill(inputImage, None, leftCorner, whiteColor)
这是结果:
请注意,部分位于红色矩形之外的形状现在如何全部由白色连接。让我们再次填充,但这次使用我之前提取的红色:
# Second Flood-fill
cv2.floodFill(inputImage, None, leftCorner, floodColor)
这会产生下图:
让我们通过AND
将此结果与原始 non-zero 掩码相结合来创建最终图像:
# Create final image:
outImage = cv2.bitwise_and(inputImage, inputImage, mask=binaryMask)
这是最终结果:
问题非常接近。
我的解决方案也很接近...
假设颜色是黑色白色和红色(一般情况下可能比较棘手),我们可以使用以下阶段:
- 用白色填充黑色背景(使用
cv2.floodFill
)。
红色边界上的白色物体与背景合并。
- 用黑色填充白色背景(使用
cv2.floodFill
)。
红色边界上的白色物体将变成黑色。
- 将红色通道从原始图像复制到“填充”图像。
一个白色像素的红色通道是255,所以黑白变成红色。
代码示例:
import cv2
import numpy as np
img = cv2.imread('red_white_black.jpg')
# Copy the original image to img2
img2 = img.copy()
# Fill the black background with white color
cv2.floodFill(img2, None, seedPoint=(0, 0), newVal=(255, 255, 255), loDiff=(50, 50, 50), upDiff=(50, 50, 50))
cv2.imshow('black background', img2) # Show img2 for testing
# Fill the white background with black color
cv2.floodFill(img2, None, seedPoint=(0, 0), newVal=(0, 0, 0), loDiff=(50, 50, 50), upDiff=(50, 50, 50))
cv2.imshow('white background', img2) # Show img2 for testing
# Copy the red color channel from the original image to img2
img2[:, :, 2] = img[:, :, 2]
cv2.imshow('img2', img2) # Show img2 for testing
cv2.waitKey()
cv2.destroyAllWindows()
结果:
黑色背景:
白色背景:
img2
:
红色周围的黑边是因为原始图像是 JPEG 而不是 PNG(颜色不纯),并且红色不是纯红色。
我们可能会使用以下代码修复它(代码不是很优雅)...
red = img[:, :, 2]
r = np.median(img[:, :, 2][red > 50])
g = np.median(img[:, :, 1][red > 50])
b = np.median(img[:, :, 0][red > 50])
mask = np.logical_and(img[:, :, 0] > 100, img2[:, :, 0] <= 100)
img3 = img2.copy()
img3[:, :, 2][mask] = r
img3[:, :, 1][mask] = g
img3[:, :, 0][mask] = b
img3[:, :, 2] = cv2.morphologyEx(img3[:, :, 2], cv2.MORPH_CLOSE, np.ones((3, 3), np.uint8))
img3[:, :, 1] = cv2.morphologyEx(img3[:, :, 1], cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
img3[:, :, 0] = cv2.morphologyEx(img3[:, :, 0], cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
cv2.imshow('img3', img3)
cv2.waitKey()
cv2.destroyAllWindows()
结果:
考虑这张图片:
我想用红色更改与黑色像素接触的白色像素集,这样:
我尝试在 python
中使用此代码:
import numpy as np
from PIL import Image
im = Image.open('image.png')
data = np.array(im)
r1, g1, b1 = 255, 255, 255 # Original value
r2, g2, b2 = 0, 0, 255 # Value that we want to replace it with
red, green, blue = data[:,:,0], data[:,:,1], data[:,:,2]
mask = (red == r1) & (green == g1) & (blue == b1)
data[:,:,:3][mask] = [r2, g2, b2]
im = Image.fromarray(data)
但是我把所有的白色像素都换成了红色。但也可能是一个 UNIX
方法建议。
请 post 输入图像的无损版本。有损图像会修改像素值,从而产生影响处理的伪像。我重新创建了您的图像并将其保存为 lossless PNF file。
我正在使用 OpenCV 来获得您想要的结果。我用您原始输入的 non-zero 元素创建了一个遮罩。然后,我使用 Flood-fill 用你想要的颜色填充外部形状。如果您 AND
两张图片都可以获得最终图像。
让我们看看代码:
# import opencv:
import cv2
# image path
path = "D://opencvImages//"
fileName = "rectsLossless.png"
# Reading an image in default mode:
inputImage = cv2.imread(path + fileName)
# Grayscale image:
grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
# Get non-zero mask:
binaryThresh = 1
_, binaryMask = cv2.threshold(grayscaleImage, binaryThresh, 255, cv2.THRESH_BINARY)
此位创建 non-zero 像素掩码:
这将有助于将所有 non-white 的元素归零。该图像是掩码的第一部分。现在,让我们用红色填充外部形状。这是通过三个步骤实现的:
# Get image dimensions:
(imageHeight, imageWidth) = inputImage.shape[:2]
# Get image center:
xCenter = int(0.5 * imageWidth)
yCenter = int(0.5 * imageHeight)
# Get flood-fill target color
floodColor = inputImage[yCenter, xCenter]
print("Flood Color: %s" % floodColor)
# numpy array to tuple
floodColor = (int(floodColor[0]), int(floodColor[1]), int(floodColor[2]))
第一步获取实际填充颜色。我想红色或多或少位于图像的中心。然后,第二步涉及用白色填充所有“前景”像素。让我们在左上角播种:
# Flood fill at top left corner:
leftCorner = (1, 1)
whiteColor = (255, 255, 255)
cv2.floodFill(inputImage, None, leftCorner, whiteColor)
这是结果:
请注意,部分位于红色矩形之外的形状现在如何全部由白色连接。让我们再次填充,但这次使用我之前提取的红色:
# Second Flood-fill
cv2.floodFill(inputImage, None, leftCorner, floodColor)
这会产生下图:
让我们通过AND
将此结果与原始 non-zero 掩码相结合来创建最终图像:
# Create final image:
outImage = cv2.bitwise_and(inputImage, inputImage, mask=binaryMask)
这是最终结果:
问题非常接近
我的解决方案也很接近...
假设颜色是黑色白色和红色(一般情况下可能比较棘手),我们可以使用以下阶段:
- 用白色填充黑色背景(使用
cv2.floodFill
)。
红色边界上的白色物体与背景合并。 - 用黑色填充白色背景(使用
cv2.floodFill
)。
红色边界上的白色物体将变成黑色。 - 将红色通道从原始图像复制到“填充”图像。
一个白色像素的红色通道是255,所以黑白变成红色。
代码示例:
import cv2
import numpy as np
img = cv2.imread('red_white_black.jpg')
# Copy the original image to img2
img2 = img.copy()
# Fill the black background with white color
cv2.floodFill(img2, None, seedPoint=(0, 0), newVal=(255, 255, 255), loDiff=(50, 50, 50), upDiff=(50, 50, 50))
cv2.imshow('black background', img2) # Show img2 for testing
# Fill the white background with black color
cv2.floodFill(img2, None, seedPoint=(0, 0), newVal=(0, 0, 0), loDiff=(50, 50, 50), upDiff=(50, 50, 50))
cv2.imshow('white background', img2) # Show img2 for testing
# Copy the red color channel from the original image to img2
img2[:, :, 2] = img[:, :, 2]
cv2.imshow('img2', img2) # Show img2 for testing
cv2.waitKey()
cv2.destroyAllWindows()
结果:
黑色背景:
白色背景:
img2
:
红色周围的黑边是因为原始图像是 JPEG 而不是 PNG(颜色不纯),并且红色不是纯红色。
我们可能会使用以下代码修复它(代码不是很优雅)...
red = img[:, :, 2]
r = np.median(img[:, :, 2][red > 50])
g = np.median(img[:, :, 1][red > 50])
b = np.median(img[:, :, 0][red > 50])
mask = np.logical_and(img[:, :, 0] > 100, img2[:, :, 0] <= 100)
img3 = img2.copy()
img3[:, :, 2][mask] = r
img3[:, :, 1][mask] = g
img3[:, :, 0][mask] = b
img3[:, :, 2] = cv2.morphologyEx(img3[:, :, 2], cv2.MORPH_CLOSE, np.ones((3, 3), np.uint8))
img3[:, :, 1] = cv2.morphologyEx(img3[:, :, 1], cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
img3[:, :, 0] = cv2.morphologyEx(img3[:, :, 0], cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
cv2.imshow('img3', img3)
cv2.waitKey()
cv2.destroyAllWindows()
结果: