由于某个项目需要我们对板卡上显示的数字进行识别,但是yolo系列的网络之前并没有试过,而且当时时间有点紧,考虑到之前用过opencv做过点图像处理的工作,了解了一点opencv的强大之处,故抱着试试看的心态开始在网络上查阅相关内容。
经过一番寻找,终于找到了这篇文章。http://t.csdn.cn/0PJMhhttp://t.csdn.cn/0PJMh 该功能的主要框架便是借鉴这位博主的实现方法,但在我的数据集上实现的时候出现了错误,当最大边框被提取出来后,矫正出来的图像不是目标图像,非常扭曲,在jupyter notebook中逐步实现后发现是reorder出现了问题,故这篇博客里在前面提到的博客的基础上重写了reorder函数,记录下来这个处理方法。
getcontour() 参考原链接
- 传入经过 cv2.threshold(img,210,255,cv2.THRESH_BINARY)处理过的 thresh
- 返回最大轮廓的四个角点和构成边的顶点
reorder()
- 传入 getcontour得到的四个角点,由于后续在做矫正的时候需要严格按照(左上角,右上角,左下角,右下角)顺序排列的角点坐标,而getcontour() 返回的四个角点不一定按照这个顺序排列,所以我们需要进行 reorder(),也就是在这里原博主的代码在我的数据集上出现了问题,故重写了该函数,保证了正确运行。
- 返回 严格按照(左上角,右上角,左下角,右下角)顺序排列的角点坐标
- 注意:该重新排序方法只适合于没有上下概念的边框或者有上下概念但没有上下翻转的情况
- 没有上下概念比如一些简单的几何图形
- 有上下概念但没有上下翻转的情况比如手写数字,6没有旋转到会被识别成9的程度。
def reorder (myPoints):
# 在进行图像矫正时,我们需要严格按照(左上角,右上角,左下角,右下角)顺序排列的contour坐标,由于可能会出现顺序错乱的情况,所以需要重排
# pts1即未矫正的边框顶点
pts1 = np.float32(myPoints)
# pts1_new作为矫正完的返回值
pts1_new = np.zeros(pts1.shape)
temp = pts1.reshape((4,2))
# 如果视频中数字没有过于倾斜,其角点的方位可由四个角点的纵坐标均值,处于纵坐标均值以上的两个角点的横坐标均值,处于纵坐标均值以下的两个角点的横坐标均值得到
means_y = 0
up_mean_x = 0
down_mean_x = 0
means_y = temp[:,1].sum()/4
for point in temp:
if (point[1] < means_y):
up_mean_x += point[0]/2
else:
down_mean_x += point[0]/2
for point in temp:
# 当未矫正角点处于上半部分时,通过比较它与上半部分横坐标均值可得出它是左上角点还是右上角点
if (point[1]<means_y):
# 小于即为左上角点
if (point[0]<up_mean_x):
pts1_new[0][0] = point
# 大于即为右上角点
else:
pts1_new[1][0] = point
# 判断左下角点还是右下角点同理
else:
# 小于即为左下角点
if (point[0]<down_mean_x):
pts1_new[2][0] = point
# 大于即为右下角点
else:
pts1_new[3][0] = point
return pts1_new
getWarp() 参考原链接
- 传入 getcontour得到的四个角点和图像(thresh)
- 返回 矫正后的图像
最终效果如下所示: