#include<opencv2\opencv.hpp>

#include<iostream> using namespace cv; using namespace std; int areas;

//该函数用来验证是否是我们想要的区域,车牌定位原理其实就是在图片上寻找矩形,我们可以用长宽比例以及面积来验证是否是我们想要的矩形,宽高比为520/110=4.7272 (车牌的长除以宽),区域面积最小为15个像素,最大为125个像素

bool VerifySize(RotatedRect candidate) {     float error = 0.4; //40%的误差范围

float aspect = 4.7272;//宽高比例

int min = 25 * aspect * 25; //最小像素为15

int max = 125 * aspect * 125;//最大像素为125

float rmin = aspect - aspect*error;//最小误差

float rmax = aspect + aspect*error;//最大误差

int area = candidate.size.height*candidate.size.width;//求面积

float r = (float)candidate.size.width / (float)candidate.size.height;//长宽比

if (r < 1)

r = 1 / r;

if (area<min || area>max || r<rmin || r>rmax)

return false;

else

return true; } int main(int argc, char** argv) {

Mat src;

src = imread("D:\\Car1.jpg");//读取含车牌的图片

if (!src.data)     {

cout << "Could not open Car.jph.." << endl;

return -1;

}

Mat img_gray;

cvtColor(src, img_gray, CV_BGR2GRAY);//灰度转换

Mat img_blur;

blur(img_gray, img_blur, Size(5, 5));//用来降噪

Mat img_sobel;

Sobel(img_gray, img_sobel, CV_8U, 1, 0, 3);//Sobel滤波,对x进行求导,就是强调y方向,对y进行求导,就是强调x方向,在此我们对x求导,查找图片中的竖直边

Mat img_threshold;

threshold(img_sobel, img_threshold, 0, 255, THRESH_BINARY | THRESH_OTSU);

Mat element = getStructuringElement(MORPH_RECT, Size(21, 5));//这个Size很重要!!不同的图片适应不同的Size,待会在下面放图,大家就知道区别了

morphologyEx(img_threshold, img_threshold,MORPH_CLOSE,element);//闭操作,就是先膨胀后腐蚀,目的就是将图片联通起来,取决于element的Size

。     /*接下来就是提取轮廓*/

vector<vector<Point>>contours;

findContours(img_threshold, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

Mat result = Mat::zeros(src.size(), CV_8U);

drawContours(result, contours, -1, Scalar(255));

vector<RotatedRect> rects; //用来存放旋转矩形的容器

//Mat result1 = Mat::zeros(src.size(), CV_8U);

Mat result1;

src.copyTo(result1);

for (size_t i = 0; i < contours.size(); i++)     {

Point2f vertices[4];//用来存放旋转矩形的四个点

RotatedRect mr = minAreaRect(Mat(contours[i]));

//minAreaRect 寻找最小的矩形

if (VerifySize(mr))//筛选是否是我们需要的区域,如果验证成功,就放到rects里,

{

//if (mr.angle > -30) {

mr.points(vertices);

for (size_t j = 0; j < 4; j++)

{

line(result1, vertices[j], vertices[(j + 1) % 4], Scalar(0, 0, 255), 2, 8);

cout << "矩形坐标"<<j<<"为" << vertices[j] << endl;

}

cout << "height:" << mr.size.height << endl << "weight:" << mr.size.width << endl;

rects.push_back(mr);

cout << "矩形角度:" << mr.angle << endl;     //  }

}

}

vector<Mat>output;//用于存放识别到的图像

for (size_t i = 0; i < rects.size(); i++)

{

Mat dst_warp;

Mat dst_warp_rotate;

Mat rotMat(2, 3, CV_32FC1);

dst_warp = Mat::zeros(src.size(), src.type());

float r = (float)rects[i].size.width / (float)rects[i].size.height;

float  angle = rects[i].angle;

if (r < 1)

angle = angle + 90;

rotMat = getRotationMatrix2D(rects[i].center,angle, 1);//其中的angle参数,正值表示逆时针旋转,关于旋转矩形的角度,以为哪个是长哪个是宽,在下面会说到

warpAffine(src, dst_warp_rotate, rotMat, dst_warp.size());//将矩形修正回来

Size rect_size = rects[i].size;

if (r < 1)

swap(rect_size.width, rect_size.height);

Mat dst(rects[i].size, CV_8U);

getRectSubPix(dst_warp_rotate, rect_size, rects[i].center, dst);//裁剪矩形

/*以下代码是将裁减到的矩形设置为相同大小,并且提高对比度*/

Mat resultResized;

resultResized.create(33, 144, CV_8UC3);

resize(dst, resultResized, resultResized.size(), 0, 0, INTER_CUBIC);

Mat grayResult;

cvtColor(resultResized, grayResult, CV_BGR2GRAY);

blur(grayResult, grayResult, Size(3, 3));

equalizeHist(grayResult, grayResult); //均值化提高对比度

output.push_back(grayResult); //存放图片

}

char name[20] = "";

for (size_t i = 0; i < output.size(); i++)

{

if(i==0){

imwrite("D:\\CCar.jpg",output[0]);

sprintf_s(name, "识别到的第%d个车牌", i+1);

imshow(name, output[i]);

}

}

waitKey(0);

return 0;

}

#include <iostream> #include <opencv2/opencv.hpp>

using namespace std; using namespace cv;

int main(){

Mat img = imread("D:\\CCar.jpg",1);

/*  第一个参数是图片的绝对地址  第二个参数表示图片读入的方式(flags可以缺省,缺省时flags=1,表示以彩色图片方式读入图片)  flags>0时表示以彩色方式读入图片  flags=0时表示以灰度图方式读入图片  flags<0时表示以图片的本来的格式读入图片     */

imshow("123", img);

//“123”是显示框的名字

int a = waitKey(10000);

//通过整型变量a获取waitKey函数的返回值

cout << a << endl;

/*     waitKey(x)  表示等x毫秒,在这期间如果有按键按下,则返回按键的ascii码,等待结束则会返回-1.     如果x=0,那么无限等待下去,直到有按键按下     !!!另外,在imshow之后如果没有waitKey语句则不会正常显示图像。即imshow不会生效!!!

*/

//estroyAllWindows();

//销毁窗口

Rect rect1(5,0,17,27);

//创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height

Mat image_cut1 = Mat(img, rect1);

//从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

Mat image_copy1 = image_cut1.clone();

//clone函数创建新的图片

imshow("1",image_copy1);

waitKey();

imwrite( "D:\\Bar1.jpg", image_copy1);

//保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

Rect rect2(23,0,16,27);

//创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height

Mat image_cut2 = Mat(img, rect2);

//从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

Mat image_copy2 = image_cut2.clone();

//clone函数创建新的图片

imshow("2",image_copy2);

waitKey();

imwrite( "D:\\Bar2.jpg", image_copy2);

//保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

Rect rect3(45,0,18,27);

//创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height

Mat image_cut3 = Mat(img, rect3);

//从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

Mat image_copy3 = image_cut3.clone();

//clone函数创建新的图片

imshow("3",image_copy3);    waitKey();

imwrite( "D:\\Bar3.jpg", image_copy3);

//保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

Rect rect4(63,0,16,27);

//创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height

Mat image_cut4 = Mat(img, rect4);

//从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

Mat image_copy4 = image_cut4.clone();

//clone函数创建新的图片

imshow("4",image_copy4);

waitKey();

imwrite( "D:\\Bar4.jpg", image_copy4);

//保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

Rect rect5(79,0,16,27);

//创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height

Mat image_cut5 = Mat(img, rect5);

//从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

Mat image_copy5 = image_cut5.clone();

//clone函数创建新的图片

imshow("5",image_copy5);

waitKey();

imwrite( "D:\\Bar5.jpg", image_copy5);

//保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

Rect rect6(95,0,16,27);

//创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height

Mat image_cut6 = Mat(img, rect6);

//从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

Mat image_copy6 = image_cut6.clone();

//clone函数创建新的图片

imshow("6",image_copy6);

waitKey();

imwrite( "D:\\Bar6.jpg", image_copy6);

//保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

Rect rect7(111,0,16,27);

//创建一个Rect框,属于cv中的类,四个参数代表x,y,width,height

Mat image_cut7 = Mat(img, rect7);

//从img中按照rect进行切割,此时修改image_cut时image中对应部分也会修改,因此需要copy

Mat image_copy7 = image_cut7.clone();

//clone函数创建新的图片    imshow("7",image_copy7);

waitKey();

imwrite( "D:\\Bar7.jpg", image_copy7);

//保存mat格式的图片成jpg格式,或者png,bmp格式,文件大小依次递增

return 0;

}

车牌识别代码OpenCV的更多相关文章

  1. 《zw版·Halcon-delphi系列原创教程》简单的令人发指,只有10行代码的车牌识别脚本

    <zw版·Halcon-delphi系列原创教程>简单的令人发指,只有10行代码的车牌识别脚本 简单的令人发指,只有10行代码的车牌识别脚本      人脸识别.车牌识别是opencv当中 ...

  2. 《Mastering Opencv ...读书笔记系列》车牌识别(II)

    http://blog.csdn.net/jinshengtao/article/details/17954427   <Mastering Opencv ...读书笔记系列>车牌识别(I ...

  3. 《Mastering Opencv ...读书笔记系列》车牌识别(I)

    http://blog.csdn.net/jinshengtao/article/details/17883075/  <Mastering Opencv ...读书笔记系列>车牌识别(I ...

  4. 基于opencv的车牌识别系统

    前言 学习了很长一段时间了,需要沉淀下,而最好的办法就是做一个东西来应用学习的东西,同时也是一个学习的过程. 概述     OpenCV的全称是:Open Source Computer Vision ...

  5. opencv 视觉项目学习笔记(二): 基于 svm 和 knn 车牌识别

    车牌识别的属于常见的 模式识别 ,其基本流程为下面三个步骤: 1) 分割: 检测并检测图像中感兴趣区域: 2)特征提取: 对字符图像集中的每个部分进行提取: 3)分类: 判断图像快是不是车牌或者 每个 ...

  6. opencv颜色识别代码分享

    android 平台 opencv 实现颜色识别代码:http://www.eyesourcecode.com/thread-40682-1-1.htmlopencv的颜色识别简单实现的代码:http ...

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

    主要代码参考https://blog.csdn.net/wzh191920/article/details/79589506 GitHub:https://github.com/yinghualuow ...

  8. EasyPR--一个开源的中文车牌识别系统

    我正在做一个开源的中文车牌识别系统,Git地址为:https://github.com/liuruoze/EasyPR. 我给它取的名字为EasyPR,也就是Easy to do Plate Reco ...

  9. 车牌识别LPR(三)-- LPR系统整体结构

    第三篇:系统的整体架构 LPR系统大体上可由图像采集系统,图像处理系统,数据库管理系统三个子系统组成.它综合了通讯.信息.控制.传感.计算机等各种先进技术,构成一个智能电子系统. 图像采集系统:图像采 ...

随机推荐

  1. HashMap 在高并发下引起的死循环

    HashMap 基本实现(JDK 8 之前) HashMap 通常会用一个指针数组(假设为 table[])来做分散所有的 key,当一个 key 被加入时,会通过 Hash 算法通过 key 算出这 ...

  2. linux下 安装 ImageMagick 及其 php imagick扩展(转)

    linux下 安装 ImageMagick 及其 php imagick扩展 PHP版本7.1.3 : ImageMagick版本 ImageMagick-7.0.8-3: PHP扩展imagick版 ...

  3. 对Zlib单元进行再封装

    对Zlib单元进行再封装 低版本DELPHI,如D7,ZLIB.pas单元封装的很简陋,因此有必要再封装,以增加使用的便利性. 高版本DELPHI,zlib.pas本身提供的接口已经相当完善. Zli ...

  4. .prop() vs .attr()

    .prop() vs .attr() Update 1 November 2012 My original answer applies specifically to jQuery 1.6. My ...

  5. PyTorch Tutorials 3 Neural Networks

    %matplotlib inline Neural Networks 使用torch.nn包来构建神经网络. 上一讲已经讲过了autograd,nn包依赖autograd包来定义模型并求导. 一个nn ...

  6. Somatic hypermutation (or SHM) is a cellular mechanism by which the immune system adapts to the new foreign elements that confront it (e.g. microbes), as seen during class switching. Somatic hypermut

    Somatic hypermutation (or SHM) is a cellular mechanism by which the immune system adapts to the new ...

  7. 使用redis-py的两个类Redis和StrictRedis时遇到的坑

    使用redis-py的两个类Redis和StrictRedis时遇到的坑 前言: 今天产品经理说,有几个队列排序的功能不能用了.对比了下以前的代码查到了一个原因,这个比较的坑,总结起来也是自己没好好看 ...

  8. load ifc

    void setRootNode( osg::Group* root ) { m_main_view->setSceneData( root ); if( m_hud_camera ) { ro ...

  9. osg 在fbx模型中添加自定义节点

  10. Cisco Port-Channel 设置(链路聚合--重点)

    Port-Channel 的在实际工作中的主要作用是将两个或多个端口捆绑成为一个虚拟通道. interface Port-channel1 description port(1/0/5-6) swit ...