Opencv 车牌定位相关资料

车牌定位流程:


流程.png

1、高斯模糊:http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

目的:对图像去噪,为边缘检测算法做准备。

2、灰度化

目的:为边缘检测算法准备灰度化环境。

3、sobel运算(得到图像的一阶水平方向导数):https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/sobel_derivatives/sobel_derivatives.html

目的:检测图像中的垂直边缘,便于区分车牌。(Sobel运算只能对灰度图像有效,因此进行sobel运算前必须进行前面的灰度化工作)

4、二值化:(非黑即白)

目的:对图像的每个像素做一个阈值处理。为后续的形态学操作准备。

(灰度图像中,每个像素值是0-255,表示灰暗程度。设定一个阈值t,小于t的设为0,否则设为1)

5、形态学操作(闭操作)

目的:将车牌字符连接成一个连通区域,便于取轮廓

形态学操作的对象是二值化图像,腐蚀,膨胀是许多形态学操作的基础。

腐蚀:

原理:像素x至于模板的中心,根据模版的大小,遍历所有被模板覆盖的其他像素,修改像素x的值为所有像素中最小的值。(对于中心点像素x,模板范围内没有黑色则保留,否则该像素涂黑)

腐蚀.jpg

膨胀:

原理:与腐蚀操作相反

膨胀.jpg

开操作:

原理:先腐蚀,再膨胀

开操作.jpg

闭操作:

原理:先膨胀,再腐蚀

闭操作.jpg

6、求轮廓

目的:将连通域的外围画出来,便于形成外接矩形

7、尺寸判断

目的:初步筛选排除不可能是车牌的矩形(中国车牌的一般大小是440mm*140mm,宽高比为3.14)

/**
* 尺寸校验(宽高比&面积)
*/
int PlateLocate::verifySizes(RotatedRect rotatedRect)
{
    //容错率
    float error = 0.75f;
    //理想宽高比
    float aspect = float(136) / float(36);
    //真实宽高比
    float realAspect = float(rotatedRect.size.width) / float(rotatedRect.size.height);
    if (realAspect < 1) realAspect = (float)rotatedRect.size.height / (float)rotatedRect.size.width;
    //真实面积
    float area = rotatedRect.size.height * rotatedRect.size.width;
    //最小 最大面积 不符合的丢弃
    //给个大概就行 随时调整
    //尽量给大一些没关系, 这还是初步筛选。
    int areaMin = 44 * aspect * 14;
    int areaMax = 440 * aspect * 140;

    //比例浮动 error认为也满足
    //最小宽高比
    float aspectMin = aspect - aspect * error;
    //最大宽高比
    float aspectMax = aspect + aspect * error;

    if ((area < areaMin || area > areaMax) || (realAspect < aspectMin || realAspect > aspectMax))
        return 0;
    return 1;
}

8、角度判断
目的:初步筛选排除不可能是车牌的矩形

9、旋转矩形
目的:将偏斜的车牌调整为水平,为后面的车牌判断与字符识别提高成功率

仿射变换:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.html

/**
* 转换安全矩形,防止矩形框超出图像边界
*/
void PlateLocate::safeRect(Mat src, RotatedRect rect, Rect2f& safa_rect)
{
    //RotatedRect 没有坐标
    //转为正常的带坐标的边框
    Rect2f boudRect = rect.boundingRect2f();
    //左上角 x,y
    float tl_x = boudRect.x > 0 ? boudRect.x : 0;
    float tl_y = boudRect.y > 0 ? boudRect.y : 0;
    //这里是拿 坐标 x,y 从0开始的 所以-1
    //比如宽长度是10,x坐标最大是9, 所以src.clos-1 
    //右下角
    float br_x = boudRect.x + boudRect.width < src.cols
        ? boudRect.x + boudRect.width - 1
        : src.cols - 1;
    float br_y = boudRect.y + boudRect.height < src.rows
        ? boudRect.y + boudRect.height - 1
        : src.rows - 1;
    float  w = br_x - tl_x;
    float h = br_y - tl_y;
    if (w <= 0 || h <= 0) return;
    safa_rect = Rect2f(tl_x, tl_y, w, h);
}
/**
* 旋转
*/
void PlateLocate::rotation(Mat src, Mat& dst, Size rect_size, Point2f center, double angle)
{
    //获得旋转矩阵
    Mat rot_mat = getRotationMatrix2D(center, angle, 1);
    //运用仿射变换
    Mat mat_rotated;
    //矫正后 大小会不一样,但是对角线肯定能容纳
    int max = sqrt(pow(src.rows, 2) + pow(src.cols, 2));
    warpAffine(src, mat_rotated, rot_mat, Size(max, max),
        INTER_CUBIC);
    //imshow("旋转前", src);
    //imshow("旋转后", mat_rotated);
    //截取 尽量把车牌多余的区域截取掉
    getRectSubPix(mat_rotated, Size(rect_size.width, rect_size.height), center, dst);
    //imshow("截取后", dst);
    //waitKey();
    mat_rotated.release();
    rot_mat.release();
}
/**
* 矩形矫正
*/
void PlateLocate::tortuosity(Mat src, vector<RotatedRect>& rects, vector<Mat>& dst_plates)
{
    //循环要处理的矩形
    for (RotatedRect roi_rect : rects) {
        //矩形角度
        float roi_angle = roi_rect.angle;
        float r = (float)roi_rect.size.width / (float)roi_rect.size.height;
        if (r < 1) {
            roi_angle = 90 + roi_angle;
        }
        //矩形大小
        Size roi_rect_size = roi_rect.size;
        //让rect在一个安全的范围(不能超过src)
        Rect2f  safa_rect;
        safeRect(src, roi_rect, safa_rect);
        //候选车牌
        //抠图  这里不是产生一张新图片 而是在src身上定位到一个Mat 让我们处理
        //数据和src是同一份
        Mat src_rect = src(safa_rect);
        //真正的候选车牌
        Mat dst;
        //不需要旋转的 旋转角度小没必要旋转了
        if (roi_angle - 5 < 0 && roi_angle + 5 > 0) {
            dst = src_rect.clone();
        }
        else {
            //相对于roi的中心点 不减去左上角坐标是相对于整个图的
            //减去左上角则是相对于候选车牌的中心点 坐标
            Point2f roi_ref_center = roi_rect.center - safa_rect.tl();
            Mat rotated_mat;
            //矫正 rotated_mat: 矫正后的图片
            rotation(src_rect, rotated_mat, roi_rect_size, roi_ref_center, roi_angle);
            dst = rotated_mat;
        }
        //调整大小
        Mat plate_mat;
        //高+宽
        plate_mat.create(36, 136, CV_8UC3);
        resize(dst, plate_mat, plate_mat.size());
        dst_plates.push_back(plate_mat);
        dst.release();
    }
}

10、调整大小
目的:确保候选车牌导入机器学习模型之前尺寸一致

HSV颜色模型

如果我们想找出一副图像中的蓝色部分,我们需要检查rgb分量中的blue分量就可以了。一般blue分量是0-255的值,即便蓝色分量255了,由于另外两个分量的影响,需要考虑各个分量的配比问题,rgb作为颜色判断很难实现,就有了hsv模型hsv,photoshop中hsb

HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。这个模型中颜色的参数分别是:色调(H),饱和度(S),明度(V)。

hsv模型.png

色调H

用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;

饱和度S

饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。

亮度V

亮度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。

在OpenCV中hsv 数据为8UC则取值分别为 0-180 0-255 0-255 ,即蓝色应该是120。


hsv范围.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351