python cv2 指针仪表读数

2023-11-03 12:10
文章标签 python 指针 cv2 仪表 读数

本文主要是介绍python cv2 指针仪表读数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

cv2识别指针式仪表(持续更新)

    • 问题描述
    • 解决方案
    • 效果预览
    • python cv2实现
      • 1、模板匹配
      • 2、直线拟合
      • 3、表盘读数
    • 提升准确率的方法
    • 参考资料


问题描述

最近遇到一个仪表盘读数的问题,主要要识别三种仪表盘
四分之一圆
圆形
双指针
参考了许多博客和论文,打算先用一种传统的方法试一下


解决方案

方案一:传统方法

  1. 模板匹配
  2. 直线拟合
  3. 表盘读数

方案二: 深度学习 (后续实现)

  1. YOLOX等目标检测方法识别表盘
  2. 目标检测方法识别数字、指针、指针旋转原点
  3. 欧式距离求相邻数字
  4. 字符识别模型识别数字
  5. 根据相邻数字求得指针所指数值

效果预览

1、原图
原图
2、模板图
模板图
3、模板匹配结果
模板匹配结果
4、识别结果

可以看出识别结果会有细微的偏差,但是通过调参可以缩小误差


python cv2实现

1、模板匹配

选取合适的模板图,并根据模板图中关键点坐标求出各角度对应数值

import cv2
import numpy as np
from math import cos, pi, sin, acos#模板匹配方法
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR','cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
method = cv2.TM_CCOEFF_NORMED#centers表示所有模板图片的指针中心点坐标,(0,0)位于图片左上角
centers = [[47,50],[67,74],[102,96],[63,64],[66,67],[65,67],[107,105],[104,106],[94,89],[57,55],[66,71]]
#scales表示所有模板图片刻度线所在坐标
scales=[{0:(8,68),1000:(7,46),2000:(14,20),3000:(38,8),4000:(64,5),5000:(84,22),6000:(98,42),7000:(96,66)},{0:(13,67),150:(17,50),200:(21,36),250:(30,27),300:(41,22),450:(65,18)},{0:(24,97),1000:(27,73),1500:(30,50),2000:(47,40),2500:(56,28),3000:(68,25),4000:(83,16),5000:(93,16),6000:(99,17)},{0:(14,63),50:(19,48),100:(26,29),150:(44,17),200:(65,13)},{0:(14,67),200:(17,46),300:(24,32),400:(36,22),500:(50,15),600:(65,13)},{0:(15,66),10:(14,55),20:(19,39),30:(32,36),40:(46,15),50:(63,13)},{0:(30,105),1:(26,86),2:(36,71),3:(40,52),4:(58,42),5:(71,27),6:(90,27),7.2:(110,19)},{0:(20,105),20:(21,80),40:(35,58),60:(54,39),80:(77,27),100:(101,26)},{0:(25,90),0.5:(24,77),1.0:(32,57),1.5:(47,38),2.0:(66,24),2.5:(91,19)},{0:(13,55),100:(12,45),200:(18,29),300:(29,19),400:(38,12),600:(57,10)},{0:(18,71),200:(16,62),400:(21,43),600:(31,26),800:(43,18),1000:(64,14)}]
#angles表示所有模板图片对应刻度相对中心点的角度
angles=[]
#模板原图大小
original_template_image_size = [(128,124),(107,105),(164,166),(99,97),(104,107),(106,99),(163,160),(161,162),(140,140),(95,104),(112,114)]#计算各个模板图刻度对应的角度
def calculate_angles(centers, scales):template_number = len(centers)for i in range(0, template_number):angles.append({})#print(f"模板{i+1}:")for k, v in scales[i].items():#第一个模板图片为圆形表盘,以中心点为轴,→为起始边向下旋转所成角度为r,r属于(0,360)if i == 0:r = acos((v[0] - centers[i][0])/((v[0] - centers[i][0]) ** 2 + (v[1] - centers[i][1]) ** 2) ** 0.5)r = int(r * 180 / pi)if 1000 < k < 7000:r = 360 - relse:r = acos((centers[i][0] - v[0])/((v[0] - centers[i][0]) ** 2 + (v[1] - centers[i][1]) ** 2) ** 0.5)r = int(r * 180 / pi)angles[i][k]=r#print(f"{k}刻度的角度为:",angles[i][k])calculate_angles(centers,scales)

Tips:

  1. 模板匹配方法的选取可能对结果产生巨大影响
  2. 模板图片选取十分重要!!

2、直线拟合

对于一红一黑双指针问题,先识别红指针,再识别黑指针。具体问题具体分析,关键在于获取指针角度,而不是识别出指针

#获取指定图片的指针角度
def get_pointer_angle(img, template_type):#shape = img.shapecenter = centers[template_type]center_x = center[0]center_y = center[1]freq_list = []#圆形表盘if template_type == 0:for i in range(361):x = 0.6 * center_x * cos(i * pi / 180) + center_xy = 0.6 * center_x * sin(i * pi / 180) + center_yx1 = 0.4 * center_x * cos(i * pi / 180) + center_xy1 = 0.4 * center_x * sin(i * pi / 180) + center_ytemp = img.copy()cv2.line(temp, (int(x1), int(y1)), (int(x), int(y)), 255, thickness=2)freq_list.append((np.sum(temp), i))#cv2.imshow('get_pointer_angle', temp)#cv2.waitKey(10)else:for i in range(91):x = center_x - 0.6 * center_x * cos(i * pi / 180)y = center_y - 0.6 * center_x * sin(i * pi / 180)temp = img.copy()cv2.line(temp, (center_x, center_y), (int(x), int(y)), 255, thickness=2)freq_list.append((np.sum(temp), i))#cv2.imshow('get_pointer_angle', temp)#cv2.waitKey(30)#cv2.destroyAllWindows()freq = max(freq_list, key = lambda x:x[0])return freq[1]#对于一红一黑双指针,先识别出红指针
def get_red_pointer_angle(img, template_type):center = centers[template_type]center_x = center[0]center_y = center[1]freq_list = []for i in range(91):x = center_x - 0.6 * center_x * cos(i * pi / 180)y = center_y - 0.6 * center_y * sin(i * pi / 180)temp = img.copy()cv2.line(temp, (center_x, center_y), (int(x), int(y)), (0, 0, 255), thickness=2)#cv2.imshow('red_pointer', temp)#cv2.waitKey(30)temp = np.sum(temp, axis=0)temp = np.sum(temp, axis=0)#获取图片中红色亮度的总和temp = temp[2]freq_list.append((np.sum(temp), i))#cv2.destroyAllWindows()freq = min(freq_list, key = lambda x:x[0])red_pointer_angle = freq[1]return red_pointer_angle

3、表盘读数

根据指针角度求数值

#根据角度和表盘类型,求得指针式仪表盘数值
def get_pointer_meter_value(angle, template_type):#value是所要求得指针数值,scale_value_down是刚好小于指针数值的表盘刻度数值,scale_value_over是刚好大于指针数值的表盘刻度数值value = 0scale_value_down = -1scale_value_up = 0#表盘为圆形if template_type == 0:if angles[template_type][0] < angle < angles[template_type][1000]:scale_value_down = 0scale_value_up = 1000elif angles[template_type][1000] < angle < angles[template_type][2000]:scale_value_down = 1000scale_value_up = 2000elif angles[template_type][2000] < angle < angles[template_type][3000]:scale_value_down = 2000scale_value_up = 3000elif angles[template_type][3000] < angle < angles[template_type][4000]:scale_value_down = 3000scale_value_up = 4000elif angles[template_type][4000] < angle < angles[template_type][5000]:scale_value_down = 4000scale_value_up = 5000elif angles[template_type][5000] < angle < angles[template_type][6000]:scale_value_down = 5000scale_value_up = 6000elif angles[template_type][7000] < angle < angles[template_type][0]:return 0else:angles_difference_angle = angles[template_type][7000] + 360 - angles[template_type][6000]if angle > angles[template_type][6000]:pointer_difference_angle = angle - angles[template_type][6000]else:pointer_difference_angle = angle + 360 - angles[template_type][6000]value = 6000 + 1000 * pointer_difference_angle / angles_difference_anglereturn value#表盘为四分之一圆else:    for k,v in angles[template_type].items():if angle < v:if k==0:return 0else:scale_value_up = kif scale_value_down != -1:break;else:scale_value_down = kangles_difference_angle = angles[template_type][scale_value_up] - angles[template_type][scale_value_down] #刻度线间角度差值pointer_difference_angle = angle - angles[template_type][scale_value_down]#下游刻度线与指针角度的差值value = scale_value_down + (scale_value_up-scale_value_down) * pointer_difference_angle / angles_difference_anglereturn value

提升准确率的方法

  1. 选用更规范的模板图片
  2. 选用其他模板匹配方法
  3. 调整模板图尺寸
  4. 直线拟合时采用更高精度
  5. 直线拟合选取更优直线宽度
  6. 高斯滤波等去噪手段预处理

完整源码地址:https://github.com/frankstorming/meter_reading


参考资料

使用OpenCV进行仪表数值读取

基于深度学习的指针式仪表图像智能读数方法

这篇关于python cv2 指针仪表读数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/338088

相关文章

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

精选20个好玩又实用的的Python实战项目(有图文代码)

《精选20个好玩又实用的的Python实战项目(有图文代码)》文章介绍了20个实用Python项目,涵盖游戏开发、工具应用、图像处理、机器学习等,使用Tkinter、PIL、OpenCV、Kivy等库... 目录① 猜字游戏② 闹钟③ 骰子模拟器④ 二维码⑤ 语言检测⑥ 加密和解密⑦ URL缩短⑧ 音乐播放

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

Python pandas库自学超详细教程

《Pythonpandas库自学超详细教程》文章介绍了Pandas库的基本功能、安装方法及核心操作,涵盖数据导入(CSV/Excel等)、数据结构(Series、DataFrame)、数据清洗、转换... 目录一、什么是Pandas库(1)、Pandas 应用(2)、Pandas 功能(3)、数据结构二、安

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

Python安装Pandas库的两种方法

《Python安装Pandas库的两种方法》本文介绍了三种安装PythonPandas库的方法,通过cmd命令行安装并解决版本冲突,手动下载whl文件安装,更换国内镜像源加速下载,最后建议用pipli... 目录方法一:cmd命令行执行pip install pandas方法二:找到pandas下载库,然后

Python实现网格交易策略的过程

《Python实现网格交易策略的过程》本文讲解Python网格交易策略,利用ccxt获取加密货币数据及backtrader回测,通过设定网格节点,低买高卖获利,适合震荡行情,下面跟我一起看看我们的第一... 网格交易是一种经典的量化交易策略,其核心思想是在价格上下预设多个“网格”,当价格触发特定网格时执行买

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

使用Python构建智能BAT文件生成器的完美解决方案

《使用Python构建智能BAT文件生成器的完美解决方案》这篇文章主要为大家详细介绍了如何使用wxPython构建一个智能的BAT文件生成器,它不仅能够为Python脚本生成启动脚本,还提供了完整的文... 目录引言运行效果图项目背景与需求分析核心需求技术选型核心功能实现1. 数据库设计2. 界面布局设计3

Python进行JSON和Excel文件转换处理指南

《Python进行JSON和Excel文件转换处理指南》在数据交换与系统集成中,JSON与Excel是两种极为常见的数据格式,本文将介绍如何使用Python实现将JSON转换为格式化的Excel文件,... 目录将 jsON 导入为格式化 Excel将 Excel 导出为结构化 JSON处理嵌套 JSON: