Resizing Image in Python without losing letter quality - python

I have tried using the following code in order resize my picture, but I lose so much quality that I cannot even read the letters clearly. At first I create it the picture from a string, which has very good quality .
handoverNote = str.encode(handoverNote)
with open("test.png", "wb") as f:
f.write(codecs.decode(handoverNote, "base64"))
image = Image.open("test.png")
image.thumbnail((500, 500), Image.ANTIALIAS)
image.save("test2.png", quality=95)
But after resizing the image looks unreadable or alstmost unrecognizable like in this example:
This is the original image, I get without resizing.
What am I doing wrong here? Is it because I use PNG?

Related

Is saving PIL images after modifying necessary?

I'm using PIL module to get some data out of some images. I do this:
img = Image.open("example.jpg")
img = img.convert('L')
img.resize((800, 800))
data_list.append(np.array(img).flatten()/255)
I modify the image and then save the data that I want in a list. Is it okay to then just leave the image like this and not save it? because I don't really care about the image after I got the thing I want, so I prefer keep the images as it was. Is there a problem with changing an image and not saving it or I should do something to reset it?
When using img = Image.open("example.jpg") PIL only loads a copy of the image into the memory. The actual image file stays untouched, so you don't need to add any additional code.
You can however delete the variable with del img, which can be useful, especially with bigger images to clear up the memory.

Why can't tesseract extract text that has a black background?

I have attached a very simple text image that I want text from. It is white with a black background. To the naked eye it seems absolutely legible but apparently to tesseract it is a rubbish. I have tried changing the oem and psm parameters but nothing seems to work. Please note that this works for other images but for this one.
Please try running it on your machine and see if it works. Or else I might have to change my ocr engine altogether.
Note: It was working earlier until I tried to add black pixels around the image to help the extraction process. Also I don't think that tesseract was trained on black text on a white background. It should be able to do this too. Also if this was true why does it work for other text images that have the same format as this one
Edit: Miraculously I tried running the script again and this time it was able to extract Chand properly but failed in the below mentioned case. Also please look at the parameters I have used. I have read the documentation and I feel this would be the right choice. I have added the image for your reference. It is not about just this image. Why is tesseract failing for such simple use cases?
To find the desired result, you need to know the followings:
Page-segmentation-modes
Suggested Image processing methods
The input images are boldly written, we need to shrink the bold font and then assume the output as a single uniform block of text.
To shrink the images we could use erosion
Result will be:
Erode
Result
CHAND
BAKLIWAL
Code:
# Load the library
import cv2
import pytesseract
# Initialize the list
img_lst = ["lKpdZ.png", "ZbDao.png"]
# For each image name in the list
for name in img_lst:
# Load the image
img = cv2.imread(name)
# Convert to gry-scale
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Erode the image
erd = cv2.erode(gry, None, iterations=2)
# OCR with assuming the image as a single uniform block of text
txt = pytesseract.image_to_string(erd, config="--psm 6")
print(txt)

how to reduce png image filesize in PIL

I have used PIL to convert and resize JPG/BMP file to PNG format. I can easily resize and convert it to PNG, but the file size of the new image is too big.
im = Image.open('input.jpg')
im_resize = im.resize((400, 400), Image.ANTIALIAS) # best down-sizing filter
im.save(`output.png')
What do I have to do to reduce the image file size?
PNG Images still have to hold all data for every single pixel on the image, so there is a limit on how far you can compress them.
One way to further decrease it, since your 400x400 is to be used as a "thumbnail" of sorts, is to use indexed mode:
im_indexed = im_resize.convert("P")
im_resize.save(... )
*wait *
Just saw an error in your example code:
You are saving the original image, not the resized image:
im=Image.open(p1.photo)
im_resize = im.resize((400, 400), Image.ANTIALIAS) # best down-sizing filter
im.save(str(merchant.id)+'_logo.'+'png')
When you should be doing:
im_resize.save(str(merchant.id)+'_logo.'+'png')
You are just saving back the original image, that is why it looks so big. Probably you won't need to use indexed mode them.
Aother thing: Indexed mode images can look pretty poor - a better way out, if you come to need it, might be to have your smalle sizes saved as .jpg instead of .png s - these can get smaller as you need, trading size for quality.
You can use other tools like PNGOUT

Python Image Library: clean Downsampling

I've been having trouble trying to get PIL to nicely downsample images. The goal, in this case, is for my website to automagically downsample->cache the original image file whenever a different size is required, thus removing the pain of maintaining multiple versions of the same image. However, I have not had any luck. I've tried:
image.thumbnail((width, height), Image.ANTIALIAS)
image.save(newSource)
and
image.resize((width, height), Image.ANTIALIAS).save(newSource)
and
ImageOps.fit(image, (width, height), Image.ANTIALIAS, (0, 0)).save(newSource)
and all of them seem to perform a nearest-neighbout downsample, rather than averaging over the pixels as it should Hence it turns images like
http://www.techcreation.sg/media/projects//software/Java%20Games/images/Tanks3D%20Full.png
to
http://www.techcreation.sg/media/temp/0x5780b20fe2fd0ed/Tanks3D.png
which isn't very nice. Has anyone else bumped into this issue?
That image is an indexed-color (palette or P mode) image. There are a very limited number of colors to work with and there's not much chance that a pixel from the resized image will be in the palette, since it will need a lot of in-between colors. So it always uses nearest-neighbor mode when resizing; it's really the only way to keep the same palette.
This behavior is the same as in Adobe Photoshop.
You want to convert to RGB mode first and resize it, then go back to palette mode before saving, if desired. (Actually I would just save it in RGB mode, and then turn PNGCrush loose on the folder of resized images.)
This is over a year old, but in case anyone is still looking:
Here is a sample of code that will see if an image is in a palette mode, and make adjustments
import Image # or from PIL import Image
img = Image.open(sourceFile)
if 'P' in img.mode: # check if image is a palette type
img = img.convert("RGB") # convert it to RGB
img = img.resize((w,h),Image.ANTIALIAS) # resize it
img = img.convert("P",dither=Image.NONE, palette=Image.ADAPTIVE)
#convert back to palette
else:
img = img.resize((w,h),Image.ANTIALIAS) # regular resize
img.save(newSourceFile) # save the image to the new source
#img.save(newSourceFile, quality = 95, dpi=(72,72), optimize = True)
# set quality, dpi , and shrink size
By converting the paletted version to RGB, we can resize it with the anti alias. If you want to reconvert it back, then you have to set dithering to NONE, and use an ADAPTIVE palette. If there options aren't included your result (if reconverted to palette) will be grainy. Also you can use the quality option, in the save function, on some image formats to improve the quality even more.

Transparent PNG in PIL turns out not to be transparent

I have been hitting my head against the wall for a while with this, so maybe someone out there can help.
I'm using PIL to open a PNG with transparent background and some random black scribbles, and trying to put it on top of another PNG (with no transparency), then save it to a third file.
It comes out all black at the end, which is irritating, because I didn't tell it to be black.
I've tested this with multiple proposed fixes from other posts. The image opens in RGBA format, and it's still messed up.
Also, this program is supposed to deal with all sorts of file formats, which is why I'm using PIL. Ironic that the first format I tried is all screwy.
Any help would be appreciated. Here's the code:
from PIL import Image
img = Image.open(basefile)
layer = Image.open(layerfile) # this file is the transparent one
print layer.mode # RGBA
img.paste(layer, (xoff, yoff)) # xoff and yoff are 0 in my tests
img.save(outfile)
I think what you want to use is the paste mask argument.
see the docs, (scroll down to paste)
from PIL import Image
img = Image.open(basefile)
layer = Image.open(layerfile) # this file is the transparent one
print layer.mode # RGBA
img.paste(layer, (xoff, yoff), mask=layer)
# the transparancy layer will be used as the mask
img.save(outfile)

Categories

Resources