demo-int-table/back/api/tracer.py

67 lines
1.9 KiB
Python

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),
}