Hello,
I'm actually working on a webcam software with which I will control a UR co-bot to pick and place objects about forms and colors. I'm working with Python and OpenCV, I managed to recognize the shapes with the `findcountor` and `drawcontour` function, and I sort them with the `approxPolyDP` function. Now I would like to determine for instance the length of each side of a rectangle and then calculate the middle of a side and that point will be sent to the robot to catch it with the gripper.
I tried a lot of things and I searched on a lot of forums but I didn't got any usable information, if you have any idea please let me know.
Here is my code:
import cv2
import numpy as np
import imutils
from shapeDetector import ShapeDetector
import shapely.geometry as shapgeo
lower = {'red':(169, 100, 100),
'blue':(108, 100, 100),
'yellow':(18, 100, 100),
'green':(59, 100, 100)}
upper = {'red':(189, 255, 255),
'blue':(128, 255, 255),
'yellow':(54, 255, 255),
'green':(79, 255, 255)}
colors = {'red':(0,0,255),
'blue':(255,0,0),
'yellow':(38, 255, 255),
'green':(0, 255, 0)}
camera = cv2.VideoCapture(0)
def drawContours(frame,c):
(x,y,w,h) = cv2.boundingRect(c)
if w > 50 and h > 50:
cv2.drawContours(frame, [c], -1, colors[key], 2)
cv2.circle(frame, (cX, cY), 7, (255, 255, 255), -1)
cv2.putText(frame, "center", (cX - 20, cY - 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255),2)
cv2.putText(frame, shape, (cX + 20, cY + 20), cv2.FONT_HERSHEY_SIMPLEX,
0.5, (255, 255, 255), 2)
c = c.astype("float")
c *= ratio
c = c.astype("int")
cv2.imshow("Frame", frame)
return frame
while True:
(grabbed, frame) = camera.read()
resized = imutils.resize(frame, width=600)
ratio = frame.shape[0] / float(resized.shape[0])
blurred = cv2.GaussianBlur(frame, (11,11), 0)
hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
for key, value in upper.items():
kernel = np.ones((9,9),np.uint8)
mask = cv2.inRange(hsv, lower[key], upper[key])
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
#mask = cv2.morphologyEx(mask, cv2.MORPH_GRADIENT, kernel)
cnts = cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
sd = ShapeDetector()
for c in cnts:
M = cv2.moments(c)
cX = int((M["m10"] / M["m00"]) * ratio)
cY = int((M["m01"] / M["m00"]) * ratio)
shape = sd.detect(c)
drawContours(frame, c)
#cv2.imshow("mask",mask)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
camera.release()
cv2.destroyAllWindows()
**Here is the shape detection:**
import cv2
class ShapeDetector:
def __init__(self):
pass
def detect(self, c):
# initialize the shape name and approximate the contour
shape = "unidentified"
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.04 * peri, True)
# if the shape is a triangle, it will have 3 vertices
if len(approx) == 3:
shape = "triangle"
# if the shape has 4 vertices, it is either a square or
# a rectangle
elif len(approx) == 4:
# compute the bounding box of the contour and use the
# bounding box to compute the aspect ratio
(x, y, w, h) = cv2.boundingRect(approx)
ar = w / float(h)
# a square will have an aspect ratio that is approximately
# equal to one, otherwise, the shape is a rectangle
shape = "square" if ar >= 0.95 and ar <= 1.05 else "rectangle"
# if the shape is a pentagon, it will have 5 vertices
elif len(approx) == 5:
shape = "pentagon"
# if the shape is a hexagon, it will have 6 vertices
elif len(approx) == 6:
shape = "hexagon"
# otherwise, we assume the shape is a circle
else:
shape = "circle"
# return the name of the shape
return shape
↧