指针式仪表识别读数 Python(已开源数据集)

这篇具有很好参考价值的文章主要介绍了指针式仪表识别读数 Python(已开源数据集)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


一、前言

第一个版本的指针式仪表识别读数程序写得有点乱,有空重新整理下代码,写成了类MeterDetection进行封装。
原始指针仪表识别地址
基于深度学习方法的指针识别
程序地址:指针式仪表读数源码github
数据集为coco.zip,在github中
记得点个star

二、使用方法


1.安装相关的库

pip install -r requirments.txt

numpy==1.19.5
opencv_python==4.5.5.64

2.运行

python main.py

<main.py>

from MeterClass import *
if __name__ =="__main__":  

    #多张图片,修改输入文件夹

    # imglist=glob.glob('input/*.jpg')  
    # for imgpath in  imglist: 
    #     A=MeterDetection(imgpath)
    #     A.Readvalue()
    #一张图片
    imgpath='images/1.jpg'
    A=MeterDetection(imgpath) 	#创建类对象
    readValue=A.Readvalue()		#调用类方法

三、方法说明

MeterDetection类说明

<MeterClass.py>

类参数

定义了类中的相关参数

class MeterDetection:
    def __init__(self,path):
        self.imageName=path.split('/')[-1].split('.')[0]
        self.outputPath=os.getcwd()+'/outputs/'
        self.image=cv2.imread(path)
        self.circleimg=None
        self.panMask=None           #霍夫圆检测切割的表盘图片
        self.poniterMask =None      #指针图片
        self.numLineMask=None       #刻度线图片
        self.centerPoint=None       #中心点[x,y]
        self.farPoint=None          #指针端点[x,y]
        self.zeroPoint=None         #起始点[x,y]
        self.r=None                 #半径
        self.divisionValue=100/360  #分度值
        self.makeFiledir()
        self.markZeroPoint()

主函数

调用类中其他的方法进行仪表读数

 def Readvalue(self):
        try:
            self.ImgCutCircle()
            self.ContoursFilter()
            self.FitNumLine()
            self.getIntersectionPoints()
            self.FitPointerLine()
            v1=[self.zeroPoint[0]-self.centerPoint[0],self.centerPoint[1]-self.zeroPoint[1]]
            v2=[self.farPoint[0]-self.centerPoint[0],self.centerPoint[1]-self.farPoint[1]]
            theta=Functions.GetClockAngle(v1,v2)
            readValue=self.divisionValue*theta
            print(theta,readValue)
            return readValue
        except Exception as e:# 写一个except
            print("程序错误:",e)

self.ImgCutCircle() 截取表盘区域,滤除背景

    def ImgCutCircle(self):
        #截取表盘区域,滤除背景
        img=self.image
        dst = cv2.pyrMeanShiftFiltering(img, 10, 100)
        cimage = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)
        circles = cv2.HoughCircles(cimage, cv2.HOUGH_GRADIENT, 1, 80, param1=100, param2=20, minRadius=80, maxRadius=0)
        circles = np.uint16(np.around(circles))  # 把类型换成整数
        r_1 = circles[0, 0, 2]
        c_x = circles[0, 0, 0]
        c_y = circles[0, 0, 1]
        circle = np.ones(img.shape, dtype="uint8")
        circle = circle * 255
        cv2.circle(circle, (c_x, c_y), int(r_1), 0, -1)
        bitwiseOr = cv2.bitwise_or(img, circle)
        cv2.imwrite(self.outputPath+self.imageName + '_1_imgCutCircle.jpg' , bitwiseOr)
        self.cirleData = [r_1, c_x, c_y]
        self.panMask=bitwiseOr
       
        return bitwiseOr

指针式仪表识别读数 Python(已开源数据集)

self.ContoursFilter() 对轮廓进行筛选

    def ContoursFilter(self):
        #对轮廓进行筛选
        """
        :funtion : 提取刻度线,指针
        :param a: 高斯滤波 GaussianBlur,自适应二值化adaptiveThreshold,闭运算
        :param b: 轮廓寻找 findContours,
        :return:lineSet,new_needleset
        """
        r_1, c_x, c_y = self.cirleData

        img = self.image.copy()
        # cv2.circle(img, (c_x, c_y), 20, (23, 28, 28), -1)
        img = cv2.GaussianBlur(img, (3, 3), 0)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        binary = cv2.adaptiveThreshold(~gray, 255,
                                    cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -10)
        # cv2.circle(binary, (c_x, c_y), int(r_1*0.5), (0, 0, 0),5)
        # 闭运算
        # kernel = np.ones((3, 3), np.uint8)
        #膨胀
        # dilation = cv2.dilate(binary, kernel, iterations=1)
        # kernel2 = np.ones((3, 3), np.uint8)
        #腐蚀
        # erosion = cv2.erode(dilation, kernel2, iterations=1)
        
        #轮廓查找,根据版本不同,返回参数不同
        if cv2.__version__ >'4.0.0':
            contours, hier = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
        else:
            aa,contours, hier = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
        cntset = []  # 刻度线轮廓集合
        cntareas = []  # 刻度线面积集合

        needlecnt = []  # 指针轮廓集合
        needleareas = []  # 指针面积集合
        radiusLength = [r_1 * 0.6, r_1 * 1] # 半径范围

      
        # cv2.drawContours(img, contours, -1, (255, 90, 60), 2)
        # cv2.imwrite(self.outputPath+self.imageName + '_2_----numLineMask.jpg' , img)
        localtion = []
        for cnt in contours:
            rect = cv2.minAreaRect(cnt)
            # print(rect)
            #(中心点坐标,(宽度,高度),旋转的角度)=   = rect
            a, (w, h), c = rect  
            w = int(w)
            h = int(h)
            ''' 满足条件:“长宽比例”,“面积”'''
            if h == 0 or w == 0:
                pass
            else:
                dis = Functions.Disttances((c_x, c_y), a)
                # if (radiusLength[0] < dis and radiusLength[1] > dis):
                if (radiusLength[0] < dis and radiusLength[1] > dis):
                    #矩形筛选
                    if h / w > 4 or w / h > 4:
                        localtion.append(dis)
                        cntset.append(cnt)
                        cntareas.append(w * h)
                else:
                    if w > r_1 / 2 or h > r_1 / 2:
                        needlecnt.append(cnt)
                        needleareas.append(w * h)
        cntareas = np.array(cntareas)
        areasMean = Functions.couputeMean(cntareas)  # 中位数,上限区
        new_cntset = []
        # 面积
        for i, cnt in enumerate(cntset):
            if (cntareas[i] <= areasMean * 1.5 and cntareas[i] >= areasMean * 0.8):
                new_cntset.append(cnt)

        self.r = np.mean(localtion)
        mask = np.zeros(img.shape[0:2], np.uint8)
        self.poniterMask = cv2.drawContours(mask, needlecnt, -1, (255, 255, 255), -1)  # 生成掩膜
        mask = np.zeros(img.shape[0:2], np.uint8)
        self.numLineMask = cv2.drawContours(mask, new_cntset, -1, (255, 255, 255), -1)  # 生成掩膜

        cv2.imwrite(self.outputPath+self.imageName + '_2_numLineMask.jpg' , self.numLineMask)
        cv2.imwrite(self.outputPath+self.imageName + '_3_poniterMask.jpg' , self.poniterMask)
        # for cnt in needlecnt:
        #     cv2.fillConvexPoly(mask,cnt , 255)
        self.new_cntset=new_cntset
        
        return new_cntset

指针式仪表识别读数 Python(已开源数据集)指针式仪表识别读数 Python(已开源数据集)

self.FitNumLine()轮廓拟合直线

    def FitNumLine(self):
        """ 轮廓拟合直线"""
        lineSet = []  # 拟合线集合
        img=self.image.copy()
        for cnt in self.new_cntset:
            rect = cv2.minAreaRect(cnt)
            # 获取矩形四个顶点,浮点型
            box = cv2.boxPoints(rect)
            box = np.int0(box)
            cv2.polylines(img, [box], True, (0, 255, 0), 1)  # pic
            output = cv2.fitLine(cnt, 2, 0, 0.001, 0.001)
            k = output[1] / output[0]
            k = round(k[0], 2)
            b = output[3] - k * output[2]
            b = round(b[0], 2)
            x1 = 1
            x2 = img.shape[0]
            y1 = int(k * x1 + b)
            y2 = int(k * x2 + b)
            # cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 1)
            #lineSet:刻度线拟合直线数组,k斜率 b
            lineSet.append([k, b])  # 求中心点的点集[k,b]
        cv2.imwrite(self.outputPath+self.imageName + '_4_fitNumLine.jpg' , img)
        self.lineSet=lineSet
        return lineSet

指针式仪表识别读数 Python(已开源数据集)

self.getIntersectionPoints()获取刻度线交点

    def getIntersectionPoints(self):
        #获取刻度线交点
        img = self.image
        lineSet=self.lineSet
        w, h, c = img.shape
        point_list = []
        xlist=[]
        ylist=[]
        if len(lineSet) > 2:
            # print(len(lineSet))
            np.random.shuffle(lineSet)
            lkb = int(len(lineSet) / 2)
            kb1 = lineSet[0:lkb]
            kb2 = lineSet[lkb:(2 * lkb)]
            # print('len', len(kb1), len(kb2))
            kb1sample = random.sample(kb1, int(len(kb1) / 2))
            kb2sample = random.sample(kb2, int(len(kb2) / 2))
        else:
            kb1sample = lineSet[0]
            kb2sample = lineSet[1]
        for i, wx in enumerate(kb1sample):
            # for wy in kb2:
            for wy in kb2sample:
                k1, b1 = wx
                k2, b2 = wy
                # print('kkkbbbb',k1[0],b1[0],k2[0],b2[0])
                # k1-->[123]
                try:
                    if (b2 - b1) == 0:
                        b2 = b2 - 0.1
                    if (k1 - k2) == 0:
                        k1 = k1 - 0.1
                    x = (b2 - b1) / (k1 - k2)
                    y = k1 * x + b1
                    x = int(round(x))
                    y = int(round(y))
                except:
                    x = (b2 - b1 - 0.01) / (k1 - k2 + 0.01)
                    y = k1 * x + b1
                    x = int(round(x))
                    y = int(round(y))
                # x,y=solve_point(k1, b1, k2, b2)
                if x < 0 or y < 0 or x > w or y > h:
                    break
                # point_list.append([x, y])
                xlist.append(x)
                ylist.append(y)
                # cv2.circle(img, (x, y), 2, (122, 22, 0), 2)
        # print('point_list',point_list)
        cx=int(np.mean(xlist))
        cy=int(np.mean(ylist))
        self.centerPoint=[cx,cy]
        cv2.circle(img, (cx, cy), 2, (0, 0, 255), 2)
        cv2.imwrite(self.outputPath+self.imageName + '_5_IntersectionPoints.jpg' , img)
        return img

指针式仪表识别读数 Python(已开源数据集)

self.FitPointerLine()拟合指针直线段

    def FitPointerLine(self):
        #拟合指针直线段
        img =self.poniterMask
        orgin_img=self.image.copy()
        # kernel = np.ones((3, 3), np.uint8)
        # mask = cv2.dilate(img, kernel, iterations=1)
        # img = cv2.erode(mask, kernel, iterations=1)
        lines = cv2.HoughLinesP(img, 1, np.pi / 180, 100, minLineLength=int(self.r / 2), maxLineGap=2)
        # nmask = np.zeros(img.shape, np.uint8)
        # lines = mential.findline(self=0, cp=[x, y], lines=lines)
        # print('lens', len(lines))
        dmax=0
        pointerLine=[]
        #最长的线段为指针
        for line in lines:
            x1, y1, x2, y2 = line[0]
            d1=Functions.Disttances((x1, y1),(x2, y2))
            if(d1>dmax):
                dmax=d1
                pointerLine=line[0]      
        x1, y1, x2, y2 = pointerLine
        d1=Functions.Disttances((x1, y1),(self.centerPoint[0],self.centerPoint[1]))
        d2=Functions.Disttances((x2, y2),(self.centerPoint[0],self.centerPoint[1]))
        if d1 > d2:
            self.farPoint = [x1, y1]
        else:
            self.farPoint = [x2, y2]

        cv2.line(orgin_img, (x1, y1), (x2, y2), 20, 1, cv2.LINE_AA)
        cv2.circle(orgin_img,(self.farPoint[0],self.farPoint[1]), 2, (0, 0, 255),2)
        cv2.imwrite(self.outputPath+self.imageName + '_6_PointerLine.jpg' , img)
        cv2.imwrite(self.outputPath+self.imageName + '_7_PointerPoint.jpg' , orgin_img)

指针式仪表识别读数 Python(已开源数据集)
指针式仪表识别读数 Python(已开源数据集)

读数

计算夹角

            v1=[self.zeroPoint[0]-self.centerPoint[0],self.centerPoint[1]-self.zeroPoint[1]]
            v2=[self.farPoint[0]-self.centerPoint[0],self.centerPoint[1]-self.farPoint[1]]
            theta=Functions.GetClockAngle(v1,v2)
            readValue=self.divisionValue*theta

总结

对程序重新进行封装,提高了可读性
程序地址:指针式仪表读数源码github
记得点个star
创作不易,有需要开发的可以联系我,在校研究生文章来源地址https://www.toymoban.com/news/detail-417883.html

到了这里,关于指针式仪表识别读数 Python(已开源数据集)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于深度学习的指针式仪表倾斜校正方法——论文解读

    中文论文题目:基于深度学习的指针式仪表倾斜校正方法 英文论文题目:Tilt Correction Method of Pointer Meter Based on Deep Learning 周登科、杨颖、朱杰、王库.基于深度学习的指针式仪表倾斜校正方法[J].计算机辅助设计与图形学学报, 2020, 32(12):9.DOI:10.3724/SP.J.1089.2020.18288.        针对仪

    2024年02月12日
    浏览(44)
  • 一个指针式的时钟,12小时内时针和分针重复多少次,分别是什么时间

    之前看过一个鸡汤,说中国学生和国外学生,老师提出这个问题,仅是问重合多少次。中国学生拿出笔闷头算,国外学生直接拿出表直接调时间………… 但是这个问题如果是重合的具体时间如何用C语言算 结果 重复时间 小时: 1  分钟 5  重复时间 小时: 1  分钟 6  重复时间

    2024年02月10日
    浏览(72)
  • PYTHON+YOLOV5+OPENCV,实现数字仪表自动读数,并将读数结果进行输出显示和保存

    最近完成了一个项目,利用python+yolov5实现数字仪表的自动读数,并将读数结果进行输出和保存,现在完成的7788了,写个文档记录一下, 若需要数据集和源代码可以私信。 最后实现的结果如下: 首先查阅文献和文档,好家伙,不看不知道,做相似项目的很多资料都是硕士研

    2024年02月03日
    浏览(52)
  • 水表表盘读数识别新体验,带你进入华为云ModelArts算法套件的世界

    数字时代,数字化服务已经发展到各行各业,我们的生活中也随处可见。 数字化服务的便捷了我们的衣食住行的方方面面,除了我们日常化的出行、饮食、购物,其实住方面也已有了很深的发展。 水电燃气这三项和我们生活息息相关的能源,也已经基本上数字化、线上化了

    2024年02月21日
    浏览(38)
  • Qt(C++)绘制指针仪表盘显示当前温度

    当前文章要实现的功能: 使用Qt绘制一个仪表盘,用来显示当前的温度,绘制刻度、绘制数字、绘制温度指针。仪表盘全程使用QPainter进行绘制,QPainter是Qt框架中非常重要的一个类,绘制功能的实现离不开它。如果想要使用Qt进行高质量的绘图或UI设计,必须掌握QPainter的使用

    2024年02月07日
    浏览(44)
  • 巡检机器人之仪表识别系统

    作者主页:爱笑的男孩。 博客简介:分享机器学习、深度学习、python相关内容、日常BUG解决方法及WindowsLinux实践小技巧。 如发现文章有误,麻烦请指出,我会及时去纠正。有其他需要可以私信我或者发我邮箱:zhilong666@foxmail.com 目录 一、前言 二、项目介绍 三、项目展示 数字

    2024年02月05日
    浏览(36)
  • Selenium 点击、输入、截图、读数、切换页(Chrome109.0.5414.75;python 3.7.9)

    selenium入门超详细教程——网页自动化操作 入门指南 | Selenium python命令行运行找不到自定义模块 excel:读取账号密码(pandas)、记录读数(openpyxl) word:操作word(pipywin32) 网页操作:seleinium 截图裁剪:PIL 窗口获取:【待完成】 windows 批处理文件bat中当前目录。 BAT脚本中

    2024年03月25日
    浏览(49)
  • 毕设开源 python 机器视觉 车牌识别

    🚩 基于python 机器视觉 的车牌识别系统 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:2分 🧿 选题指导, 项目分享:见文末 车牌识别其实是个经典的机器视觉任务了,通过图像处理技术检测、定位、识别车牌上的字符,实现计算机对车牌

    2024年03月13日
    浏览(52)
  • 几种python入门级OCR开源库中文识别效果对比

    目录   素材图片 pytesseract easyocr PaddleOCR 总结 pytesseract是google做的ocr库,一般用在验证码的识别。实测中文的识别速度最快,但是效果也是最差的。 安装: 下载中文语言包,把语言包放在tessdata目录: chi_sim.traineddata 编码: 结果: 支持CUDA的显示进行运算,因笔者没有此类显

    2024年02月16日
    浏览(48)
  • 基于python-opencv,svm的开源人脸识别项目

      前言       本项目是我自己在学校里完成的一个小项目,本项目为基于python-opencv,svm的人脸识别开源项目,不同于其他的直接从kaggle等获取划分好的数据集,本项目致力于从无到有的完成机器学习的所有步骤,即: 目录 项目展示: 一、数据采集 1.创建爬虫项目 2.修改set

    2024年02月08日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包