import io import base64 import cv2 import numpy as np def numpy_arr_to_zip_str(arr): f = io.BytesIO() np.savez_compressed(f, arr=arr) return base64.b64encode(f.getvalue()) def numpy_zip_str_to_arr(zip_str): f = io.BytesIO(base64.b64decode(zip_str)) return np.load(f)['arr'].tolist() def read_image(content: bytes) -> np.ndarray: """ Image bytes to OpenCV image :param content: Image bytes :returns OpenCV image :raises TypeError: If content is not bytes :raises ValueError: If content does not represent an image """ if not isinstance(content, bytes): raise TypeError(f"Expected 'content' to be bytes, received: {type(content)}") image = cv2.imdecode(np.frombuffer(content, dtype=np.uint8), cv2.IMREAD_COLOR) if image is None: raise ValueError(f"Expected 'content' to be image bytes") return image def parse_image(img): (img_h, img_w) = img.shape[:2] t = 1920 w = t h = int((img_h / img_w) * t) img = cv2.resize(img, (w, h)) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = 255 - gray gray = cv2.threshold(gray, 250, 255, cv2.THRESH_BINARY)[1] gray = cv2.blur(gray, (10, 5)) contours, hierarchy = cv2.findContours(gray, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) for cnt in contours: area = cv2.contourArea(cnt) # if area > 150000 and area < 500000: cv2.drawContours(img, [cnt], 0, (255, 0, 0), 2) svg_paths = [] for cnt in contours: if len(cnt) > 80: svg_path = "M" for i in range(len(cnt)): x, y = cnt[i][0] svg_path += f"{x} {y} " svg_paths.append(svg_path) return { "width": w, "height": h, "paths": svg_paths, "array": gray.tolist(), "b64": numpy_arr_to_zip_str(gray), }