任务要求:
图像识别说明:需要识别的实物共6个:50mm*50mm红色小正方体(10分)、黄色小
正方体(10分)、绿色小正方体(10分)、罐装雪碧(绿 15分)、罐装可乐(红 15
分)、罐装可乐(蓝 15分)。如未完成识别实物就抓取放入仓库则每个只得5分。
实现思路:
通过传统视觉实现颜色识别,几何形状的识别,可以将立方体看作正方形,易拉罐看作椭圆形,颜色识别可以通过将摄像头的RGB值转化为HSV值识别。
以下为python代码:
import numpy as np
import cv2
class ShapeAnalysis:
def __init__(self):
self.shapes = {'triangle': 0, 'rectangle': 0, 'polygons': 0, 'circles': 0}
def analysis(self, frame):
h, w, ch = frame.shape
result = np.zeros((h, w, ch), dtype=np.uint8)
# 二值化图像
print("start to detect lines...\n")
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
# cv.imshow("input image", frame)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in range(len(contours)):
# 提取与绘制轮廓
cv2.drawContours(result, contours, cnt, (0, 255, 0), 2)
# 轮廓逼近
epsilon = 0.01 * cv2.arcLength(contours[cnt], True)
approx = cv2.approxPolyDP(contours[cnt], epsilon, True)
# 分析几何形状
corners = len(approx)
shape_type = ""
# if corners == 3:
# count = self.shapes['triangle']
# count = count+1
# self.shapes['triangle'] = count
# shape_type = "三角形"
if corners == 4:
count = self.shapes['rectangle']
count = count + 1
self.shapes['rectangle'] = count
shape_type = "立方体"
if corners >= 10:
count = self.shapes['circles']
count = count + 1
self.shapes['circles'] = count
shape_type = "易拉罐"
if 4 < corners < 10:
count = self.shapes['polygons']
count = count + 1
self.shapes['polygons'] = count
shape_type = "易拉罐"
# 求解中心位置
mm = cv2.moments(contours[cnt])
cx = int(mm['m10'] / mm['m00'])
cy = int(mm['m01'] / mm['m00'])
cv2.circle(result, (cx, cy), 3, (0, 0, 255), -1)
# 颜色分析
color = frame[cy][cx]
color_str = "(" + str(color[0]) + ", " + str(color[1]) + ", " + str(color[2]) + ")"
# 计算面积与周长
p = cv2.arcLength(contours[cnt], True)
area = cv2.contourArea(contours[cnt])
print("颜色: %s 形状: %s "% (color_str, shape_type))
# print("周长: %.3f, 面积: %.3f 颜色: %s 形状: %s "% (p, area, color_str, shape_type))
font = cv2.FONT_HERSHEY_SIMPLEX
lower_green = np.array([35, 110, 106]) # 绿色范围低阈值
upper_green = np.array([77, 255, 255]) # 绿色范围高阈值
lower_red = np.array([0, 127, 128]) # 红色范围低阈值
upper_red = np.array([10, 255, 255]) # 红色范围高阈值
kernel = np.ones((5, 5), np.uint8) # 卷积核
# cap = cv2.VideoCapture('1.mp4') # 打开视频文件
cap = cv2.VideoCapture(0) # 打开USB摄像头
if (cap.isOpened()): # 视频打开成功
flag = 1
else:
flag = 0
num = 0
if (flag):
while (True):
ret, frame = cap.read() # 读取一帧
ld = ShapeAnalysis()
ld.analysis(frame)
if ret == False: # 读取帧失败
break
hsv_img = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask_green = cv2.inRange(hsv_img, lower_green, upper_green) # 根据颜色范围删选
mask_red = cv2.inRange(hsv_img, lower_red, upper_red)
# 根据颜色范围删选
mask_green = cv2.medianBlur(mask_green, 7) # 中值滤波
mask_red = cv2.medianBlur(mask_red, 7) # 中值滤波
mask = cv2.bitwise_or(mask_green, mask_red)
contours, hierarchy = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
contours2, hierarchy2 = cv2.findContours(mask_red, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours:
(x, y, w, h) = cv2.boundingRect(cnt)
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 255), 2)
cv2.putText(frame, "Green", (x, y - 5), font, 0.7, (0, 255, 0), 2)
for cnt2 in contours2:
(x2, y2, w2, h2) = cv2.boundingRect(cnt2)
cv2.rectangle(frame, (x2, y2), (x2 + w2, y2 + h2), (0, 255, 255), 2)
cv2.putText(frame, "Red", (x2, y2 - 5), font, 0.7, (0, 0, 255), 2)
num = num + 1
cv2.imshow("dection", frame)
if cv2.waitKey(20) & 0xFF == 27:
break
# opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) # 形态学开运算
# bila = cv2.bilateralFilter(mask, 10, 200, 200) # 双边滤波消除噪声
# edges = cv2.Canny(opening, 50, 100) # 边缘识别
# # 识别圆形
# circles = cv2.HoughCircles(
# edges, cv2.HOUGH_GRADIENT, 1, 100, param1=100, param2=10, minRadius=10, maxRadius=500)
# if circles is not None: # 如果识别出圆
# for circle in circles[0]:
# # 获取圆的坐标与半径
# x = int(circle[0])
# y = int(circle[1])
# r = int(circle[2])
# cv2.circle(frame, (x, y), r, (0, 0, 255), 3) # 标记圆
# cv2.circle(frame, (x, y), 3, (255, 255, 0), -1) # 标记圆心
# text = 'x: ' + str(x) + ' y: ' + str(y)
# cv2.putText(frame, text, (10, 30), font, 1, (0, 255, 0), 2, cv2.LINE_AA, 0) # 显示圆心位置
# else:
# # 如果识别不出,显示圆心不存在
# cv2.putText(frame, 'x: None y: None', (10, 30), font, 1, (0, 255, 0), 2, cv2.LINE_AA, 0)
# cv2.imshow('frame', frame)
# cv2.imshow('mask', mask)
# cv2.imshow('edges', edges)
# k = cv2.waitKey(5) & 0xFF
# if k == 27:
# break
cv2.waitKey(0)
cv2.destroyAllWindows()