How to save grayscale image in Python? - python

I am trying to save a grayscale image using matplotlib savefig(). I find that the png file which is saved after the use of matplotlib savefig() is a bit different from the output image which is showed when the code runs. The output image which is generated when the code is running contains more details than the saved figure.
How can I save the output plot in such a manner that all details are stored in the output image?
My my code is given below:
import cv2
import matplotlib.pyplot as plt
plt.figure(1)
img_DR = cv2.imread(‘image.tif',0)
edges_DR = cv2.Canny(img_DR,20,40)
plt.imshow(edges_DR,cmap = 'gray')
plt.savefig('DR.png')
plt.show()
The input file (‘image.tif’) can be found from here.
Following is the output image which is generated when the code is running:
Below is the saved image:
Although the two aforementioned images denote the same picture, one can notice that they are slightly different. A keen look at the circular periphery of the two images shows that they are different.

Save the actual image to file, not the figure. The DPI between the figure and the actual created image from your processing will be different. Since you're using OpenCV, use cv2.imwrite. In your case:
cv2.imwrite('DR.png', edges_DR)
Use the PNG format as JPEG is lossy and would thus give you a reduction in quality to promote small file sizes. If accuracy is the key here, use a lossless compression standard and PNG is one example.
If you are somehow opposed to using OpenCV, Matplotlib has an equivalent image writing method called imsave which has the same syntax as cv2.imwrite:
plt.imsave('DR.png', edges_DR, cmap='gray')
Note that I am enforcing the colour map to be grayscale for imsave as it is not automatically inferred like how OpenCV writes images to file.

Since you are using cv2 to load the image, why not using it also to save it.
I think the command you are looking for is :
cv2.imwrite('gray.jpg', gray_image)

Using a DPI that matches the image size seems to make a difference.
The image is of size width=2240 and height=1488 (img_DR.shape). Using fig.get_size_inches() I see that the image size in inches is array([7.24, 5.34]). So an appropriate dpi is about 310 since 2240/7.24=309.4 and 1488/5.34=278.65.
Now I do plt.savefig('DR.png', dpi=310) and get
One experiment to do would be to choose a high enough DPI, calculate height and width of figure in inches, for example width_inch = width_pixel/DPI and set figure size using plt.figure(figsize=(width_inch, height_inch)), and see if the displayed image itself would increase/decrease in quality.
Hope this helps.

Related

Python Image Scaling

I'm trying to scale a screenshot using this code :
im = Image.open(img_path)
im = im.resize((newWidth,newHeight),Image.ANTIALIAS)
but this results in a very low quality image especially texts are impossible to read
Original
Click for original Image
Scaled
Click for scaled Image
I have tried other algorithms in PIL but none of them gives the result I wanted.
I actually tried to resize my images inside Office PowerPoint and texts are clear and readable.
PowerPoint scaled
Click for Office scaled Image
Are there any other ways which I can scale the Images ?
it had worked for me.
import imutils
im = imutils.resize(im, width=Image.ANTIALIAS)
if you want for details, you can examine https://www.programcreek.com/python/example/93640/imutils.resize

Issue while plotting single channeled images (e.g. grayscale) using imshow

While plotting single channel image (i.e. while plotting grayscale images) when using Python it does not plot in gray-scale.
Example: expected output, after converting a coloured image using COLOR_BGR2GRAY from open cv :
But, the output obtained is:
Can anyone help me find out, what is the exact issue?
Upon researching, I found out that, the issue is actually not with open cv, but it is with matplotlib package. While displaying the image, the matplotlib package uses a colormap and hence it has to be explicitly set to gray, using :
plt.imshow(image, cmap="gray")

Python Wand Scaling Issue

I'm using Python Wand module(version 0.4.3.) to convert an image stored in pdf to PNG. Final PNG quality is great when I saved the final image in its orignal image width and height. But, when I try to save it to smaller image final PNG gets blurry and quality is not that great.
The difference between two images is shown here. Top image is converted to original size (10800x7200px). The second one is scale to 1250x833px.
Is there any way I can improve the second image? I played with different filter and blur setting.But, could not get the image quality I want. Any help is greatly appreciated.
Code I used to convert PDF to png in its original size:
def pdf_to_png(pdf_name, res):
with Image(filename=pdf_name, resolution=res) as img:
with Image(width=img.width,height=img.height, background=Color("white")) as bg:
bg.composite(img,0,0)`
bg.save(filename="Drawing_improved_wand.png")`
pdf_to_png('Drawing_1.pdf', 300)
Code for resized png:
with Image(filename="Drawing_1.pdf", resolution=(300,300)) as img:
with Image(width=1250, height=833, background=Color("white")) as bg:
img.resize(1250, 833,filter='undefined', blur=1)
img.format = 'png'
bg.composite(img,0,0)
bg.save(filename='Drawing_improved_wand1250x833.png')
This is likely due to an inefficiency with how ImageMagick handles rasterization form PDF text + vectors, and not because of anything you're doing wrong. The large PNG likely has the same problems as the small one, but since the resolution is almost an order of magnitude higher, the effects become imperceptible.
If when exporting to the large PNG the file looks good, I would use this for further processing (like scaling down) and not the PDF.
have you try to set blur < 1?
for example:
img.resize(1250, 833,filter='undefined', blur=0.1)

matplotlib: saved imshow pdf looks different from the plot window

The following figure was plotted using imshow in matplotlib with option interpolation='none':
However, after I saved it as a pdf file, the saved pdf file looks quite different:
The problem is: the blue patterns become very blurry.
My question is: How can I save a pdf figure that looks exactly like the plot window?
I solved this problem by specifying the dpi in the savefig for filetype pdf. Even though i read online that dpi is not supposed to make a difference in the vector based pdf format in theory, it did solve the problem for me in practice.
plt.imshow(np.random.random((10,10)))
plt.savefig("test.pdf", dpi=300)
PDF format is a vector image format. This means it is upto the program you open it in to interpret how it should be drawn. This can have some benefits when you want to be able to arbitrarily zoom in and out of an image while keeping high quality. However some programs can modify the image through anti-aliasing.
Your best bet for consistency is to use a pixel based image format. I would suggest try saving it as a .png.

Strange bug while combining images in Python

I have a hundred 10x10 px images, and I want to combine them into a big 100x100 image. I'm using the Image library to first create a blank image and then paste in the smaller images:
blank = Image.new('P',(100,100))
blank.paste(im,box)
The smaller images are in color, but the resulting image turns out in all grayscale. Is there a fix or workaround for this?
It's probably something to do with using a palette type image (mode P). Is there a specific reason you are doing this? If not, try passing 'RGB' as the first argument.

Categories