您的位置:首页 > 理论基础 > 计算机网络

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

2017-07-19 15:32 603 查看

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

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

车牌号提取

本篇用到的原始图像为:



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

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




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

// CV_THRESH_BINARY_INV 当前点值大于60时,设置为0,否则设置为255
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);




下一步进行轮廓检测,对检测到的所有轮廓,通过大小、宽高比等信息,删除那些不正确的轮廓

这一步与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);


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



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



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

/* 验证字母 */
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;
}


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

#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;
}


参考:

直方图均衡化: http://blog.csdn.net/morewindows/article/details/8364690

OpenCV3直方图均衡化:http://blog.csdn.net/qq_23880193/article/details/49187731

图像阈值化:http://blog.csdn.net/nnsword/article/details/32103381

系列文章

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

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

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

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: