OpenCV+CLion 人脸识别+人脸模型训练

OpenCV windows 版本编译+CLion项目导入参考:

CLion+OpenCV 识别身份证号码---检测身份证号码_xxwbwm的博客-CSDN博客

代码:

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

using namespace cv;
using namespace std;

class CascadeDetectorAdapter : public DetectionBasedTracker::IDetector {
public:
    CascadeDetectorAdapter(cv::Ptr<cv::CascadeClassifier> detector) :
            IDetector(),
            Detector(detector) {
        CV_Assert(detector);
    }

    void detect(const cv::Mat &Image, std::vector<cv::Rect> &objects) {
        Detector->detectMultiScale(Image, objects, scaleFactor, minNeighbours, 0, minObjSize, maxObjSize);
    }

    ~CascadeDetectorAdapter() {

    }

private:
    CascadeDetectorAdapter();

    cv::Ptr<cv::CascadeClassifier> Detector;
};

DetectionBasedTracker *getTracker() {
    // OpenCV自带模型位置F:\opencvWin\opencv\build\etc\lbpcascades
    String path = "F:\\opencvWin\\opencv\\build\\etc\\lbpcascades\\lbpcascade_frontalface.xml";
//    String path = "F:\\opencvWin\\facetrain\\samples\\data\\cascade.xml";//无法识别

    Ptr<CascadeClassifier> classifier = makePtr<CascadeClassifier>(path);
    //适配器
    Ptr<CascadeDetectorAdapter> mainDetector = makePtr<CascadeDetectorAdapter>(classifier);

    Ptr<CascadeClassifier> classifier1 = makePtr<CascadeClassifier>(path);
    //适配器
    Ptr<CascadeDetectorAdapter> trackingDetector = makePtr<CascadeDetectorAdapter>(classifier1);
    //跟踪器
    DetectionBasedTracker::Parameters DetectorParams;
    DetectionBasedTracker *tracker = new DetectionBasedTracker(mainDetector, trackingDetector, DetectorParams);
    return tracker;
}

int main() {
    DetectionBasedTracker *tracker = getTracker();

    //开启跟踪器
    tracker->run();
    //获取相机数据
    VideoCapture capture(0);

    Mat Sourceimg;
    Mat gray;
    Mat test;
    while (1) {
        capture >> Sourceimg;
        //转灰度图处理
        cvtColor(Sourceimg, gray, COLOR_BGR2GRAY);
        //增强对比度 (直方图均衡)
        equalizeHist(gray, gray);
        //创建保存检测到人脸的向量集合
        std::vector<Rect> faces;
        //灰度图识别处理
        tracker->process(gray);
        //获取结果
        tracker->getObjects(faces);

        for (Rect face : faces) {
            //分别指定 bgra
            if (face.x < 0 || face.width < 0 || face.x + face.width > Sourceimg.cols ||
                face.y < 0 || face.height < 0 || face.y + face.height > Sourceimg.rows) {
                continue;
            }
            //在原图画框框
            rectangle(Sourceimg, face, Scalar(255, 0, 255));
#if 0
            int i = 0;
            while (true){
                //制作正样本
                Mat m;
                //把img中的脸部位拷贝到m中
                Sourceimg(face).copyTo(m);
                //把人脸 重新设置为 24x24大小的图片
                resize(m, m, Size(24, 24));
                //转成灰度
                cvtColor(m, m, COLOR_BGR2GRAY);
                char p[200];
                sprintf(p, "F:/opencvWin/facetrain/samples/vivid/%d.jpg", i++);
                //把mat写出为jpg文件
                imwrite(p, m);
                m.release();
                if(i == 100){
                    break;
                }
            }
#endif
        }
        imshow("camera", Sourceimg);
        //27 == ESC  等待30毫秒退出
        if (waitKey(30) == 27) {
            break;
        }
    }
    if (!Sourceimg.empty()) Sourceimg.release();
    if (!gray.empty()) gray.release();
    capture.release();
    tracker->stop();
    delete tracker;
    return 0;
}

上面加载的lbpcascade_frontalface.xml人脸模型是opencv源码自带的,可以借助此模型训练我们自己的人脸模型,接下来介绍训练我自己的人脸模型,打开此段代码,当识别到人脸的时候把我们人脸信息转存成大小为24*24(像素)的图片,存贮100张,原因:我只有300张负样本图片(不包含人脸即可)

#if 0
            int i = 0;
            while (true){
                //制作正样本
                Mat m;
                //把img中的脸部位拷贝到m中
                Sourceimg(face).copyTo(m);
                //把人脸 重新设置为 24x24大小的图片
                resize(m, m, Size(24, 24));
                //转成灰度
                cvtColor(m, m, COLOR_BGR2GRAY);
                char p[200];
                sprintf(p, "F:/opencvWin/facetrain/samples/vivid/%d.jpg", i++);
                //把mat写出为jpg文件
                imwrite(p, m);
                m.release();
                if(i == 100){
                    break;
                }
            }
#endif

正样本:

将正样本信息整理成xxx.xxx(任意文件名,任意文件后缀)我这里保存到了vivid.data文件

vivid.data文件内容:

vivid/0.jpg 1 0 0 24 24
vivid/1.jpg 1 0 0 24 24
vivid/2.jpg 1 0 0 24 24
vivid/3.jpg 1 0 0 24 24
vivid/4.jpg 1 0 0 24 24
vivid/5.jpg 1 0 0 24 24
vivid/6.jpg 1 0 0 24 24
vivid/7.jpg 1 0 0 24 24
vivid/8.jpg 1 0 0 24 24
vivid/9.jpg 1 0 0 24 24

参数含义:

vivid/x.jpg 样本位置(全路径为:F:\opencvWin\facetrain\samples\vivid\x.jpg)

1  表示只有一张人脸

0  0 表示人脸的起始位置

24 24 表示人脸的大小,也就是终止位置

如果一张图片多张人脸,eg:2张人脸

vivid/0.jpg 2  0 0 50 50     80 80 130 130 

0 0 50 50 第一张人脸起始终止点,80 80 130 130 第二张人脸起始终止点

文件内容的书写,可以用代码完成:

import java.io.*;
public class GeneateFile{
		public static void main(String[] args) throws Exception{//FileOutputStream 
			FileOutputStream fos = new FileOutputStream("F:/opencvWin/facetrain/samples/vivid/vivid.data");
			for(int i =0 ;i<100;i++){
				String content = String.format("vivid/%d.jpg 1 0 0 24 24\n",i);
				fos.write(content.getBytes());
			} 
			fos.close();
	}
}

将vivid.data文件转换成vec样本文件

opencv_createsamples -info vivid.data -vec vivid.vec -num 100 -w 24 -h 24
-info: 正样本描述
-vec : 输出的正样本文件
-num : 正样本数量
-w -h: 输出样本的大小
opencv_createsamples -info vivid.data -vec vivid.vec -num 100 -w 24 -h 24
结果:
F:\opencvWin\facetrain\samples>opencv_createsamples -info vivid.data -vec vivid.vec -num 100 -w 24 -h 24
Info file name: vivid.data
Img file name: (NULL)
Vec file name: vivid.vec
BG  file name: (NULL)
Num: 100
BG color: 0
BG threshold: 80
Invert: FALSE
Max intensity deviation: 40
Max x angle: 1.1
Max y angle: 1.1
Max z angle: 0.5
Show samples: FALSE
Width: 24
Height: 24
Max Scale: -1
Create training samples from images collection...
Done. Created 100 samples

F:\opencvWin\facetrain\samples>

上述显示表示成功。

修改生成vivid.data的java代码,生成负样本bg.data文件

import java.io.*;
public class GeneateFileOpp{
		public static void main(String[] args) throws Exception{//FileOutputStream 
			FileOutputStream fos = new FileOutputStream("F:/opencvWin/facetrain/samples/bg/bg.data");
			for(int i =0 ;i<300;i++){
				String content = String.format("bg/%d.jpg\n",i);
				fos.write(content.getBytes());
			} 
			fos.close();
	}
}

bg.data文件内容(省略部分):注意没有人脸信息哦

bg/0.jpg
bg/1.jpg
bg/2.jpg
bg/3.jpg
bg/4.jpg
bg/5.jpg
bg/6.jpg
bg/7.jpg
bg/8.jpg
bg/9.jpg
bg/10.jpg

训练:

opencv_traincascade -data data -vec vivid.vec -bg bg.data -numPos 100 -numNeg 300 -numStages
15 -featureType LBP -w 24 -h 24
-data : 目标目录需要手动创建,用于存放生成的模型,名字可以自定义
-vec : 正样本
-bg : 负样本
-numPos :每级分类器训练时所用到的正样本数目
-numNeg :每级分类器训练时所用到的负样本数目,可以大于-bg数目
-numStages:训练分类器的级数,如果层数多,分类器的误差就更小,但是检测速度慢。(15-20)
-featureType: LBP
-w -h

执行成功结果:

Training until now has taken 0 days 0 hours 0 minutes 18 seconds.

===== TRAINING 7-stage =====
<BEGIN
POS count : consumed   100 : 100
NEG count : acceptanceRatio    0 : 0
Required leaf false alarm rate achieved. Branch training terminated. 

此时在data目录会有以下文件:

 修改上面模型加载路径,即可检测模型是否有效,操作如下:

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值