From f1bf23abf218e4d47de96f809a70edb8bb62450c Mon Sep 17 00:00:00 2001 From: Abderrahim Date: Wed, 11 Aug 2021 18:18:25 +0200 Subject: [PATCH 1/3] handle all rotation angles --- easyocr/utils.py | 87 +++++++++++++++++++++--------------------------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/easyocr/utils.py b/easyocr/utils.py index 4972a57fb..b295674a0 100644 --- a/easyocr/utils.py +++ b/easyocr/utils.py @@ -755,43 +755,47 @@ def reformat_input_batched(image, n_width=None, n_height=None): return img, img_cv_grey +def rotate(image, angle, center = None, scale = 1.0): + """ + Rotate the image arount its center according to the angle chosen + + """ + (h, w) = image.shape[:2] + if center is None: + center = (w / 2, h / 2) + # Perform the rotation + M = cv2.getRotationMatrix2D(center, angle, scale) + rotated = cv2.warpAffine(image, M, (w, h)) + return rotated + + + + def make_rotated_img_list(rotationInfo, img_list): + result_img_list = img_list[:] # add rotated images to original image_list max_ratio=1 - if 90 in rotationInfo: - for img_info in img_list: - ninty_image = cv2.rotate(img_info[1],cv2.ROTATE_90_COUNTERCLOCKWISE) - height,width = ninty_image.shape - ratio = calculate_ratio(width,height) - max_ratio = max(max_ratio,ratio) - result_img_list.append((img_info[0],ninty_image)) - - if 180 in rotationInfo: - for img_info in img_list: - one_eighty_image = cv2.rotate(img_info[1],cv2.ROTATE_180) - height,width = one_eighty_image.shape + + for angle in rotationInfo: + for img_info in img_list : + rotated = rotate (img_info[1],angle) + height,width = rotated.shape ratio = calculate_ratio(width,height) max_ratio = max(max_ratio,ratio) - result_img_list.append((img_info[0], one_eighty_image)) - - if 270 in rotationInfo: - for img_info in img_list: - two_seventy_image = cv2.rotate(img_info[1], cv2.ROTATE_90_CLOCKWISE) - height,width = two_seventy_image.shape - ratio = calculate_ratio(width,height) - max_ratio = max(max_ratio,ratio) - result_img_list.append((img_info[0],two_seventy_image)) - + result_img_list.append((img_info[0], rotated)) return result_img_list def set_result_with_confidence(result_list, origin_len): + set_len = len(result_list)//origin_len k = 0 - result_to_split = [[],[],[],[]] + result_to_split = [[] for i in range(set_len)] # list having the same length of the rotation_info list : each element is a list of rotated images in the same direction + + # fill for i in range(set_len): tmp_list = [] for j in range(origin_len): @@ -800,33 +804,18 @@ def set_result_with_confidence(result_list, origin_len): result_to_split[i] += tmp_list - result1 = result_to_split[0] - result2 = result_to_split[1] - result3 = result_to_split[2] - result4 = result_to_split[3] - + + + ## choose the best result from different rotations + final_result = [] - for i in range(origin_len): - result = result1[i] # format : ([[,],[,],[,],[,]], 'string', confidnece) - confidence = result1[i][2] - - if result2: - if result2[i][2] > confidence: - if len(result2[i][1]) >= len(result[1]): - result = result2[i] - confidence = result2[i][2] - - if result3: - if result3[i][2] > confidence: - if len(result3[i][1]) >= len(result[1]): - result = result3[i] - confidence = result3[i][2] - - if result4: - if result4[i][2] > confidence: - if len(result4[i][1]) >= len(result[1]): - result = result4[i] - confidence = result4[i][2] + for i in range(origin_len): + result = result_to_split[0][i] # format : ([[,],[,],[,],[,]], 'string', confidnece) + confidence = result_to_split[0][i][2] + for rot in range (1,set_len): + if (result_to_split[rot] and len(result_to_split[rot][i][1]) >= len(result[1])): + result = result_to_split[rot][i] + confidence = result_to_split[rot][i][2] final_result.append(result) From 424dea1dcb50bd171ad0aeb3f369c24e51047c29 Mon Sep 17 00:00:00 2001 From: Abderrahim Date: Thu, 12 Aug 2021 10:33:54 +0200 Subject: [PATCH 2/3] handle rotation without border crop --- easyocr/utils.py | 18 ++---------------- rotated.png | Bin 0 -> 2645 bytes word_1.png | Bin 0 -> 2672 bytes 3 files changed, 2 insertions(+), 16 deletions(-) create mode 100644 rotated.png create mode 100644 word_1.png diff --git a/easyocr/utils.py b/easyocr/utils.py index b295674a0..c87c748a6 100644 --- a/easyocr/utils.py +++ b/easyocr/utils.py @@ -6,6 +6,7 @@ import math import cv2 from PIL import Image, JpegImagePlugin +from scipy import ndimage import hashlib import sys, os from zipfile import ZipFile @@ -755,21 +756,6 @@ def reformat_input_batched(image, n_width=None, n_height=None): return img, img_cv_grey -def rotate(image, angle, center = None, scale = 1.0): - """ - Rotate the image arount its center according to the angle chosen - - """ - (h, w) = image.shape[:2] - if center is None: - center = (w / 2, h / 2) - # Perform the rotation - M = cv2.getRotationMatrix2D(center, angle, scale) - rotated = cv2.warpAffine(image, M, (w, h)) - return rotated - - - def make_rotated_img_list(rotationInfo, img_list): @@ -780,7 +766,7 @@ def make_rotated_img_list(rotationInfo, img_list): for angle in rotationInfo: for img_info in img_list : - rotated = rotate (img_info[1],angle) + rotated = ndimage.rotate(img_info[1], angle, reshape=True) height,width = rotated.shape ratio = calculate_ratio(width,height) max_ratio = max(max_ratio,ratio) diff --git a/rotated.png b/rotated.png new file mode 100644 index 0000000000000000000000000000000000000000..b7a59632f6e09adbf0c8f0d92c5581c297f389e6 GIT binary patch literal 2645 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 Dux%Id literal 0 HcmV?d00001 diff --git a/word_1.png b/word_1.png new file mode 100644 index 0000000000000000000000000000000000000000..fd46c60ea649bf044f60590112b5e992c622c19b GIT binary patch literal 2672 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 ezpLY))A>II0gX`WVd%X80000 Date: Thu, 12 Aug 2021 10:37:19 +0200 Subject: [PATCH 3/3] handle rotation without cropping border --- rotated.png | Bin 2645 -> 0 bytes word_1.png | Bin 2672 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 rotated.png delete mode 100644 word_1.png diff --git a/rotated.png b/rotated.png deleted file mode 100644 index b7a59632f6e09adbf0c8f0d92c5581c297f389e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2645 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 Dux%Id diff --git a/word_1.png b/word_1.png deleted file mode 100644 index fd46c60ea649bf044f60590112b5e992c622c19b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2672 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 ezpLY))A>II0gX`WVd%X80000