I've tried converting my image to grayscale using multiple methods, but my image won't convert
I tried:
image = cv2.imread(r"path\shoe.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow('Gray image',gray)
But the image stays the same
you can read images as grayscale directly
import cv2
import matplotlib.pyplot as plt
img_path=r'your path'
img=cv2.imread(img_path,cv2.IMREAD_GRAYSCALE)
plt.imshow(img)
This works for me in Python/OpenCV with your image on my Mac desktop along with the script. Two issues. 1) Your image is webp not png (at least what I can download from your link). 2) You need to add cv2.waitKey(0).
import cv2
image = cv2.imread("shoe.webp")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow('Gray image',gray)
cv2.waitKey(0)
Related
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]
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."
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)
This is my code:
img = cv2.imread(some_path, 0)
Original image:
After running the code:
Obviously losing a lot of transparency.
You can use PILLOW:
from PIL import Image
img = Image.open('image_to_grayscale.png').convert('LA')
img.save('greyscale.png')
Result:
I want to convert an image loaded
TestPicture = cv2.imread("flowers.jpg")
I would like to run a PIL filter like on the example with the variable
TestPicture
but I'm unable to convert it back and forth between these types.
Is there a way to do these conversions?
Can OpenCV do all of the image filters that are in the PIL package?
Example:
Result:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
threshold_img = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
im_pil = cv2_to_pil(threshold_img)
pytesseract.image_to_string(im_pil)
Out[5]: 'TUM'
Yes OpenCV is more robust and flexible and can perform most of the image processing routines which are available out there, So probably this filter can be done with OpenCV> However, there may not be a straightforward API for that.
Anyways, as far as the conversion of image format from OpenCV to PIL is concerned you may use Image.fromarray as:
import cv2
import numpy as np
from PIL import Image
img = cv2.imread("path/to/img.png")
# You may need to convert the color.
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
im_pil = Image.fromarray(img)
# For reversing the operation:
im_np = np.asarray(im_pil)
But you must keep in mind that, OpenCV follows BGR convention and PIL follows RGB color convention, so to keep the things consistent you may need to do use cv2.cvtColor() before conversion.
Pillow and OpenCV use different formats of images. So you can't just read an image in Pillow and manipulate it into an OpenCV image.
Pillow uses the RGB format as #ZdaR highlighted, and OpenCV uses the BGR format. So, you need a converter to convert from one format to another.
To convert from PIL image to OpenCV use:
import cv2
import numpy as np
from PIL import Image
pil_image=Image.open("demo2.jpg") # open image using PIL
# use numpy to convert the pil_image into a numpy array
numpy_image=numpy.array(pil_img)
# convert to a openCV2 image, notice the COLOR_RGB2BGR which means that
# the color is converted from RGB to BGR format
opencv_image=cv2.cvtColor(numpy_image, cv2.COLOR_RGB2BGR)
To convert from OpenCV image to PIL image use:
import cv2
import numpy as np
from PIL import Image
opencv_image=cv2.imread("demo2.jpg") # open image using openCV2
# convert from openCV2 to PIL. Notice the COLOR_BGR2RGB which means that
# the color is converted from BGR to RGB
color_converted = cv2.cvtColor(opencv_image, cv2.COLOR_BGR2RGB)
pil_image=Image.fromarray(color_converted)
Here are two functions to convert image between PIL and OpenCV:
def toImgOpenCV(imgPIL): # Conver imgPIL to imgOpenCV
i = np.array(imgPIL) # After mapping from PIL to numpy : [R,G,B,A]
# numpy Image Channel system: [B,G,R,A]
red = i[:,:,0].copy(); i[:,:,0] = i[:,:,2].copy(); i[:,:,2] = red;
return i;
def toImgPIL(imgOpenCV): return Image.fromarray(cv2.cvtColor(imgOpenCV, cv2.COLOR_BGR2RGB));
Convert from OpenCV img to PIL img will lost transparent channel. While convert PIL img to OpenCV img will able to keep transparent channel, although cv2.imshow not display it but save as png will gave result normally.