import cv2
import numpy as np
thresh_gaizi=117
thresh_gaizi_range=3
thresh_yemian=257
thresh_yemian_range=3
thresh_baozhuang=436
thresh_baozhuang_range=3
value_gaizi=0
value_yemian=0
value_baozhuang=0
#对比1
#mask_img=mask_hsv #使用预先标定的颜色抠图
#对比2
#mask_img=dst #使用Sobel融合后的检测抠图
#对比3
#mask_img=edge_output #使用Canny边缘检测算法的检测抠图
mask_use=1 # 1-hsv 2-canny 3-canny
#(c1)是否窗口打印消息-调试使用但是会降低检测速度
debug_print=0 #调试阶段1 正式使用追求速度0
#选择检测形状
detect_what=0#1圆 0矩形
#(c2)选择是否出现标定颜色界面
detect_biaoding=1# 每次换一个光照环境 给1 鼠标点击颜色区域矫正颜色数值,获取范围填写在color_dist的最大最小中
#(c3)选择检测多少颜色
#检测一种颜色 Lower颜色下限数值 Upper颜色上限数值
#color_dist = {'red': {'Lower': np.array([0, 230, 150]), 'Upper': np.array([10, 255, 190])},}
#检测多种颜色-有更多自己往后添加
color_dist = {'red': {'Lower': np.array([160, 80, 150]), 'Upper': np.array([190, 210, 220])},
'yello': {'Lower': np.array([0, 0, 0]), 'Upper': np.array([170, 160, 80])}
}
hsvshow=0
#鼠标点击函数
def getposHsv(event,x,y,flags,param):
if event==cv2.EVENT_LBUTTONDOWN:
print("HSV is",hsvshow[y,x])
def getColorBox(shareData,shareLock):
cap = cv2.VideoCapture(0)
#cv2.namedWindow('imageHSV', 1)
if mask_use==1 and detect_biaoding==1:
cv2.namedWindow('HSV', 1)
cv2.setMouseCallback("HSV",getposHsv)#鼠标函数
while cap.isOpened():
ret, frame = cap.read()
if frame is not None:
gs_frame = cv2.GaussianBlur(frame, (5, 5), 0) # 高斯模糊
hsv = cv2.cvtColor(gs_frame, cv2.COLOR_BGR2HSV) # 转化成HSV图像
global hsvshow
hsvshow=hsv
erode_hsv = cv2.erode(hsv, None, iterations=2) # 腐蚀 粗的变细
global color_dist
if mask_use==1:
#color_dist=color_dist
pass
else:
color_dist = {'red': {'Lower': np.array([0, 190, 140]), 'Upper': np.array([10, 255, 255])} }
for nowcoloe in color_dist:
#使用纯颜色抠图
global mask_hsv
if mask_use==1:
mask_hsv = cv2.inRange(erode_hsv, color_dist[nowcoloe]['Lower'], color_dist[nowcoloe]['Upper'])
# 灰度图像
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 高斯模糊,降低噪声
blurred = cv2.GaussianBlur(gray, (3, 3), 0)
# 图像梯度
#对比1 横向检测
xgrad = cv2.Sobel(blurred, cv2.CV_16SC1, 1, 0)
absX = cv2.convertScaleAbs(xgrad) # 转回uint8
#对比2 纵向检测
ygrad = cv2.Sobel(blurred, cv2.CV_16SC1, 0, 1)
absY = cv2.convertScaleAbs(ygrad)
#对比3 横+纵检测
dst = cv2.addWeighted(absX,0.5,absY,0.5,0)
#cv2.imshow("absX", absX)
#cv2.imshow("absY", absY)
#cv2.imshow("absX_absY", dst)
edge_output = cv2.Canny(xgrad, ygrad, 50, 150)
cv2.imshow("absX_absY_canny", edge_output)
#img = cv2.GaussianBlur(mask_hsv,(3,3),0)
#canny = cv2.Canny(img, 50, 150)
#下面检测用那个放开那个 默认是1
mask_img=frame
if mask_use==1:
#对比1
mask_img=mask_hsv #使用预先标定的颜色抠图erode_hsv
elif mask_use==2:
#对比2
mask_img=dst #使用Sobel融合后的检测抠图
elif mask_use==3:
#对比3
mask_img=edge_output #使用Canny边缘检测算法的检测抠图
#print(colorshow)
cnts = cv2.findContours(mask_img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
draw_color=(255,255,255)
if nowcoloe=="red":
draw_color=(0,0,255)
elif nowcoloe=="yello":
draw_color=(0,255,255)
elif nowcoloe=="green":
draw_color=(0,255,0)
image=frame
if cnts:
cnt = max(cnts, key=cv2.contourArea)
c=cnt
#函数可以计算面积,也可以使用矩 M[‘m00’]
area=cv2.contourArea(c)
#if area<1000:#踢出小边界
#continue
perimeter = cv2.arcLength(c,True) #计算周长
#hull = cv2.convexHull(cnt) #凸包
#最大边界矩形(包围盒)
draw_rec=0
if draw_rec:
x,y,w,h = cv2.boundingRect(c)
image = cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,255),2)
#旋转矩形
draw_rec_ro=0
if draw_rec_ro :
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(image,[box],0,(255,0,255),2)
#最小外接圆
draw_yuan=0
if draw_yuan:
(x,y),radius = cv2.minEnclosingCircle(c)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(image,center,radius,(0,255,0),2)
# 计算每一个轮廓的中心点
M = cv2.moments(c)#计算图像的矩,并返回一个字典 根据这些矩的值可以得到重心
M["m00"]=M["m00"]+0.001 #避免除以0
cX = int((M["m10"] / M["m00"]))
cY = int((M["m01"] / M["m00"]))
#print("面积",area,"周长",perimeter,'最小外接圆',radius,'轮廓的中心点',(cX,cY))
#检测圆形
if detect_what==1:
#用圆拟合目标
(x, y), radius = cv2.minEnclosingCircle(cnt)
with shareLock:
shareData[1]=int(x)
shareData[2]=int(y)
shareData[3]=int(radius)
if debug_print==1:
print("r",radius)
#画圆函数 radius 半径 int(x), int(y) 位置
cv2.circle(image, (int(x), int(y)), int(radius), draw_color, 2)
pass
#检测矩形
else:
#
# 获取最小外接矩阵,中心点坐标,宽高,旋转角度
rect = cv2.minAreaRect(cnt)
## 获取矩形四个顶点,浮点型
box = cv2.boxPoints(rect)
# 取整
box = np.int0(box)
# 获取四个顶点坐标
left_point_x = np.min(box[:, 0])
right_point_x = np.max(box[:, 0])
top_point_y = np.min(box[:, 1])
bottom_point_y = np.max(box[:, 1])
left_point_y = box[:, 1][np.where(box[:, 0] == left_point_x)][0]
right_point_y = box[:, 1][np.where(box[:, 0] == right_point_x)][0]
top_point_x = box[:, 0][np.where(box[:, 1] == top_point_y)][0]
bottom_point_x = box[:, 0][np.where(box[:, 1] == bottom_point_y)][0]
if nowcoloe=="red":
#print("red",box[2][0],box[2][1])
value_gaizi=bottom_point_y
#value_yemian=0
#value_baozhuang=0
if value_gaizi>= (thresh_gaizi-thresh_gaizi_range) and value_gaizi<= (thresh_gaizi+thresh_gaizi_range):
cv2.putText(image, str("cap level:ok"), (120,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
else:
cv2.putText(image, str("cap level:error"), (120,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
cv2.putText(image, str(top_point_y), (50,top_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
cv2.putText(image, str(bottom_point_y), (50,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
pt1=(0,top_point_y)
pt2=(left_point_x,top_point_y)
cv2.line(image, pt1, pt2, color=(0,255,0), thickness=2)
pt1=(0,bottom_point_y)
pt2=(left_point_x,bottom_point_y)
cv2.line(image, pt1, pt2, color=(0,255,0), thickness=2)
elif nowcoloe=="yello":
#value_gaizi=bottom_point_y
value_yemian=top_point_y
value_baozhuang=bottom_point_y
if value_yemian>= (thresh_yemian-thresh_yemian_range) and value_yemian<= (thresh_yemian+thresh_yemian_range):
cv2.putText(image, str("liquid level:ok"), (120,top_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
else:
cv2.putText(image, str("liquid level:error"), (120,top_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
if value_baozhuang>= (thresh_baozhuang-thresh_baozhuang_range) and value_baozhuang<= (thresh_baozhuang+thresh_baozhuang_range):
cv2.putText(image, str("package level:ok"), (120,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
else:
cv2.putText(image, str("package level:error"), (120,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
#print("yello",box[0][0],box[0][1])
cv2.putText(image, str(top_point_y), (50,top_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2)
cv2.putText(image, str(bottom_point_y), (50,bottom_point_y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2)
pt1=(0,top_point_y)
pt2=(left_point_x,top_point_y)
cv2.line(image, pt1, pt2, color=(255,255,0), thickness=2)
pt1=(0,bottom_point_y)
pt2=(left_point_x,bottom_point_y)
cv2.line(image, pt1, pt2, color=(255,255,0), thickness=2)
#print(box)
with shareLock:
shareData[1]=box[0][0]#右上角h
shareData[2]=box[0][1]#右上角w
shareData[3]=box[2][0]#左下角h
shareData[4]=box[2][1]#左下角w
#print(rect)
if debug_print==1:
#print("h",box[0][0]-box[2][0],"w",box[0][1]-box[2][1])
h=abs(box[2][0]-box[0][0])
w=abs(box[2][1]-box[0][1])
#周长
zhouchang=(h+w)*2
txt = "Length:"+str(zhouchang)+" w:"+str(w)+" h:"+str(h)
cv2.putText(image, txt, (50,50), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2)
#颜色
colorshow=(color_dist[nowcoloe]['Lower']+color_dist[nowcoloe]['Upper'])/2
txt = "Color-R G B:"+str(colorshow)
cv2.putText(image, txt, (50,100), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2)
#坐标点
x=int((box[0][0]+box[2][0])/2)
y=int((box[0][1]+box[2][1])/2)
txt = "Position-x:"+str(x)+" y:"+str(y)
cv2.putText(image, txt, (50,150), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 255), 2)
txt ="w:"+str(w)+" h:"+str(h)
cv2.putText(image, txt, (50,200), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2)
if rect[1][0]<90 and rect[1][1]<90: #剔除掉像素小于90×90的框 排除干扰
pass
else:
cv2.drawContours(image, [np.int0(box)], -1, draw_color, 2)
#为了加快速度 检测进程连窗口都可以不显示,图像送给给主线程序来显示
cv2.imshow("RGB",image)
key=cv2.waitKey(1)
if key == ord('q') or key == ord('Q'):
shareData[5]=0
break
if mask_use==1 and detect_biaoding==1:
cv2.imshow("HSV",hsv)
key=cv2.waitKey(1)
if key == ord('q') or key == ord('Q'):
break
#单独测试代码
from multiprocessing import Process,Manager
if __name__ == '__main__':
#进程共享内存
manager=Manager()
shareData=manager.dict()#共享数据
shareLock=manager.Lock() #进程数据锁
#根据检测的形状 数据含义不同
shareData[1]=0# 圆-x 矩形-左上角h
shareData[2]=0# 圆-y 矩形-左上角w
shareData[3]=0# 圆-r 矩形-右下角h
shareData[4]=0# 圆-无 矩形-右下角w
shareData[8]=0 #wegiht
shareData[9]=1# 控制标志 控制检测进程关闭
#开启进程1
p1=Process(target=getColorBox,args=(shareData,shareLock)) #必须加,号
p1.deamon=True #伴随主进程关闭而关闭
p1.start()
#主进程不断获取进程1返回的结果
while 1:
if shareData[9]==0:#串口按退出
break
#print(shareData[1],shareData[2],shareData[3],shareData[4])