Skip to content

Instantly share code, notes, and snippets.

@jackersson
Last active March 14, 2017 12:06
Show Gist options
  • Save jackersson/7b8f74556cc96055a3bc155c638548db to your computer and use it in GitHub Desktop.
Save jackersson/7b8f74556cc96055a3bc155c638548db to your computer and use it in GitHub Desktop.
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
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
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
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
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