『工程项目实践』条形码的检测与识别
文章目录
- 前言
- 一、条形码的检测
- 1.1 目标
- 1.2 思路
- 1.3 代码
- 二、条形码的识别
- 2.1 正常角度
- 2.2 180度旋转
- 2.3 45度旋转
前言
在日常生活中,经常会看到条形码的应用,比如超市买东西的生活,图书馆借书的时候。。。
那么这些东西是如何做到准确检测出条形码的位置呢?
这就是今天要介绍的内容了
这篇博文的目标是演示使用计算机视觉和图像处理技术实现条形码的检测。
通过本篇文章的学习,我们能学到的内容包括:
- 图像处理中常用的一些操作流程,包括滤波、阈值化处理、膨胀、腐蚀和轮廓查找等
- 更重要的一点,希望通过这个案例,能够帮助大家建立分析问题和处理问题的思路
需要注意的是,这个算法并不适用于所有的条形码,但是它应该能给你一个基本的直觉,告诉你应该应用什么类型的技术
一、条形码的检测
1.1 目标
找到条形码的位置,而去除掉干扰的因素
1.2 思路
利用条形码的自身特点,一般都是矩形形状,而且条码的条带是黑色的,矩形区域是白色的
1.3 代码
step 1: 得到只剩下高水平梯度和低垂直梯度的图像区域
import numpy as np
import argparse
import imutils
import cv2# 构造参数解析并分析参数
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to the image file")
args = vars(ap.parse_args())image = cv2.imread(args["image"])
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 计算图片 x 和 y 方向的 Scharr 梯度大小
# 使用 Scharr 操作符(这里制定ksize=1)去构造图片在水平和垂直方向上的梯度幅值表示。
ddepth = cv2.cv.CV_32F if imutils.is_cv2() else cv2.CV_32F
gradX = cv2.Sobel(gray, ddepth=ddepth, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, ddepth=ddepth, dx=0, dy=1, ksize=-1)# 用 x 方向的梯度减去 y 方向的梯度 -> 得到只剩下了高水平梯度和低垂直梯度的图像区域。
gradient = cv2.subtract(gradX, gradY)
gradient = cv2.convertScaleAbs(gradient)
cv2.imwrite('./test_img/gradient.jpg', gradient)
step 2: 如何过滤掉图片中的噪声,重点关注条形码区域。
# 对图片进行模糊和阈值化操作
# 使用一个卷积核大小为 9x9 的均值滤波作用于梯度图片。对图片进行这个操作将有助于平滑图片中的高频噪声。
# 然后将模糊化后的图片进行阈值化,
blurred = cv2.blur(gradient, (9, 9))
cv2.imwrite('./test_img/blurred.jpg', blurred)
(_, thresh) = cv2.threshold(blurred, 200, 255, cv2.THRESH_BINARY)
# thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 5, 3)
cv2.imwrite('./test_img/thresh.jpg', thresh)# 进行阈值化操作,更加容易的检测出条形码的“斑点”状区域
# 核的宽度大于高度,因此允许我们缩小条形码垂直条带之间的间隙
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
cv2.imwrite('./test_img/closed.jpg', closed)
step 3: 进行腐蚀与膨胀操作,腐蚀操作将会“腐蚀”掉图片中的白色像素点,因此将会清除这些小的斑点,而膨胀操作将会“扩张”剩余的白色像素,并使白色区域变长。如果在腐蚀过程中去除了小的斑点,则在膨胀的过程中不会再次出现。在一系列的腐蚀和膨胀操作之后,这些小斑点已经被成功的移除了,只剩下条形码的区域。
# 执行一系列的腐蚀和膨胀操作
closed = cv2.erode(closed, None, iterations=2)
closed = cv2.dilate(closed, None, iterations=2)
step 4: 最后寻找一下图片中条形码的区域的轮廓。
# 找到阈值化后图片中的轮廓,然后进行根据区域进行排序,仅保留最大区域
cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]# 计算最大轮廓的旋转边界框
rect = cv2.minAreaRect(c)
box = cv2.cv.BoxPoints(rect) if imutils.is_cv2() else cv2.boxPoints(rect)
box = np.int0(box)# 在检测到的条形码周围绘制边界框并显示图片
cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
cv2.imwrite('./test_img/bar_det.jpg', image)
二、条形码的识别
识别图片中的条码(pyzbar)及条码图片矫正和增强
step 1: 导入所需要的包
import cv2
import pyzbar.pyzbar as pyzbar
import numpy as np
2.1 正常角度
image = cv2.imread("./test_img/test01.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
texts = pyzbar.decode(gray)
tt = ''
for text in texts:tt = text.data.decode("utf-8")
print(tt)
2.2 180度旋转
image = cv2.imread("./test_img/test03.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
texts = pyzbar.decode(gray)
print(texts)
if not texts:print("未识别成功")
else:tt = ''for text in texts:tt = text.data.decode("utf-8")print("识别成功")print(tt)
2.3 45度旋转
def barcode(gray):texts = pyzbar.decode(gray)if not texts:angle = barcode_angle(gray)if angle < -45:angle = -90 - angletexts = bar(gray, angle)if not texts:gray = np.uint8(np.clip((1.1 * gray + 10), 0, 255))angle = barcode_angle(gray)if angle < -45:angle = -90 - angletexts = bar(gray, angle)return textsdef bar(image, angle):gray = imagebar = rotate_bound(gray, 0 - angle)roi = cv2.cvtColor(bar, cv2.COLOR_BGR2RGB)texts = pyzbar.decode(roi)return textsdef barcode_angle(image):gray = imageret, binary = cv2.threshold(gray, 220, 255, cv2.THRESH_BINARY_INV)kernel = np.ones((8, 8), np.uint8)dilation = cv2.dilate(binary, kernel, iterations=1)erosion = cv2.erode(dilation, kernel, iterations=1)erosion = cv2.erode(erosion, kernel, iterations=1)erosion = cv2.erode(erosion, kernel, iterations=1)contours, hierarchy = cv2.findContours(erosion, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)if len(contours) == 0:rect = [0, 0, 0]else:rect = cv2.minAreaRect(contours[0])return rect[2]def rotate_bound(image, angle):(h, w) = image.shape[:2](cX, cY) = (w // 2, h // 2)M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)cos = np.abs(M[0, 0])sin = np.abs(M[0, 1])nW = int((h * sin) + (w * cos))nH = int((h * cos) + (w * sin))M[0, 2] += (nW / 2) - cXM[1, 2] += (nH / 2) - cYreturn cv2.warpAffine(image, M, (nW, nH))image = cv2.imread("./test_img/test03.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
texts = barcode(gray)
print(texts)
if not texts:print("未识别成功")
else:tt = ''for text in texts:tt = text.data.decode("utf-8")print("识别成功")print(tt)
『工程项目实践』条形码的检测与识别相关推荐
- 『工程项目实践』银行卡识别(CTPN+CRNN)
银行卡识别 前言 一.数据预处理 1.1 数据准备 1.2 数据增强 二.训练(CRNN) 三.需要修改的内容 3.1 数据增强 3.2 训练 四.CRNN 结构说明 4.1 CNN 4.2 BiLS ...
- 『工程项目实践』表格识别 — V1.0
文章目录 前言 一.整体识别流程 二.去印章:remove_mark 三.寻找表格区域:get_pt 四.图片分割:TransformTable 五.文本部分检测 六.文本部分识别 七.表格部分的处理 ...
- 【项目实践】中英文文字检测与识别项目(CTPN+CRNN+CTC Loss原理讲解)
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:opencv学堂 OCR--简介 文字识别也是图像领域一 ...
- JavaWeb『Vue.js』快速入门
Vue快速入门 第一节 准备Vue.js环境 1.开发中的最佳实践 2.Vue框架的js文件获取 3.本地创建vue.js文件 4.创建HTML文档并引入vue.js 第二节 Vue.js基本语法:声 ...
- 『实践』VirtualBox 5.1.18+Centos 6.8+hadoop 2.7.3搭建hadoop完全分布式集群及基于HDFS的网盘实现...
『实践』VirtualBox 5.1.18+Centos 6.8+hadoop 2.7.3搭建hadoop完全分布式集群及基于HDFS的网盘实现 1.基本设定和软件版本 主机名 ip 对应角色 mas ...
- 『AD域攻防实践』第二期学习笔记
上一周的直播课中,小伙伴们跟随御守实验室的师傅一起了解了"AD域在攻防对抗场景下的安全现状",课程结束后,我们为大家整理了学习笔记,也将录屏和PPT公布在了公众号和微信群,帮助大家 ...
- 技术人的成长手册|勤思考、反内卷,史海峰关于技术人职业『高可用』的探索与实践...
经历过谷底的低迷,也有过高潮的狂欢.也许史海峰的经历和思考,能够给那些只经历过互联网繁荣.时下正在经受所谓『互联网寒冬』的年轻工程师们一些新的职业感悟. 2022 年虽然还有 3 个月,但这已经注定是 ...
- 『实践』Yalmip获取对偶函数乘子
『实践』Yalmip获取对偶函数乘子 一.sdpsetting设置 Yalmip网站给出的说明 savesolveroutput默认为0,需要设置为1才会保存输出结果. 下面是我模型的约束个数: 二. ...
- 成都链安重磅出品 | 基于VS Code插件的智能合约自动形式化验证工具Beosin—VaaS『离线免费版』...
11月4日,成都链安重磅推出『离线免费版』智能合约自动形式化验证工具Beosin-VaaS,该版本基于流行的开发工具VS Code插件,供广大开发者免费使用.获得方式如下,欢迎体验使用: https: ...
最新文章
- 为什么要学习 Markdown?究竟有什么用?
- 清华大学矣晓沅:“九歌”——基于深度学习的中国古典诗歌自动生成系统
- webpack源码分析之三:loader
- 【IM】关于集成学习Bagging和Boosting的理解
- VS.Net 开发 MSN一样缓慢出来的提示信息的方法
- linux vps 命令,CentOS最常用Linux vps操作命令整理大全
- java main方法背后的故事?(转)
- 二维数组子数组矩形和
- 淘宝店的图片哪里来的
- javascript 创建对象方式
- 一些在PHPStudy部署中出现的问题解决
- 初试SpringStateMachine框架实现状态机
- 【Elasticsearch】高亮查询 highlighting (一)
- Houdini学习笔记
- hdmi接口和计算机连接,hdmi接口,教您hdmi接口怎么连接电视
- dubbo服务出现大量超时问题
- 进入Java世界的第一个程序Hello world
- uniAPP上架iOS商店踩到的坑(记录)
- 用PowerBI进行数据分析的基本流程框架
- H5实现九宫格效果抽奖
热门文章
- 降低复试线二次录取!22年这些学校明确保护一志愿!
- 真正让我们学会建站需要凭借三大因素,当你具备了这三个因素学会建站指日可待
- python wraps函数_python装饰器---@wraps
- hibernate中日期条件查询问题setDate,setTimestamp
- 运维部门工作总结_运维年终工作总结-年终工作总结
- html翻牌动画效果,纯css3实现图片翻牌特效
- CCNA认证试题一(附答案和解析)中文版(一)
- oracle hwm调整语法,oracle 10g 下 HWM 在线调整用 Shrink 是较佳选择
- 从团购网的漏洞看网站安全性问题
- HDU献给杭电五十周年校庆的礼物 (切蛋糕,线段划分区域)