0
点赞
收藏
分享

微信扫一扫

OpenCV自学笔记19. 基于SVM和神经网络的车牌识别(三)


基于SVM和神经网络的车牌识别(三)

本系列文章参考自《深入理解OpenCV实用计算机视觉项目解析》仅作学习用途

车牌号提取

本篇用到的原始图像为:

OpenCV自学笔记19. 基于SVM和神经网络的车牌识别(三)_#include

首先,对车牌图像用直方图均衡化处理,相当于提高了图像的对比度。

// 车牌号识别
Mat src = imread("2715DTZ.jpg", 0);
// 直方图均衡化
equalizeHist(src, src);
imshow("【均衡化后的灰度图】", src);

OpenCV自学笔记19. 基于SVM和神经网络的车牌识别(三)_神经网络_02

然后,对图像反转阈值化,把黑色区域变为白色,白色区域变为黑色

// CV_THRESH_BINARY_INV 当前点值大于60时,设置为0,否则设置为255
threshold(src, src, 60, 255, CV_THRESH_BINARY_INV);
imshow("【阈值化后的图像】", src);

OpenCV自学笔记19. 基于SVM和神经网络的车牌识别(三)_神经网络_03

在阈值化后,进行膨胀操作,目的是把数字显示得更加清楚,这一步是书上没有的

//膨胀操作
Mat element = getStructuringElement(0, Size(3, 3));
Mat dst;
dilate(src, dst, element);
imshow("【膨胀后的图像】", dst);

OpenCV自学笔记19. 基于SVM和神经网络的车牌识别(三)_车牌识别_04

下一步进行轮廓检测,对检测到的所有轮廓,通过大小、宽高比等信息,删除那些不正确的轮廓
这一步与​​​OpenCV自学笔记17. 基于SVM和神经网络的车牌识别(一)​​中的验证思想类似

// 为了更好地绘制出轮廓,按照BGR三通道从新读取图片,这样就可以画其他颜色了
Mat copy = imread("2715DTZ.jpg");
vector<vector<Point>> contours;

// CV_RETR_EXTERNAL 只检测外轮廓
// CV_CHAIN_APPROX_NONE 存储所有轮廓点
findContours(dst, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

for (int i = 0; i < contours.size(); i++) {
drawContours(copy, contours, i, Scalar(0, 255, 0), 1); // 绘制轮廓
Rect rect = boundingRect(contours[i]);
rectangle(copy, rect, Scalar(0,0,255), 1);

Mat roi(src, rect);
if (verifyLetter(roi)) {
// 绘制通过验证的矩形
rectangle(copy, rect, Scalar(255, 0, 0), 2);

// 保存图像
imwrite( to_string(i) + ".jpg", roi);
}
}

imshow("【绘制轮廓】", copy);

结果见下图,蓝色的是通过验证的矩形

OpenCV自学笔记19. 基于SVM和神经网络的车牌识别(三)_#include_05

程序运行后,在目录下能看到切割后字母:

OpenCV自学笔记19. 基于SVM和神经网络的车牌识别(三)_#include_06

下面是验证程序,套路都是一样的

/* 验证字母 */
bool verifyLetter(Mat r) {
const float aspect = 45.0f / 77.0f;
float charAspect = (float)r.cols / (float)r.rows;
float error = 0.35;
float minHeight = 15;
float maxHeight = 28;
float minAspect = 0.2;
float maxAspect = aspect + aspect * error;
float area = countNonZero(r);
float bbArea = r.cols * r.rows;
float percPixels = area / bbArea;
return percPixels < 0.8

到此为止,本篇的全部代码如下:

#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <ml.hpp>
#include <string.h>

using namespace std;
using namespace cv;
using namespace ml;

/* 验证字母 */
bool verifyLetter(Mat r) {
const float aspect = 45.0f / 77.0f;
float charAspect = (float)r.cols / (float)r.rows;
float error = 0.35;
float minHeight = 15;
float maxHeight = 28;
float minAspect = 0.2;
float maxAspect = aspect + aspect * error;
float area = countNonZero(r);
float bbArea = r.cols * r.rows;
float percPixels = area / bbArea;
return percPixels < 0.8 &&
charAspect > minAspect &&
charAspect < maxAspect &&
r.rows >= minHeight && r.rows <= maxHeight;
}

int main() {
Mat src = imread("2715DTZ.jpg", 0);
Mat copy = imread("2715DTZ.jpg");

equalizeHist(src, src);
imshow("【均衡化后的灰度图】", src);

threshold(src, src, 60, 255, CV_THRESH_BINARY_INV);
imshow("【阈值化后的图像】", src);

//膨胀操作
Mat element = getStructuringElement(0, Size(3, 3));
Mat dst;
dilate(src, dst, element);
imshow("【膨胀后的图像】", dst);

vector<vector<Point>> contours;
findContours(dst, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

for (int i = 0; i < contours.size(); i++) {
drawContours(copy, contours, i, Scalar(0, 255, 0), 1); // 绘制轮廓

Rect rect = boundingRect(contours[i]);
rect.height += 1;
rect.width += 1;
rectangle(copy, rect, Scalar(0,0,255), 1);

Mat roi(src, rect);
if (verifyLetter(roi)) {
// 绘制通过验证的矩形
rectangle(copy, rect, Scalar(255, 0, 0), 1);

// 图像切割
imwrite( to_string(i) + ".jpg", roi);
}
}
imshow("【绘制轮廓】", copy);

waitKey();
return 0;
}

系列文章

​​OpenCV自学笔记17. 基于SVM和神经网络的车牌识别(一)​​​
​​​OpenCV自学笔记18. 基于SVM和神经网络的车牌识别(二)​​​
​​​OpenCV自学笔记19. 基于SVM和神经网络的车牌识别(三)​​​
​​​OpenCV自学笔记20. 基于SVM和神经网络的车牌识别(四)​​

OpenCV自学笔记19. 基于SVM和神经网络的车牌识别(三)_车牌识别_07


举报

相关推荐

0 条评论