2019年11月24日开发手记
通过opencv求出了各轮廓的中心点,并对各中心点进行排序并求出最大最小值点,根据求出的这些最大最小点绘制矩形。
效果如图:
速度为20ms左右,从效果来看该算法无法绘制出准确的运动图像,并且面对多个运动物体时效果更差,决定更换为层次聚类算法,先得到每个轮廓的中心点,再用层次聚类算法得到运动图像所包含的簇,再依据该簇所包含的轮廓点绘制矩形。
凝聚层级聚类(HAC)是自下而上的一种聚类算法。HAC首先将每个数据点视为一个单一的簇,然后计算所有簇之间的距离来合并簇,知道所有的簇聚合成为一个簇为止。
具体步骤:
1. 首先我们将每个数据点视为一个单一的簇,然后选择一个测量两个簇之间距离的度量标准。例如我们使用average linkage作为标准,它将两个簇之间的距离定义为第一个簇中的数据点与第二个簇中的数据点之间的平均距离。
2. 在每次迭代中,我们将两个具有最小average linkage的簇合并成为一个簇。
3. 重复步骤2知道所有的数据点合并成一个簇,然后选择我们需要多少个簇。
层次聚类优点:
(1)不需要知道有多少个簇
(2)对于距离度量标准的选择并不敏感
(3)可以表示出方向
缺点:效率低
问题的关键在于如何将findContours找到的轮廓整合到一个轮廓,或者说如何将多个元组整合为一个元组。将已经find的轮廓重新还原为点集。
部分代码:
image,contoursdiff, hierarchydiff = cv2.findContours(iimg.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#image为图像,contourdiff为轮廓点 if len(contoursdiff)>2: s = Stack() s.isEmpty() for c in contoursdiff: #print(1) #求出中心点 M = cv2.moments(c) #print(c) #print(M) if M["m00"]!=0: cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) s.push([cX,cY]) print(s.stack) if len(s.stack)!=0: x,y,x_1,y_1=maoposort(s.stack) cv2.rectangle(iimg, (x, y), (x_1, y_1), (255, 255, 0), 2) else: for c in contoursdiff: # 计算轮廓的边界框,在当前帧中画出该框 (x, y, w, h) = cv2.boundingRect(c) # print(x,y,w,h) cv2.rectangle(iimg, (x, y), (x + w, y + h), (255, 255, 0), 2)