如何将 rgb 图像转换为 cmyk?

How to convert a rgb image into a cmyk?

我想将 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

I don't know how to convert the 1 channel resulted image to 4 channel.

对于 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) #

你可以让 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)

如果您想通过实施公式自己完成,最好使用 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