0

I have encountered a very strange problem. Imshow() is showing the same image for the three first imshows - why? (Only the red channel, it seems to have zeroed blue and green) I'm creating a copy of the original image, but it seems the operations affect all images. The forth imshow shows the red channel as grey-scale as expected. What am I doing wrong?

    ##### Image processing ####
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('/home/pi/Documents/testcode_python/Tractor_actual/Pictures/result2.jpg') #reads as BGR
print(img.shape)

no_blue=img
no_green=img
only_red=img[:,:,2] #Takes only red channel from BGR image and saves to "only_red"

no_blue[:,:,0]=np.zeros([img.shape[0], img.shape[1]]) #Puts Zeros on Blue channels for "no_blue"
no_green[:,:,1]=np.zeros([img.shape[0], img.shape[1]])

print(no_blue.shape)

cv2.imshow('Original',img)
cv2.imshow('No Blue',no_blue)
cv2.imshow('No Green',no_green)
cv2.imshow('Only Red', only_red)
cv2.waitKey(0)
cv2.destroyAllWindows()

enter image description here

Raz
  • 3
  • 4
  • I think you need to make a copy of the image. As it is written above, your no_blue, no_green, and only_red all point to the same image. See https://stackoverflow.com/a/16535453/5386938 –  Dec 15 '20 at 18:24
  • As an aside, you can set a subset of an array to a single scalar with just normal assignment. I.e. you can just do `no_blue[:, :, 0] = 0`. You don't have to construct a separate array and then assign the values, that would be slower and serve no purpose. – alkasm Dec 15 '20 at 18:42
  • Thank you! Making copies solved the issue. Much appreciated for quick support. – Raz Dec 15 '20 at 19:57

1 Answers1

0

You would need to create a copy of the image to avoid using the same memory location as img. Not sure if this is what you are looking in for only_red, but having all three channels with blue and green set to 0 will avoid it from being considered a single channel grayscale image.

    ##### Image processing ####
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('/home/pi/Documents/testcode_python/Tractor_actual/Pictures/result2.jpg') #reads as BGR
print(img.shape)

no_blue=img.copy() # copy of img to avoid using the same memory location as img
no_green=img.copy() # copy of img to avoid using the same memory location as img
only_red=img.copy() # similarly to above. 

# You also need all three channels of the RGB image to avoid it being interpreted as single channel image.
only_red[:,:,0] = np.zeros([img.shape[0], img.shape[1]])
only_red[:,:,1] = np.zeros([img.shape[0], img.shape[1]])
# Puts zeros for green and blue channels

no_blue[:,:,0]=np.zeros([img.shape[0], img.shape[1]]) #Puts Zeros on Blue channels for "no_blue"
no_green[:,:,1]=np.zeros([img.shape[0], img.shape[1]])

print(no_blue.shape)

cv2.imshow('Original',img)
cv2.imshow('No Blue',no_blue)
cv2.imshow('No Green',no_green)
cv2.imshow('Only Red', only_red)
cv2.waitKey(0)
cv2.destroyAllWindows()
SJ11
  • 244
  • 1
  • 3
  • Thank you - works like a charm! I did not consider that it would use the same memory allocation. – Raz Dec 15 '20 at 19:55