Spaces:
Runtime error
Runtime error
| from io import BytesIO | |
| from pathlib import Path | |
| from typing import Union, List | |
| import numpy as np | |
| import cv2 | |
| from PIL import UnidentifiedImageError, Image | |
| InputType = Union[str, np.ndarray, bytes, Path, Image.Image] | |
| class LoadImage: | |
| def __init__( | |
| self, | |
| ): | |
| pass | |
| def __call__(self, img: InputType) -> np.ndarray: | |
| if not isinstance(img, InputType.__args__): | |
| raise LoadImageError( | |
| f"The img type {type(img)} does not in {InputType.__args__}" | |
| ) | |
| origin_img_type = type(img) | |
| img = self.load_img(img) | |
| img = self.convert_img(img, origin_img_type) | |
| return img | |
| def load_img(self, img: InputType) -> np.ndarray: | |
| if isinstance(img, (str, Path)): | |
| self.verify_exist(img) | |
| try: | |
| img = np.array(Image.open(img)) | |
| except UnidentifiedImageError as e: | |
| raise LoadImageError(f"cannot identify image file {img}") from e | |
| return img | |
| if isinstance(img, bytes): | |
| img = np.array(Image.open(BytesIO(img))) | |
| return img | |
| if isinstance(img, BytesIO): | |
| img = np.array(Image.open(img)) | |
| return img | |
| if isinstance(img, np.ndarray): | |
| return img | |
| if isinstance(img, Image.Image): | |
| return np.array(img) | |
| raise LoadImageError(f"{type(img)} is not supported!") | |
| def convert_img(self, img: np.ndarray, origin_img_type): | |
| if img.ndim == 2: | |
| return cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) | |
| if img.ndim == 3: | |
| channel = img.shape[2] | |
| if channel == 1: | |
| return cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) | |
| if channel == 2: | |
| return self.cvt_two_to_three(img) | |
| if channel == 3: | |
| if issubclass(origin_img_type, (str, Path, bytes, Image.Image)): | |
| return cv2.cvtColor(img, cv2.COLOR_RGB2BGR) | |
| return img | |
| if channel == 4: | |
| return self.cvt_four_to_three(img) | |
| raise LoadImageError( | |
| f"The channel({channel}) of the img is not in [1, 2, 3, 4]" | |
| ) | |
| raise LoadImageError(f"The ndim({img.ndim}) of the img is not in [2, 3]") | |
| def cvt_two_to_three(img: np.ndarray) -> np.ndarray: | |
| """gray + alpha → BGR""" | |
| img_gray = img[..., 0] | |
| img_bgr = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR) | |
| img_alpha = img[..., 1] | |
| not_a = cv2.bitwise_not(img_alpha) | |
| not_a = cv2.cvtColor(not_a, cv2.COLOR_GRAY2BGR) | |
| new_img = cv2.bitwise_and(img_bgr, img_bgr, mask=img_alpha) | |
| new_img = cv2.add(new_img, not_a) | |
| return new_img | |
| def cvt_four_to_three(img: np.ndarray) -> np.ndarray: | |
| """RGBA → BGR""" | |
| r, g, b, a = cv2.split(img) | |
| new_img = cv2.merge((b, g, r)) | |
| not_a = cv2.bitwise_not(a) | |
| not_a = cv2.cvtColor(not_a, cv2.COLOR_GRAY2BGR) | |
| new_img = cv2.bitwise_and(new_img, new_img, mask=a) | |
| new_img = cv2.add(new_img, not_a) | |
| return new_img | |
| def verify_exist(file_path: Union[str, Path]): | |
| if not Path(file_path).exists(): | |
| raise LoadImageError(f"{file_path} does not exist.") | |
| class LoadImageError(Exception): | |
| pass | |
| def plot_rec_box_with_logic_info(img_path, logic_points, sorted_polygons, without_text=True): | |
| """ | |
| :param img_path | |
| :param output_path | |
| :param logic_points: [row_start,row_end,col_start,col_end] | |
| :param sorted_polygons: [xmin,ymin,xmax,ymax] | |
| :return: | |
| """ | |
| # 读取原图 | |
| img = cv2.imread(img_path) | |
| img = cv2.copyMakeBorder( | |
| img, 0, 0, 0, 100, cv2.BORDER_CONSTANT, value=[255, 255, 255] | |
| ) | |
| # 绘制 polygons 矩形 | |
| for idx, polygon in enumerate(sorted_polygons): | |
| x0, y0, x1, y1 = polygon[0], polygon[1], polygon[2], polygon[3] | |
| x0 = round(x0) | |
| y0 = round(y0) | |
| x1 = round(x1) | |
| y1 = round(y1) | |
| cv2.rectangle(img, (x0, y0), (x1, y1), (0, 0, 255), 1) | |
| # 增大字体大小和线宽 | |
| font_scale = 1.0 # 原先是0.5 | |
| thickness = 2 # 原先是1 | |
| if without_text: | |
| return img | |
| cv2.putText( | |
| img, | |
| f"{idx}", | |
| (x1, y1), | |
| cv2.FONT_HERSHEY_PLAIN, | |
| font_scale, | |
| (0, 0, 255), | |
| thickness, | |
| ) | |
| return img | |
| def plot_rec_box(img, sorted_polygons): | |
| """ | |
| :param img_path | |
| :param output_path | |
| :param sorted_polygons: [xmin,ymin,xmax,ymax] | |
| :return: | |
| """ | |
| img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) | |
| # 处理ocr_res | |
| img = cv2.copyMakeBorder( | |
| img, 0, 0, 0, 100, cv2.BORDER_CONSTANT, value=[255, 255, 255] | |
| ) | |
| # 绘制 ocr_res 矩形 | |
| for idx, polygon in enumerate(sorted_polygons): | |
| x0, y0, x1, y1 = polygon[0], polygon[1], polygon[2], polygon[3] | |
| x0 = round(x0) | |
| y0 = round(y0) | |
| x1 = round(x1) | |
| y1 = round(y1) | |
| cv2.rectangle(img, (x0, y0), (x1, y1), (0, 0, 255), 1) | |
| # 增大字体大小和线宽 | |
| font_scale = 1.0 # 原先是0.5 | |
| thickness = 2 # 原先是1 | |
| # cv2.putText( | |
| # img, | |
| # str(idx), | |
| # (x1, y1), | |
| # cv2.FONT_HERSHEY_PLAIN, | |
| # font_scale, | |
| # (0, 0, 255), | |
| # thickness, | |
| # ) | |
| return img | |
| def format_html(html:str): | |
| html = html.replace("<html>","") | |
| html = html.replace("</html>","") | |
| html = html.replace("<body>", "") | |
| html = html.replace("</body>", "") | |
| return f""" | |
| <!DOCTYPE html> | |
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Complex Table Example</title> | |
| <style> | |
| table {{ | |
| border-collapse: collapse; | |
| width: 100%; | |
| }} | |
| th, td {{ | |
| border: 1px solid black; | |
| padding: 8px; | |
| text-align: center; | |
| }} | |
| th {{ | |
| background-color: #f2f2f2; | |
| }} | |
| </style> | |
| </head> | |
| <body> | |
| {html} | |
| </body> | |
| </html> | |
| """ | |
| def box_4_2_poly_to_box_4_1(poly_box: Union[np.ndarray, list]) -> List[float]: | |
| """ | |
| 将poly_box转换为box_4_1 | |
| :param poly_box: | |
| :return: | |
| """ | |
| return [poly_box[0][0], poly_box[0][1], poly_box[2][0], poly_box[2][1]] |