How to extract characters from images where their positions are known? - image

I have a set of png images of 300dpi . Each image is full of text (not handwritten), digits (not handwritten).
l want to extract each character and save it in a different image.
For each character in the image l have its position stored in csv file.
For instance in image1.png for a given character “k” l have its position :
“k”=[left=656, right=736,top=144,down= 286]
Is there any python library which allows to do that ?. As input l have the images (png format) and csv file that contains the position of each character of each images.
after executing the code l stack at this line :
img_charac=img[int(coords[2]):int(coords[3]),int(coords[0]):int(coords[1])]
l got the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object has no attribute '__getitem__'

So if I understood correctly, this has nothing to do with image processing, just file opening, image cropping and saving.
With a csv file looking like ,
an input image looking like
I get results like
import cv2
import numpy as np
import csv
path_csv= #path to your csv
#stock coordinates of characters from your csv in numpy array
npa=np.genfromtxt(path_csv+"cs.csv", delimiter=',',skip_header=1,usecols=(1,2,3,4))
nb_charac=len(npa[:, 0]) #number of characters
#stock the actual letters of your csv in an array
characs=[]
cpt=0
#take characters
f = open(path_csv+"cs.csv", 'rt')
reader = csv.reader(f)
for row in reader:
if cpt>=1: #skip header
characs.append(str(row[0]))
cpt+=1
#open your image
path_image= #path to your image
img=cv2.imread(path_image+"yourimagename.png")
path_save= #path you want to save to
#for every line on your csv,
for i in range(nb_charac):
#get coordinates
coords=npa[i,:]
charac=characs[i]
#actual cropping of the image (easy with numpy)
img_charac=img[int(coords[2]):int(coords[3]),int(coords[0]):int(coords[1])]
#saving the image
cv2.imwrite(path_save+"carac"+str(i)+"_"+str(charac)+".png",img_charac)
This is sort of quick and dirty, the csv opening is a bit messy for example (you could get all the info with one opening and converting), and should be adapted to your csv file anyway.

Related

Viewing/Editing YAML content in a window using PySimpleGUI

I am learning python and PySimpleGUI seems like a good start for exercises. With this self-exercise I'm working on, I would like to view and edit a YAML file. So far, I am able to create a prompt to browse and select a yaml. I am able to print the data in the console. But my next step is to view the yaml view PySimpleGUI window. I will work on how to edit the yaml content once I can figure out how to display it.
Here is my code:
import PySimpleGUI as sg
import yaml
from yaml.loader import SafeLoader
import os
working_directory = os.getcwd()
layout = [
[sg.Text("Shoose your yaml file:")],
[sg.InputText(key="-FILE_PATH-"),
sg.FileBrowse(initial_folder=working_directory, file_types=[("YAML Files","*.yaml")])],
[sg.Button("Submit"), sg.Exit()],
[sg.Multiline(size=(30,5), key= data)]
]
window = sg.Window("File Loader", layout).Finalize()
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, 'Exit'):
break
elif event == "Submit":
file_path = values["-FILE_PATH-"];
with open(file_path) as f:
data = yaml.load(f, Loader=SafeLoader)
# print(data)
print(values[data])
window.close()
Running this code i get this error:
Traceback (most recent call last):
File "yaml_gui.py", line 13, in <module>
[sg.Multiline(size=(30,5), key= data)]
NameError: name 'data' is not defined
I'm stuck because I am not sure why it is returning this error. The code works if I decide to just print the results in my terminal by using print(data). But when I use print(values[data]), it doesn't work.

Saving Dask DataFrame with image column to HDF5

I am trying to load images of varying sizes into a Dask DataFrame column and save the dataframe to HDF5 file format.
Here's the standard approach:
import glob
import dask.dataframe as dd
import pandas as pd
import numpy as np
from skimage.io import imread
dir = '/Users/petioptrv/Downloads/mask'
filenames = glob.glob(dir + '/*.png')[:5]
df = pd.DataFrame({"paths": filenames})
ddf = dd.from_pandas(df, npartitions=2)
ddf['images'] = ddf['paths'].apply(imread, meta=('images', np.uint8))
ddf.to_hdf('test.h5', '/data')
I get the following error message:
...
File "/Users/petioptrv/miniconda3/envs/dask/lib/python3.7/site-packages/pandas/io/pytables.py", line 2214, in set_atom_string
item=item, type=inferred_type
TypeError: Cannot serialize the column [images] because
its data contents are [mixed] object dtype
Essentially, PyTables detects that the column has an object dtype and checks if it's of type str. It's not, so it throws an exception.
I can probably hack it by opening the images into byte-arrays and converting those to strings, but that is far from the ideal scenario.
Try specifying the data_columns as suggested in this issue.
ddf.to_hdf('test.h5', '/data', format = 'table', data_columns = ['images'])

FileNotFoundError: No such file: 'someones_epi.nii.gzip'

I am trying to load an MRI, I keep getting the following error:
Traceback (most recent call last):
File "F:/Study/Projects/BTSaG/Programs/t3.py", line 2, in <module> epi_img = nib.load('someones_epi.nii.gzip')
File "C:\Users\AnkitaShinde\AppData\Local\Programs\Python\Python35-32\lib\site-packages\nibabel\loadsave.py", line 38, in load raise FileNotFoundError("No such file: '%s'" % filename)
FileNotFoundError: No such file: 'someones_epi.nii.gzip'
The code is used is as follows:
import nibabel as nib
epi_img = nib.load('someones_epi.nii.gzip')
epi_img_data = epi_img.get_data()
epi_img_data.shape(53, 61, 33)
import matplotlib.pyplot as plt
def show_slices(slices):
""" Function to display row of image slices """
fig, axes = plt.subplots(1, len(slices))
for i, slice in enumerate(slices):
axes[i].imshow(slice.T, cmap="gray", origin="lower")
slice_0 = epi_img_data[26, :, :]
slice_1 = epi_img_data[:, 30, :]
slice_2 = epi_img_data[:, :, 16]
show_slices([slice_0, slice_1, slice_2])
plt.suptitle("Center slices for EPI image")
I have also updated the loadsave.py file in nibabel but it didn't work. Please help.
Edit:
The earlier error was resolved. Now another error has been encountered.
Traceback (most recent call last):File "F:\Study\Projects\BTSaG\Programs\t3.py", line 2, in <module> epi_img = nib.load('someones_epi.nii.gzip')
File "C:\Users\AnkitaShinde\AppData\Local\Programs\Python\Python35-32\lib\site-packages\nibabel\loadsave.py", line 47, in load filename)
nibabel.filebasedimages.ImageFileError: Cannot work out file type of "someones_epi.nii.gzip"
This is an old question, however I may have the solution for it.
I just figured out that nibabel.save() does not allow me to have dot . or dash - in the folder names. These can exist in filenames however. In your case, the current path is:
C:\Users\AnkitaShinde\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\nibabel\someones_epi.nii.gzip
I would change it to:
C:\Users\AnkitaShinde\AppData\Local\Programs\Python\Python35_32\Lib\site_packages\nibabel\someones_epi.nii.gzip
This is just to give an example. Of course, I don't mean that you actually change the names of these package folders as it might cause other errors.
The actual solution would be to move the file someones_epi.nii.gzip to the user structure, something like:
C:\Users\AnkitaShinde\Desktop\nibabel\someones_epi.nii.gzip

Python 3 - GeoPy and encoding

I'm using DictWriter to write a dictionary to a csv after some geolocation work.
location = geolocator.reverse(coords)
row["address"] = location.address
writer.writerow(row)
Which generates this:
File "C:\bin64\python\3.4.3\lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u200e' in
position 118: character maps to <undefined>
My problem was in how I was opening the file. I suppose I should have posted that in the question. I needed to set the encoding upon opening the file.
with open('results.csv', mode='w', encoding='utf-8', newline='') as file:
...

Python edit file with an insanely long line

I am trying to edit particular html files that I download in python. I am running into a problem where I run my code to edit the file and my python context locks up. I checked the file it's writing to and found that there are two files. The html file and a .bak file.
The html file starts out at 0kb and the .bak file constantly grows to a point, maybe 12 mb or so, then the .html file will grow to a larger size, then the .bak file will grow again. This seems to cycle endlessly. The html file I am editing is 22kb. I watched the output file grow to a gig once just to see if it would stop... It doesn't.
Here is the function I am using to edit the file:
def replace(self, search_str, replace_str):
f = open(self.path,'r+')
content = f.readlines()
for i, line in enumerate(content):
content[i] = line.replace(search_str, replace_str)
f.writelines(content)
f.close()
The issue, I imagine relates to the fact that the html file, as downloaded, is mostly in a single line with ~ 21,000 characters in it. Any ideas?
edit:
I have also tried another function, but get the same result:
def replace(self, search_str, replace_str):
assert self.path != None, 'No file path provided.'
fi = fileinput.FileInput(self.path,inplace=1)
for line in fi:
if search_str in line:
line=line.replace(search_str,replace_str)
print line
fi.close()
Try using generator. Thats the way to go if you need to read a large file
for line in open(self.path,'r+'):
# do stuff with line
I re-wrote the function to write everything out to a new file and it works.
def replace(self, search_str, replace_str):
f = open(self.path,'r+')
new_path = self.path.split('.')[0]+'.TEMP'
new_f = open(new_path,'w')
new_lines = [x.replace(search_str, replace_str) for x in f]
new_f.writelines(new_lines)
f.close()
new_f.close()
os.remove(self.path)
os.rename(new_path, self.path)

Resources