这篇文章主要介绍了OpenCV 表盘指针自动读数的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
前段时间参加了一个表盘指针读数的比赛,今天来总结一下
数据集一共有一千张图片:
方法一:径向灰度求和
基本原理:
将图像以表盘圆心转换成极坐标,然后通过矩阵按行求和找到二值图最大值即为指针尖端
导入
来源gaodai.ma#com搞#代!码网
需要用到的包
import cv2 as cv import numpy as np import math from matplotlib import pyplot as plt import os
图像预处理
去除背景:利用提取红色实现
def extract_red(image): """ 通过红色过滤提取出指针 """ red_lower1 = np.array([0, 43, 46]) red_upper1 = np.array([10, 255, 255]) red_lower2 = np.array([156, 43, 46]) red_upper2 = np.array([180, 255, 255]) dst = cv.cvtColor(image, cv.COLOR_BGR2HSV) mask1 = cv.inRange(dst, lowerb=red_lower1, upperb=red_upper1) mask2 = cv.inRange(dst, lowerb=red_lower2, upperb=red_upper2) mask = cv.add(mask1, mask2) return mask
获得钟表中心:轮廓查找,取出轮廓的外接矩形,根据矩形面积找出圆心
def get_center(image): """ 获取钟表中心 """ edg_output = cv.Canny(image, 100, 150, 2) # canny算子提取边缘 cv.imshow('dsd', edg_output) # 获取图片轮廓 contours, hireachy = cv.findContours(edg_output, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) center = [] cut=[0, 0] for i, contour in enumerate(contours): x, y, w, h = cv.boundingRect(contour) # 外接矩形 area = w * h # 面积 if area 4000: continue cv.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 1) cx = w / 2 cy = h / 2 cv.circle(image, (np.int(x + cx), np.int(y + cy)), 1, (255, 0, 0)) ## 在图上标出圆心 center = [np.int(x + cx), np.int(y + cy)] break return center[::-1]
由上面的图像可以看出,圆心定位还是非常准确的
图片裁剪
def ChangeImage(image): """ 图像裁剪 """ # 指针提取 mask = extract_red(image) mask = cv.medianBlur(mask,ksize=5)#去噪 # 获取中心 center = get_center(mask) # 去除多余黑色边框 [y, x] = center cut = mask[y-300:y+300, x-300:x+300] # 因为mask处理后已经是二值图像,故不用转化为灰度图像 return cut
剪裁后的图像如下图所示:
极坐标转换
注意:需要将图片裁剪成正方形
def polar(image): """ 转换成极坐标 """ x, y = 300, 300 maxRadius = 300*math.sqrt(2) linear_polar = cv.linearPolar(image, (y, x), maxRadius, cv.WARP_FILL_OUTLIERS + cv.INTER_LINEAR) mypolar = linear_polar.copy() #将图片调整为从0度开始 mypolar[:150, :] = linear_polar[450:, :] mypolar[150:, :] = linear_polar[:450, :] cv.imshow("linear_polar", linear_polar) cv.imshow("mypolar", mypolar) return mypolar
由图像就可以很容易发现指针的顶点
计算角度
def Get_Reading(sumdata): """ 读数并输出 """ peak = [] # s记录遍历时波是否在上升 s = sumdata[0] sumdata[i+1] and sumdata[i] > 70000: peak.append(sumdata[i]) s=False # 下降阶段 if s==False and sumdata[i] peak[-1]: peak.append(max(a,b)) longindex = (sumdata.index(peak[-1]))%599 longnum = (longindex + 1)//25*50 # 先初始化和长的同一刻度 #shortindex = longindex shortnum = round(longindex / 6) try: shortindex = sumdata.index(peak[-2]) shortnum = round(shortindex / 6) except IndexError: i=0 while i 80000: continue elif possibleshort 17800: shortindex = sumdata.index(possibleshort) - 1 shortnum = round(shortindex / 6) break return [longnum,shortnum%100]
def test(): """ RGS法测试 """ image = cv.imread("./BONC/1_{0:0>4d}".format(400) + ".jpg-600") newimg = ChangeImage(image) polarimg = polar(newimg) psum = polarimg.sum(axis=1, dtype = 'int32') result = Get_Reading(list(psum)) print(result)
if __name__ == "__main__": test() k = cv.waitKey(0) if k == 27: cv.destroyAllWindows() elif k == ord('s'): cv.imwrite('new.jpg-600', src) cv.destroyAllWindows()
[1050, 44]
方法二:Hough直线检测
原理:利用Hough变换检测出指针的两条边,从而两条边的中线角度即为指针刻度
数据预处理与上面的方法类似
可以看到分别检测出了两个指针的左右两条边,然后可以由这四个角度算出两个指针中线的角度,具体计算过程
以上就是OpenCV 表盘指针自动读数的示例代码的详细内容,更多请关注gaodaima搞代码网其它相关文章!