-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpattern_finder.py
91 lines (73 loc) · 2.98 KB
/
pattern_finder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
__author__ = 'Mark'
import cv2
import threading
import copy
from pattern_type import PatternType
class PatternFinder(threading.Thread):
# Read only properties:
@property
def recognition_in_progress(self):
return self._new_data.is_set()
@property
def pattern_found(self):
return self._pattern_found
@property
def pattern_points(self):
return copy.deepcopy(self._pattern_points)
def __init__(self, pattern_type, pattern_dims):
super().__init__()
self.pattern_type = pattern_type
self.pattern_dims = pattern_dims
self._new_data = threading.Event()
# Input
self._frame = None
#Output
self._pattern_found = False
self._pattern_points = None
self.daemon = True
def run(self):
while True:
self._new_data.wait()
self._find_pattern()
def start_pattern_recognition(self, frame, copy_frame=True):
"""
Starts the pattern recognition from image.
:param frame: input image
:param copy_frame: whether the thread makes it's own copy of image before starting the pattern recognition.
:raises RuntimeError: when start_pattern_recognition is called while last pattern recognition is not yet
complete.
"""
if self._new_data.is_set():
raise RuntimeError("Tried to start new pattern recognition before last one was complete.")
if copy_frame:
self._frame = copy.deepcopy(frame)
else:
self._frame = frame
#Signal thread
self._new_data.set()
def _find_pattern(self):
"""
Tries to find pattern from 'self.frame'
If found, 'self._pattern_found' will be set to "True" and 'self._pattern_points' will be filled with
coordinates.
If pattern is not found in the frame 'self._pattern_found' will be set to "False"
When the recognition has ended, Event 'self._new_data' will be cleared
"""
gray = cv2.cvtColor(self._frame, cv2.COLOR_BGR2GRAY)
if self.pattern_type == PatternType.Checkerboard:
self._pattern_found, self._pattern_points = cv2.findChessboardCorners(
image=gray,
patternSize=self.pattern_dims,
flags=0 # cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE
)
if self._pattern_found:
# Improve found points' accuracy
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)
self._pattern_points = cv2.cornerSubPix(gray, self._pattern_points, (11, 11), (-1, -1), criteria)
elif self.pattern_type == PatternType.AsymmetricCircles:
self._pattern_found, self._pattern_points = cv2.findCirclesGrid(
image=gray,
patternSize=self.pattern_dims,
flags=cv2.CALIB_CB_ASYMMETRIC_GRID # + cv2.CALIB_CB_CLUSTERING
)
self._new_data.clear()