Python-opencv的指针检测、表盘识别算法案例分析

主要通过opencv库内霍夫曼直线检测和圆检测实现指针识别,文章主要介绍思路。
源码下载地址https://download.csdn.net/download/qq_44781688/20009503.
(内涵报告和解释 分析)
python版本为3.7 但运行的库都很普通也没有什么特别复杂的计算,所以其他版本理论上应该也不会出现什么错误,其他库自行安装即可。
欢迎交流讨论

去除表盘,保留指针(效果好可省略)

首先创建了一个light.py文件,利用两个表盘一样指针不同的图片对应位置比较留下最亮的像素,得到没有指针的表盘。
需要表盘位置比较准确,两张图表盘位置相近,否则太大差异没有意义
不相同也可以通过模板匹配或者截取部分等方式对齐,自行学习研究

用Image库求最亮去除指针,保存方便下一步去除表盘
from PIL import Image,ImageChops
#两图像求最亮去除指针
im=ImageChops.lighter(Image.open('6.jpg'), Image.open('7.jpg'))
im.save("none1.jpg")

创建了一个pointer.py文件 保留指针

与没有指针的none.jpg作比较 尽量去除表盘留下指针
实际发现2.5量程的表盘没有完全对齐 效果不是特别好 还需要进一步处理
1.6量程对齐了 效果很好
def pointer(filepath,judge):
    im=Image.open(filepath)
    if judge:
        im_none= Image.open("none1.jpg")
    else:
        im_none = Image.open("none.jpg")   #选取不同的量程图片做处理
    im1= ImageChops.difference(im_none,im)
    im1.save("pointer.jpg")
    im = cv2.imread("pointer.jpg")
    return im

保留指针后图片实例
已经难以看到表盘,效果非常理想

表盘圆心检测

利用 cv2.HoughCircles函数检测圆,一般来说不需要太多预处理,直接彩色图读进去处理即可,简单调整参数后即可检测到想要大小范围的圆。也可以用导入形态学

from scipy.ndimage import measurements

其中measurements.center_of_mass()可以找到各个物体中心,结果类似。但是不会一个物体检测到多次,但对同一圆参数不同可能cv2.HoughCircles会检测到多个,以下代码借此求平均加强精度
中心一般都不是特别准,需要简单调整结果如加减等

图像预处理 求中心

import cv2
import numpy as np
def centre(filepath,judge):
    org = cv2.imread(filepath,1)
    img = org
    img_gray = cv2.cvtColor(org, cv2.COLOR_BGR2GRAY)
    # 低同滤波进行平滑图像
    img_gray = cv2.medianBlur(img_gray, 5)
    cimg = cv2.cvtColor(img_gray, cv2.COLOR_GRAY2BGR)
    # 提取圆形
    circles = cv2.HoughCircles(img_gray,cv2.HOUGH_GRADIENT,1,10,param1=150,param2=90,minRadius=465,maxRadius=485)

    circles = np.uint16(np.around(circles))
    x = 0
    y = 0
    j=0
    for i in circles[0,:]:
    # draw the outer circle
        cv2.circle(img,(i[0],i[1]),i[2],(0,0,255),10)
        x = (x*j+i[0])/(j+1)
        y = (y*j+i[1])/(j+1)
        j=j+1
    # draw the center of the circle
        if judge:
            y=y+8
            x=x+1
            cv2.circle(img, (int(x), int(y)), 2, (0, 0, 255), 5)#刻度不同图像不同偏差不同
        else:
            x=x-8
            y=y-4
            cv2.circle(img,(int(x), int(y)),2,(0,0,255),5)

    # 显示原图和处理后的图像
    # cv2.imshow("org",org)
    cv2.imshow("processed",img)
    print("中心为:",i[0]-8,i[1]-4)
    cv2.waitKey(0)
    img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
    return img,int(x),int(y)
if __name__ == "__main__":
    img,x,y=centre("5.jpg",0)
    print(x,y)

圆心结果图示可见检测精度非常高。标记基本和圆心完全重合。

主程序段(指针识别到输出)

pointer.py文件完成调取上述函数,完成对应部分后输出结果和图像
主要程序流程图

预处理

主要为了边缘检测后方便检测直线

frame = pointer.pointer(filepath,judge)#进行指针处理的图像 大部分运算用这个
frame = cv2.cvtColor(frame,cv2.COLOR_RGB2BGR)
gray = frame.copy()
# cv2.imshow('origin', gray)
subplot(332)
imshow(gray)
title("去除表盘")

# 高斯除噪
kernel = np.ones((6, 6), np.float32) / 36
gray_cut_filter2D = cv2.filter2D(org[0:org.shape[0], 0:org.shape[1]], -1, kernel)
# 灰度图 二值化
gray_img = cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY)
ret, thresh1 = cv2.threshold(gray_img, 80, 100, cv2.THRESH_BINARY)  # 小于70 黑 大于200白
#边缘检测
test_main = thresh1.copy()
edges = cv2.Canny(test_main, 50, 200, apertureSize=3)

直线检测

主要用了cv2.HoughLinesP直接输出确定直线的两个点坐标,选取最长的两条直线,输出的前两个line,即为表针两边直线。(由于表针较粗所以能检测到两条,但是由于不是从中心所以角度不能直接计算读数,要求交点再通过中心计算)通过sympy库内的Line函数表示直线用intersection函数求两条直线交集,交点即为直线段点
也可以用cv2.HoughLines函数,输出的是距离和直线角度

lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength=15, maxLineGap=60)  # 函数将通过步长为1的半径和步长为π/180的角来搜索所有可能的直线
for line in lines:
    # print(lines)  # 多维数组
    x1, y1, x2, y2 = line[0]
    cv2.line(result, (x1, y1), (x2, y2), (0, 0, 255),3)
    cv2.drawMarker(result,(x2,y2),(255, 0, 0),thickness=2,markerType=cv2.MARKER_STAR,line_type=cv2.LINE_8,markerSize=20)

x1, y1, x2, y2 = lines[0][0]
l = Line(Point(x1, y1),Point( x2, y2))
x1, y1, x2, y2 = lines[1][0]
l1 = Line(Point(x1, y1),Point( x2, y2))
x = np.float64(l1.intersection(l)) #sympy库求直线交点
print("指针端点",x)

主要问题/其他方案

1.表针细,只检测到一条直线且过圆心,就通过输出的直线角度直接计算读数,但是通常误差可能大
2.其他影响检测到一条直线不过圆心:这就要圆心检测之后以圆心和半径创建用sympy库内Circle,直线与圆求交点,交点即与圆心和指针端点在同一条直线上。可视为指针端点

C1 = Circle(Point(x0, y0), 400)
l1 = Line(Point(x1, y1),Point( x2, y2))
 print(l1.intersection(C1))

但是这样会输出两个点,需要区分指针方向来区分交点选哪一个
3.利用两条直线检测,可以不用区分交点位置,因为两条直线交点只有一个。但是还有问题就是个别图片检测不到两条直线或者检测到其他非表针的直线,就要多修改参数或者改变预处理方式尽量去除干扰
本文就是在发现指针旁文字多时出错进而多加了去除表盘的操作

角度计算

直接使用指针端点和圆心直线斜率计算角度容易出现返回值小于180度的情况,无法显示180-360度的角度。
下面代码自己编写了计算函数通过两直线向量积求角度沿顺时针0-360输出

def angle(v1,v2):
    x1,y1 = [v1[2]-v1[0],v1[3]-v1[1]]
    x2,y2 = [v2[2]-v2[0],v2[3]-v2[1]]
    dot = x1*x2+y1*y2
    det = x1*y2-y1*x2
    theta = np.arctan2(det, dot)
    theta = theta if theta>0 else 2*np.pi+theta
        distinguish = 2.5/(2.54/2.5)/265 #比例关系
    output = theta * 180 / np.pi * distinguish
    return output

绘制和显示

outpointer=org
if judge:
    org_x0, org_y0 = 340,719  #图像零点坐标 第一个刻度不是很均匀 实际选为零刻度下标点位置
else:
    org_x0, org_y0 = 418,738
cv2.line(outpointer, (int(x[0][0]), int(x[0][1])), (x0,y0), 255, 3)
cv2.line(outpointer, (org_x0,org_y0), (x0,y0), 255, 3)
out = angle.angle((x0, y0,org_x0,org_y0),(x0, y0,int(x[0][0]), int(x[0][1])),judge)
subplot(337)
imshow(outpointer)
title("指针")
number = Image.new('RGB', (1280, 1024), 'black')
drawer = ImageDraw.Draw(number)  #标注
font = ImageFont.truetype("simhei.ttf",200, encoding="utf-8")
drawer.text((0, 500), text="读数为", font=font, fill='red')
drawer.text((600, 500), text="%0.4f"%out, font=font, fill='red')
number = array(number)
subplot(338)
imshow(number)
title("读数")
show()

结果展示

表盘2.5量程结果示意图
表盘1.6量程结果示意图
图示可见运行结果精度非常高
由于许多段落对于思路展示没有意思,所有代码有一定删减
有意者下载测试使用
源码下载地址https://download.csdn.net/download/qq_44781688/20009503.(内含报告和使用说明)其中每个函数成文件写了main函数可以单独运行调试
欢迎大家学习交流,有问题可以私信或者评论,我见到会尽快回复。

  • 14
    点赞
  • 137
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论
Python-opencv品质检测算法可以分为两类:基于图像处理技术和基于机器学习技术。 1. 基于图像处理技术的品质检测算法: (1) 图像去噪算法: 例如高斯滤波、中值滤波、双边滤波等,可以去除图像中的噪声。 (2) 图像增强算法: 例如直方图均衡化、自适应直方图均衡化、拉普拉斯算子增强等,可以增强图像的亮度和对比度。 (3) 边缘检测算法: 例如Sobel算子、Canny算子等,可以检测图像中的边缘。 (4) 形态学处理算法: 例如膨胀、腐蚀、开运算、闭运算等,可以去除图像中的小噪点和孔洞。 (5) 特征提取算法: 例如颜色直方图、纹理特征、形状特征等,可以提取图像的特征信息。 2. 基于机器学习技术的品质检测算法: (1) 支持向量机(SVM)算法: SVM算法可以通过训练数据集,学习到一种分类模型,用于分类任务。 (2) 决策树算法: 决策树算法可以通过训练数据集,学习到一种分类模型,用于分类任务。 (3) 随机森林算法: 随机森林算法是一种集成学习算法,它可以通过多个决策树模型的投票来进行分类任务。 (4) 深度学习算法: 深度学习算法可以通过深度神经网络模型,学习到一种分类模型,用于分类任务。 以上是常用的python-opencv品质检测算法,您可以根据具体需求选择合适的算法进行实现。如果您还有其他问题,请随时向我提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ζั͡ޓއއ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值