import os import numpy as np import matplotlib.pyplot as plt import scipy as scp def levenshteinDistance(s1, s2): if len(s1) > len(s2): s1, s2 = s2, s1 distances = range(len(s1) + 1) for i2, c2 in enumerate(s2): distances_ = [i2+1] for i1, c1 in enumerate(s1): if c1 == c2: distances_.append(distances[i1]) else: distances_.append(1 + min((distances[i1], distances[i1 + 1], distances_[-1]))) distances = distances_ return distances[-1] def unit_gaussian_filter(sigma): """Create and returns a 2D square gaussian filter""" x_grid = np.linspace(-3*int(sigma+1),3*int(sigma+1), 6*int(sigma+1)+1) X,Y = np.meshgrid(x_grid, x_grid) R = X*0 for i in range(0,R.shape[0]): for j in range(0,R.shape[1]): R[i,j] = 1 / (2*np.pi*sigma*sigma) * np.exp(-(X[i,j]*X[i,j] + Y[i,j]*Y[i,j]) / (2*sigma*sigma)) return R def calculate_img_correlation(img1, img2): """Calculation of the correlation between the two images. Produces a 2D map, and returns the maximum of it.""" if(img2.size > img1.size): img2, img1 = img1, img2 #img_template = scp.signal.correlate2d(img1, img1, "same") img_corr = scp.signal.correlate2d(img1, img2, "same") # sum_template = np.sum(img_template) # sum_test = np.sum(img_test) # ratio = sum_template/sum_test # img_test = img_test*ratio # max_template = np.amax(img_template) max_corr = np.amax(img_corr) index = np.where(img_corr == max_corr) # ratio_max = max_template/max_test return max_corr, index def otsu_algo(img): """Calculates the threshold between upper and lower values in an image. Uses the Otsu algorithm and returns the lower threshold value.""" histo, edges = np.histogram(img, bins=255, range=(0,255)) sum_tot = np.sum(histo) w = np.zeros(len(histo)) mu = np.zeros(len(histo)) w[0] = histo[0] mu[0] = 1*histo[0] for i in range(1,len(histo)): w[i] = w[i-1] + histo[i] mu[i] = mu[i-1] + (i+1)*histo[i] w = w/sum_tot mu = mu/sum_tot muN = mu[len(histo)-1] crit = np.zeros(len(histo)) for i in range(0,len(histo)): crit[i] = w[i]*(muN-mu[i])*(muN-mu[i]) + (1-w[i])*mu[i]*mu[i] max_crit = np.amax(crit) place = np.where(crit == max_crit) if(type(place) != int): place = place[0] thresh = int(np.floor(place[0]/len(histo)*np.amax(img))) thresh = edges[thresh] return thresh def img_cells_zero(img_origin, img_gauss, threshold): """Switches off all the values of ing_gauss lower than the threshold in img_origin.""" for i in range(0,img_origin.shape[0]): for j in range(0,img_origin.shape[1]): if(img_gauss[i,j]<=threshold): img_origin[i,j]=0 def img_one_border_remove(img, start="begin", axis=0): """Find the limit of a black border in an image. Use "begin" or "end" through the selected axis (0 or 1) to find the limit from the upper/left or lower/right borders of the image. Returns the index limit.""" if(start=="begin"): add = 1 i = 0 else: add = -1 i = img.shape[axis-1]-1 axis_sum = np.sum(img, axis=axis) while(axis_sum[i] == 0): i = i+add return i def img_black_borders_remove(img): """Find the borders of an image and removes them.""" y_beg = img_one_border_remove(img) x_beg = img_one_border_remove(img, axis=1) y_end = img_one_border_remove(img, start="end") x_end = img_one_border_remove(img, start="end", axis=1) return img[x_beg:x_end, y_beg:y_end] def resize(img, shape): """Resizes an image to a different shape with the bilinear method.""" img_final = np.zeros(shape) y_vect = np.linspace(0, img.shape[0]-1, shape[0]) x_vect = np.linspace(0, img.shape[1]-1, shape[1]) for j in range(0,shape[0]): for i in range(0,shape[1]): y0 = int(np.floor(y_vect[j])) y1 = int(np.ceil(y_vect[j])) x0 = int(np.floor(x_vect[i])) x1 = int(np.ceil(x_vect[i])) x_coma = x_vect[i]-np.floor(x_vect[i]) y_coma = y_vect[j]-np.floor(y_vect[j]) img_final[j,i] = (1-x_coma)*(1-y_coma)*img[y0,x0] + (x_coma)*(1-y_coma)*img[y0,x1] + (1-x_coma)*(y_coma)*img[y1,x0] + (x_coma)*(y_coma)*img[y1,x1] return img_final def signal_processing_process(img_template, img_scanned): img_gauss = scp.signal.correlate2d(img_scanned, unit_gaussian_filter(1.5), "same") thresh = otsu_algo(img_gauss) img_cells_zero(img_scanned, img_gauss, thresh) im_trunc = img_black_borders_remove(img_scanned) ratio = (img_template.shape[0]/im_trunc.shape[0], img_template.shape[1]/im_trunc.shape[1]) shape1 = (int(img_template.shape[0]/ratio[0]), int(img_template.shape[1]/ratio[0])) shape2 = (int(img_template.shape[0]/ratio[1]), int(img_template.shape[1]/ratio[1])) if(shape1[0] != shape2[0] or shape1[1] != shape2[1]): img_final_1 = resize(img_template, shape1) img_final_2 = resize(img_template, shape2) max1, location1 = calculate_img_correlation(img_final_1, im_trunc) max2, location2 = calculate_img_correlation(img_final_2, im_trunc) if(max1 > max2): img_final = img_final_1 ratio = ratio[0] location = location1 else: img_final = img_final_2 ratio = ratio[1] location = location2 offset = (img_final.shape[0]//2-location[0], img_final.shape[1]//2-location[1]) return img_final, im_trunc, ratio, offset # to be tried: # - delete black borders (gauss to highlight written content, blacken and delete what is not the paper) # - resize with root method # no rotation ! if __name__ == "__main__": #used for tests im1 = plt.imread("/home/inc0nnu-rol/Documents/La Gemme/OCR_paper_form/test.png") im2 = plt.imread("/home/inc0nnu-rol/Documents/La Gemme/OCR_paper_form/test2.png") im3 = plt.imread("/home/inc0nnu-rol/Documents/La Gemme/OCR_paper_form/test3.png") im1 = (im1[:,:,0]+im1[:,:,1]+im1[:,:,2])*255//3 im2 = (im2[:,:,0]+im2[:,:,1]+im2[:,:,2])*255//3 im3 = (im3[:,:,0]+im3[:,:,1]+im3[:,:,2])*255//3 img_fin, ratios, offset = signal_processing_process(im1, im3) # img_gauss = scp.signal.correlate2d(im3, unit_gaussian_filter(1.5), "same") # # thresh = otsu_algo(img_gauss) # img_cells_zero(im3, img_gauss, thresh) # im_trunc = img_black_borders_remove(im3) # # plt.imshow(im_trunc) # plt.show() # # ratio = (im1.shape[0]/im_trunc.shape[0], im1.shape[1]/im_trunc.shape[1]) # # shape1 = (int(im1.shape[0]/ratio[0]), int(im1.shape[1]/ratio[0])) # shape2 = (int(im1.shape[0]/ratio[1]), int(im1.shape[1]/ratio[1])) # # if(shape1[0] != shape2[0] or shape1[1] != shape2[1]): # img_final_1 = resize(im1, shape1) # img_final_2 = resize(im1, shape2) # max1 = calculate_img_correlation(img_final_1, im_trunc) # max2 = calculate_img_correlation(img_final_2, im_trunc) # if(max1 > max2): # img_final = img_final_1 # else: # img_final = img_final_2 print(ratios, offset) plt.imshow(img_fin) plt.show() # Gauss = unit_gaussian_filter(1.5) # im_template = scp.signal.correlate2d(im1, im1, "same") # im_filt = scp.signal.correlate2d(im2, im_trunc, "same") # # plt.imshow(im_test) # plt.show() # # sum_template = np.sum(im_template) # sum3 = np.sum(im_test) # ratio = sum_template/sum3 # im_test = im_test*ratio # # max_template = np.amax(im_template) # min_template = np.amin(im_template) # max_im_test = np.amax(im_test) # min_im_test = np.amin(im_test) # # ratio_max = max_template/max_im_test # ratio_min = min_template/min_im_test # # index_max_template = np.where(im_template == np.amax(im_template)) # index_min_template = np.where(im_template == np.amin(im_template)) # index_max_im_test = np.where(im_test == np.amax(im_test)) # index_min_im_test = np.where(im_test == np.amin(im_test)) # Gauss = unit_gaussian_filter(5) # plt.imshow(Gauss) # plt.show() # print(np.sum(Gauss)) #max_index = (bla[0][0], bla[1][0])