Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert a rgb image into a cmyk?

I want to convert a RGB image into CMYK. This is my code; the first problem is when I divide each pixel by 255, the value closes to zero, so the resulting image is approximately black! The second problem is that I don't know how to convert the one-channel resultant image to 4 channels. Of course, I'm not sure the made CMYK in the following code is correct. Thank you for your attention


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()
like image 401
MH.AI.eAgLe Avatar asked Mar 23 '20 13:03

MH.AI.eAgLe


People also ask

How do I convert RGB to CMYK without losing color?

Can you convert RGB to CMYK without losing color? You cannot convert between RGB and CMYK without some amount of color difference of some sort. It's a good idea to do test prints of your work with a high quality printer to see how your colors turn out.

Do printers convert RGB to CMYK?

For years, commercial printers have told graphic designers to convert RGB colors to CMYK before packaging your files to send to print. This is to make sure you can accurately see what the colors you are using will look like in print, since your computer monitor displays color in bright RGB while print uses CMYK.

What happens when you convert RGB to CMYK?

When an image is converted from RGB to CMYK, it moves between color spaces. Because of the nature of the two color spaces, not all colors in one are contained in the other. A gamut describes the range of different Colors that can be seen or reproduced.


2 Answers

You can let PIL/Pillow do it for you like this:

from PIL import Image

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

If I use IPython, I can time loading, converting and saving that at 13ms in toto like this:

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

If you want to do it yourself by implementing your formula, you would be better off using vectorised Numpy rather than for loops. This takes 35ms.

#!/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)

If you want to check your results, you need to be aware of a few things. Not all image formats can save CMYK, that's why I saved as TIFF. Secondly, your formula leaves all your values as floats in the range 0..1, so you probably want scale back up by multiplying by 255 and converting to uint8.

Finally, you can be assured of what the correct result is by simply using ImageMagick in the Terminal:

magick drtrump.jpg -colorspace CMYK result.tif
like image 123
Mark Setchell Avatar answered Oct 27 '22 07:10

Mark Setchell


You don't need to do CMYK = C + M + Y + K.

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

For ndim arrays you can use numpy.dstack. Documentation link.

Edit

The incorrect results are caused due to int division. You need to perform float division. One method to achieve that is to convert array B, G, and R to 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) #
like image 2
mibrahimy Avatar answered Oct 27 '22 09:10

mibrahimy