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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010429424/article/details/75366862

基于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;
}

参考:

  1. 直方图均衡化: http://blog.csdn.net/morewindows/article/details/8364690
  2. OpenCV3直方图均衡化:http://blog.csdn.net/qq_23880193/article/details/49187731
  3. 图像阈值化:http://blog.csdn.net/nnsword/article/details/32103381

系列文章

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

这里写图片描述

展开阅读全文

没有更多推荐了,返回首页