Last active
March 14, 2017 12:06
-
-
Save jackersson/7b8f74556cc96055a3bc155c638548db to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def is_circle(perimetr, area): | |
if perimetr == 0: | |
return False | |
circularity = 4*math.pi*(area/(perimetr**2)) | |
if 0.7 < circularity < 1.2: | |
return True | |
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Shape: | |
name = "undefined" | |
contour = [] //Vector of points | |
area = 0 | |
width = 0 | |
height = 0 | |
perimetr = 0 | |
center = (0, 0) //Point | |
bool valid(): | |
if area > 100: | |
return True | |
return False | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ShapeDetector: | |
Shape detect(self, c): | |
shape = Shape() | |
shape.perimetr = cv2.arcLength(c, True) | |
shape.contour = cv2.approxPolyDP(c, 0.04 * shape.perimetr, True) | |
shape.area = cv2.contourArea(c) | |
approx = shape.contour | |
if len(approx) == 3: | |
shape.name = "triangle" | |
elif len(approx) == 4: | |
(x, y, w, h) = cv2.boundingRect(approx) | |
ar = w / float(h) | |
shape.name = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle" | |
elif len(approx) == 5: | |
shape.name = "pentagon" | |
elif len(approx) == 6: | |
shape.name = "hexagon" | |
elif len(approx) == 7: | |
shape.name = "heptagon" | |
elif len(approx) == 8: | |
shape.name = "octagon" | |
elif len(approx) == 9: | |
shape.name = "nonagon" | |
elif len(approx) == 10: | |
shape.name = "decagon" | |
elif is_circle(shape.perimetr, shape.area ) == True: | |
shape.name = "circle" | |
else: | |
shape.name = "unidentified" | |
valid = False | |
return shape |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def detect_shapes(cnts): | |
shapes = [] | |
for c in cnts: | |
try: | |
# Find center of contour | |
M = cv2.moments(c) | |
cX = int((M["m10"] / M["m00"])) | |
cY = int((M["m01"] / M["m00"])) | |
# | |
shape = sd.detect(c) | |
shape.center = (cX, cY) | |
if shape.valid() == True: | |
shapes.append(shape) | |
except ZeroDivisionError: | |
continue | |
return shapes | |
def draw_angles(image, shape): | |
angles = find_angles(shape) | |
cont = shape.contour | |
for par in angles: | |
index, angle = par[0], par[1] | |
cnt = cont[index][0] | |
cv2.putText(image, str(int(angle)), (cnt[0], cnt[1]), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0),1) | |
def draw_shapes(image, shapes): | |
color = (255, 0, 0) | |
font = cv2.FONT_HERSHEY_SIMPLEX | |
for shape in shapes: | |
cv2.drawContours(image, [shape.contour], -1, (0, 255, 0), 2) | |
cv2.putText(image, str(shape), shape.center, font, 0.5, color,1) | |
pt = (shape.center[0], shape.center[1] + 15) | |
cv2.putText(image, "Area:" + str(int(shape.area)), pt, font, 0.5, color,1) | |
draw_angles(image, shape) | |
def find_countours(thresholded): | |
image, countours, hierarchies = cv2.findContours(thresholded, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) | |
return countours |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def vector(a, b): | |
return [a[0] - b[0], a[1] - b[1]] | |
def distance(vec): | |
return (vec[0]**2 + vec[1]**2)**0.5 | |
def dot(a, b): | |
return a[0] * b[0] + a[1] * b[1] | |
def get_angle(start, far, end): | |
a = vector(far, start) | |
b = vector(far, end ) | |
ab = dot(a, b) | |
dist_ab = distance(a) * distance(b) | |
calc = min(max((ab / dist_ab), -1.0), 1.0) | |
angle = math.acos(calc) * 180 / math.pi | |
return angle | |
def find_angles(shape): | |
conts = shape.contour | |
n = len(conts) | |
#print conts | |
if n < 3: | |
return [] | |
angles = [] | |
for i in range(len(conts)): | |
start = conts[i][0] | |
mid_index = i + 1 | |
if ( mid_index >= n ): | |
mid_index = abs(mid_index - n) | |
target = conts[mid_index][0] | |
end_index = i + 2 | |
if ( end_index >= n ): | |
end_index = abs(end_index - n) | |
end = conts[end_index][0] | |
angle = get_angle(start, target, end) | |
angles.append([mid_index, angle]) | |
return angles |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment