PIL image shows OK but saves black - python

Using PIL Image to binarize an image to optimize OCR shows good results on-screen but saves all black PNG. And when passing the image object to process with pytesseract it also returns no text...
Note: I don't really need to save the processed image as long as the OCR works.
basepath = 'img_bin/'
image_list = os.listdir(basepath)
for file in image_list:
if os.path.isfile(os.path.join(basepath, file)):
print(file)
img = Image.open(basepath+file).convert("L")
img = ImageOps.invert(img)
threshold = 20
table = []
pixelArray = img.load()
for y in range(img.size[1]): # binaryzate it
List = []
for x in range(img.size[0]):
if pixelArray[x,y] > threshold:
List.append(0)
else:
List.append(255)
table.append(List)
img = Image.fromarray(np.array(table))
img.show()
img.save(basepath+'processed.png')
img_lines = pytesseract.image_to_string(img)
print(len(img_lines))
print(img_lines)
OUTPUTS:
print(len(img_lines)) -> 1
print(img_lines) -> <0x0c>
img.show():
saved 'processed.png'

You need to convert the image mode to RGB:
if img.mode != 'RGB':
img = img.convert('RGB')
img.save(basepath+'processed.png')
That's because the save method assumes RGB mode.

Related

error: im not able to convert my images from bgr to rgb: TypeError: Expected Ptr<cv::UMat> for argument 'src'

#error: im not able to convert my images from bgr to rgb
images = []
path = 'E:\subjects\AI\Face-Mask-Detection-master\without-mask-detections'
listimages=os.listdir(path)
encode_list = []
for img in listimages:
images.append(img)
img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
encode = face_recognition.face_encodings(img)
encode_list.append(encode)
print(images)
#encodeListKnown= find_encoding(images)
#print(len(encodeListKnown))
The file name you are using (img) does not include the full path and cannot be opened. Also, your code does not open the image file. You should build the full path and open it using:
for file in listimages:
img = cv2.imread(os.path.join(path, file))
images.append(img)
img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
encode = face_recognition.face_encodings(img)
encode_list.append(encode)

How to perform binary thresholding on a set of images (.png format) and write them in another folder with same file name (and same .png extension)?

I have 450 image labels (for semantic segmentation) in .png format. But, in order to use these images, I have to convert them into binary images. So, I have written a code which performs this task. However, in the final folder where these binary images are saved, the file names got shuffled. I am unable to understand why. Below is my code.
import matplotlib, cv2
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image, ImageOps
import glob
%matplotlib inline
filename = '/content/gdrive/My Drive/mm/train_labels_binary/' #folder to save output images
images = glob.glob("/content/gdrive/My Drive/mm/train_labels/*.png")
print(len(images))
image_no = 1
for image in images:
img = cv2.imread(image)
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
_,threshold_img = cv2.threshold(gray_img, 181, 255, cv2.THRESH_BINARY)
#threshold_img = cv2.cvtColor(threshold_img, cv2.COLOR_GRAY2RGB)
cv2.imwrite(filename + str(image_no) + '.png', threshold_img)
image_no = image_no + 1
If you want to preserve the original filenames use the basename function:
import os
filename = '/content/gdrive/My Drive/mm/train_labels_binary/' #folder to save output images
images = glob.glob("/content/gdrive/My Drive/mm/train_labels/*.png")
print(len(images))
image_no = 1
for image in images:
img = cv2.imread(image)
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
_,threshold_img = cv2.threshold(gray_img, 181, 255, cv2.THRESH_BINARY)
#threshold_img = cv2.cvtColor(threshold_img, cv2.COLOR_GRAY2RGB)
image_filename = os.path.basename(image)
path = os.path.join(filename, image_filename)
cv2.imwrite(path, threshold_img)
image_no = image_no + 1

Difficulty in writing crops of images using OpenCV and Python

I am using the following code to read multiple images from a folder and to take a specific crop from all of them and also write them at the end. The cropping part does not seem to work meaning the cropped parts are not getting written.
# import the necessary packages
import cv2
import os, os.path
#image path and valid extensions
imageDir = "C:\\Users\\Sayak\\Desktop\\Training\\eye\\1" #specify your path here
image_path_list = []
valid_image_extensions = [".jpg", ".jpeg", ".png", ".tif", ".tiff"] #specify your vald extensions here
valid_image_extensions = [item.lower() for item in valid_image_extensions]
#create a list all files in directory and
#append files with a vaild extention to image_path_list
for file in os.listdir(imageDir):
extension = os.path.splitext(file)[1]
if extension.lower() not in valid_image_extensions:
continue
image_path_list.append(os.path.join(imageDir, file))
#loop through image_path_list to open each image
for imagePath in image_path_list:
image = cv2.imread(imagePath)
# display the image on screen with imshow()
# after checking that it loaded
if image is not None:
cv2.imshow(imagePath, image)
elif image is None:
print ("Error loading: " + imagePath)
#end this loop iteration and move on to next image
continue
crop_img = image[200:400, 100:300]
cv2.imwrite('pic{:>05}.jpg'.format(imagePath), crop_img)
# wait time in milliseconds
# this is required to show the image
# 0 = wait indefinitely
# exit when escape key is pressed
key = cv2.waitKey(0)
if key == 27: # escape
break
# close any open windows
cv2.destroyAllWindows()
I have modified your code posted above. The problem lies with your string formatting used in cv2.imwrite(). The first argument must be an absolute path to where the file should be saved, but your code is passing in something like this.
pic{:>05}.jpg => pic/home/ubuntu/Downloads/10_page.png.jpg. When I used a valid file name there is no problem saving the cropped image at all.
#loop through image_path_list to open each image
for i,imagePath in enumerate(image_path_list):
image = cv2.imread(imagePath)
# display the image on screen with imshow()
# after checking that it loaded
if image is not None:
cv2.imshow(imagePath, image)
elif image is None:
print ("Error loading: " + imagePath)
#end this loop iteration and move on to next image
continue
# Please check if the size of original image is larger than the pixels you are trying to crop.
(height, width, channels) = image.shape
if height >= 400 and width >= 300:
plt.imshow(image)
plt.title('Original')
plt.show()
crop_img = image[100:400, 100:400]
# Problem lies with this path. Ambiguous like pic/home/ubuntu/Downloads/10_page.png.jpg
print('pic{:>05}.jpg'.format(imagePath))
# Try a proper path. A dirname + file_name.extension as below, you will have no problem saving.
new_image = os.path.join(imageDir,'{}.png'.format(str(i)))
cv2.imwrite(new_image, crop_img)
plt.imshow(crop_img)
plt.title('Cropped')
plt.show()

cv2.resize() error: saves the same picture with different names

I am new in programming and trying to make an image resizer. I wanted to make possibility to write custom prefix by the user before in the filenames. Sizes are also customable.
The cv2.imshow() works fine, but cv2.resize() does not. If I check it with imshow, it shows only one picture despite of the for loop, and then cv2.imwrite saves only one picture with the names all the selected pictures.
The lists seems to be OK.
I hope I am clear, the code:
def openfiles():
global picture_original
global file_path
global f
# Valid filetypes
file_types=[("Jpeg files","*.jpg"),("PNG files","*.png"),("BMP files","*.bmp"),("all files","*.*")]
window.filenames = filedialog.askopenfilenames(initialdir = "/",title = "Select file",filetypes = (file_types)) # TUPLE of filepath/filenames
#f = []
# Creating a list from the tuple
for pics in window.filenames:
f.append(pics)
f = [picture.replace('/', "\\") for picture in f]
try:
for picture in f:
picture_original = cv2.imread(picture, 1)
#cv2.imshow("Preview", picture_original)
#cv2.waitKey(1)
except:
msgbox_openerror() # Error opening the file
# Getting the filepath only from the list "f":
file_path = f[0].rsplit("\\",1)[0]
view_list()
def save_command():
"""
function to save the resized pictures
"""
global picture_resized
global prefix
prefix = "Resized_"
lst_filename = []
lst_renamed = []
for i in f:
#print(f)
path,filename = os.path.split(i) # path - only filepath | filename - only filename with extension
lst_filename.append(prefix+filename)
for i in range(len(f)):
lst_renamed.append(os.path.join(path, lst_filename[i]))
for i in range(len(f)):
picture_resized = cv2.resize(picture_original, ((int(width.get())), int(height.get())))
cv2.imshow("Preview", picture_resized)
cv2.waitKey(1)
for i in lst_renamed:
cv2.imwrite(i, picture_resized)
I hope someone have some ideas. Thank you in advance!
This is an example to resize by a ratio and saves your image
def ResizeImage(filepath, newfileName,ratio):
image = cv2.imread(filepath) #Open image
height, width = image.shape[:2] #Shapes
image2 = cv2.resize(image, (width/ratio, height/ratio), interpolation = cv2.INTER_AREA)
cv2.imwrite(newfileName,image2) #saves, True if OK
return filepath
So if you call
image = "originalpath"
resized = ResizeImage(image,"Resized_"+image,2)
newImage = cv2.imread(resized)
cv2.imshow("new",newImage)
cv2.waitKey(1)
You should get your Image resized by half

Crop transparent PNG image with my own coords with python and PIL

Now my code write PNG, but I can't open it - errors of file.
Without crooping all works, but I need crop png file. With my coords (no PIL box), and transparent images.
Image.open(imagefile)
#image = image.crop(crop_coords) #only work without cropping
image.thumbnail([x, y], Image.ANTIALIAS)
imagefile = StringIO()
imagefile = open(file_destination, 'w')
try:
image.save(imagefile, "PNG", quality=90)
except:
print "Cannot save user image"
Thanks for help.
I have noticed that problem is only for png files with indexed PNG alpha images.
from PIL import Image
#from StringIO import StringIO
img = Image.open("foobar.png")
png_info = {}
if img.mode not in ['RGB','RGBA']:
img = img.convert('RGBA')
png_info = img.info
img = img.crop( (0,0,400,400) )
img.thumbnail([200, 200], Image.ANTIALIAS)
file_destination='quux.png'
# imagefile = StringIO()
imagefile = open(file_destination, 'wb')
try:
img.save(imagefile, "png", quality=90, **png_info)
imagefile.close()
except:
print "Cannot save user image"
thanks for:
PIL does not save transparency
You must open the file in binary mode, otherwise it will write something but file may be corrupted. According to the test you do, the file will be corrupted or not, that may not be because of the crop itself.
Here is a working version I made:
from PIL import Image
#from StringIO import StringIO
img = Image.open("foobar.png")
img = img.crop( (0,0,400,400) )
img.thumbnail([200, 200], Image.ANTIALIAS)
file_destination='quux.png'
# imagefile = StringIO()
imagefile = open(file_destination, 'wb')
try:
img.save(imagefile, "png", quality=90)
imagefile.close()
except:
print "Cannot save user image"
Here is a simple solution using numpy and Pillow, just change the questionmarks with your own coords!
from PIL import Image
import numpy as np
def crop(png_image_name):
pil_image = Image.open(png_image_name)
np_array = np.array(pil_image)
# z is the alpha depth, leave 0
x0, y0, z0 = (?, ?, 0)
x1, y1, z1 = (?, ?, 0)
cropped_box = np_array[x0:x1, y0:y1, z0:z1]
pil_image = Image.fromarray(cropped_box, 'RGBA')
pil_image.save(png_image_name)

Categories

Resources