def sharpen_images_and_get_text_files( jpg_list: list, source_directory: str, target_directory: str = 'OCR/jpgs_sharpened', do_save_img: bool = True): picture_nr = 0 results_list = [] for picture in jpg_list: if picture_nr > 1000: break picture_nr += 1 img = cv.imread(source_directory + '/' + picture) print(source_directory + '/' + picture) gray = color_to_gray(img) if gray.shape[1] % 2 == 0: new_column = np.zeros((1, img.shape[1]), np.uint8) new_column.fill(255) gray = np.r_[gray, new_column] gauss_blurred = cv.GaussianBlur(gray, (5, 3), 0, 0) filtered = cv.bilateralFilter(gauss_blurred, 13, 75, 75) last = cv.adaptiveThreshold(filtered, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 11, 7) if do_save_img: save_img(last, picture, target_directory + '/') # geht nur mit .JPG am Ende. results_list.append(last) return results_list
def merge_pictures(picture: str, do_save_img: bool = True, gray_1=None, img_obj_given=False): img_2 = get_contours(picture, source_dir_path='OCR/jpgs_cut') if not img_obj_given: img_1 = cv.imread('OCR/jpgs_sharpened/' + picture) gray_1 = cv.cvtColor(img_1, cv.COLOR_BGR2GRAY) if gray_1.shape[1] < img_2.shape[1]: new_column = np.zeros((1, gray_1.shape[1]), np.uint8) new_column.fill(255) gray_1 = np.r_[gray_1, new_column] # Falls das Konturenbild angepasst wurde, müssen die Shapes wieder angepasst werden. dst = cv.bitwise_and(gray_1, img_2) if do_save_img: save_img(dst, picture, 'OCR/jpgs_added/') return dst
break starting.append(columns_to_delete[col]) starting = max(starting) ending = [] for col in range(len(columns_to_delete) - 1, 1, -1): if columns_to_delete[col] - 1 != columns_to_delete[col -1]: break ending.append(columns_to_delete[col]) ending = min(ending) if dimension == gray.shape[0]: print(starting, ending) gray[0:starting, 0:gray.shape[1]] = 0 gray[ending:gray.shape[0], 0:gray.shape[1]] = 0 else: print(starting, ending) gray[0:gray.shape[0], 0:starting] = 0 gray[0:gray.shape[0], ending:gray.shape[1]] = 0 # alle Spalten in dieser Liste mit 255 auffüllen! # shape[0] ist width, shape[1] ist heigth # # herausfinden, was der perfekte Winkel ist (berechnen aus der Anzahl der schwarzen Pixel # wenn man die Regionen auswertet. (besser sind wenige Regionen # mit einem hohen Gesamtwert als viele Regionen mit einem niedrigen Gesamtwert! # noch versuchen, die Kante zu finden!!! # closing vor dem Abschneiden ist sinnvoll! save_img(gray, 'lala.JPG', 'jpgs_sharpened/') # geht nur mit .JPG am Ende. break
def determine_rotation_degree_and_rotate(picture, do_save_img: bool = True, do_remove_borders: bool = True, img_obj=None, img_obj_given: bool = False): if img_obj_given: img = img_obj else: img = cv.imread('OCR/jpgs_sharpened/' + picture) degree_values = {} degree_dicts = {} for degree in range(-10, 10, 1): if degree not in degree_dicts: degree_dicts[str(degree)] = {} deg = degree / 10 if len(img.shape) > 2: gray = color_to_gray(img) else: gray = img gray = rotate_by_degree(gray, deg) total_rows_to_delete = [] total_columns_to_delete = [] cleaned_rows_to_delete = [] cleaned_columns_to_delete = [] to_delete_nr = 0 for dimension in [0, 1]: new_shape = gray.shape[dimension] number_of_regions = int(new_shape / 50) * 2 region_length = int(new_shape / number_of_regions) for column in range(0, new_shape): if dimension == 1: pixel_list = [row[column] for row in gray] else: pixel_list = gray[column] region_list = [ pixel_list[i:i + region_length] for i in range(0, len(pixel_list), region_length) ] regions_with_characters = [ 0 if statistics.mean(region) >= 200 else 1 for region in region_list ] if sum(regions_with_characters) <= len(region_list) * 0.35: region_nr = 0 if region_nr not in [ 0, 1, len(region_list) - 1, len(region_list) - 2, len(region_list) - 3 ]: if sum(regions_with_characters[region_nr - 2:region_nr + 3]) > 2: regions_with_characters[region_nr] = 1 region_nr += 1 if sum(regions_with_characters) <= len(region_list) * 0.35: if dimension == 0: total_rows_to_delete.append(column) to_delete_nr += 1 else: total_columns_to_delete.append(column) to_delete_nr += 1 for i in total_rows_to_delete[:-3]: cleaned_rows_to_delete.append(i) if any(row for row in range(i + 1, i + 3) if row not in total_rows_to_delete): break total_rows_to_delete.reverse() for i in total_rows_to_delete: cleaned_rows_to_delete.append(i) if any(column for column in range(i - 1, i - 3, -1) if column not in total_rows_to_delete): break for i in total_columns_to_delete[:-3]: cleaned_columns_to_delete.append(i) if any(row for row in range(i + 1, i + 3) if row not in total_columns_to_delete): break total_columns_to_delete.reverse() for i in total_columns_to_delete: cleaned_columns_to_delete.append(i) if any(column for column in range(i - 1, i - 3, -1) if column not in total_columns_to_delete): break degree_values[str(degree)] = to_delete_nr degree_dicts[str(degree)]['columns'] = cleaned_columns_to_delete degree_dicts[str(degree)]['rows'] = cleaned_rows_to_delete sorted_values = sorted(degree_values.items(), key=lambda x: x[1], reverse=True) minimals = [int(val[0]) for val in sorted_values[:10]] m = stats.trim_mean(minimals, 0.2) if len(img.shape) > 2: gray = color_to_gray(img) else: gray = img gray = rotate_by_degree(gray, int(m) / 10) if do_remove_borders: for key in degree_dicts[str(int(m))]: if key == 'columns': for column in degree_dicts[str(int(m))]['columns']: for i in range(gray.shape[0]): gray[i, column] = 255 else: for row in degree_dicts[str(int(m))]['rows']: for i in range(gray.shape[1]): gray[row, i] = 255 if do_save_img: save_img(gray, picture, 'OCR/jpgs_rotated/') # geht nur mit .JPG am Ende. return gray
def get_contours(picture, do_save_img: bool = True, source_dir_path: str = 'OCR/jpgs_cut', target_dir_path: str = 'OCR/jpgs_contours'): img = cv.imread(source_dir_path + '/' + picture) gray = color_to_gray(img) # sollte man das auch für das zweite Bild machen? if gray.shape[1] % 2 == 0: new_column = np.zeros((1, img.shape[1]), np.uint8) new_column.fill(255) gray = np.r_[gray, new_column] # verhindert, dass sich die Reihen nach unten verschieben; gibt beim merge Probleme. last = cv.GaussianBlur(gray, (5, 3), 0, 0) fil = cv.bilateralFilter(last, 5, 75, 75) last = cv.adaptiveThreshold(fil, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 11, 7) # Kernel unter 5 und über 15 nicht sinnvoll cons, hierarchy = cv.findContours(last, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) mask = np.zeros(gray.shape, np.uint8) mask.fill(255) top_level_contour_indices = [] second_level_contour_indices = [] third_level_contour_indices = [] con_nr = 0 for con_hierarchy in hierarchy[0]: if con_hierarchy[3] == -1: top_level_contour_indices.append(con_nr) con_nr += 1 con_nr = 0 for con_hierarchy in hierarchy[0]: if con_hierarchy[3] in top_level_contour_indices: second_level_contour_indices.append(con_nr) con_nr += 1 con_nr = 0 for con_hierarchy in hierarchy[0]: if con_hierarchy[3] in second_level_contour_indices: third_level_contour_indices.append(con_nr) cv.drawContours(mask, [cons[con_nr]], 0, (255, 255, 255), -1, lineType=8) # Draw contours on the colour image con_nr += 1 mean_third_level = statistics.median([ cv.contourArea(cons[con_nr]) for con_nr in third_level_contour_indices ]) for con_nr in second_level_contour_indices: if cv.contourArea(cons[con_nr]) > mean_third_level: cv.drawContours(mask, [cons[con_nr]], 0, 0, -1, lineType=8) cv.drawContours(mask, [cons[con_nr]], 0, (255, 255, 255), 1, lineType=8) for con_nr in third_level_contour_indices: cv.drawContours(mask, [cons[con_nr]], 0, (255, 255, 255), -1, lineType=8) opening = cv.dilate(mask, (3, 3), iterations=2) erosion = cv.dilate(opening, (3, 3), iterations=2) if do_save_img: save_img(erosion, target_dir_path + '/' + picture, 'OCR/jpgs_contours/') return erosion
def cut_articles(jpgs_list: list): picture_nr = 0 for picture in jpgs_list: if picture_nr > 1000: break picture_nr += 1 img = cv.imread('OCR/jpgs/' + picture) img = cv.copyMakeBorder(img, 100, 100, 100, 100, cv.BORDER_CONSTANT, value=(255, 255, 255)) gray = color_to_gray(img) ret, new = cv.threshold(gray, 85, 255, cv.THRESH_BINARY) blur = cv.GaussianBlur(new, (225, 151), 0) ret2, th2 = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU) blur = cv.GaussianBlur(th2, (225, 151), 0) ret3, th3 = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU) blur = cv.GaussianBlur(th3, (225, 151), 0) ret4, th4 = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU) blur = cv.GaussianBlur(th4, (225, 151), 0) ret5, th5 = cv.threshold(blur, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU) contours, hierarchy = cv.findContours(th5, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) inner_contours = [ con for con in contours if cv.contourArea(con) not in [9931053, 9943198] ] contours_sorted = sorted(inner_contours, key=cv.contourArea) max_log = max([ int(math.log10(cv.contourArea(con))) for con in contours_sorted[-10:] ]) largest_area = contours_sorted[-1] contours_sorted = [ con for con in contours_sorted if int(math.log10(cv.contourArea(con))) >= max_log - 1 ] mask = np.zeros(img.shape, np.uint8) mask.fill(255) cv.drawContours(mask, contours, -1, 0) dst = cv.bitwise_and(img, mask) max_x = 0 max_y = 0 min_x = img.shape[1] min_y = img.shape[0] for c in [largest_area]: x, y, w, h = cv.boundingRect(c) min_x = min(x, min_x) min_y = min(y, min_y) max_x = max(x + w, max_x) max_y = max(y + h, max_y) roi = gray[min_y:max_y, min_x:max_x] avg_color_per_row = np.average(roi, axis=0) avg_color = np.average(roi, axis=1) save_img(roi, picture, 'jpgs_cut/')