cv2 edited image saves with wrong colors - python

I'm working on a grayscale .tif file:
I convert it to BGR and try to draw some colorful stuff on it. If I save the result as .png, it's all still in shades of gray, including the drawn elements. If I save it as .jpg, colors of them are okay, but the rest of image is a lot brighter than it was, which I definitely don't want to happen.
simplified example of what I'm trying to do:
def draw_lines(image_path):
image = cv2.cvtColor(cv2.imdecode(np.fromfile(image_path, dtype=np.uint8), cv2.IMREAD_UNCHANGED), cv2.COLOR_GRAY2BGR)
cv2.line(image, (0,10), (image.shape[1], 1000), (0, 255, 0), 10)
cv2.imwrite("result.jpg", image)

I'm not exactly sure why, but apparently the problem was caused by usage of flag cv2.IMREAD_UNCHANGED
After changing this line to image = cv2.imdecode(np.fromfile(image_path, dtype=np.uint8), cv2.IMREAD_COLOR) everything works fine, no matter which extension

Related

Error when trying to change the default colour of rectangle in OpenCV

I'm working to create bounding boxes around the data I need to extract from an image. (I am using Jupyter notebook for python and OpenCV).
For this, I am drawing rectangles of desired coordinates and am using the following line of code:
cv2.rectangle(img,(50,82),(440,121), (0, 255, 0), 1)
This is for some reason giving only a black rectangle even though (0,255,0) is supposed to give green. What's more, if I use any other colour, for example (255,255,0), the box doesn't appear at all.
Thanks in advance for your help!
Is the image img that you are drawing on binary or grayscale? If so, make it color by merging the same image 3 times so that you have an RGB image with R=G=B. Or convert it Gray2BGR using cvtColor(). That is in Python/OpenCV do either
img = cv2.merge([img,img,img])
or
img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGB)

Image.open() gives a plain white image

I am trying to edit this image:
However, when I run
im = Image.open(filename)
im.show()
it outputs a completely plain white image of the same size. Why is Image.open() not working? How can I fix this? Is there another library I can use to get non-255 pixel values (the correct pixel array)?
Thanks,
Vinny
Image.open actually seems to work fine, as does getpixel, putpixel and save, so you can still load, edit and save the image.
The problem seems to be that the temp file the image is saved in for show is just plain white, so the image viewer shows just a white image. Your original image is 16 bit grayscale, but the temp image is saved as an 8 bit grayscale.
My current theory is that there might actually be a bug in show where a 16 bit grayscale image is just "converted" to 8 bit grayscale by capping all pixel values to 255, resulting in an all-white temp image since all the pixels values in the original are above 30,000.
If you set a pixel to a value below 255 before calling show, that pixel shows correctly. Thus, assuming you want to enhance the contrast in the picture, you can open the picture, map the values to a range from 0 to 255 (e.g. using numpy), and then use show.
from PIL import Image
import numpy as np
arr = np.array(Image.open("Rt5Ov.png"))
arr = (arr - arr.min()) * 255 // (arr.max() - arr.min())
img = Image.fromarray(arr.astype("uint8"))
img.show()
But as said before, since save seems to work as it should, you could also keep the 16 bit grayscale depth and just save the edited image instead of using show.
you can use openCV library for loading images.
import cv2
img = cv2.imread('image file')
plt.show(img)

ImageChops.difference not working with simple png images

I am creating a simple script to check if images are the same or different.
My code works for the jpg files but not for the png files.
For some reason, my code below thinks that the below png:
is the same as below png
from PIL import Image, ImageChops
img1 = Image.open('./1.png')
img2 = Image.open('./2.png')
img3 = Image.open('./A.jpg')
img4 = Image.open('./B.jpg')
diff1 = ImageChops.difference(img3, img4)
diff = ImageChops.difference(img2, img1)
print(diff.getbbox())
if diff.getbbox():
diff.show() # does not work for me. should show image if they are different
print(diff1.getbbox())
if diff1.getbbox():
diff1.show() # this works not sure why the PNG files do not
I am running this on Ubuntu. I am not sure what I am doing wrong. Any help would be great thanks!
Working code after #Mark's help: https://github.com/timothy/image_diff/blob/master/test.py
Not 100% certain what's going on here, but if you take your two images and split them into their channels and lay the channels out side-by-side, with ImageMagick:
magick 1.png -separate +append 1ch.png
You can see the Red, Green and Blue channels all contain shapes but there is a superfluous alpha channel (the rightmost area) serving no purpose - other than to confuse PIL!
If you change your code to drop the alpha channel like this, it then works:
img1 = Image.open('1.png').convert('RGB')
img2 = Image.open('2.png').convert('RGB')
diff = ImageChops.difference(img2, img1)
diff.getbbox()
(28, 28, 156, 156)
Difference image:
I note also that the ImageChops.difference documentation says "one of the images must be "1" mode" and have no idea if that is an issue.

Transparet pixels are being pasted as black in PIL

I paste an image with transparent pixels, but they are black in the final image
img = Image.new('RGBA', (100, 100), "white")
arbol16 = Image.open("arbol16.png")
img.paste(arbol16,( 0, 0, 16, 16))
img.show()
arbol16.png image file:
The paste method does not take into account the alpha of the image it's pasting; you need to add a mask parameter to control that. If the image you're pasting is RGBA you can just pass it twice.
arbol16 = arbol16.convert("RGBA")
img.paste(arbol16, (0, 0, 16, 16), arbol16)
I think you're (understandably) being confused by what the img.show() is displaying — which I believe is wrong (and may in fact be a bug). On my Windows system a temporary .BMP image is displayed, and it looks like the transparent pixels are black.
However if you add a line like img.save('arbol16_mod.png') at the end and then view that image file by manually opening it in some image file viewing program, such as Paint, Windows Photo Viewer, or Photoshop, the result is correct.

Python opencv drawContours does not show anything

I followed the tutorial at this page but nothing seems to happen when the line cv2.drawContours(im,contours,-1,(0,255,0),3) is executed. I was expecting to see star.jpg with a green outline, as shown in the tutorial. Here is my code:
import numpy as np
import cv2
im = cv2.imread('C:\Temp\ip\star.jpg')
print im.shape #check if the image is loaded correctly
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(im,contours,-1,(0,255,0),3)
pass
There are no error messages. star.jpg is the star from the above mentioned webpage.
I am using opencv version 2.4.8 and Python 2.7.
Is drawContours supposed to show an image on my screen? If so, what did I do wrong? If not, how do I show the image?
Thanks
Edit:
Adding the following lines will show the image:
cv2.imshow("window title", im)
cv2.waitKey()
waitKey() is needed otherwise the window will just show a gray background. According to this post, that's because waitKey() tells it to start handling the WM_PAINT event.
I had the same issue. I believe the issue is that the underlying image is 1-channel rather than 3-channel. Therefore, you need to set the color so it's nonzero in the first element (e.g. (255,0,0)).
i too had the same problem. The thing is it shows, but too dark for our eyes to see.
Solution:
change the colour from (0,255,0) (for some weird reason, i too had give exactly the same color!) to (128,255,0) (or some better brighter colour)
You have to do something to the effect of:
cv2.drawContours(im,contours,-1,(255,255,0),3)
cv2.imshow("Keypoints", im)
cv2.waitKey(0)
I guess your original image is in gray bit plane. Since your bit plane is Gray instead of BGR and so the contour is not showing up. Because it's slightly black and grey which you cannot distinguish. Here's the simple solution [By converting the bit plane]:
im=cv2.cvtColor(im,cv2.COLOR_GRAY2BGR)
cv2.drawContours(im,contours,-1,(0,255,0),3)

Categories

Resources