opencv实现车牌识别之车牌号定位_1

简介

  按照在哪里跌倒就在哪里爬起来的精神,本章继续做车牌号的检测识别。所有步骤分为3步完成:车牌号定位,车牌号字符分割、字符识别。
本章为第一部分:车牌号定位。

效果演示

  正式开始讲解之前,先看下车牌号定位出来的效果演示。注:本文所有图片均来源于网络。
                 
  如图所示,定位到车牌号之后,将车牌号用黄色框选起来,同时将该车牌复制为新图片显示出来。

代码及实现原理讲解

图像灰阶/二值化

  首先也是常用的操作,将图像灰阶化,然后从像素值为255一侧开始,以累积像素占总像素5%的的地方作为二值化的阀值,进而获得对应的二值化图像。
对应代码如下:
void pic_gray(Mat& mat1, Mat& mat2){
	IplImage pI = mat1;
	uchar* ptr;
	CvScalar s;

	int width = mat1.rows;
	int height = mat1.cols;

	mat2 = cv::Mat(width, height, CV_8UC1, 1);
	ptr = mat2.ptr(0);
	for(int i = 0; i < width; i++){
		for(int j=0; j<height; j++){
			s = cvGet2D(&pI,i,j);
			int grayScale = (int)(s.val[0]*0.299 + s.val[1]*0.587 + s.val[2]*0.114);
			ptr[i*height+j] = grayScale;
		}
	}
}
int histogram_Calculate(Mat& mat1, int number){
	Mat gray_hist;
	int histSize = 255;
	float range[] = { 0, 255 } ;
	const float* histRange = { range };
	bool uniform = true;
	bool accumulate = false;
	int width, height;
	int i, j;
	uchar* ptr = mat1.ptr(0);
	long int pixel_all = 0, pixel_Calc = 0;

	calcHist(&mat1, 1, 0, Mat(), gray_hist, 1, &histSize, &histRange, uniform, accumulate);

	width = gray_hist.rows;
	height = gray_hist.cols;

	for(i=0; i<=width; i++){
		pixel_all += ptr[i];
	}

	for(i=0; i<=width; i++){
		pixel_Calc += ptr[255 - i];
		if(((pixel_Calc * 100) / pixel_all) > number){
			i = 255 - i;
			break;
		}
	}
	return i;
}

void pic_Thresholding(Mat& mat1, int threshold){
	uchar* ptr = mat1.ptr(0);
	int width = mat1.rows;
	int height = mat1.cols;

	for(int i = 0; i < width; i++){
		for(int j=0;j<height;j++){
			if(ptr[i*height+j] > 125){
				ptr[i*height+j] = 255;
			}else{
				ptr[i*height+j] = 0;
			}
		}
	}
}

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <math.h>
#include <string.h>
#include <opencv/cv.h>
#include <stdio.h>
#include "lib/normal.h"

#define DEBUG

#ifdef DEBUG
#define DE(format, ...) printf(format, ## __VA_ARGS__)
#else
#define DE(format, ...) while(0)
#endif

int main(int argc,char *argv[]){
	int threshold = 0;
	Mat img = cv::imread(argv[1]);
	double x_beta;
	int width = img.rows;
	int height = img.cols;
	int** selection_1, selection_Number_1;
	int** address_1, address_Number_1;
	int i, j, color_num, box_flag;
	Mat img_3, img_4, img_5;
	Mat img_2;
	char str[2];
	Point s1, s2;
	Scalar color = Scalar( 0, 255, 255);

	namedWindow("img");
	imshow("img",img);
	pic_gray(img, img_2);

	threshold = histogram_Calculate(img_2, 5);
	DE("threshold:%d\n",threshold);

	pic_Thresholding(img_2, threshold);

	namedWindow("tmp");
	imshow("tmp", img_2);

	waitKey(0);
	return 0;
}

  首先pic_gray来讲源图像img,转化为灰阶图像img_2;接着用histogram_Calculate函数,以5%的比例算出二值化的阀值threshold,最后用pic_Thresholding,
二值化图像。
  效果演示如下:
                                     

图像分割

  车牌是使用是蓝底白字,而这个二值化图像img_2中,蓝色的背景被去除了,留下了白色的字。而根据车牌的特点,每一行中蓝色和白色的交替应该至少是7次。
转化在这个img_2的二值图像中,则表示在车牌所在的行中,像素值的跳变至少是7次。所以根据这个特性,可以将图像中,可能是车牌号所在位置的图像分割出来。
使用的代买如下:
int** selection_Function_1(Mat& mat1, int* number){
    int **a, i, j, flag, num = 0, enter_flag = 0;
    int width = mat1.rows;
    int height = mat1.cols;
    uchar* ptr = mat1.ptr(0);

    a = (int**)malloc(width * sizeof(int*));

    for(i=0; i<width; i++){
        flag = 0;
        for(j=0; j< height-1; j++){
            if(ptr[i*height + j] != ptr[i*height + j +1]){
                flag += 1;
            }
        }
        if((flag >= 7) && (enter_flag == 0)){
            a[num] = (int* )malloc(2 * sizeof(int));
            a[num][0] = i;
            enter_flag = 1;
        }else if((enter_flag != 0) && (flag < 7)){
            if(i - a[num][0] < 8){
                continue;
            }
            a[num][1] = i - 1;
            num ++;
            enter_flag = 0;
        }
    }
    *number = num;
    return a;
}
void pic_cutting(Mat& mat1, Mat& pic_cutting, int** selection, int number){
    int real_height = mat1.cols;
    IplImage pI_1 = mat1;
    IplImage pI_2;
    IplImage pI_3;
    CvScalar s;

    pic_cutting = cv::Mat(selection[number][1] - selection[number][0], real_height, CV_8UC3, 1);
    pI_2 = pic_cutting;

    for(int i = selection[number][0]; i < selection[number][1]; i++){
        for(int j=0; j<real_height; j++){
            s = cvGet2D(&pI_1, i, j);
            cvSet2D(&pI_2, i-selection[number][0], j, s);
        }
    }
}

int main(int argc,char *argv[]){
    ................
    selection_1 = selection_Function_1(img_2, &selection_Number_1);
    for(i=0; i< selection_Number_1; i++){
        DE("selection_1[%d]:%d, %d\n", i, selection_1[i][0], selection_1[i][1]);
    }

    for(i=0; i<selection_Number_1; i++){
        pic_cutting(img, img_3, selection_1, i);
        sprintf(str, "%d", i);
        namedWindow(str);
        imshow(str, img_3);
    }
    waitKey(0);
    return 0;
}
  首先使用函数selection_Function_1,将二值图像img_2中连续出现了至少七次跳变行的图像行开始位置与结束位置保存到二维数组selection_1,img_2中一共有
多少次出现满足连续出现至少七次跳变行图像的统计保存在selection_Number_1中。
  接着函数pic_cutting用img源图像长度作为新图像长度,用selection_1中保存的行开始,结束位置作为新图像宽度,从源图像中将对应位置的图像复制到img_3
中。显示效果如下:
   
  从显示效果途中,我们看到原图像被分割为了6张图片,车牌在第五张图片中。

图片筛选

  从车牌号特性知道,车牌的背景为蓝色。这里就是检测分割出来的图片中,蓝色占的数量,将不满足要求的图片抛弃掉。
接着将筛选出来的图片,再一次灰阶、二值化。
代码如下:
int choice_Color(Mat& mat1, int color_Start, int color_End){
    int width = mat1.rows;
    int height = mat1.cols;
    uchar* ptr = mat1.ptr(0);
    IplImage pI_1;
    int flag[width];
    int num, i, j, num_width = 0;
    CvScalar s;

    pI_1 = mat1;
    cvCvtColor(&pI_1, &pI_1, CV_BGR2HSV);
    for(i=0; i<width; i++){
        num = 0;
        for(j=0; j<height; j++){
            s = cvGet2D(&pI_1, i, j);
            if((s.val[0] >= color_Start) && (s.val[0] <= color_End)){
                num += 1;
            }
        }
        if(num > 20){
            flag[i] = 1;
            num_width += 1;
        }else{
            flag[i] = 0;
        }
        num = 0;
    }
    return num_width;
}

int main(int ragc, char** argv){
        ..........
       for(i=0; i<selection_Number_1; i++){
        pic_cutting(img, img_3, selection_1, i);
        color_num = choice_Color(img_3, 110, 120);   //蓝色为H:110--120
        DE("color_num:%d\n", color_num);
        if(color_num > 5){
            IplImage pI_1 = img_3;
            cvCvtColor(&pI_1, &pI_1, CV_HSV2BGR);

            pic_gray(img_3, img_3);
            threshold = histogram_Calculate(img_3, 3);
            pic_Thresholding(img_3, threshold);

            sprintf(str, "%d", i);
            namedWindow(str);
            imshow(str, img_3);
        }
    }
    waitKey(0);
    return 0;
}
  使用choice_Color将分割出来的每张图片img_3都依次转化为HSV,然后根据H来检测出图像中蓝色像素超过20的行数,并将该数据返回到color_num中。
接着判断如果color_num 大于了5行就表示该图像不能抛弃。
演示效果如下:
         
  因为该图像中,蓝色干扰背景相当多,所以该步骤,只筛选丢弃了最后一张图片。
时间: 2024-11-04 17:37:19

opencv实现车牌识别之车牌号定位_1的相关文章

opencv实现车牌识别之车牌号定位_2

简介 前一篇讲解到了将用蓝色筛选后的图片,再一次灰阶/二值化.现在从这里继续讲解. 矩形检测 因为车牌是一个矩形.所以接着将又一次二值化之后的图片,进行膨胀,之后在进行矩形检测.框选出可能是车牌号的矩形区域. 代码如下: int** car_License_box(Mat& mat1, Mat& mat2, int* number){ Mat threshold_output; vector<vector<Point> > contours; vector<V

opencv实现车牌识别之字符识别

简介 在前面已经讲了车牌的定位和对车牌字符的分割,这里继续是最后对车牌的识别. 字符识别 主要是用了两张办法,第一个是前面 <opencv实现车牌识别之失败经验> 这一篇中用到过的,opencv自带的getPSNR函数,这里不再对它进行讲解. 另一种方法是将分割出来的字符和模板字符都分割成9宫格形式,对比比较每个块中,像素占的比例来匹配分辨出字符. 具体代码如下: double proCale(Mat& mat1, int width_1, int height_1, int widt

opencv实现车牌识别之字符分割

简介 在前一篇中,我们已经定位出来了在图片中车牌号的位置,并且将车牌号图片复制成了新图片,并显示出来,本章在这些被截取出来的图片上继续处理. 截取出来的新图片如下: 图像灰阶/二值化 首先也是选择将图像进行灰阶,然后采用以255一遍开始,取占了总pixel为5%的地方作为阀值,进行二值化. 代码如下: #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <math.h

基于opencv的车牌识别系统

前言 学习了很长一段时间了,需要沉淀下,而最好的办法就是做一个东西来应用学习的东西,同时也是一个学习的过程. 概述     OpenCV的全称是:Open Source Computer Vision Library.OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows和Mac OS操作系统上.它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python.Ruby.MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算

毕业设计 python opencv实现车牌识别 界面

主要代码参考https://blog.csdn.net/wzh191920/article/details/79589506 GitHub:https://github.com/yinghualuowu 答辩通过了,补完~ 这里主要是用两种方法进行定位识别 # -*- coding: utf-8 -*- __author__ = '樱花落舞' import tkinter as tk from tkinter.filedialog import * from tkinter import ttk

CNN:人工智能之神经网络算法进阶优化,六种不同优化算法实现手写数字识别逐步提高,应用案例自动驾驶之捕捉并识别周围车牌号—Jason niu

import mnist_loader from network3 import Network from network3 import ConvPoolLayer, FullyConnectedLayer, SoftmaxLayer training_data, validation_data, test_data = mnist_loader.load_data_wrapper() mini_batch_size = 10 #NN算法:sigmoid函数:准确率97% net = Netw

毕业设计 python opencv实现车牌识别 颜色判断

主要代码参考https://blog.csdn.net/wzh191920/article/details/79589506 GitHub:https://github.com/yinghualuowu 答辩通过了,补完~ 该部分代码还包括缩小边界 def img_color(card_imgs): colors = [] for card_index, card_img in enumerate(card_imgs): green = yello = blue = black = white

毕业设计 python opencv实现车牌识别 矩形矫正

主要代码参考https://blog.csdn.net/wzh191920/article/details/79589506 GitHub:https://github.com/yinghualuowu 答辩通过了,补完~ 用的是仿射变换 def img_Transform(car_contours,oldimg,pic_width,pic_hight): car_imgs = [] for car_rect in car_contours: if car_rect[2] > -1 and ca

文通Android平台车牌识别SDK

关键词: Android平台,车牌识别.车牌号识别.汽车牌照识别. 产品描述 文通车牌识别系统是北京文通科技有限公司开发的基于移动平台的车牌识别应用程序,支持Android等多种主流移动操作系统.该产品采用手机.平板电脑摄像头拍摄汽车牌照图像,然后通过OCR软件对车牌颜色.车牌号进行识别. 产品特色 整牌识别率高,尤其汉字识别遥遥领先同类产品: 识别速度快,极致优化的车牌定位和识别算法: 支持牌照全,包括蓝牌.黄牌(双).军牌(双).武警牌(双).警牌.农用车牌.教练车牌.大使馆车牌等各种规格牌