Files
procat2/markup/img.py
2019-10-18 13:11:53 -07:00

112 lines
3.9 KiB
Python

import os
import shutil
from PIL import Image, ImageFilter, ImageDraw, ImageFont
import numpy
import imutils
import cv2
import dumper
import random as rng
from pathlib import Path
from django.conf import settings
from .utils import cv2_rect
WORKDIR = os.path.join(settings.ASSET_DIR, 'markup', 'work')
# https://www.pyimagesearch.com/2014/10/20/finding-shapes-images-using-python-opencv/
def find_shapes(image_path):
path = Path(image_path)
img = Image.open(image_path, 'r')
if not img.mode in ('RGBA', 'LA'):
print('no alpha channel: {}'.format(img.mode))
return None
alpha_layer = img.convert('RGBA').split()[-1]
alpha_layer = alpha_layer.filter(ImageFilter.GaussianBlur(5))
threshold = 5
alpha_layer = alpha_layer.point(lambda p: p > threshold and 255)
threshold = numpy.array(alpha_layer)
# alternate method
# blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# thresh = cv2.threshold(blurred, 60, 255, cv2.THRESH_BINARY)[1]
thresh_path = str(path.with_suffix('.thresh.png'))
# print('write to', thresh_path)
cv2.imwrite(thresh_path, threshold)
os.chmod(thresh_path, 0o664)
shutil.chown(thresh_path, group='procat')
contours = cv2.findContours(threshold, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
# print("{} shapes".format(len(contours)))
bboxes = []
for c in contours:
# bounding rect
x, y, w, h = cv2.boundingRect(c)
# essentially center of mass
# NOT center of the bbox!
# M = cv2.moments(c)
# if M["m00"] == 0: M["m00"] = 0.00001
# cX = int(M["m10"] / M["m00"])
# cY = int(M["m01"] / M["m00"])
#print('add contour rect: {}'.format(cv2_rect(x, y, w, h)))
bboxes.append(cv2_rect(x, y, w, h))
# draw contours
contour_image = numpy.zeros((threshold.shape[0], threshold.shape[1], 3), dtype=numpy.uint8)
for i in range(len(contours)):
# compute the center of the contour
color = (rng.randint(0,512), rng.randint(0,512), rng.randint(0,512))
cv2.drawContours(contour_image, contours, i, color)
rect = bboxes[i]
cv2.rectangle(contour_image, (rect.left, rect.top), (rect.right, rect.bottom), color, 1)
# cv2.circle(contour_image, (cX, cY), 2, color, -1)
# cv2.putText(contour_image, "center", (cX - 20, cY - 15),
# cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 1)
contour_path = str(path.with_suffix('.contour.png'))
#print('write to', contour_path)
cv2.imwrite(contour_path, contour_image)
os.chmod(contour_path, 0o664)
shutil.chown(contour_path, group='procat')
return img.width, img.height, bboxes
def write_debug_image(cat_name, page_num, prods, scribbles):
path = os.path.join(WORKDIR, "debug-{}-{}.png".format(cat_name, page_num))
pagew = int(11*72)
pageh = int(8.5*72)
img = Image.new('RGBA', (pagew, pageh), 'white')
draw = ImageDraw.Draw(img, 'RGBA')
fnt = ImageFont.truetype('/usr/share/fonts/truetype/lato/Lato-Regular.ttf', 10)
for prod in filter(lambda p: p['page'] == page_num, prods):
rect = prod['rect']
fill_color = "hsv(120, 22%, 100%)" if 'matched' in prod else None
outline_color = "hsv(120, 50%, 100%)"
draw.rectangle((rect.p1(pageh), rect.p2(pageh)),
fill=fill_color, outline=outline_color, width=2)
bl = rect.p1(pageh)
draw.text((bl[0] + 3, bl[1] + 3), prod['material'],
font=fnt, fill="hsv(120, 22%, 50%)")
for scribble in filter(lambda s: s['page'] == page_num, scribbles):
rect = scribble['rect']
draw.rectangle((rect.p1(pageh), rect.p2(pageh)), outline="hsv(210, 22%, 100%)", width=2)
for box in scribble['bboxes']:
draw.rectangle((box.p1(pageh), box.p2(pageh)), outline="hsv(0, 22%, 100%)", width=2)
img.save(path)