当前仓库属于暂停状态,部分功能使用受限,详情请查阅 仓库状态说明
1 Star 0 Fork 2

宋Theway/快递标签识别-python
暂停

forked from 小小/快递标签识别-python
暂停
 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
express.py 8.41 KB
一键复制 编辑 原始数据 按行查看 历史
import cv2 as cv
import numpy as np
###进行泛洪填充,去除图片的背景
def ClearBackground(img):
h, w = img.shape[:2]
# 低通滤波,进行降噪
blured = cv.blur(img, (5, 5))
# cv.namedWindow("blured",0)
# cv.imshow("blured",blured)
# 掩码长和宽都比输入图像多两个像素点,满水填充不会超出掩码的非零边缘
mask = np.zeros((h + 2, w + 2), np.uint8)
# 进行泛洪填充,去除图片的背景
cv.floodFill(blured, mask, (w - 1, h - 1), (255, 255, 255), (2, 2, 2), (3, 3, 3), 8)
cv.namedWindow("ClearBack", 0)
cv.imshow("ClearBack", blured)
return blured
###做闭运算,使图形的缝隙连接,形成不同的区域,返回处理后的二值图
def CloseImage(img,w,h):
# 转为灰度图像
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 使用Scharr滤波器操作(指定使用ksize = -1)构造灰度图在水平和竖直方向上的梯度幅值表示
gradX = cv.Sobel(gray, ddepth=cv.CV_32F, dx=1, dy=0, ksize=-1)
gradY = cv.Sobel(gray, ddepth=cv.CV_32F, dx=0, dy=1, ksize=-1)
# Scharr操作之后,从x-gradient中减去y-gradient,通过减法操作,得到高水平梯度和低竖直梯度的图像区域
gradient = cv.subtract(gradX, gradY)
gradient = cv.convertScaleAbs(gradient)
# 梯度图进行平均模糊,有助于平滑梯度表征的图形中的高频噪声
blurred = cv.blur(gradient, (3, 3))
# 图像二值化
(_, thresh) = cv.threshold(blurred, 100, 255, cv.THRESH_BINARY)
# cv2.getStructuringElement构造长方形。宽度大于长度,可以消除条形码中各垂直条之间的缝隙
kernel = cv.getStructuringElement(cv.MORPH_RECT, (w, h))
# 形态学闭运算,消除缝隙
closed = cv.morphologyEx(thresh, cv.MORPH_CLOSE, kernel)
# 腐蚀,膨胀,去除其中的小噪点
closed = cv.erode(closed, None, iterations=4)
closed = cv.dilate(closed, None, iterations=4)
return closed
###得到条形码+收寄信息的区域
# 传入进过了闭运算的二值图
# 返回一个box
def GetRegion(img):
h, w = img.shape[:2]
# 寻找图像的轮廓
cnts = cv.findContours(img, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
cnts = cnts[1]
# 对所有轮廓按面积降序
cc = sorted(cnts, key=cv.contourArea, reverse=True)
###确定二维码区域为哪一个
# 条形码区域为面积最大的
cNum = cc[0]
cConnect = cc[1]
# 得到轮廓的矩阵信息
rect = cv.minAreaRect(cNum)
box = np.int0(cv.boxPoints(rect))
rectC = cv.minAreaRect(cConnect)
boxC = np.int0(cv.boxPoints(rectC))
mi = 99999
ma = -1
for i in range(0, 4):
x1 = int(box[i][0])
if x1 > ma:
ma = x1
if x1 < mi:
mi = x1
# 如果占比大于图片宽度的0.7,则不是条形码区域
# print((ma - mi) / w)
if (ma - mi) / w > 0.7:
if len(cc) > 2:
# 条形码区域为面积第二大的
cNum = cc[1]
cConnect = cc[0]
else:
print("图片处理存在错误!错误地点1:express.GetRegion()")
rect = cv.minAreaRect(cNum)
box = np.int0(cv.boxPoints(rect))
rectC = cv.minAreaRect(cConnect)
boxC = np.int0(cv.boxPoints(rectC))
# print(box)
return box,boxC
###根据已有box裁剪出快递单号的图片
def CutExpressImage(box,img):
# 按最后一列排序
box1 = box[np.lexsort(box.T)]
# 确定数字区域的宽高与起点
roiw = abs(box1[0][0] - box1[1][0])
# 数字区域 取条形码的2/3高度
roih = int(2 * abs(box1[0][1] - box1[2][1]) / 3)
# 选取条形码下方的数字区域
# 确定左上角的点,以及宽高,裁剪
roiPoint = box1[2]
if box[2][0] > box1[3][0]:
roiPoint = box1[3]
# print(roiw, " ", roih, " ", roiPoint)
# 裁剪
diget_img = img[roiPoint[1]:(roiPoint[1] + roih), roiPoint[0]:(roiPoint[0] + roiw)]
# 保存数字区域
cv.imwrite("./img/expressImg.jpg",diget_img)
cv.namedWindow("ImageExpress",0)
cv.imshow("ImageExpress", diget_img)
###根据已有box裁剪出联系人信息的图片
def CutConnectImage(boxC,img):
###确定包含信息的区域
# 按最后一列排序
boxC1 = boxC[np.lexsort(boxC.T)]
# 确定宽高与起点
roiCw = abs(boxC1[0][0] - boxC1[1][0])
# 高度
roiCh = abs(boxC1[0][1] - boxC1[2][1])
# 选取条形码下方的数字区域
# 确定左上角的点,以及宽高,裁剪
roiCPoint = boxC1[0]
if boxC[0][0] > boxC1[1][0]:
roiCPoint = boxC1[1]
# 裁剪信息区域
connect_img = img[roiCPoint[1]:(roiCPoint[1] + roiCh), roiCPoint[0]:(roiCPoint[0] + roiCw)]
cv.imwrite("img/connectImg.jpg", connect_img)
cv.namedWindow("ImageConnect", 0)
cv.imshow("ImageConnect", connect_img)
###展现已经得到的ROI区域
def ShowImageROI(blured,closed,box,boxC):
# 在图片上画出快递单号区域,显示为红色
cv.drawContours(blured, [box], -1, (0, 0, 255), 8)
# 在图片上画出信息区域,显示为绿色
cv.drawContours(blured, [boxC], -1, (0, 255, 0), 8)
cv.namedWindow("ImageROI", 0)
cv.imshow("ImageROI", blured)
cv.namedWindow("ImageClosed", 0)
cv.imshow("ImageClosed", closed)
cv.waitKey(0)
###读入图片,快递识别主程序
def GetImageROI(path):
#读入图像
orginImg = cv.imread(path) #"img/c2.jpg"
###去除背景
blured = ClearBackground(orginImg)
###闭运算,消除同一区域的缝隙
closed = CloseImage(blured,80,3)
###确定条形码+信息的区域
box, boxC = GetRegion(closed)
###将快递单号裁剪并保存
CutExpressImage(box,blured)
###将联系电话信息裁剪并保存
CutConnectImage(boxC,blured)
###为便于观察,显示出ROI区域
ShowImageROI(blured,closed,box,boxC)
if __name__ == '__main__':
# ImageRead("img/c1.jpg")#
# ImageRead("img/c2.jpg")#
# ImageRead("img/c3.jpg")
# ImageRead("img/c4.jpg")
# ImageRead("img/c5.jpg")#
# ImageRead("img/c6.jpg")
# ImageRead("img/z1.jpg")
GetImageROI("img/z2.jpg")
# ImageRead("img/z3.jpg")#
# ImageRead("img/z4.jpg")#
# ImageRead("img/z5.jpg")
# ImageRead("img/z6.jpg")
#得到灰度图
# grayImg = cv.cvtColor(orginImg,cv.COLOR_BGR2GRAY)
###
# #定义结构元素
# kernel = cv.getStructuringElement(cv.MORPH_RECT,(50, 50))
# #开闭运算,先开运算去除背景噪声,再继续闭运算填充目标内的孔洞
# opened = cv.morphologyEx(grayImg, cv.MORPH_OPEN, kernel)
# closed = cv.morphologyEx(opened, cv.MORPH_CLOSE, kernel)
# cv.imshow("closed", closed)
# #求二值图
# ret, binary = cv.threshold(closed,250,255,cv.THRESH_BINARY)
# cv.imshow("binary", binary)
# #找到轮廓
# _,contours, hierarchy = cv.findContours(binary,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
# #绘制轮廓
# cv.drawContours(orginImg,contours,-1,(0,0,255),3)
# #绘制结果
# cv.namedWindow("result",0)
# cv.imshow("result", orginImg)
# #自适应阈值
# binaryImg = cv.adaptiveThreshold(grayImg, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 11, 2)
# cannyImg = cv.Canny(blured, 50, 150)
# # 寻找出所有轮廓集合 http://blog.sina.com.cn/s/blog_662c78590100z0rg.html
# contours = cv.findContours(cannyImg, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# contours = contours[1]
# # 按面积降序
# contours = sorted(contours, key=cv.contourArea, reverse=True)
# 曲线逼近
# 简化边界-方便找出轮廓
# cv.drawContours(orginImg, approx, -1, (0, 0, 255), 30)
# #自适应阈值
# binaryWImg = cv.adaptiveThreshold(binaryImg, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 101, 2)
# #进行均值滤波
# meanImg = cv.blur(binaryWImg, (5, 5))
# #进行固定阈值过滤
# meanImg = cv.threshold(meanImg, 100, 255, cv.THRESH_BINARY)[1]
# #对图片进行腐蚀膨胀3次操作,让选择题突出,便于处理
# meanImg = cv.erode(meanImg, None, iterations=3)
# #进行均值滤波
# meanImg = cv.adaptiveThreshold(meanImg, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 101, 2)
# meanImg = cv.blur(meanImg, (25, 25))
# meanImg = cv.threshold(meanImg, 100, 255, cv.THRESH_BINARY)[1]
# cv.namedWindow("GrayImage",0)
# cv.imshow("GrayImage",cannyImg)
# cv.waitKey(0)
#1.预处理
#2.ROI定位条形码区域
#3.裁剪数字区域
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Python
1
https://gitee.com/eeex-diouf/express_label_identification_python.git
git@gitee.com:eeex-diouf/express_label_identification_python.git
eeex-diouf
express_label_identification_python
快递标签识别-python
master

搜索帮助

23e8dbc6 1850385 7e0993f3 1850385