繁体   English   中英

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

[英]How to desaturate one color in an image using OpenCV2 in Python?

所以我正在运行一些应该允许我去饱和然后使图像饱和的代码。 我有一个应该允许我这样做的函数,但无论我如何更改代码,它总是会改变颜色,因此它不会去饱和。

我的功能:

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

每次运行它时,它都会将颜色变为洋红色,而不是我期望的不饱和外观。 我希望颜色范围仍然保留在 BGR 中,而不是任何其他颜色范围。 是否有任何代码可以帮助我解决这个问题,原始而不是依赖另一个内置函数?

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

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

这是在 Python OpenCV 中降低绿色饱和度的一种简单方法。 这样做的方法是转换为 CMYK,然后去饱和 C 和 Y 通道。 不幸的是,OpenCV 没有内置的 BGR2CMYK 颜色转换。 所以需要进行计算。 这种方法也会影响其他颜色。

输入:

在此处输入图片说明

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%:

在此处输入图片说明

去饱和度到 25%:

在此处输入图片说明

去饱和到 0:

在此处输入图片说明

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

  • 读取输入
  • 转换为 HSV 和单独的通道
  • 去饱和 S 通道
  • 与原始 H 和 V 通道合并
  • 转换回 BGR
  • 创建一个一维 LUT 图像,除了白色的绿色外,其他地方都是黑色的
  • 将 LUT 应用到 H 通道并保存为 0 到 1 范围内的蒙版
  • 创建一个混合图像,即蒙版为白色(对应于绿色)的去饱和图像和蒙版为黑色(绿色除外)的原始图像
  • 保存为结果

输入:

在此处输入图片说明

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%:

在此处输入图片说明

去饱和绿色 25%:

在此处输入图片说明

去饱和绿色 0:

在此处输入图片说明

暂无
暂无

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

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