如何在Python中使用OpenCV2对图像中的一种颜色进行去饱和?

2024-09-30 18:13:37 发布

您现在位置:Python中文网/ 问答频道 /正文

所以我运行了一段代码,可以让我去饱和,然后饱和图像。我有一个函数,应该允许我这样做,但无论我如何改变代码,它总是改变颜色,所以它不会去饱和

我的功能:

def desaturation(img,percent=.5):
    imgGreen=img[:,:,1]
    desatGreen=imgGreen*percent
    desatImg=img[:,:,:]
    desatImg[:,:,1]=desatGreen
    return desatImg

每次我运行它时,它都会将颜色转换为洋红色,而不是我所期望的不饱和的外观。我希望颜色范围仍然保留在BGR中,而不是任何其他颜色范围。有没有什么代码可以帮助我完成这项工作,不依赖其他内置函数,而是直接完成

编辑:我设置了百分比变量,因此它不能超过1,也不能低于0

编辑:我想去饱和整个图像。我编写代码的方式有点误导


Tags: 函数代码图像功能编辑imgreturn颜色
2条回答

下面是一种在Python OpenCV中去除绿色饱和度的简单方法。方法是转换成CMYK,然后使C和Y通道去饱和。不幸的是,OpenCV没有内置BGR2CMYK颜色转换。所以我们需要进行计算。此方法也会影响其他颜色

输入:

enter image description here

import cv2
import numpy as np

img = cv2.imread("barn.jpg")
scale = 255
percent = 0.5
#percent = 0.25
#percent = 0

# separate b,g,r
b,g,r = cv2.split(img)
b = b.astype(np.float32)
g = g.astype(np.float32)
r = r.astype(np.float32)

# convert to cmyk
# see 
# https://stackoverflow.com/questions/14088375/how-can-i-convert-rgb-to-cmyk-and-vice-versa-in-python/41220097
# https://www.codeproject.com/Articles/4488/XCmyk-CMYK-to-RGB-Calculator-with-source-code
c = 1 - r / scale
m = 1 - g / scale
y = 1 - b / scale
k = cv2.min(cv2.min(c, m),y)
c = scale * (c - k) / (1 - k)
m = scale * (m - k) / (1 - k)
y = scale * (y - k) / (1 - k)

# desaturate neighbors of G which are C,Y
c = cv2.multiply(c, percent)
y = cv2.multiply(y, percent)

# convert back to bgr
r = scale * (1.0 - c / scale) * (1.0 - k)
g = scale * (1.0 - m / scale) * (1.0 - k)
b = scale * (1.0 - y / scale) * (1.0 - k)
r = r.clip(0,255).astype(np.uint8)
g = g.clip(0,255).astype(np.uint8)
b = b.clip(0,255).astype(np.uint8)
img_desat = cv2.merge([b,g,r])

# save result
cv2.imwrite('barn_desat_0p5.jpg', img_desat)
#cv2.imwrite('barn_desat_0p25.jpg', img_desat)
#cv2.imwrite('barn_desat_0.jpg', img_desat)

cv2.imshow('img', img)
cv2.imshow('img_desat', img_desat)
cv2.waitKey(0)
cv2.destroyAllWindows()

去饱和至50%:

enter image description here

将饱和度降至25%:

enter image description here

将饱和度降至0:

enter image description here

在Python OpenCV中去除颜色(绿色)饱和度的正确方法是在HSV颜色空间中工作

  • 读取输入
  • 转换为HSV和独立频道
  • 去饱和S通道
  • 与原始H和V通道合并
  • 转换回BGR
  • 创建一个1D LUT图像,该图像除绿色区域为白色外,其余区域均为黑色
  • 将LUT应用于H通道并另存为范围为0到1的掩码
  • 创建一个混合图像,即遮罩为白色(对应于绿色)的去饱和图像和遮罩为黑色(绿色除外)的原始图像
  • 保存为结果

输入:

enter image description here

import cv2
import numpy as np

img = cv2.imread("barn.jpg")
percent = 0.5
#percent = 0.25
#percent = 0

# convert to HSV
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)

# desaturate
s_desat = cv2.multiply(s, percent).astype(np.uint8)
hsv_new = cv2.merge([h,s_desat,v])
bgr_desat = cv2.cvtColor(hsv_new, cv2.COLOR_HSV2BGR)

# create 1D LUT for green
# (120 out of 360) = (60 out of 180)  +- 25
lut = np.zeros((1,256), dtype=np.uint8)
white = np.full((1,50), 255, dtype=np.uint8)
lut[0:1, 35:85] = white
print(lut.shape, lut.dtype)

# apply lut to hue channel as mask
mask = cv2.LUT(h, lut)
mask = mask.astype(np.float32) / 255
mask = cv2.merge([mask,mask,mask])

# mask bgr_desat and img
result = mask * bgr_desat + (1 - mask)*img
result = result.clip(0,255).astype(np.uint8)

# save result
cv2.imwrite('barn_desat2_0p5.jpg', result)
#cv2.imwrite('barn_desat2_0p25.jpg', result)
#cv2.imwrite('barn_desat2_0.jpg', result)

cv2.imshow('img', img)
cv2.imshow('bgr_desat', bgr_desat)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

使绿50%去饱和:

enter image description here

去饱和绿25%:

enter image description here

去饱和绿色0:

enter image description here

相关问题 更多 >