简体   繁体   English

如何用黑色更改联系人中的像素集 colors

[英]How to change the set of pixel colors in contatc with black color

Considering this image:考虑这张图片:

在此处输入图像描述

I would like to change the set of white pixels in contact with black pixels by red, this way:我想通过红色更改与黑色像素接触的白色像素集,这样: 在此处输入图像描述

I tried to use this code in python :我试图在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)

But I changed all white pixels by red.但是我把所有的白色像素都换成了红色。 But could be an UNIX approach suggestion too.但也可能是UNIX方法建议。

Please, post lossless versions of your input images.请发布输入图像的无损版本。 Lossy images modify the value of the pixels, creating artifacts that affect processing.有损图像会修改像素值,从而产生影响处理的伪像。 I recreated your image and saved it as a lossless PNF file .我重新创建了您的图像并将其保存为无损 PNF 文件

I'm using OpenCV to get the result you want.我正在使用 OpenCV 来获得您想要的结果。 I created a mask with the non-zero elements of your original input.我用原始输入的非零元素创建了一个掩码。 Then, I used Flood-fill to fill the outer shapes with the color you want.然后,我使用Flood-fill用你想要的颜色填充外部形状。 The final image can be obtained if you AND both images.如果你AND两个图像,可以获得最终图像。

Let's see the code:让我们看看代码:

# 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)

This bit creates the non-zero pixels mask:该位创建非零像素掩码:

This will help to zero all the elements that are non-white.这将有助于将所有非白色元素归零。 That image is the first part of the mask.该图像是掩码的第一部分。 Now, let's fill the outer shapes with red color.现在,让我们用红色填充外部形状。 This is achieved in three steps:这是通过三个步骤实现的:

# 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]))

The first step gets the actual filling color.第一步获取实际的填充颜色。 I suppose that the red is located more or less at the center of the image.我想红色或多或少位于图像的中心。 Then, the second step involves filling all the "foreground" pixels with white.然后,第二步涉及用白色填充所有“前景”像素。 Let's seed at the top left corner:让我们在左上角播种:

# Flood fill at top left corner:
leftCorner = (1, 1)
whiteColor = (255, 255, 255)
cv2.floodFill(inputImage, None, leftCorner, whiteColor)

This is the result:这是结果:

Note how the shapes that are partially outside of the red rectangle are all now connected by the white color.请注意,部分位于红色矩形之外的形状现在如何全部由白色连接。 Let's fill again, but this time using the red color I extracted previously:让我们再次填充,但这次使用我之前提取的红色:

# Second Flood-fill
cv2.floodFill(inputImage, None, leftCorner, floodColor)

This yields the following image:这会产生以下图像:

Let's create the final image by AND ing this result with the original non-zero mask:让我们通过将结果与原始非零掩码进行AND运算来创建最终图像:

# Create final image:
outImage = cv2.bitwise_and(inputImage, inputImage, mask=binaryMask)

This is the final result:这是最终结果:

The question is very close to this question .这个问题非常接近这个问题
My solution is close too...我的解决方案也很接近......

Assuming the colors are black white and red (the general case may be trickier), we may use the following stages:假设 colors 是黑色白色和红色(一般情况可能比较棘手),我们可以使用以下阶段:

  • Fill the black background with white color (using cv2.floodFill ).用白色填充黑色背景(使用cv2.floodFill )。
    The white object on the red boundary are merged with the background.红色边界上的白色 object 与背景合并。
  • Fill the white background with black color (using cv2.floodFill ).用黑色填充白色背景(使用cv2.floodFill )。
    The white object on the red boundary are going to be black.红色边界上的白色 object 将变为黑色。
  • Copy the red color channel from the original image to "filled" image.将红色通道从原始图像复制到“填充”图像。
    The red channel of a white pixel is 255, so black and white becomes red.白色像素的红色通道是 255,所以黑色和白色变成红色。

Code sample:代码示例:

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()

Results:结果:
Black background:黑色背景:
在此处输入图像描述

White background:白色背景:
在此处输入图像描述

img2 : img2
在此处输入图像描述

The black margins around the red, are because the original image is JPEG and not PNG (colors are not pure), and the red is not pure red.红色周围的黑色边缘是因为原始图像是 JPEG 而不是 PNG(颜色不纯),并且红色不是纯红色。

We may fix it using the following code (the code in not very elegant)...我们可以使用以下代码修复它(代码不是很优雅)...

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()

Result:结果:
在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM