-
Notifications
You must be signed in to change notification settings - Fork 36
/
detectWithWebCamera.py
165 lines (127 loc) · 6.23 KB
/
detectWithWebCamera.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
import cv2
import numpy as np
import time
from imutils.perspective import four_point_transform
#from imutils import contours
#import imutils
camera = cv2.VideoCapture(0)
def findTrafficSign():
'''
This function find blobs with blue color on the image.
After blobs were found it detects the largest square blob, that must be the sign.
'''
# define range HSV for blue color of the traffic sign
lower_blue = np.array([85,100,70])
upper_blue = np.array([115,255,255])
while True:
# grab the current frame
(grabbed, frame) = camera.read()
if not grabbed:
print("No input image")
break
frame = imutils.resize(frame, width=500)
frameArea = frame.shape[0]*frame.shape[1]
# convert color image to HSV color scheme
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# define kernel for smoothing
kernel = np.ones((3,3),np.uint8)
# extract binary image with active blue regions
mask = cv2.inRange(hsv, lower_blue, upper_blue)
# morphological operations
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# find contours in the mask
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
# defite string variable to hold detected sign description
detectedTrafficSign = None
# define variables to hold values during loop
largestArea = 0
largestRect = None
# only proceed if at least one contour was found
if len(cnts) > 0:
for cnt in cnts:
# Rotated Rectangle. Here, bounding rectangle is drawn with minimum area,
# so it considers the rotation also. The function used is cv2.minAreaRect().
# It returns a Box2D structure which contains following detals -
# ( center (x,y), (width, height), angle of rotation ).
# But to draw this rectangle, we need 4 corners of the rectangle.
# It is obtained by the function cv2.boxPoints()
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
# count euclidian distance for each side of the rectangle
sideOne = np.linalg.norm(box[0]-box[1])
sideTwo = np.linalg.norm(box[0]-box[3])
# count area of the rectangle
area = sideOne*sideTwo
# find the largest rectangle within all contours
if area > largestArea:
largestArea = area
largestRect = box
# draw contour of the found rectangle on the original image
if largestArea > frameArea*0.02:
cv2.drawContours(frame,[largestRect],0,(0,0,255),2)
#if largestRect is not None:
# cut and warp interesting area
warped = four_point_transform(mask, [largestRect][0])
# show an image if rectangle was found
#cv2.imshow("Warped", cv2.bitwise_not(warped))
# use function to detect the sign on the found rectangle
detectedTrafficSign = identifyTrafficSign(warped)
#print(detectedTrafficSign)
# write the description of the sign on the original image
cv2.putText(frame, detectedTrafficSign, tuple(largestRect[0]), cv2.FONT_HERSHEY_SIMPLEX, 0.65, (0, 255, 0), 2)
# show original image
cv2.imshow("Original", frame)
# if the `q` key was pressed, break from the loop
if cv2.waitKey(1) & 0xFF is ord('q'):
cv2.destroyAllWindows()
print("Stop programm and close all windows")
break
def identifyTrafficSign(image):
'''
In this function we select some ROI in which we expect to have the sign parts. If the ROI has more active pixels than threshold we mark it as 1, else 0
After path through all four regions, we compare the tuple of ones and zeros with keys in dictionary SIGNS_LOOKUP
'''
# define the dictionary of signs segments so we can identify
# each signs on the image
SIGNS_LOOKUP = {
(1, 0, 0, 1): 'Turn Right', # turnRight
(0, 0, 1, 1): 'Turn Left', # turnLeft
(0, 1, 0, 1): 'Move Straight', # moveStraight
(1, 0, 1, 1): 'Turn Back', # turnBack
}
THRESHOLD = 150
image = cv2.bitwise_not(image)
# (roiH, roiW) = roi.shape
#subHeight = thresh.shape[0]/10
#subWidth = thresh.shape[1]/10
(subHeight, subWidth) = np.divide(image.shape, 10)
subHeight = int(subHeight)
subWidth = int(subWidth)
# mark the ROIs borders on the image
cv2.rectangle(image, (subWidth, 4*subHeight), (3*subWidth, 9*subHeight), (0,255,0),2) # left block
cv2.rectangle(image, (4*subWidth, 4*subHeight), (6*subWidth, 9*subHeight), (0,255,0),2) # center block
cv2.rectangle(image, (7*subWidth, 4*subHeight), (9*subWidth, 9*subHeight), (0,255,0),2) # right block
cv2.rectangle(image, (3*subWidth, 2*subHeight), (7*subWidth, 4*subHeight), (0,255,0),2) # top block
# substract 4 ROI of the sign thresh image
leftBlock = image[4*subHeight:9*subHeight, subWidth:3*subWidth]
centerBlock = image[4*subHeight:9*subHeight, 4*subWidth:6*subWidth]
rightBlock = image[4*subHeight:9*subHeight, 7*subWidth:9*subWidth]
topBlock = image[2*subHeight:4*subHeight, 3*subWidth:7*subWidth]
# we now track the fraction of each ROI
leftFraction = np.sum(leftBlock)/(leftBlock.shape[0]*leftBlock.shape[1])
centerFraction = np.sum(centerBlock)/(centerBlock.shape[0]*centerBlock.shape[1])
rightFraction = np.sum(rightBlock)/(rightBlock.shape[0]*rightBlock.shape[1])
topFraction = np.sum(topBlock)/(topBlock.shape[0]*topBlock.shape[1])
segments = (leftFraction, centerFraction, rightFraction, topFraction)
segments = tuple(1 if segment > THRESHOLD else 0 for segment in segments)
cv2.imshow("Warped", image)
if segments in SIGNS_LOOKUP:
return SIGNS_LOOKUP[segments]
else:
return None
def main():
findTrafficSign()
if __name__ == '__main__':
main()