Error Opening PGM file with PIL and SKIMAGE - python-3.x

I have following Image file:
Image
I used PIL and Skimage to open it but I get following errors
First with PIL (tried with and without trucate option):
Code:
from PIL import Image, ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
img = Image.open("image_output.pgm")
Erorr:
OSError: cannot identify image file 'image_output.pgm'
And with Skimage:
Code:
from skimage import io
img = io.imread("image_output.pgm")
Error:
OSError: cannot identify image file <_io.BufferedReader name='image_output.pgm'>
I can open the file with GUI applications like system photo viewer and Matlab.
How can I diagnose what is wrong with image? I compared the byte data with other PGM files which I can open in Python, but could not identify the difference.
Thanks.

Your file is P2 type PGM, which means it is in ASCII - you can view it in a normal text editor. It seems neither PIL, nor skimage want to read that, but are happy to read the corresponding P5 type which is identical except it is written in binary, rather than ASCII.
There are a few options...
1) You could use OpenCV to read it:
import cv2
im = cv2.imread('a.pgm')
2) You could convert it to P5 with ImageMagick and then read the output.pgm file with skimage or PIL:
magick input.pgm output.pgm
3) If adding OpenCV, or ImageMagick as a dependency is a real pain for you, it is possible to read a PGM image yourself:
#!/usr/bin/env python3
import re
import numpy as np
# Open image file, slurp the lot
with open('input.pgm') as f:
s = f.read()
# Find anything that looks like numbers
# Technically, there could be comments that should be ignored
l=re.findall(r'[0-9P]+',s)
# List "l" will contain: P5, width, height, 255, pixel1, pixel2, pixel3...
# Technically, if l[3]>255, you should change the type of the Numpy array to uint16, but that is not the case
w, h = int(l[1]), int(l[2])
# Make Numpy image from data
ni = np.array(l[4:],dtype=np.uint8).reshape((h,w))

Related

How to save "IPython.core.display.SVG" as PNG file?

I am trying to save a variable with data-type of "IPython.core.display.SVG" as a PNG file in Jupyter Notebook environment.
First I tried:
with open('./file.png','wb+') as outfile:
outfile.write(my_svg.data)
And I got the error:
TypeError: a bytes-like object is required, not 'str'
Next, I tried:
with open('./file.png','wb+') as outfile:
outfile.write(my_svg.data.encode('utf-8'))
But, I cannot open "file.png". The operating system gives error:
The file “file.png” could not be opened. It may be damaged or use a file format that Preview doesn’t recognize.
I can save "my_svg" with "svg" extension as below:
with open('./file.svg','wb+') as outfile:
outfile.write(my_svg.data.encode('utf-8'))
But, when I want to convert "file.svg" into "file.png" by:
import cairosvg
cairosvg.svg2png(url="./file.svg", write_to="./file.png")
I get the error:
ValueError: unknown locale: UTF-8
This is how I get "IPython.core.display.SVG" data-type in Jupyter Notebook:
from rdkit import Chem
from rdkit.Chem.Draw import rdMolDraw2D
from IPython.display import SVG
smile_1 = 'C(C(N)=O)c(c)c'
smile_2 = 'o(cn)c(c)c'
m1 = Chem.MolFromSmiles(smile_1,sanitize=False)
Chem.SanitizeMol(m1, sanitizeOps=(Chem.SanitizeFlags.SANITIZE_ALL^Chem.SanitizeFlags.SANITIZE_KEKULIZE^Chem.SanitizeFlags.SANITIZE_SETAROMATICITY))
m2 = Chem.MolFromSmiles(smile_2,sanitize=False)
Chem.SanitizeMol(m2, sanitizeOps=(Chem.SanitizeFlags.SANITIZE_ALL^Chem.SanitizeFlags.SANITIZE_KEKULIZE^Chem.SanitizeFlags.SANITIZE_SETAROMATICITY))
mols = [m1, m2]
legends = ["smile_1", "smile_2"]
molsPerRow=2
subImgSize=(200, 200)
nRows = len(mols) // molsPerRow
if len(mols) % molsPerRow:
nRows += 1
fullSize = (molsPerRow * subImgSize[0], nRows * subImgSize[1])
d2d = rdMolDraw2D.MolDraw2DSVG(fullSize[0], fullSize[1], subImgSize[0], subImgSize[1])
d2d.drawOptions().prepareMolsBeforeDrawing=False
d2d.DrawMolecules(list(mols), legends=legends)
d2d.FinishDrawing()
SVG(d2d.GetDrawingText())
Environment:
macOS 11.2.3
python 3.6
RDKit version 2020.09.1
Any help is greatly appreciated.
Instead of creating an SVG with rdkit and trying to convert it to a PNG, why not just create a PNG directly?
from rdkit.Chem import Draw
from rdkit import Chem
# create rdkit mol
smile = 'CCCC'
mol = Chem.MolFromSmiles(smile)
# create png
d2d = Draw.MolDraw2DCairo(200, 200)
d2d.DrawMolecule(mol)
d2d.FinishDrawing()
png_data = d2d.GetDrawingText()
# save png to file
with open('mol_image.png', 'wb') as png_file:
png_file.write(png_data)
I am not sure why MolDraw2DCairo is not working for you but using the package you mention (cairosvg) you could extend your code sample quite easily:
# extra imports
import cairosvg
import tempfile
# replace molecule drawing part
d2d = rdMolDraw2D.MolDraw2DSVG(fullSize[0], fullSize[1], subImgSize[0], subImgSize[1])
d2d.drawOptions().prepareMolsBeforeDrawing=False
d2d.DrawMolecules(list(mols), legends=legends)
d2d.FinishDrawing()
svg_text = d2d.GetDrawingText()
# save to png file
with tempfile.NamedTemporaryFile(delete=True) as tmp:
tmp.write(svg_text.encode())
tmp.flush()
cairosvg.svg2png(url=tmp.name, write_to="./mol_img.png")

pytesseract unable to recognize complex math formula from image

I am using pytesseract module in python, pytesseract recognizes text from image but it dosen't work on images that contain complex math formulas like under-root, derivation, integration math problem or equation.
code 2.py
# Import modules
from PIL import Image
import pytesseract
import cv2
# Include tesseract executable in your path
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
# Create an image object of PIL library
image = Image.open('23.jpg')
# img = cv2.imread('123.jpg')
# pass image into pytesseract module
# pytesseract is trained in many languages
image_to_text = pytesseract.image_to_string(image, lang='eng+equ')
image_to_text1 = pytesseract.image_to_string(image)
# Print the text
print(image_to_text)
# print(image_to_text1)
# workon digits
Output:
242/33
2x
2x+3X
2X+3x=4
2x?-3x +1=0
(x-1)(x+1) =x2-1
(x+2)/((x+3)(x-4))
7-4=3
V(x/2) =3
2xx—343=6x—3 (x#3)
Jeeta =e* +e
dy 2
S=2?-3
dz ¥
dy = (a? — 3)dx
Input image
To work with MATH language you should install the proper language for tesseract. In your case it is 'equ' from https://github.com/tesseract-ocr/tessdata/raw/3.04.00/equ.traineddata . The full list of available languages is described at https://tesseract-ocr.github.io/tessdoc/Data-Files
I'm not familiar with tesseract language install for windows. But there is a documentation at https://github.com/tesseract-ocr/tesseract/wiki :
If you want to use another language, download the appropriate training
data, unpack it using 7-zip, and copy the .traineddata file into the
'tessdata' directory, probably C:\Program Files\Tesseract-OCR\tessdata
And at first try to process your image with cli only ( without pyhton ), because cli has a full list of the options to tune.
I used this Code and it worked!
import re
import cv2
import pytesseract as tess
path = (r"C:\Users\10\AppData\Local\Tesseract-OCR\tesseract.exe")
tess.pytesseract.tesseract_cmd = path
png = "Downloads/m.png"
text = tess.image_to_string(png)
text.replace(" ", "")
pattern = re.compile("([0-9][=+-/*])")
equations = [x for x in text if bool(re.match(pattern, x))]
print(re.findall(r'(.*)', str(text))[0])

Python 3.x - Slightly Precise Optical Character Recognition. What should I use?

import time
# cv2.cvtColor takes a numpy ndarray as an argument
import numpy as nm
import pytesseract
# importing OpenCV
import cv2
from PIL import ImageGrab, Image
bboxes = [(1469, 1014, 1495, 1029)]
def imToString():
# Path of tesseract executable
pytesseract.pytesseract.tesseract_cmd = 'D:\Program Files (x86)\Tesseract-OCR' + chr(92) + 'tesseract.exe'
while (True):
for box in bboxes:
# ImageGrab-To capture the screen image in a loop.
# Bbox used to capture a specific area.
cap = ImageGrab.grab(bbox=box)
# Converted the image to monochrome for it to be easily
# read by the OCR and obtained the output String.
tesstr = pytesseract.image_to_string(
cv2.cvtColor(nm.array(cap), cv2.COLOR_BGR2GRAY), lang='eng', config='digits') # ,lang='eng')
cap.show()
#input()
time.sleep(5)
print(tesstr)
# Calling the function
imToString()
It captures an image like this:
It isn't always two digits it can be one or three digits too.
Pytesseract returns values like: asi and oli
So, which Image To Text (OCR) Algorithm should I use for this problem? And, how to use that? I need a very precise value in this example it's 53 so the output should be around 50.

How to convert binary image to RGB with PIL?

I have PIL Image in binary and I need to convert it in RGB. I did this diskew image
binary image
I need this way:
I already tried this which is not working
from PIL import Image as im
img = im.fromarray((255 * Image).astype("uint8")).convert("RGB")
I still don't understand why you convert to RGBA if you want RGB, but this code converts your image to RGB as you ask:
#!/usr/local/bin/python3
import numpy as np
from PIL import Image
# Open input image
im = Image.open('text.png').convert('RGB')
# Invert
npim = 255 - np.array(im)
# Save
Image.fromarray(npim).save('result.png')

opencv2 python3 imread with NoneType

I program in Ubuntu system with python3, opencv2. There are several images in the folder that need to be processed. When I use imread, print(img.shape) shows AttributeError: 'NoneType' object has no attribute 'shape'. And I checked the created images' size is 0 bytes. The strange thing is that there are some images can be read successfully, but some are NoneType. Thanks for your help.
import glob as gb
import cv2
import random
import os
import numpy as np
shared_path="/home/train_1/"
folder_list=["HTC-1-M7"]
for j in range(len(folder_list)):
output_path=os.path.join("/home/test/",folder_list[j])
camera_path= os.path.join(shared_path,folder_list[j])
img_path = gb.glob(camera_path+"/*.jpg")
counter=1
for path in img_path:
img = cv2.imread(path)
print(img.shape)
kernel = np.array([[-1,2,-2,2,-1],[2,-6,8,-6,2],[-2,8,-12,8,-2],[2,-6,8,-6,2],[-1,2,-2,2,-1]],np.float32)/12
img = cv2.filter2D(img,-1,kernel)
It means that somewhere a function which should return a image just returned None and therefore it has no shape attribute.
Try print(img) to check if your image is None or an actual numpy object. You probably get this error because your image path may be wrong in a way. Make sure your path is completely correct.

Resources