IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> Opencv项目实战Vision-Life(3) 车牌识别 -> 正文阅读

[人工智能]Opencv项目实战Vision-Life(3) 车牌识别

前言

今天是Vision-Life项目组的第三个小项目,做的是一个简单的车牌识别。

车牌识别算是一个比较经典的项目了,网上也有很多资料,没什么创意,做的目的呢是因为它恰好涵盖了我之前一段时间所学的知识,权当是对前面知识的总结复习吧🍔🍟🍿

知识体系

架构

rqwerqwer

效果图

对指定图片可以达到检测的目的

gasdgsdag

检测车牌位置

图像预处理

图像预处理包括:降分辨率、灰度、降噪与Canny边缘检测

img = cv2.imread('carcard.jpg')
img = cv2.resize(img,(640,420),interpolation=cv2.INTER_LANCZOS4)
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 双边滤波模糊
gray_img = cv2.bilateralFilter(gray_img,3,45,45)
gray_img = cv2.Canny(gray_img,20,300)

首先我们选一张图片,它初始的时候是这样子的

大小为1080x540,RGB格式

carcard

由于不同图像的分辨率不同,所以我们要统一大小。同时要保证,我们感兴趣的区域(ROI,这里是车牌),必须保留在框架中

img = cv2.resize(img,(640,420),interpolation=cv2.INTER_LANCZOS4)

这里我使用640*420的分辨率,相较之前缩小了一半

resize

因为在处理图像的时候我们不需要关注颜色细节,所以灰度图能减少图像的颜色通道,方便后期处理

gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

gray1

灰度变换之后,由于车的背景(如两座山,围栏)对识别有影响,所以我们应对图片进行滤波,突出主题,为后面的Canny检测作铺垫

gray_img = cv2.bilateralFilter(gray_img,3,45,45)

注意事项

这里为什么用双边滤波呢?我们知道,双边滤波在模糊的同时,还能突出边缘。这大大改善Canny检测的效果

开始的时候我曾用过中值滤波,发现边缘也被模糊了。于是Canny检测后的图像的矩形轮廓有断点,计算机无法找到车牌的位置

fsdfaf

上图是对灰度图模糊的对比,也许你看不出有什么区别

但如果我Canny检测之后呢?

fsdfgsdgf

我们放大车牌部分,发现中值模糊下的断点更多,而双边模糊的断点更少;从而左边的车牌构不成一个完整的轮廓,而右边的可以构成一个完整的轮廓,从而被计算机找到

寻找车牌轮廓

# opencv2返回两个值:contours、hierarchy。opencv3返回三个值:img(图像)、countours(轮廓)、hierarchy(层次结构)
contours = cv2.findContours(gray_img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

# imutils.grab_contours的作用,返回cnts中的countors(轮廓),不区分opencv2或opencv3
contours = imutils.grab_contours(contours)

# 想要过滤掉那些微小琐碎的轮廓,只显示这幅图中面积大的轮廓。代码思路是将findContours查找到的轮廓按照面积排序
contours = sorted(contours,key=cv2.contourArea, reverse = True)[0:10]
screenCnt = None

for c in contours:
    area = cv2.contourArea(c)
    print(area)
    epsilon = 0.02*cv2.arcLength(c,True)

    # approxPolyDP()返回值顶点的坐标
    approx = cv2.approxPolyDP(c,epsilon,True)

    if len(approx) == 4:
      screenCnt = approx
      print(len(screenCnt))
      cv2.drawContours(img, [screenCnt], -1, (0, 0, 255), 1)

      break

  1. cv2.findContours()寻找到轮廓
  2. 由于Opencv2和3函数返回值不同,所以我们imutils.grab_contours()统一返回的数据格式
  3. sorted()将各个轮廓按面积大小由高到低排序,[0:10]是指排到第十名就不排了
  4. 轮询各个轮廓
  5. cv2.approxPolyDP()得到各个轮廓顶点坐标(坐标的个数不限,反正按顺序连接这些顶点能大概绘制出轮廓的样子就行)
  6. 因为车牌是矩形,所以我们车牌轮廓一定有4个顶点(理想状态下…)
  7. cv2.drawContours()绘制车牌区域

经过这一系列操作后,我们的图像将会变成这样

fsdgag

这样,车牌部分就被找出来了😎😎😎

字符分割

蒙版操作

现在我们知道车牌在哪里了,剩下的信息对我们来说几乎没用。因此,我们可以对没用的部分进行遮挡(涂黑)

# 创建蒙版
img_mask = np.zeros(gray_img.shape,np.uint8)

new_img = cv2.drawContours(img_mask,[screenCnt],0,255,-1)
cv2.imshow('new_img',new_img)
# 与操作
img=cv2.bitwise_and(img,img,mask=new_img)

被遮挡的图像如下

dsggfsdga

于是,我们可以根据蒙版的数值(黑=0,白=255),裁剪图像

蒙版图👇👇👇

mask

裁剪操作

(x,y)=np.where(img_mask==255)
topx=np.max(x)
topy=np.max(y)
bottomx=np.min(x)
bottomy=np.min(y)
Cropped = np.zeros(gray_img.shape,np.uint8)
Cropped = cv2.rectangle(Cropped,(topy,topx),(bottomy,bottomx),255,1)
Cropped=img[bottomx:topx,bottomy:topy]
  1. np.where(img_mask==255)找蒙版为白色像素,np.max(y)找返回的y数组里最大的那个值
  2. Cropped = cv2.rectangle(Cropped,(topy,topx),(bottomy,bottomx),255,1)这里要注意坐标格式为==(y,x)==
  3. Cropped=img[bottomx:topx,bottomy:topy]直接操作元组切割图像,注意bottomx:topx,bottomy:topy,topx-bottomx>0

裁剪后的图像如下

Crop

最后放大一下裁剪的图像,方便OCR识别

Cropped = cv2.resize(Cropped,(400,200),interpolation=cv2.INTER_LANCZOS4)

字符识别

OCR(Optical character recognition,光学字符识别)是一种将图像中的手写字或者印刷文本转换为机器编码文本的技术。通过数字方式存储文本数据更容易保存和编辑,可以存储大量数据,比如1G的硬盘可以存储数百万本书。

OCR工具安装

参考链接:Python OCR工具pytesseract详解

这里我装的路径为:pytesseract.pytesseract.tesseract_cmd=r’D:\GoogleOCR\tesseract.exe’

将路径复制到代码上

import cv2
import numpy as np
import imutils
import pytesseract
pytesseract.pytesseract.tesseract_cmd=r'D:\GoogleOCR\tesseract.exe'

数字识别

# 识别字符
text = pytesseract.image_to_string(Cropped,config='--psm 11')
print("Detected license plate number is:",text)
print(text[0:7])

打印一下

Detected license plate number is: CZ20FSE.

成功🤔🤤🤤🤤

再看一次效果

gasdgsdag

结语

代码已经扔进仓库里了,需要的自取:Vision-Life3 车牌检测

接下来如果有时间的话,将会用Opencv4+Unity3D做点好玩的东西,应该会非常有充满想象力🤔🤔🤔

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:32:32  更:2022-03-24 00:37:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/9 1:54:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码