OpenCV Shows Gray Window - python

I'm trying to display an image using OpenCV. I have the following very basic code:
import cv2
img = cv2.imread('myimage.png', 0) # Reads a Gray-scale image
img2 = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.imshow("window", img2)
The window is opened properly, with the correct size, but it's gray - there's no image. The image is read properly (looking at both img and img2 in the debugger I see the expected values, not just one shade).
Note: Obviously I intend to do some image processing prior to showing the image, but first I need to be able to see the image...

OK, got it.
Turns out I needed to let OpenCV start handling events, it wasn't handling the WM_PAINT event. Adding cv2.waitKey() fixed this.

Sometimes the image size is high enough for imshow().
Try to resize the image by:
dimensions = (400,800)
image= cv2.imread('myimage.png', 0)
resized = cv2.resize(image, dimensions, interpolation = cv2.INTER_AREA)
cv2.imshow("window", resized )

Related

PIL, CV2: Image quality breaks after converting from PIL to Numpy

I have this image and I read as a PIL file. Then, I save it back using save method in PIL and imwrite method in cv2. Saving the image with imwrite downgrades the image quality (it becomes black and white and text can't be read).
image = Image.open("image.png")
cv2_image = numpy.asarray(image)
image.save("pil.png")
cv2.imwrite("opencv.png", cv2_image)
Here are the output files:
pil.png
opencv.png
The input image is a palette image - see here. So, you need to convert it to RGB otherwise you just pass OpenCV the palette indices but without the palette.
So, you need:
image = Image.open(...).convert('RGB')
Now make it into a Numpy array:
cv2image = np.array(image)
But that will be in RGB order, so you need to reverse the channel order:
cv2image = cv2image[..., ::-1]

How to change the background of an image using PIL?

I was trying to find how to remove/change the background of a grayscale image in Python using PIL package but I failed. What I have is an RGB image which has a white background and I would like to load it, resize, change the background from white to black and save. So far I can do the beginning:
from PIL import Image
img = Image.open('my_picture.jpg').convert('LA')
# im1 = img.crop((left, top, right, bottom))
which gives me a grayscale image of a size I want but now I do not know how to change the background. I have found a really good post using cv2 for cropping the image out from a green bg and also another setting the background directly, but I couldn't find it for PIL. Is there such an option?
Convert image into RGB and get the data. Then do follow the step.
from PIL import Image
img = Image.open("test_image.jpg")
img = img.convert("RGB")
datas = img.getdata()
new_image_data = []
for item in datas:
if item[0] in list(range(190, 256)):
new_image_data.append((255, 204, 100))
else:
new_image_data.append(item)
img.putdata(new_image_data)
img.save("test_image_altered_background.jpg")
img.show()
You can get some idea from here

Open high resolution images with Opencv

I can't open a 24MP pictures on Python with opencv. It only opens the upper left part apparently and not the full image. The kernel also stops after running the code.
Here's my code:
import cv2
import numpy as np
PICTURE_PATH_NAME = "IMG.JPG"
img = cv2.imread(PICTURE_PATH_NAME)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("Gray Image", gray)
cv2.waitKey(0)
See the documentation for imshow as to how to get it to scale your image to fit the window at https://docs.opencv.org/4.1.1/d7/dfc/group__highgui.html#ga453d42fe4cb60e5723281a89973ee563
"If you need to show an image that is bigger than the screen
resolution, you will need to call namedWindow("", WINDOW_NORMAL)
before the imshow."

Why reading colored image as Gray Scale in OpenCv is different from convert same image from BGR to GRAY [duplicate]

I am working in opencv(2.4.11) python(2.7) and was playing around with gray images. I found an unusual behavior when loading image in gray scale mode and converting image from BGR to GRAY. Following is my experimental code:
import cv2
path = 'some/path/to/color/image.jpg'
# Load color image (BGR) and convert to gray
img = cv2.imread(path)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Load in grayscale mode
img_gray_mode = cv2.imread(path, 0)
# diff = img_gray_mode - img_gray
diff = cv2.bitwise_xor(img_gray,img_gray_mode)
cv2.imshow('diff', diff)
cv2.waitKey()
When I viewed the difference image, I can see the left out pixels instead of jet black image. Can you suggest any reason? What is the correct way of working with gray images.
P.S. When I use both the images in SIFT, keypoints are different which may lead to different outcome specially when working with bad quality images.
Note: This is not a duplicate, because the OP is aware that the image from cv2.imread is in BGR format (unlike the suggested duplicate question that assumed it was RGB hence the provided answers only address that issue)
To illustrate, I've opened up this same color JPEG image:
once using the conversion
img = cv2.imread(path)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
and another by loading it in gray scale mode
img_gray_mode = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
Like you've documented, the diff between the two images is not perfectly 0, I can see diff pixels in towards the left and the bottom
I've summed up the diff too to see
import numpy as np
np.sum(diff)
# I got 6143, on a 494 x 750 image
I tried all cv2.imread() modes
Among all the IMREAD_ modes for cv2.imread(), only IMREAD_COLOR and IMREAD_ANYCOLOR can be converted using COLOR_BGR2GRAY, and both of them gave me the same diff against the image opened in IMREAD_GRAYSCALE
The difference doesn't seem that big. My guess is comes from the differences in the numeric calculations in the two methods (loading grayscale vs conversion to grayscale)
Naturally what you want to avoid is fine tuning your code on a particular version of the image just to find out it was suboptimal for images coming from a different source.
In brief, let's not mix the versions and types in the processing pipeline.
So I'd keep the image sources homogenous, e.g. if you have capturing the image from a video camera in BGR, then I'd use BGR as the source, and do the BGR to grayscale conversion cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Vice versa if my ultimate source is grayscale then I'd open the files and the video capture in gray scale cv2.imread(path, cv2.IMREAD_GRAYSCALE)

cv2.imshow and numpy.dstack core dumped

I am trying to stack two images together, so i can show both in a single window.
First image is the original, 3-channel image, second one is a gray version.
I did the color conversion with cv2.cvtColor, transformed back to 3-channel with numpy.dstack,
and when i try cv2.imshow, it gives me a "core dumped" error.
Am i missing something? I need both images to have the same number of channels to stack them
with numpy.hstack. This happens on a Ubuntu 64bit machine.
import cv2
import numpy as np
img = cv2.imread("/home/bernie/Dropbox/Python/Opencv/lena512.jpg")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = np.dstack((gray,gray,gray))
#res = np.hstack((img,gray))
print gray.dtype
print gray.shape
cv2.imshow('gray',gray)
#cv2.imshow('res',res)
cv2.waitKey()
addition
On the other hand, using
gray = cv2.cvtColor(gray,cv2.COLOR_GRAY2BGR)
in line 7 works without complaints, so i will stick to this for now. This means that there is a difference
between
the cv2.cvtColor result and numpy.dstack result for turning a 1-channel image to 3-channel with equal values.
As suggested in the comments, try using cv2.merge since apparently it's strided differently from np.dstack:
gray = cv2.merge([gray]*3)
See #fraxel's link for more info

Categories