百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

一步一步详细讲解:python+opencv的车牌提取大全

nanshan 2024-10-08 05:30 21 浏览 0 评论

1 说明:

=====

1.1 环境:

python3.8,深度操作系统deepin-linux,微软编辑器vscode,opencv版本4.2.0。

1.2 上一篇:

《强!全套完整中文车牌识别,纯python来实现和代码分析》

1.3 本次讲解:超级详细,一步一步,注释分析,小白都会。

1.4 注意:代码为注释讲解版,有点繁琐,但是可读性较高,大神可以封装成函数,去掉注释和窗口显示过程。


2 图片:来自今日头条免费正版图库:

===代码逐步分析===

3 读取图片并显示原始图片:额外知识

=============================

3.1 cv2法:显示是原图,省略。牵涉到知识点是图片的通道的拆分和合并。

import cv2
origin_image = cv2.imread('/home/xgj/Desktop/car911/2.jpeg')
cv2.imshow('image', origin_image)
cv2.waitKey(0)

3.2 matplotlib法:

import cv2
#---第2步:读取待检测原始的图片---
origin_image = cv2.imread('/home/xgj/Desktop/car911/2.jpeg')

#---第3步:显示图片法---
'''
# cv2显示图片法:原图
cv2.imshow('image', origin_image)
cv2.waitKey(0)
'''

'''
# matplotlib法直接显示,不是原图
from matplotlib import pyplot as plt
plt.imshow(origin_image)
plt.show()
'''


# 调整通道的顺序,显示原图
# 分割通道
from matplotlib import pyplot as plt
#说明cv2读取的顺序是bgr
#而matplotlib显示rgb,故显示plt原图法需要转换
b,g,r = cv2.split(origin_image)
# 合并通道
img = cv2.merge([r, g, b])
plt.imshow(img)
plt.show()

3.3 图:


4 提取蓝色车牌:

============

4.1 代码:

#---第1步:导入所需模块---
import cv2
from matplotlib import pyplot as plt

#---第2步:读取待检测原始的图片---
origin_image = cv2.imread('/home/xgj/Desktop/car911/2.jpeg')

# 可注释掉
# 调整通道的顺序
# 分割通道
b,g,r = cv2.split(origin_image)
# 合并通道
img = cv2.merge([r, g, b])
#用matplotlib的plt显示图片
plt.imshow(img)
plt.show()

#---第3步:提取车牌部分图片---
#图像去噪灰度处理
# 3-1:对原始图片origin_image进行高斯模糊
Gausiian_image = cv2.GaussianBlur(origin_image, (3, 3), 0)
#可注释掉
plt.imshow(Gausiian_image)
plt.show()

# 3-2:灰度化处理图像
gray_image = cv2.cvtColor(Gausiian_image, cv2.COLOR_RGB2GRAY)
#可注释掉
plt.imshow(gray_image)
plt.show()

# 3-3:Sobel算子
Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0) # 对x求一阶导,垂直检测
#Sobel_y = cv2.Sobel(gray_image, cv2.CV_16S, 0, 1) # 附注:对y求一阶导,水平检测
absX = cv2.convertScaleAbs(Sobel_x)  # 转回uint8
#定义车牌
imagechepai = absX

# 3-4:图像二值化
ret, image2 = cv2.threshold(imagechepai, 0, 255, cv2.THRESH_OTSU)

# 3-5:闭操作可以将目标区域连成一个整体,便于后续轮廓的提取。
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (17, 5))
image3 = cv2.morphologyEx(image2, cv2.MORPH_CLOSE, kernelX,iterations = 3)
#可注释掉
plt.imshow(image3)
plt.show()

# 3-6:膨胀和腐蚀
#通过膨胀连接相近的图像区域,通过腐蚀去除孤立细小的色块。
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (20, 1))
kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 19))
#膨胀第1次
image4 = cv2.dilate(image3, kernelX)
plt.imshow(image4)
plt.show()
#腐蚀第1次
image5 = cv2.erode(image4, kernelX)
plt.imshow(image5)
plt.show()
#腐蚀第2次
image6 = cv2.erode(image5, kernelY)
plt.imshow(image6)
plt.show()
#膨胀第2次
image7 = cv2.dilate(image6, kernelY)
plt.imshow(image7)
plt.show()

# 3-7:中值滤波:去除图像或者其它信号中的噪声。
image8 = cv2.medianBlur(image7, 15)
plt.imshow(image8)
plt.show()

# 3-8:查找轮廓
contours, hierarchy = cv2.findContours(image8, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 3-9:判断车牌区域:
for item in contours:
    rect = cv2.boundingRect(item)
    x = rect[0]
    y = rect[1]
    weight = rect[2]
    height = rect[3]
    if (weight > (height * 3)) and (weight < (height * 4)):
        image9 = origin_image[y:y + height, x:x + weight]  #侧位车牌和黄色车牌报错
        #提取车牌,生成车牌图片
        cv2.imwrite('/home/xgj/Desktop/car911/chepai1.png', image9)
        cv2.imshow('image', image9)
        cv2.waitKey(0)

4.2 操作和效果图:

4.3 正位绿色车牌:OK,省略。(新能源汽车车牌,正面非侧位OK)

5 bug分析:

============

5.1 图:





6 黄色车牌定位和提取(图:3.jpeg):

=============================

6.1 代码:换一种思维

#---第1步:导入模块--
import cv2
import numpy as np

#---第2步:读取原图---
img = cv2.imread('/home/xgj/Desktop/car911/3.jpeg')
#可注释掉
cv2.imshow("pic1",img) #显示原图
cv2.waitKey(0)

#---第3步:预处理---
# 包括灰度处理,高斯滤波平滑处理,Sobel提取边界,图像二值化
# 3-1:灰度处理
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
cv2.imshow("pic2", gray_img)
cv2.waitKey(0)
# 3-2:高斯滤波平滑处理
GaussianBlur_img = cv2.GaussianBlur(gray_img, (3, 3), 0)
cv2.imshow("pic3", GaussianBlur_img)
cv2.waitKey(0)
# 3-3:Sobel提取边界
Sobel_img = cv2.Sobel(GaussianBlur_img, -1, 1, 0, ksize=3)
cv2.imshow("pic4", Sobel_img)
cv2.waitKey(0)
# 3-4:图像二值化
ret, binary_img = cv2.threshold(Sobel_img, 127, 255, cv2.THRESH_BINARY)

#---第4步:形态学运算---
kernel = np.ones((5, 15), np.uint8)
# 先闭运算将车牌数字部分连接,再开运算将不是块状的或是较小的部分去掉
close_img = cv2.morphologyEx(binary_img, cv2.MORPH_CLOSE, kernel)
open_img = cv2.morphologyEx(close_img, cv2.MORPH_OPEN, kernel)
# 再来一次:修改部分图像得到的轮廓边缘不整齐
kernel2 = np.ones((10, 10), np.uint8)
open_img2 = cv2.morphologyEx(open_img, cv2.MORPH_OPEN, kernel2)
#结构元素可以是矩形/椭圆/十字形,可以用cv2.getStructuringElement()来生成不同形状的结构元素
element = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))  #矩形结构
dilation_img = cv2.dilate(open_img, element, iterations=3)
cv2.imshow("pic4", dilation_img)
cv2.waitKey(0)

#---第5步:获取轮廓---
# 5-1:2个指标,易报错,与opencv版本有关
contours, hierarchy = cv2.findContours(dilation_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 测试边框识别结果,注释掉,否则汽车车牌提取后有绿色轮廓,不好看
#cv2.drawContours(img, contours, -1, (0, 255, 0), 3)
#cv2.imshow("pic5", img)  #绘制轮廓图
#cv2.waitKey(0)

# 5-2:从轮廓中提取坐标
# 将轮廓规整为长方形
rectangles = []
for c in contours:
    x = []
    y = []
    for point in c:
        y.append(point[0][0])
        x.append(point[0][1])
    r = [min(y), min(x), max(y), max(x)]
    rectangles.append(r)
    
# 5-3:用颜色识别出车牌区域
dist_r = []
max_mean = 0
for r in rectangles:
    carmask = img[r[1]:r[3], r[0]:r[2]]  #车牌区域面积大小
    hsv = cv2.cvtColor(carmask, cv2.COLOR_BGR2HSV)
    '''
    #蓝色车牌,可以使用
    low = np.array([100, 60, 60])
    up = np.array([140, 255, 255])
    '''
    #黄色车牌
    low = np.array([15, 55, 55])
    up = np.array([50, 255, 255])
    
    '''
    #绿色车牌:系能源汽车报错,因为车牌底色不是全绿,白色渐变绿色
    low = np.array([50, 50, 50])
    up = np.array([100, 255, 255])
    '''

    result = cv2.inRange(hsv, low, up)
    # 用计算均值的方式找蓝色最多的区块
    mean = cv2.mean(result)
    if mean[0] > max_mean:
        max_mean = mean[0]
        dist_r = r

# 画出识别结果,定位用,截取车牌时就不要了,否则车牌上有绿色框,不好看
#cv2.rectangle(img, (dist_r[0]+3, dist_r[1]), (dist_r[2]-3, dist_r[3]), (0, 255, 0), 2)

#参数格式:cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)
#一般格式
#qichechepai = img[y:y + height, x:x + weight]

qichechepai = img[dist_r[1]:dist_r[3], dist_r[0]+3:dist_r[2]-3]
#提取车牌,生成车牌图片
cv2.imwrite('/home/xgj/Desktop/car911/chepai3.png', qichechepai)
cv2.imshow('qichechepaitiqu', qichechepai)
cv2.waitKey(0)

6.2 操作和效果图:

6.3 新能源汽车车牌就不适合。

7 侧面车牌定位和提取:

=================

7.1 分类器:下载地址

https://github.com/zeusees/HyperLPR/blob/master/model/cascade.xml  #分类器来自别人,感谢

7.2 代码:

#---第1步:导出模块--
import cv2
import numpy as np

#---第2步:定义侦测函数
def detect(image):
    # 调用分类器,提前下载好
    cascade_path = '/home/xgj/Desktop/car911/cascade.xml'
    cascade = cv2.CascadeClassifier(cascade_path)  

    # 修改图片大小
    resize_h = 400
    height = image.shape[0]
    scale = image.shape[1] / float(height)
    image = cv2.resize(image, (int(scale * resize_h), resize_h))
    # 转为灰度图
    image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    #查找车牌
    car_plates = cascade.detectMultiScale(image_gray, 1.1, 2, minSize=(36, 9), maxSize=(36 * 40, 9 * 40))
    # print("检测到车牌数", len(car_plates))
    #判断
    if len(car_plates) > 0:
        for car_plate in car_plates:
            x, y, w, h = car_plate
            #画汽车车牌矩形并截取
            qichechepai = image[y-10: y + h + 10, x-10: x + w + 10] 
            cv2.imshow('plate', qichechepai)  #显示车牌窗口
            cv2.imwrite('/home/xgj/Desktop/car911/ccnew.png', qichechepai) #保存提取汽车车牌
            #画车牌识别定位框
            cv2.rectangle(image, (x - 10, y - 10), (x + w + 10, y + h + 10), (0, 255, 0), 2)
    cv2.imshow("image", image) #显示原图上定位并画出识别框
    
if __name__ == '__main__':
    #导入原图
    image = cv2.imread('/home/xgj/Desktop/1-chepai-dingwei/fenleiqi/cc.jpeg') 
    detect(image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

7.3 操作和效果图:

7.4 侧面新能源汽车车牌,可以搞定,小bug:


===汽车车牌定位和提取大全===

高手可以整合、定义函数、封装

不管了,好东西就应该分享。

相关推荐

实战派 | Java项目中玩转Redis6.0客户端缓存

铺垫首先介绍一下今天要使用到的工具Lettuce,它是一个可伸缩线程安全的redis客户端。多个线程可以共享同一个RedisConnection,利用nio框架Netty来高效地管理多个连接。放眼望向...

轻松掌握redis缓存穿透、击穿、雪崩问题解决方案(20230529版)

1、缓存穿透所谓缓存穿透就是非法传输了一个在数据库中不存在的条件,导致查询redis和数据库中都没有,并且有大量的请求进来,就会导致对数据库产生压力,解决这一问题的方法如下:1、使用空缓存解决对查询到...

Redis与本地缓存联手:多级缓存架构的奥秘

多级缓存(如Redis+本地缓存)是一种在系统架构中广泛应用的提高系统性能和响应速度的技术手段,它综合利用了不同类型缓存的优势,以下为你详细介绍:基本概念本地缓存:指的是在应用程序所在的服务器内...

腾讯云国际站:腾讯云服务器如何配置Redis缓存?

本文由【云老大】TG@yunlaoda360撰写一、安装Redis使用包管理器安装(推荐)在CentOS系统中,可以通过yum包管理器安装Redis:sudoyumupdate-...

Spring Boot3 整合 Redis 实现数据缓存,你做对了吗?

你是否在开发互联网大厂后端项目时,遇到过系统响应速度慢的问题?当高并发请求涌入,数据库压力剧增,响应时间拉长,用户体验直线下降。相信不少后端开发同行都被这个问题困扰过。其实,通过在SpringBo...

【Redis】Redis应用问题-缓存穿透缓存击穿、缓存雪崩及解决方案

在我们使用redis时,也会存在一些问题,导致请求直接打到数据库上,导致数据库挂掉。下面我们来说说这些问题及解决方案。1、缓存穿透1.1场景一个请求进来后,先去redis进行查找,redis存在,则...

Spring boot 整合Redis缓存你了解多少

在前一篇里面讲到了Redis缓存击穿、缓存穿透、缓存雪崩这三者区别,接下来我们讲解Springboot整合Redis中的一些知识点:之前遇到过,有的了四五年,甚至更长时间的后端Java开发,并且...

揭秘!Redis 缓存与数据库一致性问题的终极解决方案

在现代软件开发中,Redis作为一款高性能的缓存数据库,被广泛应用于提升系统的响应速度和吞吐量。然而,缓存与数据库之间的数据一致性问题,一直是开发者们面临的一大挑战。本文将深入探讨Redis缓存...

高并发下Spring Cache缓存穿透?我用Caffeine+Redis破局

一、什么是缓存穿透?缓存穿透是指查询一个根本不存在的数据,导致请求直接穿透缓存层到达数据库,可能压垮数据库的现象。在高并发场景下,这尤其危险。典型场景:恶意攻击:故意查询不存在的ID(如负数或超大数值...

Redis缓存三剑客:穿透、雪崩、击穿—手把手教你解决

缓存穿透菜小弟:我先问问什么是缓存穿透?我听说是缓存查不到,直接去查数据库了。表哥:没错。缓存穿透是指查询一个缓存中不存在且数据库中也不存在的数据,导致每次请求都直接访问数据库的行为。这种行为会让缓存...

Redis中缓存穿透问题与解决方法

缓存穿透问题概述在Redis作为缓存使用时,缓存穿透是常见问题。正常查询流程是先从Redis缓存获取数据,若有则直接使用;若没有则去数据库查询,查到后存入缓存。但当请求的数据在缓存和数据库中都...

Redis客户端缓存的几种实现方式

前言:Redis作为当今最流行的内存数据库和缓存系统,被广泛应用于各类应用场景。然而,即使Redis本身性能卓越,在高并发场景下,应用于Redis服务器之间的网络通信仍可能成为性能瓶颈。所以客户端缓存...

Nginx合集-常用功能指导

1)启动、重启以及停止nginx进入sbin目录之后,输入以下命令#启动nginx./nginx#指定配置文件启动nginx./nginx-c/usr/local/nginx/conf/n...

腾讯云国际站:腾讯云怎么提升服务器速度?

本文由【云老大】TG@yunlaoda360撰写升级服务器规格选择更高性能的CPU、内存和带宽,以提供更好的处理能力和网络性能。优化网络配置调整网络接口卡(NIC)驱动,优化TCP/IP参数...

雷霆一击服务器管理员教程

本文转载莱卡云游戏服务器雷霆一击管理员教程(搜索莱卡云面版可搜到)首先你需要给服务器设置管理员密码,默认是空的管理员密码在启动页面进行设置设置完成后你需要重启服务器才可生效加入游戏后,点击键盘左上角E...

取消回复欢迎 发表评论: