如何将RGB图像转换为CMYK?

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

CMYK formula Dr.Trump!

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

1
你在哪里找到了 CMYK = C + M + Y + K 这个公式? - mibrahimy
你可以在这里找到RGB转CMYK的实现。请查看一下。 - mibrahimy
我原以为通过这个求和,我可以得到一个单通道的结果图像,但实际上我不确定。 - MH.AI.eAgLe
非常感谢,我已经看到了,如何将返回的值显示为图像? - MH.AI.eAgLe
一个问题,你为什么要使用循环? - mibrahimy
显示剩余4条评论
2个回答

12
你可以让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毫秒:in 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)

如果你想通过实现自己的公式来完成操作,最好使用向量化的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

3

您不需要执行 CMYK = C + M + Y + K

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

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

编辑

错误的结果是由于整数除法引起的。您需要执行浮点除法。一种实现方法是将数组 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也很出色。我将其应用于循环,但结果没有改变。你猜测一下我的默认设置是什么? - MH.AI.eAgLe
原因是你的 BGR<class 'numpy.uint8'> 类型。当你执行 B = B/255 时,结果为 0 - mibrahimy
1
请查看从 numpy.uint8 转换为 numpy.float32 所需的浮点数转换。现在您应该能够获得正确的输出图像。 - mibrahimy
详细阐述不同之处。 - mibrahimy

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