arj
arj

Reputation: 703

how to write gray (1-channel) image with opencv for python

I just would like to know if it's possible to save gray 1 channel images with opencv starting from rgb images.

import cv2
bgr_img = cv2.imread('anyrgbimage.jpg')
print(bgr_img.shape) #(x,y,3)
gray_img = cv2.cvtColor(bgr_img,cv2.COLOR_BGR2GRAY)
cv2.imwrite('hopefully_gray_image.jpg',gray_img)
#cv2.imwrite('hopefully_gray_image.jpg',gray_img,[int(cv2.COLOR_BGR2GRAY)])
buh_img = cv2.imread('hopefully_gray_image.jpg')
print(buh_img.shape) #(x,y,3)

i know i can add some parameters inside cv2.imwrite, but i can't figure out what.

Upvotes: 10

Views: 30246

Answers (1)

Berriel
Berriel

Reputation: 13641

Yes, it is. Let me elaborate on @Miki's comment to your answer. If you take a look at the documentation of imread(filename[, flags]), you will see that the default flag is cv2.IMREAD_COLOR, i.e., OpenCV will load the image with 3 channels, by default (even if it has 1 or 4 channels). If you want to use the same imread(...) to load both three- and single-channel images, you should use the flag cv2.IMREAD_UNCHANGED. In practice, how does that work?

import cv2
import numpy as np

img = (np.random.random((300, 300, 3)) * 255.).astype(np.uint8)
# let's save 4 images (color/gray, png/jpg)
cv2.imwrite('img-png-color.png', img)          # output size: 270KB
cv2.imwrite('img-png-gray.png', img[:, :, 1])  # output size: 90KB
cv2.imwrite('img-jpg-color.jpg', img)          # output size: 109KB
cv2.imwrite('img-jpg-gray.jpg', img[:, :, 1])  # output size: 93KB

There are two things to note:

  • The color PNG image file is 3x larger than the gray PNG image;
  • JPEG is working well, ty :)

Now, if you read ANY of these images using the default flag, they will be loaded with a shape of (300, 300, 3). However, if you proceed as @Miki told you:

cv2.imread('img-png-color.png', cv2.IMREAD_UNCHANGED).shape  # (300, 300, 3)
cv2.imread('img-png-gray.png', cv2.IMREAD_UNCHANGED).shape   # (300, 300)
cv2.imread('img-jpg-color.jpg', cv2.IMREAD_UNCHANGED).shape  # (300, 300, 3)
cv2.imread('img-jpg-gray.jpg', cv2.IMREAD_UNCHANGED).shape   # (300, 300)

Therefore, in fact, the gray images were "saved" as single-channel.

Upvotes: 18

Related Questions