Python程序设计实例 | 条形码图片识别

news2024/11/30 10:34:51

 * 本系列推文案例中,建议Python采用3.10及以上版本,NumPy采用1.22.3及以上版本,Matplotlib采用3.5.1及以上版本,Pandas采用1.4.2及以上版本。Python从3.10这个版本开始,标准发行版本中自带的IDLE交互式环境中输入提示符>>>单独放在左侧,不能随输入语句一起复制。为了清晰区分实例在交互环境中的输入和输出,本系列推文在每个输入语句的开头依然保留输入提示符>>>。

01、应用实例背景

有位朋友开了一家淘宝商店,每天都会发出很多快递,并拍照记录,于是就有很多快递单的图片。每晚有个重复性的工作,就是把图片一张张打开,摘录其中条形码的编号,将其保存在Excel中,并把图片的名称改为“条形码编号.jpg”保存,如图1所示。

■ 图1 快递单条形码识别

这位朋友的生意越来越好,所以这个工作量就变得越来越大(每天可能有几百张图片需要识别)。他希望开发一个能自动识别条形码并修改文件名的应用程序。

图片都是jpg格式的,但快递单因为源自不同的快递公司,所以样子千奇百怪。拍照片的人也不同,所以拍出的照片不一定工整。唯一可以确定的是,每张照片都有条形码,且有良好的清晰度。

02、条形码识别程序

该应用的难点在于条形码识别,若从头开发,则工作量太大。我们找到了可以识别条形码和二维码的开源软件zbar(http://zbar.sourceforge.net/,大家当然也可以选择其他软件)。下载、安装后,就可以打开命令行,在软件安装目录的bin下输入zbarimg -h,得到如下结果:

C: work Python barcodes ZBar bin>zbarimg -h
usage: zbarimgoptions] <image >...
scan and decode bar codes from one or more image files
options:
h--help  display this help text
--version  display version information and exit
-q,-- quiet   minimal output,only print decoded symbol data
-V,--verbose   increase debug output level
-- verbose=N    set specific debug output level
-d,-- display  enable display of following images to the screen
-D,--nodisplay disable display of following images (default)
--xml,--nodisplay enable/disable XML output format-- noxm]
-- raw  output decoded symbol data without symbology prefix
--S  < CONFIG>=< VALUE >], 
-set < CONFIG>=< VALUE >],
set  decoder/scanner < CONFIG> to < VALUE> (or 1)

 这就说明安装成功了。用手机拍下一本书的ISBN条形码,如图2所示,保存为isbn.jpg。

■ 图2 ISBN条形码的图片

在操作系统的命令行窗口中运行以下代码,即可成功识别出图2所示的条形码所对应的ISBN编号。

EAN-13:9780521865715
C: work Python barcodes ZBar bin>zbarimg isbn.jpg
scanned 1 barcode symbols from 1 images

识别的关键问题解决了,接着就可以编写GUI界面了,然后通过调用zbar来解决问题。

03、界面设计

前期工作准备完毕后,就是正式的软件设计编码了。构思GUI,有以下要求。

(1) 有一个“打开”按钮,可以选择需要识别的图片;一个导出数据按钮。

(2) 数据展示窗口,可以以表格的形式呈现。

(3) 一个多行文本框,用于输出一些调试数据,如错误反馈、无法识别等信息。

利用wxFormBuilder来设计GUI。在如图3所示的GUI设计界面中,先创建一个Frame窗口。添加一个垂直的BoxSizer,加入一个ToolBar工具条和一个1行2列的GridSizer。在ToolBar工具条中,添加两个Tool按钮,选择合适的图标(source选Load From Art Provider,id选wxART_FILE_OPEN和wxART_FILE_SAVE)。在界面的左下部添加一个DataViewListCtrl用于显示数据,右下部添加一个TextCtrl用于输出调试信息。软件运行结果如图4所示。

 ■ 图3 设计软件界面

 ■ 图4 软件运行结果

04、完整代码

程序保存在barcodes.py文件中,全部代码如下:

#-*- coding:utf-8 -*
import wx
import wx.xrc
import wx.dataview
import os
import csv
from datetime import datetime
class MyFramel (wx.Frame):
definit (self,parent) :
wx.Frame.__init__(self,parent,id= wx.ID_ANY,title= u"条形码识别程序"pos = wx.DefaultPosition,size = wx.Size866,302)style = WX.DEFAULT FRAME STYLEWX.TAB TRAVERSAL)self.SetSizeHints(wx.DefaultSize,wx.DefaultSize)bSizer5 = wx.BoxSizer(wx.VERTICAL)self.m toolBar2 = wx,ToolBar(self,WX.ID ANY,wx,DefaultPosition,wx.DefaultSize,wX.TB HORIZONTAL)self.m_open = self.m toolBar2.AddTool(wx.ID ANY,u"打开”
wx.ArtProvider.GetBitmap(wx.ART FILE OPEN
WX.ART TOOLBAR),wx.NullBitmap,wX.ITEM NORMAL,
wx.EmptyString,wx.EmptyString,None)
self.m_export = self.m toolBar2.AddTool(wx.ID ANY,u"导出”wX.ArtProvider.GetBitmap(wx.ART FILE SAVEWX.ART TOOLBAR),wX.NullBitmap,wX.ITEM NORMALwx.EmptyString,wx.EmptyString,None)self.m toolBar2.Realize()bSizer5.Add(self.m toolBar2,0,WX.EXPAND,5)gSizer1 = wx.GridSizer(1,2,0,0)self.m dvc = wx.dataview.DataViewListCtrl(self,wx.ID ANY
wx.DefaultPosition,wx.DefaultSize,
wx.dataview.DV MULTIPLE wx.dataview.DV ROW LINES)
qSizer1.Add(self.m dvc,0,wx.EXPAND,5)self.m out = wx.TextCtrl(self,wX.ID ANY,wx.EmptyString,
wx.DefaultPosition,wx.DefaultSize,
WX.TE MULTILINE)
0,WX.EXPAND,5)gSizer1.Add(self.m out,bSizer5.Add(gSizer1,1,WX.EXPAND,5)
self.SetSizer(bSizer5)
self.Layout(
self.Centre(wx.BOTH)
# Connect Events
self.Bind(wx.EVT_TOOL,self.openimgs,id = self.m open.GetId())self.Bind(wx.EVT TOOL,self.export2csv,id= self.m export.GetId())#Mycode
self.m dvc.AppendTextColumn(u'日期
self.m dvc.AppendTextColumn(u'条形码',width = 120)self.m_dvc.AppendTextColumn(u'文件地址 width = 400)
del (self):def
pass
#Virtual event handlersdef openimgs(self,event)dlg = wx.FileDialog(
self,message =“Choose some images"
defaultDir = os.getcwd()
defaultFile =n
wildcard=wildcard
style = Wx.FD OPENWX.FD MULTIPLE WX.FD CHANGE DIR
if dlq.ShowModal() == wx.ID OK:
self.m out.WriteText( Recognizing!n')paths = dlg.GetPaths()
for path in paths:
tmp = os.popen%s -- raw %s'%(cmd,path)).readlines()barN
while barNum == and i< len(tmp)barNum = tmp[i].strip()
i +=1
if barNum == .
self.m out.WriteText('% s recognize fails! n'% path)continuenewname ='%sss' (os.path.dirname(path),barNum,os.path.splitext(path)[ -1:][0])
try:
os.rename(path,newname)item = [datetime.now().strftime('%Y-%m-%d'),s” barNum,newname]self.m dvc.AppendItem( item)
csvdata.append( item)
self.m out.WriteText( %s Recognize Done! n'% barNumexcept Exception as e:self.m out.WriteText(  %s rename fails! n' path)self.m out.WriteText(str(e))
dlg.Destroy()
def export2csv(self,event):
dlg = wx.FileDialog(self,message ="Save file as ...",defaultDir = os.getcwd()defaultFile=wildcard = wildcard2,style = wx.FD SAVE
dlg.SetFilterIndex(2)
if dlg.ShowModal() == wX.ID OK:
self.m out.WriteText(Exporting! n')path = dlg.GetPath()
try:with open(path,w',newline =) as csvfile:writer = csv.writer(csvfile,dialect =excel',quoting = csV.OUOTE ALL)for row in csvdata:writer.writerow(row)
self.m out.WriteText( s Export Done! n' path)except Exception as e:
self.m out.WriteText(str(e))
dlg.Destroy()
wildcard = "Pictures ( *.jpg,*.png)*.jpg;*.png All files (*.*)*.*"
wildcard2 ="CSV files (*.csv) *.csv"
cmd = os.path.realpath('Zbar/bin/zbarimq.exe')
csvdata = []
app= wX.App()
win = MyFramel(None)
win.Show()
app.MainLoop()

说明: 由于以上代码中的某些行过长,所以在代码的前端加上了数字表示行号。

注意事项:

(1) zbar软件安装在上述程序的当前目录下,可以通过Zbar\bin\zbarimg.exe运行。

(2) 目录中有中文可能会出错。

(3) 用FileDialog打开文件时会改变当前目录,所以在最初就要保存zbar命令的绝对路径。

(4) 由于条形码有以0开头的数字,用Excel打开时会自动省略,所以在数字前加了一个“'”符号。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/991643.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

腾讯云和阿里云2核2G服务器租用价格表对比

2核2G云服务器可以选择阿里云服务器或腾讯云服务器&#xff0c;腾讯云轻量2核2G3M带宽服务器95元一年&#xff0c;阿里云轻量2核2G3M带宽优惠价108元一年&#xff0c;不只是轻量应用服务器&#xff0c;阿里云还可以选择ECS云服务器u1&#xff0c;腾讯云也可以选择CVM标准型S5云…

JS中 bind()的用法,call(),apply(),bind()异同点及使用,如何手写一个bind()

✨什么是bind() bind()的MDN地址 bind() 方法创建一个新函数&#xff0c;当调用该新函数时&#xff0c;它会调用原始函数并将其 this 关键字设置为给定的值&#xff0c;同时&#xff0c;还可以传入一系列指定的参数&#xff0c;这些参数会插入到调用新函数时传入的参数的前面。…

项目(智慧教室)第五部分,Zigbee采集控制功能实现

一。IAR工程针对Zigbee的修改 补充&#xff1a;硬件配置 &#xff08;1&#xff09;拨码开关拨到公口处&#xff0c;协调器的连接 &#xff08;2&#xff09;协调器的烧写&#xff08;Zigbee协调器也需要烧写&#xff09; &#xff08;4&#xff09;温湿度模块的烧写 1.寻找Z…

工具 | XShell的学习与使用

工具 | XShell的学习与使用 时间&#xff1a;2023年9月8日09:03:29 文章目录 工具 | XShell的学习与使用1.下载2.安装 1.下载 1.官网XSHELL - NetSarang Website 2.免费版下载&#xff1a;家庭/学校免费 - NetSarang Website (xshell.com) 3.https://cdn.netsarang.net/de06d10…

LabVIEW检测润滑油中的水分和铁颗粒

LabVIEW检测润滑油中的水分和铁颗粒 润滑油广泛应用于现代机械设备&#xff0c;由于工作环境日益恶劣&#xff0c;润滑油经常被水分乳化&#xff0c;加速对机械设备的腐蚀。此外&#xff0c;润滑油还受到机械零件摩擦中产生的Fe颗粒的污染&#xff0c;削弱了其机械润滑效果。润…

mobaXterm使用pycharm

首先去pycharm的官网PyCharm: the Python IDE for Professional Developers by JetBrains 下载pycharm&#xff08;选择linux的community版本即可&#xff09; 下载后的压缩包拖拽到mobaXterm如下位置&#xff1a; 进入压缩包所在的文件夹&#xff08;图中这个位置是root目录&…

docker镜像 容器 仓库

docker镜像 Docker 运行容器前需要本地存在对应的镜像&#xff0c;如果本地不存在该镜像&#xff0c;Docker会从镜像仓库下载该镜像。 获取镜像 Docker Hub 上有大量的高质量的镜像可以用&#xff0c;这里我们就说一下怎么获取这些镜像。 从 Docker 镜像仓库获取镜像的命令…

中科驭数KPU FLEXFLOW®-2100R RDMA加速DPU卡正式发布,下一代数据中心互联的“超级高速公路”

2023服贸会期间&#xff0c;中科驭数重磅推出最新自研的高性能网络“利器”——KPU FLEXFLOW-2100R RDMA加速DPU卡。这款产品的发布标志着中科驭数在高性能计算和数据中心领域的不断创新&#xff0c;旨在面向高速网络、高性能存储搭建起算力集群内部通信的"超级高速公路”…

【前端】在Vue页面中引入其它vue页面 数据传输 相互调用方法等

主页面 home 从页面 headView 需求 在 home.vue 中引用 headView.Vue 方案: home.vue 代码: 只需要在home.vue 想要的地方添加 <headView></headView> <script>//聊天页面 import headView /view/headView.vueexport default {components: {headView},…

978. 最长湍流子数组

978. 最长湍流子数组 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff08;一&#xff09;&#xff1a;滑动窗口参考代码&#xff1a; 解题思路&#xff08;二&#xff09;&#xff1a;动态递归参考代码&#xff1a; 针对&#xff08;二&#xff09;进行优化&#x…

组件安全以及漏洞复现

组件安全 1. 概述 A9:2017-使⽤含有已知漏洞的组件 A06:2021-Vulnerable and Outdated Components ​ 组件&#xff08;例如&#xff1a;库、框架和其他软件模块&#xff09;拥有和应用程序相同的权限。如果应用程序中含有已知漏洞的组件被攻击者利用&#xff0c;可能会造成…

【2023年11月第四版教材】第11章《成本管理》(第2部分)

第11章《成本管理》&#xff08;第2部分&#xff09; 4 规划成本管理4.1 成本管理计划★★★ 5 估算成本5.1 估算成本★★★ &#xff08;19上57&#xff09; &#xff08;19下35&#xff09;5.2 数据分析★★★5.4 成本估算★★★ 6 制定预算6.1 成本基准★★★ 7 控制成本7.1…

FOXBORO FBM233 P0926GX电源模块产品特点

FOXBORO FBM233 P0926GX 是一款电源模块&#xff0c;通常用于供电和管理工业自动化和控制系统中的设备和模块。以下是可能与这款电源模块相关的一些产品特点和功能&#xff1a; 电源输出&#xff1a; FBM233 P0926GX 电源模块提供一个或多个电源输出通道&#xff0c;用于为其他…

命悬一线小游戏

欢迎来到程序小院 命悬一线 玩法&#xff1a; 点击鼠标人物摆动跳跃&#xff0c;松开鼠标跳到方格上面&#xff0c;每跳一次都会有对应的分数统计&#xff0c;不要让人物掉下哦^^。开始游戏 html <canvas id"jsGameScreen"></canvas>css .bandiv{floa…

redis八股1

参考Redis连环60问&#xff08;八股文背诵版&#xff09; - 知乎 (zhihu.com) 1.是什么 本质上是一个key-val数据库,把整个数据库加载到内存中操作&#xff0c;定期通过异步操作把数据flush到硬盘持久化。因为纯内存操作&#xff0c;所以性能很出色&#xff0c;每秒可以超过10…

java开发之个人微信的二次开发

简要描述&#xff1a; 修改我在某群的昵称 请求URL&#xff1a; http://域名/updateIInChatRoomNickName 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参…

常见锁策略

一、乐观锁和悲观锁&#xff1a; &#xff08;一&#xff09;乐观锁 和 悲观锁概念 悲观锁&#xff1a;总是假设最坏的情况&#xff0c;认为每次读写数据都会冲突&#xff0c;所以每次在读写数据的时候都会上锁&#xff0c;保证同一时间段只有一个线程在读写数据。 乐观锁&a…

从 算力云 零开始部署ChatGLM2-6B 教程

硬件最低需求&#xff0c;显存13G以上 基本环境&#xff1a; 1.autodl-tmp 目录下 git clone https://github.com/THUDM/ChatGLM2-6B.git然后使用 pip 安装依赖&#xff1a; pip install -r requirements.txtpip 使用pip 阿里的 再执行git clone之前&#xff0c;要先在命令行…

[GKCTF 2021]Crash

目录 恢复符号表&#xff0c;找到main函数 四部分加密 第一部分 第二部分 第三部分 第四段 恢复符号表&#xff0c;找到main函数 观察特征&#xff0c;应该是Go语言&#xff0c;函数没有名字&#xff0c;用脚本恢复符号表&#xff08;脚本自己去找一个&#xff09; 四部…

MySQL - binlog同步过程

文章目录 binlog作用binlog同步过程主从同步架构图&#xff08;异步同步&#xff09; binlog作用 MySQL 的 binlog(二进制日志) 是一种记录数据库所有数据更改操作的日志&#xff0c;可以用于数据库备份、恢复、错误排查、数据同步等操作。binlog 是 MySQL 中的一个重要组件&a…