前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >基于OpenCV和Python的车牌提取和字符分割

基于OpenCV和Python的车牌提取和字符分割

作者头像
荣仔_最靓的仔
发布于 2021-02-02 08:44:39
发布于 2021-02-02 08:44:39
5.1K00
代码可运行
举报
运行总次数:0
代码可运行

这是一篇介绍基于 OpenCV 和 Python 实现车牌提取项目思路和源码的文章,本文涉及一些人工智能图像识别技术,具体而言,涉及到关于车牌号码识别的研究(车牌提取和字符分割),网上查找到的方案有 tensorflow 和opencv,opencv 也是比较成熟的方案,先从简单的开始,以下是关于使用opencv实现车牌号码提取的部分。

1 车牌提取

1.1 实现思路

  1. 读取彩色的图片
  2. 转换为灰度图
  3. 高斯模糊
  4. Sobel算子进行边缘检测
  5. 图像二值化
  6. 闭操作(腐蚀和扩张)
  7. 循环找到所有的轮廓
  8. 判断车牌区域

1.2 原图

1.3 代码详解

1.3.1 导入包库

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import cv2 as cv
import matplotlib.pyplot as plt

1.3.2 读取彩色的图片

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cv.imread("E:/car.png")

1.3.3 转换为灰度图

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cv.cvtColor(img, cv.COLOR_BGR2GRAY)

1.3.4 高斯模糊

通过高斯模糊,可以去除部分的干扰,让识别更加准确。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cv.GaussianBlur(img1,(5,5),10)

1.3.5 用Sobel算子进行边缘检测

便于接下来提取轮廓

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cv.Sobel(img2,cv.CV_8U,1,0,ksize=1)
cv.Canny(img3,250,100)

1.3.6 进行二值化处理

将图像上的像素点的灰度值设置为0或255,图像呈现出明显的只有黑和白。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cv.threshold(img4,0,255,cv.THRESH_BINARY)

1.3.7 闭操作

依次进行腐蚀和扩张,这一步操作可以将目标区域连成一个整体,便于后续轮廓的提取。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cv.getStructuringElement(cv.MORPH_RECT,(43,33))
cv.dilate(img5,kernel)

1.3.8 查找轮廓

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
i,j = cv.findContours(img6,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)

1.3.9 判断车牌区域

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
result = None
for i1 in i:
    x,y,w,h = cv.boundingRect(i1)
    if w>2*h:
        print(1)
        plt.imshow(img[y:y+h,x:x+w])
        plt.show()
        result = img[y:y+h,x:x+w]

1.4 总观代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import cv2 as cv
import matplotlib.pyplot as plt

# 读取彩色的图片
img = cv.imread("E:/car.png")
plt.imshow(img)
plt.show()
# 转换为灰度图
img1 = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
plt.imshow(img1)
plt.show()
# 用Sobel进行边缘检测
# # 高斯模糊
img2 = cv.GaussianBlur(img1,(5,5),10)
plt.imshow(img2)
plt.show()
# Laplacian进行边缘检测
img3 = cv.Sobel(img2,cv.CV_8U,1,0,ksize=1)
plt.imshow(img3)
plt.show()
img4 = cv.Canny(img3,250,100)
plt.imshow(img4)
plt.show()
# 进行二值化处理
i,img5 = cv.threshold(img4,0,255,cv.THRESH_BINARY)
plt.imshow(img5)
plt.show()
# 可以侵蚀和扩张
kernel = cv.getStructuringElement(cv.MORPH_RECT,(43,33))
img6 = cv.dilate(img5,kernel)
plt.imshow(img6)
plt.show()
# # 循环找到所有的轮廓
i,j = cv.findContours(img6,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
result = None
for i1 in i:
    x,y,w,h = cv.boundingRect(i1)
    if w>2*h:
        print(1)
        plt.imshow(img[y:y+h,x:x+w])
        plt.show()
        result = img[y:y+h,x:x+w]

1.5 最终实现效果

2 车牌识别之字符分割

前面对这牌提取做个详细描述,与此相类似,车牌的字符分割也是很重要的一部分,字符分割的思想在其他项目中同样有很重要的作用。因此有必要针对字符分割的思路和实现过程做一个记录。

2.1 实现思路

总的来说,是基于像素直方图的字符分割实现的:首先对图片进行二值化处理,统计水平方向和竖直方向上各行各列的黑色像素的个数,根据像素的特点确定分割位置,进而完成字符分割。

2.2 原图

2.3 代码详解

2.3.1 导入包库

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import cv2
from matplotlib import pyplot as plt

2.3.2 读取图像,并把图像转换为灰度图像并显示

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cv2.imread('E:/3.png')  # 读取图片
cv2.cvtColor(img_, cv2.COLOR_BGR2GRAY)  # 转换了灰度化

2.3.3 将灰度图像二值化,设定阈值是100

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY_INV)

2.3.4 分割字符

水平方向:统计每一行黑色像素数量n,并记录。可以根据每一行黑色像素的数目来确定分割的起始和终止;由图可知,当 n减小到一定阈值时,为字符的边缘; 竖直方向:同理,统计每一列的黑色像素数量v,并记录。可以可以根据每一列黑色像素的数目的变化来确定分割的起始和终止。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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)

2.3.5 分割图像

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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_

2.4 总观代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import cv2
from matplotlib import pyplot as plt
## 根据每行和每列的黑色和白色像素数进行图片分割。

# 1、读取图像,并把图像转换为灰度图像并显示
img_ = cv2.imread('E:/3.png')  # 读取图片
img_gray = cv2.cvtColor(img_, cv2.COLOR_BGR2GRAY)  # 转换了灰度化
# cv2.imshow('gray', img_gray)  # 显示图片
# cv2.waitKey(0)

# 2、将灰度图像二值化,设定阈值是100
ret, img_thre = cv2.threshold(img_gray, 100, 255, cv2.THRESH_BINARY_INV)
# cv2.imshow('white_black image', img_thre)  # 显示图片
# cv2.waitKey(0)

# 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
word = []
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 > 5:
            cj = img_[1:height, start:end]
            cj = cv2.resize(cj, (15, 30))
            word.append(cj)

print(len(word))
for i,j in enumerate(word):
    plt.subplot(1,8,i+1)
    plt.imshow(word[i],cmap='gray')
plt.show()

2.5 最终实现效果

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/09/25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
dedecms用keyword标签调用含有某一关键词的文章
  前面我们探讨了调用{dede:likewords}为dedecms添加相关搜索词,如果要调用含有某一关键词的文章可以实现吗?比如ytkah的网站有很多文章中含有“微信”的词,那么想在网站首页、频道页、文章页等页面调用含有“微信”这个词的一些文章,怎么调用呢?其实只要几行代码就够了 {dede:arclist row='5' titlelen='36' orderby='pubdate' keyword='微信,公众号' typeid='栏目id'} <li>[field:textlink/]<br />
ytkah
2018/03/06
3.3K0
sql批量更换dedecms文章来源和作者
前面写了一篇修改dedecms默认文章来源 "未知"改为关键词,那个是修改以后发布的文章“来源”才会变成自己设定的关键词,如果修改之前已经有很多文章了,那些文章“来源”还是显示“未知”,如何批量更换dedecms文章来源和作者呢?可以用以下sql语句来实现:
ytkah
2022/03/14
4K0
dedecms漏洞组合拳拿站(渗透笔记)
之前也写过几篇关于dedecms漏洞复现的文章了,光是复现也没什么意思,于是利用google hacking技巧,找到了一个使用dede的站点,正好用上了之前几篇文章里提到的所有的技术。所以特地写出来,也当做一个总结吧。
tnt阿信
2020/08/05
2.9K0
dedecms漏洞组合拳拿站(渗透笔记)
【DEDE】织梦dedecms如何修改关键词的字数长度限制
DEDE织梦cms常用的参数标签汇总、以及操作过程中的一些bug问题解决方法,dede网站二开,以下龙腾飞网络科技-小吴在建站实操中笔记记录,织梦dede建站教程保存使用非常方便:
攻城狮与产品喵
2025/03/13
2600
【DEDE】织梦dedecms如何修改关键词的字数长度限制
调用{dede:likewords}为dedecms添加相关搜索词
  经常看到一些大型的网站会设置相关搜索,即使访客搜索的内容在本站暂时没有,它们也会展示一些其他搜索关键词,引导用户去点击查看,增加pv,提高用户体验;如果没有这些相关搜索,游客没有找到自己想要的内容就直接跳出页面离开你的网站,造成变相损失。   那么我们如何来添加相关搜索呢?我的网站是用dedecms搭建的,织梦cms怎么插入相关搜索呢?其实织梦文章系统已经有集成相关搜索的标签函数{dede:likewords},只是我们没有调用而已。在这里ytkah就为您详解。   调用dedecms相关搜索代码很简单
ytkah
2018/03/05
3.9K0
调用{dede:likewords}为dedecms添加相关搜索词
三种dedecms调用相关文章的方法
  在文章的末尾或侧边栏添加相关文章可以提高用户的黏度,提高pv,增加se的好印象(哈哈),那么dedecms如何调用相关文章呢?有三种方法可以实现。
ytkah
2022/03/14
6.3K0
DedeCMS织梦设置删除文章同步删除图片和附件策略
我们很多站长是否遇到这样的问题,比如我们开始建站的时候可能会更新不少的文章,也有是通过采集获取的图文。但是后续有可能考虑网站内容的变化调整,有些文章是准备删除不要。于是我们可能单篇、批量删除文章,不过我们把文章是删除,同时文章中有的图片和附件还在我们的图片文件夹中。
老蒋
2021/12/27
2.9K0
dedecms后台批量替换文章中的关键词
DEDECMS怎么样能快捷或者批量修改网站所有文章的超链接和锚文本,超链和所有关键词锚文本的链接需要修改?
ytkah
2022/03/14
3.2K0
dedecms后台批量替换文章中的关键词
DedeCMS采集文章的审核时间同步文章发布时间
不知道你有没有发现,当你采集了很多文章,过几天再来审核的时候,审核的文章发布时间,还是采集导入的时间。其实DedeCMS可以把审核时间同步到文章的发布时间。
用户1191760
2019/02/27
4.6K0
dedecms 怎么实现批量替换
相信对于很多织梦dedecms站长来说,应该经常遇到采集文章或者复制别人文章,需要批量修改文章标题、关键词、正文、作者、来源、日期等等相关信息。因为文章标题或者文章内容变动是常有的事,如果手工改动的话,肯定会让人吐血,那么有什么办法可以批量替换相关内容呢?下面,白起SEO就给大家分享两种方法。
用户1088318
2025/05/21
900
通过DedeCMS学习php代码审计
织梦(DedeCms)也是一个国产内容管理系统,曾经爆出过众多漏洞,甚至还有人开发了dedecms漏洞一键扫描器
FB客服
2021/08/24
22.2K0
DedeCMS任意用户密码重置漏洞
综述 2018年01月09日,Dedecms官方更新了DedeCMS V5.7 SP2正式版,后续在10日有网友爆出其存在任意用户密码重置漏洞。 攻击难度:低。 危害程度:高。 官方修复情况如下:目前暂未发布升级补丁 ---- 什么是DedeCMS 织梦内容管理系统(DeDeCMS) 以简单、实用、开源而闻名,是国内最知名的PHP开源网站管理系统,也是使用用户最多的PHP类CMS系统,在经历多年的发展,目前的版本无论在功能,还是在易用性方面,都有了长足的发展和进步。广泛应用于
xfkxfk
2018/03/29
4.8K0
DedeCMS任意用户密码重置漏洞
【DEDE栏目】dedecms内容模型管理—联动类别的使用、调用及修改方法
DEDE织梦cms常用的参数标签汇总、以及操作过程中的一些bug问题解决方法,dede网站二开,以下龙腾飞网络科技-小吴在建站实操中笔记记录,织梦dede建站教程保存使用非常方便:
攻城狮与产品喵
2025/03/13
5600
【DEDE栏目】dedecms内容模型管理—联动类别的使用、调用及修改方法
dedecms批量修改文章为待审核稿件怎么操作
  dedecms批量修改文章为待审核稿件要怎么操作呢?因为我们有时会出于某些原因要把文章暂时先隐藏掉,dedecms有一个比较好的功能是将文件状态设为未审核前台就可以看不到了,那要怎么批量设置呢?到后台 系统 - SQL命令行工具,输入如下命令,切记操作前一定要先备份数据库 update dede_archives set arcrank=-1; update dede_arctiny set arcrank=-1; update dede_taglist set arcrank=-1; 以上三条执行后文
ytkah
2018/03/06
2K0
搭建dedecms漏洞靶场练习环境
本文将对dedecms(织梦cms)所存在的漏洞进行分析和复现,因为代码审计较弱,代码这一块的分析借鉴了一些大佬们的思想,在这里对大佬们表示衷心的感谢。
HACK学习
2021/06/24
12.5K1
搭建dedecms漏洞靶场练习环境
【DEDE】dedecms网站修改TAG、title、keywords及栏目名称长度限制
DEDE织梦cms常用的参数标签汇总、以及操作过程中的一些bug问题解决方法,dede网站二开,以下龙腾飞网络科技-小吴实操中笔记记录,保存使用非常方便:
攻城狮与产品喵
2025/03/13
8010
【DEDE】dedecms网站修改TAG、title、keywords及栏目名称长度限制
dedecms5.7 sp2前台修改任意用户密码
其实这个漏洞出来有一段时间了,不算是一个影响特别大的漏洞,毕竟dede是一个内容管理系统,用户这一块本来就基本没有用。该漏洞的精髓就是一个弱类型的比较:'0.0'=='0'
tnt阿信
2020/08/05
2.1K0
dedecms5.7 sp2前台修改任意用户密码
织梦DedeCMS文章标题自动增加长尾关键词的方法
本文实例讲述了织梦DedeCMS文章标题自动增加长尾关键词的方法,在织梦DedeCMS后台输入标题发布后生成的网页自动带上长尾标题和长尾词。分享给大家供大家参考。具体实现方法如下:
米米素材网
2022/06/27
2.1K0
解决织梦DEDECMS发布重复标题的文章内容方法
一般我们在选择使用织梦DEDECMS程序的时候,网站的内容文章是比较多的,有的甚至是采集复制过来的。随着文章量的增加,我们也不清楚有些文章是否已经添加进来,很多可能是重复的文章。于是我们是否有一个办法检测这个文章标题是否重复呢?这里老蒋找到一个办法,我们以后有需要可以使用。
老蒋
2021/12/27
4K0
可以搜索到DedeCms后台文章列表文档id吗?或者快速定位id编辑文章
  我们在建站时有的时候发现之前的文章有错误了,要进行修改,但又不知道文章名,只知道大概的文章id,那么可以搜索到DedeCms后台文章列表文档id吗?或者快速定位文章id方便修改?   第一种方法:
ytkah
2018/03/06
1.9K0
推荐阅读
相关推荐
dedecms用keyword标签调用含有某一关键词的文章
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验