opencv python3 文本区域识别_[图像处理] Python+OpenCV实现车牌区域识别

8c80bb0a7f626bb4cabbe3fd2443bfb4.gif

点击上方蓝色字体,关注我们

15

03535457d9c17337089f647e21361f71.gif本篇文章主要调用OpenCV库(cv2)进行车牌区域识别,具体步骤包括:

1.灰度转换:将彩色图片转换为灰度图像,常见的R=G=B=像素平均值。

2.高斯平滑和中值滤波:去除噪声。

3.Sobel算子:提取图像边缘轮廓,X方向和Y方向平方和开跟。

4.二值化处理:图像转换为黑白两色,通常像素大于127设置为255,小于设置为0。

5.膨胀和细化:放大图像轮廓,转换为一个个区域,这些区域内包含车牌。

6.通过算法选择合适的车牌位置,通常将较小的区域过滤掉或寻找蓝色底的区域。

7.标注车牌位置,如果是花儿、人脸、牛角,可能需要特征提取和训练。

▽▽▽

一、读取图像及灰度转换

#encoding:utf-8

import cv2

import numpy as np

import matplotlib.pyplot as plt

#读取图片

imagePath = '10.jpg'

img = cv2.imread(imagePath)

#opencv默认的imread是以BGR的方式进行存储的

#而matplotlib的imshow默认则是以RGB格式展示

#所以此处我们必须对图片的通道进行转换

lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

#灰度图像处理

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

print(u"读入lenna图的shape为", GrayImage.shape)

#显示图形

titles = ['Source Image','Gray Image']

images = [lenna_img, GrayImage]

for i in xrange(2):

plt.subplot(1,2,i+1),plt.imshow(images[i],'gray')

plt.title(titles[i])

plt.xticks([]),plt.yticks([])

plt.show()

cv2.imshow('Gray.bmp', GrayImage)

cv2.waitKey(0)

输出结果如下图所示:

?url=http%3A%2F%2Fspider.ws.126.net%2Fd4d5dd671103ae69106cf56c4e6487f0.jpeg&thumbnail=650x2147483647&quality=80&type=jpg

二、高斯平滑和中值滤波去噪

这里原理推荐我以前C++图像处理的文章,如下:https://blog.csdn.net/column/details/eastmount-mfc.html

?url=http%3A%2F%2Fspider.ws.126.net%2Fa014ddeafde9d75d67ad4a8ca01d5254.jpeg&thumbnail=650x2147483647&quality=80&type=jpg

?url=http%3A%2F%2Fspider.ws.126.net%2Fbd47059eaf718feda3f89aaa3b9a9d1e.jpeg&thumbnail=650x2147483647&quality=80&type=jpg

完整代码如下所示:

#encoding:utf-8

import cv2

import numpy as np

import matplotlib.pyplot as plt

#读取图片

imagePath = '10.jpg'

img = cv2.imread(imagePath)

#opencv默认的imread是以BGR的方式进行存储的

#而matplotlib的imshow默认则是以RGB格式展示

#所以此处我们必须对图片的通道进行转换

lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

#灰度图像处理

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

print(u"读入lenna图的shape为", GrayImage.shape)

#直方图均衡化

#equ = cv2.equalizeHist(gray)

#高斯平滑

Gaussian = cv2.GaussianBlur(GrayImage, (3, 3), 0, 0, cv2.BORDER_DEFAULT)

#Gaussian = cv2.GaussianBlur(GrayImage, (9, 9),0)

#中值滤波

Median = cv2.medianBlur(Gaussian, 5)

#显示图形

titles = ['Source Image','Gray Image', 'Gaussian Image', 'Median Image']

images = [lenna_img, GrayImage, Gaussian, Median]

for i in xrange(4):

plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')

plt.title(titles[i])

plt.xticks([]),plt.yticks([])

plt.show()

输出结果如下图所示,分别是原图、灰度图像、高斯处理和中值滤波处理。

?url=http%3A%2F%2Fspider.ws.126.net%2Ffcc8d47aea75b91a56a7e86412743896.jpeg&thumbnail=650x2147483647&quality=80&type=jpg

三、Sobel算子提取轮廓和二值化处理

有时还需要加强图像中景物的边缘和轮廓,边缘和轮廓通常位于图像中灰度突出的地方,因而可以直观的想到用灰度的差分对边缘和轮廓进行提取,通常可以通过梯度算子进行提取。图像锐化的目的是提高图像的对比度,从而使图像更清晰,通过提高邻域内像素的灰度差来提高图像的对比度。本文采用Sobel算子提取边缘轮廓。

?url=http%3A%2F%2Fspider.ws.126.net%2F1397dc3d5bab23cdec4f77b88f05fca3.png&thumbnail=650x2147483647&quality=80&type=jpg

阈值又称为临界值,它的目的是确定出一个范围,然后这个范围内的部分使用同一种方法处理,而阈值之外的部分则使用另一种处理方法或保持原样。常用的包括产生二值图:当x=T时y=255(其中T是阈值)。阈值变换在生物学上的应用比较广泛,常用语细胞图像分割等。本文采用二值化处理将大于等于170像素的转换为255,而下于的转换为0,使得图像更加清晰。

完整代码如下所示:

#encoding:utf-8

import cv2

import numpy as np

import matplotlib.pyplot as plt

#读取图片

imagePath = '10.jpg'

img = cv2.imread(imagePath)

#opencv默认的imread是以BGR的方式进行存储的

lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

#灰度图像处理

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

print(u"读入lenna图的shape为", GrayImage.shape)

#直方图均衡化

#equ = cv2.equalizeHist(gray)

# 高斯平滑

Gaussian = cv2.GaussianBlur(GrayImage, (3, 3), 0, 0, cv2.BORDER_DEFAULT)

# 中值滤波

Median = cv2.medianBlur(Gaussian, 5)

# Sobel算子 XY方向求梯度

x = cv2.Sobel(Median, cv2.CV_8U, 1, 0, ksize = 3) #X方向

y = cv2.Sobel(Median, cv2.CV_8U, 0, 1, ksize = 3) #Y方向

absX = cv2.convertScaleAbs(x) # 转回uint8

absY = cv2.convertScaleAbs(y)

Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5,0)

cv2.imshow('dilation2', Sobel)

cv2.waitKey(0)

# 二值化处理 周围像素影响

ret, Binary = cv2.threshold(Sobel, 170, 255, cv2.THRESH_BINARY)

cv2.imshow('dilation2',Binary)

cv2.waitKey(0)

#显示图形

titles = ['Source Image','Gray Image', 'Gaussian Image', 'Median Image',

'Sobel Image', 'Binary Image']

images = [lenna_img, GrayImage, Gaussian, Median, Sobel, Binary]

for i in xrange(6):

plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')

plt.title(titles[i])

plt.xticks([]),plt.yticks([])

plt.show()

输出结果如下所示:

?url=http%3A%2F%2Fspider.ws.126.net%2Fe44030071729b94321ef870a51e02817.jpeg&thumbnail=650x2147483647&quality=80&type=jpg

四、膨胀和腐蚀处理

接下来进行膨胀和腐蚀处理,其中膨胀让轮廓突出,腐蚀去掉细节。

#encoding:utf-8

import cv2

import numpy as np

import matplotlib.pyplot as plt

#读取图片

imagePath = '10.jpg'

img = cv2.imread(imagePath)

#opencv默认的imread是以BGR的方式进行存储的

lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

#灰度图像处理

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

print(u"读入lenna图的shape为", GrayImage.shape)

#直方图均衡化

#equ = cv2.equalizeHist(gray)

#高斯平滑 去噪

Gaussian = cv2.GaussianBlur(GrayImage, (3, 3), 0, 0, cv2.BORDER_DEFAULT)

#Gaussian = cv2.GaussianBlur(GrayImage, (9, 9),0)

#中值滤波

Median = cv2.medianBlur(Gaussian, 5)

#Sobel算子 XY方向求梯度 cv2.CV_8U

x = cv2.Sobel(Median, cv2.CV_32F, 1, 0, ksize = 3) #X方向

y = cv2.Sobel(Median, cv2.CV_32F, 0, 1, ksize = 3) #Y方向

#absX = cv2.convertScaleAbs(x) # 转回uint8

#absY = cv2.convertScaleAbs(y)

#Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)

gradient = cv2.subtract(x, y)

Sobel = cv2.convertScaleAbs(gradient)

cv2.imshow('dilation2', Sobel)

cv2.waitKey(0)

#二值化处理 周围像素影响

blurred = cv2.GaussianBlur(Sobel, (9, 9),0) #再进行高斯去噪

#注意170可以替换的

ret, Binary = cv2.threshold(blurred , 90, 255, cv2.THRESH_BINARY)

cv2.imshow('dilation2', Binary)

cv2.waitKey(0)

#膨胀和腐蚀操作的核函数

element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))

element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 7))

# 膨胀让轮廓突出

Dilation = cv2.dilate(Binary, element2, iterations = 1)

# 腐蚀去掉细节

Erosion = cv2.erode(Dilation, element1, iterations = 1)

# 再次膨胀

Dilation2 = cv2.dilate(Erosion, element2,iterations = 3)

cv2.imshow('Dilation2 ', Dilation2)

cv2.waitKey(0)

#显示图形

titles = ['Source Image','Gray Image', 'Gaussian Image', 'Median Image',

'Sobel Image', 'Binary Image', 'Dilation Image', 'Erosion Image', 'Dilation2 Image']

images = [lenna_img, GrayImage, Gaussian,

Median, Sobel, Binary,

Dilation, Erosion, Dilation2]

for i in xrange(9):

plt.subplot(3,3,i+1),plt.imshow(images[i],'gray')

plt.title(titles[i])

plt.xticks([]),plt.yticks([])

plt.show()

输出结果如下图所示,可以看到轮廓区域已经被提取出来,接下来开始有选择的进行获取。

?url=http%3A%2F%2Fspider.ws.126.net%2F08992e6bb843c40667d2b5963b7da302.jpeg&thumbnail=650x2147483647&quality=80&type=jpg

五、指定算法选择车牌区域

该部分代码膨胀和腐蚀略有区别,采用closed变量实现。同时获取最理想的区域,完整代码如下所示:

#encoding:utf-8

#BY:Eastmount CSDN 2018-08-06

import cv2

import numpy as np

import matplotlib.pyplot as plt

#读取图片

imagePath = '10.jpg'

img = cv2.imread(imagePath)

#opencv默认的imread是以BGR的方式进行存储的

lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

#灰度图像处理

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

print(u"读入lenna图的shape为", GrayImage.shape)

#直方图均衡化

#equ = cv2.equalizeHist(gray)

#高斯平滑 去噪

Gaussian = cv2.GaussianBlur(GrayImage, (3, 3), 0, 0, cv2.BORDER_DEFAULT)

#Gaussian = cv2.GaussianBlur(GrayImage, (9, 9),0)

#中值滤波

Median = cv2.medianBlur(Gaussian, 5)

#Sobel算子 XY方向求梯度 cv2.CV_8U

x = cv2.Sobel(Median, cv2.CV_32F, 1, 0, ksize = 3) #X方向

y = cv2.Sobel(Median, cv2.CV_32F, 0, 1, ksize = 3) #Y方向

#absX = cv2.convertScaleAbs(x) # 转回uint8

#absY = cv2.convertScaleAbs(y)

#Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)

gradient = cv2.subtract(x, y)

Sobel = cv2.convertScaleAbs(gradient)

cv2.imshow('dilation2', Sobel)

cv2.waitKey(0)

#二值化处理 周围像素影响

blurred = cv2.GaussianBlur(Sobel, (9, 9),0) #再进行一次高斯去噪

#注意170可以替换的

ret, Binary = cv2.threshold(blurred , 170, 255, cv2.THRESH_BINARY)

cv2.imshow('dilation2', Binary)

cv2.waitKey(0)

# 膨胀和腐蚀操作的核函数

element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))

element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 7))

# 膨胀一次,让轮廓突出

Dilation = cv2.dilate(Binary, element2, iterations = 1)

# 腐蚀一次,去掉细节

Erosion = cv2.erode(Dilation, element1, iterations = 1)

# 再次膨胀,让轮廓明显一些

Dilation2 = cv2.dilate(Erosion, element2,iterations = 3)

cv2.imshow('Dilation2 ', Dilation2)

cv2.waitKey(0)

##########################################

#建立一个椭圆核函数

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (25, 25))

#执行图像形态学, 细节直接查文档,很简单

closed = cv2.morphologyEx(Binary, cv2.MORPH_CLOSE, kernel)

closed = cv2.erode(closed, None, iterations=4)

closed = cv2.dilate(closed, None, iterations=4)

cv2.imshow('erode dilate', closed)

cv2.waitKey(0)

##########################################

#显示图形

titles = ['Source Image','Gray Image', 'Gaussian Image', 'Median Image',

'Sobel Image', 'Binary Image', 'Dilation Image', 'Erosion Image', 'Dilation2 Image']

images = [lenna_img, GrayImage, Gaussian,

Median, Sobel, Binary,

Dilation, Erosion, closed]

for i in xrange(9):

plt.subplot(3,3,i+1),plt.imshow(images[i],'gray')

plt.title(titles[i])

plt.xticks([]),plt.yticks([])

plt.show()

cv2.imshow('Gray', GrayImage)

cv2.waitKey(0)

"""

接下来使用Dilation2图片确定车牌的轮廓

这里opencv3返回的是三个参数

参数一:二值化图像

参数二:轮廓类型 检测的轮廓不建立等级关系

参数三:处理近似方法 例如一个矩形轮廓只需4个点来保存轮廓信息

"""

(_, cnts, _) = cv2.findContours(closed.copy(),

cv2.RETR_LIST, #RETR_TREE

cv2.CHAIN_APPROX_SIMPLE)

#画出轮廓

c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]

print c

#compute the rotated bounding box of the largest contour

rect = cv2.minAreaRect(c)

print 'rectt', rect

Box = np.int0(cv2.boxPoints(rect))

print 'Box', Box

#draw a bounding box arounded the detected barcode and display the image

Final_img = cv2.drawContours(img.copy(), [Box], -1, (0, 0, 255), 3)

cv2.imshow('Final_img', Final_img)

cv2.waitKey(0)

输出结果如下图所示,可以看到车牌被选中了。

?url=http%3A%2F%2Fspider.ws.126.net%2Ffa41d60df84c1e132562ebebdfdc5c36.jpeg&thumbnail=650x2147483647&quality=80&type=jpg

?url=http%3A%2F%2Fspider.ws.126.net%2Ff6e92aa93f8abdc93783e847e4d36972.jpeg&thumbnail=650x2147483647&quality=80&type=jpg

END

8be478fb5a4279bcb067639582a8b6a3.gif

原文:

https://blog.csdn.net/Eastmount/article/details/81461679

参考:

https://www.jianshu.com/p/fcfbd3131b84

https://blog.csdn.net/sinat_36458870/article/details/78825571

https://blog.csdn.net/sumkee911/article/details/79435983

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值