【问题标题】:How to convert a rgb image into a cmyk?如何将 rgb 图像转换为 cmyk?
【发布时间】:2020-07-03 22:43:41
【问题描述】:

我想将 rgb 图像转换为 cmyk。这是我的代码,第一个问题是,当我将每个像素除以 255 时,值接近于零,因此结果图像近似为黑色! 第二个问题是,我不知道如何将 1 通道结果图像转换为 4 通道。 当然,我不确定以下代码中制作的 CMYK 是否正确。 感谢您的关注


import cv2
import numpy as np
import time

img = cv2.imread('image/dr_trump.jpg')

B = img[:, :, 0]
G = img[:, :, 1]
R = img[:, :, 2]

B_ = np.copy(B) 
G_ = np.copy(G)
R_ = np.copy(R)

K = np.zeros_like(B) 
C = np.zeros_like(B) 
M = np.zeros_like(B) 
Y = np.zeros_like(B) 

ts = time.time()

for i in range(B.shape[0]):
    for j in range(B.shape[1]):
        B_[i, j] = B[i, j]/255
        G_[i, j] = G[i, j]/255
        R_[i, j] = R[i, j]/255

        K[i, j] = 1 - max(B_[i, j], G_[i, j], R_[i, j])
        if (B_[i, j] == 0) and (G_[i, j] == 0) and (R_[i, j] == 0):
        # black
              C[i, j] = 0
              M[i, j] = 0  
              Y[i, j] = 0
        else:

            C[i, j] = (1 - R_[i, j] - K[i, j])/float((1 - K[i, j]))
            M[i, j] = (1 - G_[i, j] - K[i, j])/float((1 - K[i, j]))
            Y[i, j] = (1 - B_[i, j] - K[i, j])/float((1 - K[i, j]))


CMYK = C + M + Y + K 

t = (time.time() -ts)
print("Loop: {:} ms".format(t*1000))


cv2.imshow('CMYK by loop',CMYK)
cv2.waitKey(0)
cv2.destroyAllWindows()

【问题讨论】:

  • 你在哪里找到CMYK = C + M + Y + K
  • 您可以找到 rgb 到 cmyk here 的实现。请看一看。
  • 我认为通过这个总结,我在 1 个通道中得到了结果图像,但实际上我不确定。
  • 非常感谢,我已经看到了,如何将返回值显示为图像?
  • 您需要使用np.stackCMYK 堆叠在一起

标签: python opencv cv2 cmyk


【解决方案1】:

你可以让 PIL/Pillow 像这样为你做:

from PIL import Image

# Open image, convert to CMYK and save as TIF
Image.open('drtrump.jpg').convert('CMYK').save('result.tif')

如果我使用IPython,我可以像这样以 13 毫秒的时间加载、转换和保存它toto

%timeit Image.open('drtrump.jpg').convert('CMYK').save('PIL.tif')
13.6 ms ± 627 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

如果您想自己实现公式,最好使用 vectorised Numpy 而不是 for 循环。这需要 35 毫秒。

#!/usr/bin/env python3

import cv2
import numpy as np

# Load image
bgr = cv2.imread('drtrump.jpg')

# Make float and divide by 255 to give BGRdash
bgrdash = bgr.astype(np.float)/255.

# Calculate K as (1 - whatever is biggest out of Rdash, Gdash, Bdash)
K = 1 - np.max(bgrdash, axis=2)

# Calculate C
C = (1-bgrdash[...,2] - K)/(1-K)

# Calculate M
M = (1-bgrdash[...,1] - K)/(1-K)

# Calculate Y
Y = (1-bgrdash[...,0] - K)/(1-K)

# Combine 4 channels into single image and re-scale back up to uint8
CMYK = (np.dstack((C,M,Y,K)) * 255).astype(np.uint8)

如果你想检查你的结果,你需要注意一些事情。并非所有图像格式都可以保存 CMYK,这就是我保存为 TIFF 的原因。其次,您的公式将所有值保留为 0..1 范围内的浮点数,因此您可能希望通过乘以 255 并转换为 uint8 来扩大规模。

最后,您只需在终端中使用 ImageMagick 即可确定正确的结果:

magick drtrump.jpg -colorspace CMYK result.tif

【讨论】:

    【解决方案2】:

    你不需要CMYK = C + M + Y + K

    我不知道如何将 1 通道结果图像转换为 4 通道。

    对于ndim 数组,您可以使用numpy.dstack。文档link

    编辑

    不正确的结果是由于int除法造成的。 您需要执行浮点除法。实现此目的的一种方法是将数组BGR 转换为float

    B = img[:, :, 0].astype(float) # float conversion, maybe we can do better. But this results in correct answer
    G = img[:, :, 1].astype(float) #
    R = img[:, :, 2].astype(float) #
    

    【讨论】:

    • 非常感谢。它运行良好,并且 np.dstack 运行良好。我将它应用于循环,但结果没有改变。你猜我的默认值是什么?
    • 原因是你的BGR<class 'numpy.uint8'>。当您执行B = B/255 时,结果为0
    • 请查看从numpy.uint8numpy.float32 所需的浮点转换。您现在应该得到正确的输出图像。
    • 阐述不同。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 2010-12-23
    • 1970-01-01
    • 2011-01-26
    相关资源
    最近更新 更多