Animesh Pandey
Animesh Pandey

Reputation: 6018

pyplot.imsave() saves image correctly but cv2.imwrite() saved the same image as black

from scipy.misc import imread
from matplotlib import pyplot

import cv2
from cv2 import cv

from SRM import SRM ## Module for Statistical Regional Segmentation

im = imread("lena.png") 
im2 = cv2.imread("lena.png")
print type(im), type(im2), im.shape, im2.shape 
## Prints <type 'numpy.ndarray'> <type 'numpy.ndarray'> (120, 120, 3) (120, 120, 3)

srm = SRM(im, 256)
segmented = srm.run()

srm2 = SRM(im2, 256)
segmented2 = srm2.run()

pic = segmented/256
pic2 = segmented2/256

pyplot.imshow(pic)
pyplot.imsave("onePic.jpg", pic)

pic = pic.astype('uint8')
cv2.imwrite("onePic2.jpg", pic2)

pyplot.show()

onePic.jpg gives the correct segmented image but onePic2.jpg gives a complete black image. Converting the datatype to uint8 using pic = pic.astype('uint8') did not help. I still gives a black image!

onePic.jpg using pyplot.imsave():

enter image description here

onePic2.jpg using cv2.imwrite():

enter image description here

Please help!

Upvotes: 30

Views: 55208

Answers (3)

sushii2001
sushii2001

Reputation: 21

I encountered a similar situation with face detection, I wonder if there is a better way to execute this, here is my solution here as a reference.

from deepface import DeepFace
import cv2 
import matplotlib.pyplot as plt

# import image and output
img_path = "image.jpg"
detected_face = DeepFace.detectFace(img_path, target_size = (128, 128))
plt.imshow(detected_face)

# image color scaling and saving 
detected_face = cv2.cvtColor( detected_face,cv2.COLOR_BGR2RGB)
detected_face = cv2.convertScaleAbs(detected_face, alpha=(255.0))
cv2.imwrite("image_thumbnail.jpg", detected_face)

Upvotes: 2

Although I agree with @sansuiso, in my case I found a possible edge case where my images were being shifted either one bit up in the scale or one bit down.

Since we're dealing with unsigned ints, a single shift means a possible underflow/overflow, and this can corrupt the whole image.

I found cv2's convertScaleAbs with an alpha value of 255.0 to yield better results.

def write_image(path, img):
    # img = img*(2**16-1)
    # img = img.astype(np.uint16)
    # img = img.astype(np.uint8)
    img = cv.convertScaleAbs(img, alpha=(255.0))
    cv.imwrite(path, img)

This answer goes into more detail.

Upvotes: 7

sansuiso
sansuiso

Reputation: 9379

Before converting pic to uint8, you need to multiply it by 255 to get the correct range.

Upvotes: 46

Related Questions