import cv2
import numpy as np
from PIL import Image
from matplotlib import pyplot as plt
def preprocess(gray):
# # 直方图均衡化
#equ = cv2.equalizeHist(gray)
# 高斯平滑
gaussian = cv2.GaussianBlur(gray, (3, 3), 0, 0, cv2.BORDER_DEFAULT)
# 中值滤波
median = cv2.medianBlur(gaussian, 5)
# Sobel算子,X方向求梯度
sobel = cv2.Sobel(median, cv2.CV_8U, 1, 0, ksize=3)
# 二值化
ret, binary = cv2.threshold(sobel, 170, 255, cv2.THRESH_BINARY)
#cv2.imshow("binary",binary)
# 膨胀和腐蚀操作的核函数
element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (8, 6))
# 膨胀2次,让轮廓突出
dilation = cv2.dilate(binary, element2, iterations=2)
# 腐蚀一次,去掉细节
erosion = cv2.erode(dilation, element1, iterations=1)
# 再3次膨胀,让轮廓明显一些
dilation2 = cv2.dilate(erosion, element2, iterations=3)
cv2.imshow('dilation2', dilation2)
cv2.waitKey(0)
return dilation2
def findPlateNumberRegion(img):
region = []
# 查找轮廓
binary,contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 筛选面积小的
for i in range(len(contours)):
cnt = contours[i]
# 计算该轮廓的面积
area = cv2.contourArea(cnt)
# 面积小的都筛选掉
if (area < 2000):
continue
# 轮廓近似,作用很小
epsilon = 0.001 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
# 找到最小的矩形,该矩形可能有方向
rect = cv2.minAreaRect(cnt)
print("rect is: ")
print(rect)
# box是四个点的坐标
box = cv2.boxPoints(rect)
box = np.int0(box)
# 计算高和宽
height = abs(box[0][1] - box[2][1])
width = abs(box[0][0] - box[2][0])
# 车牌正常情况下长高比在2.7-5之间
ratio = float(width) / float(height)
print(ratio)
if (ratio > 5 or ratio < 2):
continue
region.append(box)
return region
def detect(img):
# 转化成灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 形态学变换的预处理
dilation = preprocess(gray)
# 查找车牌区域
region = findPlateNumberRegion(dilation)
# 用绿线画出这些找到的轮廓
for box in region:
cv2.drawContours(img, [box], 0, (0, 255, 0), 2)
ys = [box[0, 1], box[1, 1], box[2, 1], box[3, 1]]
xs = [box[0, 0], box[1, 0], box[2, 0], box[3, 0]]
ys_sorted_index = np.argsort(ys)
xs_sorted_index = np.argsort(xs)
x1 = box[xs_sorted_index[0], 0]
x2 = box[xs_sorted_index[3], 0]
y1 = box[ys_sorted_index[0], 1]
y2 = box[ys_sorted_index[3], 1]
img_org2 = img.copy()
img_plate = img_org2[y1:y2, x1:x2]
cv2.imshow('dingwei', img_plate)
cv2.imwrite('dingwei.jpg', img_plate)
cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.imshow('img', img)
# 带轮廓的图片
cv2.imwrite('contours.png', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
'''在imagePath中放入你要测试的图片'''
imagePath = '1.jpg'
im3 = Image.open(imagePath)
im3.show(imagePath)
img = cv2.imread(imagePath)
detect(img)
#进一步切割
img1 = Image.open("dingwei.jpg")
#车牌大小统一成440*140
new_img = img1.resize((440,140),Image.BILINEAR)
#车牌再次定位截取统一成([30,390],[20,390])
region = new_img.crop((30, 23, 416, 110))
region.save("dingwei1.jpg")
#对车脾进行倾斜矫正
'''imga = cv2.imread("dingwei1.jpg", 0)
imge = cv2.GaussianBlur(imga,(3,3),0)
edges = cv2.Canny(imge, 50, 150, apertureSize = 3)
lines = cv2.HoughLines(edges,1,np.pi/180,118)
for l in lines[0]:
theta = l[1]
jiao = -(1.57079-theta)*180/3.14159
pil_im = Image.open('dingwei1.jpg')
pil_im = pil_im.rotate(jiao)
pil_im.save('300.jpg')'''
im = Image.open('dingwei1.jpg')
im.show('dingwei1.jpg')
#灰度化
im = im.convert('L')
im.save('001.png')
#自己写的二值化
pixload = im.load()
for x in range(im.size[0]):
for y in range(im.size[1]):
if pixload[x,y]<125:
pixload[x,y] = 255
else:
pixload[x,y] = 0
#去掉车牌的上下的圆孔
im.save('003.png')
#im.show('003.png')
pixload2 = im.load()
print(im.size)
for x in range(im.size[1]):
count =0
for y in range(im.size[0]):
if pixload2[y,x]==0:
count=count+1
if count<50:
for y in range(im.size[0]):
pixload2[y, x] =255
im.save('004.png')
#im.show('004.png')
pixload3 = im.load()
#去掉车牌上的圆点
for x in range(im.size[0]):
count =0
for y in range(im.size[1]):
if pixload3[x,y]==0:
count=count+1
if count<0:
for y in range(im.size[1]):
pixload2[x, y] =255
im.save('005.png')
#im.show('005.png')
img = cv2.imread("005.png") # 读取图片
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换了灰度化
cv2.imshow('gray', img_gray) # 显示图片
cv2.waitKey(0)
# 2、将灰度图像二值化,设定阈值是100
img_thre = img_gray
cv2.threshold(img_gray, 140, 255, cv2.THRESH_BINARY_INV, img_thre)
cv2.imshow('threshold', img_thre)
cv2.waitKey(0)
# 3、保存黑白图片
cv2.imwrite('132.png', img_thre)
# 4、分割字符
white = [] # 记录每一列的白色像素总和
black = [] # ..........黑色.......
height = img_thre.shape[0]
width = img_thre.shape[1]
white_max = 0
black_max = 0
# 计算每一列的黑白色像素总和
for i in range(width):
s = 0 # 这一列白色总数
t = 0 # 这一列黑色总数
for j in range(height):
if img_thre[j][i] == 255:
s += 1
if img_thre[j][i] == 0:
t += 1
white_max = max(white_max, s)
black_max = max(black_max, t)
white.append(s)
black.append(t)
#print(s)
#print(t)
arg = False # False表示白底黑字;True表示黑底白字
if black_max > white_max:
arg = True
# 分割图像
def find_end(start_):
end_ = start_+1
for m in range(start_+1, width-1):
if (black[m] if arg else white[m]) > (0.95 * black_max if arg else 0.95 * white_max): # 0.95这个参数请多调整,对应下面的0.05
end_ = m
break
return end_
n = 1
start = 1
end = 2
aaa =15
bb = 0
while n < width-2:
n += 1
if (white[n] if arg else black[n]) > (0.05 * white_max if arg else 0.05 * black_max):
# 上面这些判断用来辨别是白底黑字还是黑底白字
# 0.05这个参数请多调整,对应上面的0.95
start = n
end = find_end(start)
n = end
if end-start > 9:
aaa += 1
bb = bb+1
cj = img_thre[1:height, start:end]
cv2.imwrite(str(aaa)+'.jpg',cj)
# cv2.imshow('caijian', cj)
cv2.waitKey(0)
#显示分割后的图像
aaa = aaa-bb
b = []
for i in range(bb):
aaa += 1
img = cv2.imread(str(aaa)+'.jpg',0)
b.append(img)
for c in range(bb):
print(c)
c += 1
plt.subplot(1,bb,c)
plt.imshow(b[c-1],'gray')
plt.show()
车牌字符分割



车牌字符分割是计算机视觉在智能交通系统中的一个重要应用,它涉及图像处理和模式识别技术,主要用于自动识别车辆的车牌号码。下面将详细讲解这个过程及其关键技术。 车牌字符分割通常包括以下几个步骤: 1. **预处理**:这是图像处理的第一步,用于改善图像质量,以便后续分析。在本代码中,预处理可能包括了中值滤波。中值滤波是一种非线性滤波方法,特别适用于消除椒盐噪声和斑点噪声,保护图像边缘不被模糊。 2. **边缘检测**:边缘检测是识别图像中不同区域边界的过程,有助于定位车牌。常见的边缘检测算法有Canny、Sobel和Prewitt等。在这个案例中,可能是利用这些算法来找出车牌的轮廓。 3. **二值化**:二值化是将图像转化为黑白两色,便于进行后续处理。它通过设定一个阈值,将像素值高于或低于该阈值的像素分别设置为白色(前景)或黑色(背景)。这样可以简化图像,突出重要的特征,如车牌的形状。 4. **车牌定位**:在二值化图像中,可以通过寻找特定形状(如矩形)来定位车牌。可能使用的方法包括模板匹配、霍夫变换或者机器学习模型,如Haar级联分类器,来检测车牌区域。 5. **垂直投影**:这是一种特征提取技术,通过计算图像每一列像素的白像素数量,可以帮助识别车牌的上下边缘,从而校正车牌的倾斜。 6. **倾斜矫正**:基于垂直投影的结果,可以计算出车牌的倾斜角度,然后应用几何变换(如仿射变换)来校正车牌图像,使其水平。 7. **字符分割**:最后一步是将车牌上的每个字符分开,以便单独识别。这通常涉及垂直和水平的连通组件分析,找到每个字符的边界,并将其切割出来。 对于初学者来说,这个代码提供了一个很好的实践平台,能够学习到图像处理的基本流程和关键算法。同时,由于包含了测试图片,可以直观地看到算法的效果,有助于理解和改进代码。 总体而言,车牌字符分割是图像识别领域的一个经典问题,涉及的技能广泛应用于自动驾驶、交通监控和安全系统中。掌握这些技术不仅能够提升对计算机视觉的理解,还能为未来的人工智能项目打下坚实基础。

















- 1

- #完美解决问题
- #运行顺畅
- #内容详尽
- #全网独家
- #注释完整
- _Q君临天下2019-02-18请问这个报错如何解决? binary,contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) ValueError: not enough values to unpack (expected 3, got 2)
- 斑驳的岁月2019-05-25浪费,最好别下

- 粉丝: 7
- 资源: 24
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源
- 高压直流输电模型仿真及控制切换 - 500kv和800kv电压等级的Matlab仿真模型,高压直流输电Matlab仿真模型:500kv和800kv电压等级下的LCC-HVDC控制切换分析,高压直流输电
- 待办事项列表(Todo List)
- 针对永磁同步电机性能优化的模型预测磁链控制(MPFC):消除权重系数,提升动静态性能的算法研究,针对永磁同步电机模型的优化:MPFC预测磁链控制策略与成本函数优化对比研究,永磁同步电机模型预测磁链控制
- PFC5.02D煤层开挖指南:分步操作代码与实践教学PDF文档附赠颗粒流数值模拟技术与应用指南,PFC5.02D煤层开挖代码:分步执行,直接运行的专业级开挖工具,附赠PFC5.0数值模拟技术及应用详解
- 三相PWM整流器的双闭环控制与C语言实现的PI控制及SVPWM模块优化方案,三相PWM整流器的双闭环控制与C语言实现的PI控制及SVPWM模块应用,三相PWM整流器,采用双闭环控制,用C语言实现PI控
- 投影寻踪动态聚类改进算法PPDC的MATLAB代码实现与综合评案例分析,投影寻踪动态聚类改进算法PPDC的MATLAB代码实现与综合评案例分析,投影寻踪动态聚类评价(PPDC)MATLAB代码 PPD
- 软件绿色联盟应用体验标准6.0-UX标准-OpenHarmony版.pdf
- 1_XKMF_20250211141242.xls
- GARCH-Copula-Covar模型代码详解:基于MATLAB的录屏使用教程,GARCH-Copula-COVAR模型代码实践教程:基于MATLAB平台的录屏详解,garch-copula-cov
- 光储风氢燃料电池系统仿真模型,MATLAB Simulink下的风光储电解制氢与PEM燃料电池系统仿真模型研究:风光伏耦合电解槽制氢与PEM燃料发电一体化控制策略探讨附文献参考,MATLAB Simu
- 11代12代CPU安装win10/win11系统找不到硬盘怎么办?
- deepseek最全使用攻略pdf资料×41个PDF详解资料
- Comsol软件在参数化曲面建模中创建复杂裂缝模型:可自定义参数的多相流模拟应用,Comsol参数化曲面驱动的裂缝模型生成方法:自定义形状与尺寸,应用于多相流模拟与煤层气等领域的有效工具,Comsol
- 永磁同步电机仿真技术:深入探讨矢量控制、无差电流预测控制、扩张状态观测器与无模型电流电压预测的综合应用,永磁同步电机仿真研究:矢量控制及预测电流控制方法、扩张状态观测器与无模型电流电压预测技术探讨,永
- 乐高奥迪3D模型 乐高奥迪
- 基于正负序分离控制的离网逆变器三相不平衡阻性负载波形研究,探索正负序分离控制的三相离网逆变器与不平衡阻性负载的波形研究,基于正负序分离控制的三相离网逆变器,带不平衡阻性负载 图片为基于正序控制的和基


