openCV

人脸识别追踪

  • OpenCV是一个开源发行的跨平台计算机视觉库。

  • 人脸识别使用到了OpenCV里面的Objdetect模块,目标检测模块,如:人脸检测等。

  • 人脸检测原理:

    LBP

    LBP(Local Binary Pattern,局部二值模式)是一种用来描述图像局部纹理特征的算子,具有多分辨率、灰度尺度不变、旋转不变等特性。主要用于特征提取中的纹理提取。

    基本LBP

    基本LBP

    将83与包围83的8个位置进行比较。如果大于83则取值为1,否则为0,然后将这些数据顺时针组合在一起,这样的到一个01111100,即:0x7C(124)。这就是83位置的lbp值。

    检测原理

    将一幅图片划分为若干的子区域,对每个子区域内的每个像素点都提取LBP特征,然后,在每个子区域内建立LBPH(LBP特征的统计直方图)。 每个子区域就可以用一个统计直方图来进行描述;整个图片就由若干个统计直方图组成 之后,将图片和人脸的直方图进行相似性比较。
    用横轴表示LBP值0到255,用竖轴表示区域中对应LBP数值的像素数量,这个函数图像称为直方图。
    LBPH是用来表现图像中LBP分布的情况。


    LBPH示意
  • android中实现
    Java层调用Camera接口进行离屏渲染,在回调接口中获取摄像头数据data[ ],提供给Native层备用。
    Java层准备SurfaceView,将Surface转递给Native层备用。
    Native层接收Surface,使用ANativeWindowAPI获取到window对象。
    Native层接收到Java层传来的data[ ]后:

  1. 开辟一个OpenCV的Mat
    //1、高 2、宽,rows表示高,cols表示宽
    Mat src(h + h / 2, w, CV_8UC1, data);

因为data[ ]是NV21格式的YUV420数据,
NV21

数据实际高度是h*3/2。

  1. 将 nv21的yuv数据转成了rgba
//将 nv21的yuv数据转成了rgba
cvtColor(src, src, COLOR_YUV2RGBA_NV21);
  1. 根据摄像头的前后,进行旋转、水平翻转处理
   if (cameraId == 1) {
        //前置摄像头,需要逆时针旋转90度
        rotate(src, src, ROTATE_90_COUNTERCLOCKWISE);
        //水平翻转 镜像
        flip(src, src, 1);
    } else {
        //顺时针旋转90度
        rotate(src, src, ROTATE_90_CLOCKWISE);
    }
  1. 灰度处理、对比度增强
    //灰色
    cvtColor(src, gray, COLOR_RGBA2GRAY);
    //增强对比度 (直方图均衡)
    equalizeHist(gray, gray);
  1. 加载分类器、跟踪器
    分类器的加载需要传入模型文件地址,分类器可以定位出人脸区域。跟踪器是对分类器的优化,在视频中可以根据上一次分类器的定位结果优化下一次定位的运算过程。
  2. 跟踪器运行,得到定位区域列表,在原图中绘制人脸范围矩形框
    //定位人脸 N个
    tracker->process(gray);
    tracker->getObjects(faces);
    for (Rect face : faces) {
        //画矩形
        //分别指定 bgra
        rectangle(src, face, Scalar(255, 0, 255));
    }
  1. 调用ANativeWindowAPI将Mat src绘制到window中
    //显示
    if (window) {
        //设置windows的属性
        // 因为旋转了 所以宽、高需要交换
        //这里使用 cols 和rows 代表 宽、高 就不用关心上面是否旋转了
        ANativeWindow_setBuffersGeometry(window, src.cols, src.rows, WINDOW_FORMAT_RGBA_8888);
        ANativeWindow_Buffer buffer;
        do {
            //lock失败 直接brek出去
            if (ANativeWindow_lock(window, &buffer, 0)) {
                ANativeWindow_release(window);
                window = 0;
                break;
            }
            //src.data : rgba的数据
            //把src.data 拷贝到 buffer.bits 里去
            // 一行一行的拷贝
            uint8_t *dst_data = static_cast<uint8_t *>(buffer.bits);
            int dst_linesize = buffer.stride * 4;
            uint8_t *src_data = src.data;
            int src_linesize = src.cols * 4;
            for (int i = 0; i < src.rows; ++i) {
                memcpy(dst_data + i * dst_linesize, src_data + i * src_linesize,  dst_linesize);
            }
            //提交刷新
            ANativeWindow_unlockAndPost(window);
        } while (0);
    }

车牌识别

第一步 车牌的定位

有两种方式:

  • 利用车牌加文体边缘区域丰富的特性,用Sobel进行边缘检测,分离出车牌区域。
  • 利用车牌蓝色底色的特性,用HSV原理分离出车牌区域。

Sobel过程分析

  1. 高斯模糊(平滑、降噪 )。
  2. 灰度化 去掉颜色 因为它对于我们这里没用 降噪。
  3. 边缘检测 让车牌更加突出 在调用时需要以16位来保存数据 在后续操作 以及显示的时候需要转回8位。
  4. 二值化 黑白,采用了 大律法 最大类间算法。
  5. 闭操作,将相邻的白色区域扩大 连接成一个整体。
  6. 轮廓检测findContours,将结果变成点序列放入 集合。
  7. 利用minAreaRect 将 点序列 得到最小包裹的 有角度矩形RotatedRect
  8. 进行初步的筛选 把完全不符合的轮廓给排除掉 ( 比如:1x1,5x1000 )。
  9. 矫正,因为可能斜的,处理扭曲。

HSV过程分析(颜色模型,H色调、S饱和度、V明亮度)

  1. 原Mat转换成HSV格式的Mat hsv。
  2. Mat hsv的数据在内存中一行是按照h、s、v连续分布的,所以需要遍历每一行,得到具体的h、s、v数值,比较hsv分布表:
    hsv.png

    ,判断一组h、s、v是否在蓝色范围内,把蓝色像素 凸显出来 ,其他的区域全变成黑色:

if (h >= 100 && h <= 124 && s >= 43 && s <= 255 && v >= 46 && v <= 255) {
    p[j] = 0;
    p[j + 1] = 0;
    p[j + 2] = 255;
} else {
    p[j] = 0;
    p[j + 1] = 0;
    p[j + 2] = 0;
}
  1. 把Mat hsv的h、s、v分离出来
    vector<Mat> hsv_split;
    split(hsv, hsv_split);
    Mat target = hsv_split[2];//凸显出来的图像
  1. 二值化 黑白,采用了 大律法 最大类间算法。
  2. 闭操作,将相邻的白色区域扩大 连接成一个整体。
  3. 轮廓检测findContours,将结果变成点序列放入 集合。
  4. 利用minAreaRect 将 点序列 得到最小包裹的 有角度矩形RotatedRect
  5. 进行初步的筛选 把完全不符合的轮廓给排除掉 ( 比如:1x1,5x1000 )。
  6. 矫正,因为可能斜的,处理扭曲。

使用SVM测评Sobel和HSV定位的结果

  1. 灰度化 去掉颜色 因为它对于我们这里没用 降噪。
  2. 二值化 黑白,采用了 大律法 最大类间算法。
  3. 提取特征,把特征置为一行。
  4. 调用svm测评特征,得到评分。
  5. 评分最小,即为最优定位结果。

SVM测评的模型需要大量的正样本进行训练:


image.png

SVM介绍

svm,英文全称为 Support Vector Machine,中文名叫支持向量机,是机器学习最为经典的分类方法之一。
SVM是一种线性分类器,分类的对象要求是线性可分。因此我们首先要了解什么是线性可分与线性不可分。
假如在课桌“三八线”的两旁分别放了一堆苹果和一堆荔枝,通过“三八线”这样一条直线就能把苹果和荔枝这两种类别的水果分开了(如左下图),这种情况就是线性可分的。但是如果苹果和荔枝的放置位置是苹果包围荔枝的局面(如右下图),就无法通过一条直线将它们分开(即这样的直线是不存在的),这种情况则是线性不可分的情形。

image.png

因此,只有当样本数据是线性可分的,才能找到一条线性分割线或分割面等,SVM分类才能成立。假如样本特征数据是线性不可分的,则这样的线性分割线或分割面是根本不存在的,SVM分类也就无法实现。
在二维的平面课桌上,一条直线就足以将桌面一分为二。但如果扩展到三维空间中,则需要一个平面(比如一面墙、一扇屏风等)才能将立体空间区域一分为二。
如何处理线性不可分?
在前面苹果和荔枝的例子当中,我们已经了解到 SVM 要求样本数据是线性可分的,这样才会存在分类超平面。而如果样本数据是非线性的情况,那将如何处理呢?SVM的解决办法就是先将数据变成线性可分的,再构造出最优分类超平面。
SVM 通过选择一个核函数 K ,将低维非线性数据映射到高维空间中。原始空间中的非线性数据经过核函数映射转换后,在高维空间中变成线性可分的数据,从而可以构造出最优分类超平面。
如下图所示:原始样本数据在二维空间里无法线性分割,经过核函数映射到三维空间中则可构造出分类超平面进行二类划分。
image.png

举个形象的例子:一把瓜子和一把钢珠混在一起铺在桌面,它们在二维空间是线性不可分的。如果用手在桌面上用力一拍,瓜子会弹得更高,在三维空间,瓜子和钢珠就变成了线性可分的了。

第二步 车牌的识别

在第一步中定位到了车牌整体的轮廓,还要继续把车牌中的字符Mat抠出来,把每一个字符Mat识别对应的文字。

  1. 如何抠字符?
    第一步定位后的的车牌先转灰度图,然后二值化,得到了
    image.png

    可以发现底部有一些干扰(固定螺丝),可以逐行读取Mat,分析黑白跳变的次数,如果次数较少就可以把这一行的数据全部转为黑色,得到下图:
    image.png

接下来查找轮廓findContours得到轮廓的Poin集合,再用boundingRect包裹Pont集合得到若干个矩形Rect,按照宽高情况可以筛除一下不是字符的Rect,最终得到字符的Rect集合,绘制到原图中这个样子:

image.png

然后可以在整个车牌图片宽度的2/7左右出找到城市代号字母,响应的它的左边就是省份的简称汉子。可以把这些字符分为两类:汉字+字母or数字,接下来把抠出来的这些文字图片识别即可。

  1. 如何识别字符?
    刚抠出来的字符Mat是二值化后的,接下来:
  2. 提取特征,把特征置为一行。
  3. 调用ANN_MLP测评特征。汉字由于是省份的简称数量有限,因此训练模型时可以将汉字作为单独一个模型,每个省份简称汉字单独一个文件夹存放:


    image.png

    image.png

    这样训练出来的模型测评就会返回最匹配的文件下下标,我们就可以知道对应的汉字是什么了。
    同理,可以把0-9 和A-Z这些字符在一个模型中测评。


    image.png

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

推荐阅读更多精彩内容