使用Python中的OpenCV更改图像区域的颜色

11

我有一张图片,希望将所有的白色像素变成灰色,但只限于图像的特定区域。示例图片如下,我只想更改红色矩形外的图像部分,而不更改红色矩形内的图像:

Image

我已经有了通用代码,它是来自其他Stackoverflow问题的一部分,可以更改每个白色像素的颜色,而不仅仅是在区域外的一个像素。

image = cv.imread("meme 2.jpg")
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)

# Define lower and uppper limits of what we call "white-ish"
sensitivity = 19
lower_white = np.array([0, 0, 255 - sensitivity])
upper_white = np.array([255, sensitivity, 255])

# Mask image to only select white
mask = cv.inRange(hsv, lower_white, upper_white)

# Change image to grey where we found brown
image[mask > 0] = (170, 170, 170)
cv.imwrite(file, image)

你能否在问题中添加一个链接到另一个人的问题? - Riley
这是另一个人的代码链接:https://dev59.com/alUL5IYBdhLWcg3whYZk - paul_on_pc
2个回答

4
以下是翻译的结果:

下面是在Python/OpenCV中实现这一目标的方法。

  • 读取输入图像
  • 将图像转换为HSV颜色空间
  • 根据所需的颜色进行阈值处理,生成掩膜(mask)
  • 使用掩膜(mask)更改图像中所有相应像素的颜色
  • 绘制新的矩形掩膜,用于指定不希望更改颜色的区域
  • 反转新的掩膜,用于指定要更改颜色的区域
  • 将新的掩膜应用到原始图像上
  • 将反转后的新掩膜应用到更改颜色的图像上
  • 将两个结果相加得到最终图像
  • 保存结果


输入图像:

enter image description here

import cv2
import numpy as np

# Read image
image = cv2.imread('4animals.jpg')

# Convert to HSV
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# Define lower and uppper limits of what we call "white-ish"
sensitivity = 19
lower_white = np.array([0, 0, 255 - sensitivity])
upper_white = np.array([255, sensitivity, 255])

# Create mask to only select white
mask = cv2.inRange(hsv, lower_white, upper_white)

# Change image to grey where we found white
image2 = image.copy()
image2[mask > 0] = (170, 170, 170)

# Create new rectangular mask that is white on black background
x,y,w,h = 33,100,430,550
mask2 = np.zeros_like(image)
cv2.rectangle(mask2, (x,y), (x+w,y+h), (255, 255, 255), -1)

# invert mask
mask2_inv = 255 - mask2

# apply mask to image
image_masked = cv2.bitwise_and(image, mask2)

# apply inverted mask to image2
image2_masked = cv2.bitwise_and(image2, mask2_inv)

# add together
result = cv2.add(image_masked, image2_masked)

# save results
cv2.imwrite('4animals_mask.jpg', mask)
cv2.imwrite('4animals_modified.png', image2)
cv2.imwrite('4animals_mask2.jpg', mask2)
cv2.imwrite('4animals_mask2_inv.jpg', mask2_inv)
cv2.imwrite('4animals_masked.jpg', image_masked)
cv2.imwrite('4animals_modified_masked.jpg', image2_masked)
cv2.imwrite('4animals_result.jpg', result)

cv2.imshow('mask', mask)
cv2.imshow('image2', image2)
cv2.imshow('mask2', mask2 )
cv2.imshow('mask2_inv', mask2_inv)
cv2.imshow('image_masked', image_masked)
cv2.imshow('image2_masked', image2_masked)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

颜色遮罩:

enter image description here

矩形遮罩:

enter image description here

反转的矩形遮罩:

enter image description here

颜色更改后的图像:

enter image description here

遮罩输入:

enter image description here

带有遮罩的颜色更改图像:

enter image description here

结果:

enter image description here


3

这是另一种使用Python/OpenCV的简单方法。我的先前答案过于复杂。

  • 读取输入
  • 将其转换为HSV颜色空间
  • 通过颜色阈值处理创建一个掩码图像
  • 在上一个掩码中绘制黑色矩形,表示您不想更改颜色的区域
  • 将新合并的掩码应用于图像以更改所需区域的颜色
  • 保存结果


输入:

enter image description here

import cv2
import numpy as np

# Read image
image = cv2.imread('4animals.jpg')

# Convert to HSV
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

# Define lower and uppper limits of what we call "white-ish"
sensitivity = 19
lower_white = np.array([0, 0, 255 - sensitivity])
upper_white = np.array([255, sensitivity, 255])

# Create mask to only select white
mask = cv2.inRange(hsv, lower_white, upper_white)

# Draw new rectangular mask on old mask that is black inside the rectangle and white outside the rectangle
x,y,w,h = 33,100,430,550
mask2 = mask.copy()
cv2.rectangle(mask2, (x,y), (x+w,y+h), 0, -1)

# Change image to grey where we found white for combined mask
result = image.copy()
result[mask2 > 0] = (170, 170, 170)

# save results
cv2.imwrite('4animals_mask.jpg', mask)
cv2.imwrite('4animals_mask2.jpg', mask2)
cv2.imwrite('4animals_result.jpg', result)

cv2.imshow('mask', mask)
cv2.imshow('mask2', mask2 )
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()


通过颜色阈值分割得到的掩模:

图片描述在这里

在掩模上绘制矩形后修改的掩模:

图片描述在这里

结果:

图片描述在这里


1
如果他们帮助了您,请考虑给其中一个点赞。 - fmw42
很遗憾,我没有足够的声望来点赞评论。它说:“感谢您的反馈!那些声望少于15的人投票会被记录下来,但不会改变公开显示的帖子分数。”但是它仍然应该对您有所帮助! - paul_on_pc
1
好的。感谢您的尝试。 - fmw42

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