ExamScan/scan/contours.py
2020-05-15 12:19:47 +02:00

118 lines
2.9 KiB
Python

# SPDX-License-Identifier: MIT
# Copyright (c) 2019 Akumatic
import cv2, imutils, numpy
from . import utils
######################
# Contour operations #
######################
def find_contours (
image: numpy.ndarray,
mode: int = cv2.RETR_LIST,
method: int = cv2.CHAIN_APPROX_SIMPLE
) -> list:
""" Find all contours of the filtered image
Args:
image (ndarray):
the filtered image
Returns:
A list containing contour data
"""
cnts = cv2.findContours(image.copy(), mode, method)
return imutils.grab_contours(cnts)
def find_boxes (
contours: list,
thres_area: int = 500,
pad_ratio: float = 0.05
) -> (list, list):
""" Find contours that resemble a box
Args:
contours (list):
a list containing contour data
Returns:
A list containing the box contours
"""
boxes = list()
for c in contours:
area = cv2.contourArea(c)
perimeter = cv2.arcLength(c, True)
shape_factor = utils.circularity(area, perimeter)
if 0.7 < shape_factor < 0.85 and area >= thres_area:
boxes.append(c)
return boxes
def find_center (
contours: list
) -> list:
""" Find the center coordinates of all given contours.
Args:
contours (list):
A list containing contour data
Returns:
A list containing the center coordinates and the contour as tuples
(x, y, contour).
"""
centers = []
for contour in contours:
m = cv2.moments(contour)
try:
x = int(m["m10"] / m["m00"])
y = int(m["m01"] / m["m00"])
centers.append((x, y, contour))
except ZeroDivisionError:
pass
return centers
def filter_centers (
coords: list,
radius: int
):
""" Removes all but one entry in circles given by coordinates and radius
Args:
coords (list):
a list containing tuples of coordinates (x, y)
radius (float):
the radius around a center where no other center should be
"""
a = 0
while a < len(coords):
b = a + 1
while b < len(coords):
if utils.distance(coords[a][:2], coords[b][:2]) <= radius:
del coords[b]
else:
b += 1
a += 1
def dist_center_topleft (
contour: numpy.ndarray,
center: tuple
) -> float:
""" Calculates the distance from the center of a given contour to it's
top left corner
Args:
contour (ndarray):
The contour data
center (tuple):
A tuple containing the center coordinates (x, y)
Returns:
A float with the distance from center to the top left corner as value
"""
x, y, _, _ = cv2.boundingRect(contour)
return utils.distance((x, y), center[:2])