智能家居(12)——树莓派USB摄像头捕捉人脸并识别


参考原文: https://blog.csdn.net/NRWHF/article/details/127970690

一、USB摄像头监控、拍照

参照之前博文:https://blog.csdn.net/weixin_44999992/article/details/130437955

二、树莓派安装libcurl和openssl库

  1. 下载libcurl库
    wget --no-check-certificate https://curl.se/download/curl-7.71.1.tar.bz2
  2. 下载openssl库
    wget https://www.openssl.org/source/openssl-1.1.1a.tar.gz
  3. 解压openssl
    tar vxf openssl-1.1.1a.tar.gz
  4. 安装openssl,默认安装在系统路径下,这样编译的时候就不用加动态库的环境变量路径,也不用指定动态库。
    ./config
  5. 编译
    make
  6. 安装
    sudo make install
  7. 安装完openssl后重新配置curl
    ./configure --prefix=/home/jiangyo/Desktop/httpHandler/curl-7.71.1/_install --with-ssl
  8. 编译
    make
  9. 安装
    make install
  10. 重新进行编译文件
    gcc *.c -lpthread -I …/curl-7.71.1/_install/include/ -L …/curl-7.71.1/_install/lib/ -lcurl -lwiringPi
  11. 运行a.out的时候会报错,解决办法。
    sudo apt-get update
    sudo apt-get install libcurl4-openssl-dev

三、拍照的关键指令:

fswebcam --no-banner -r 640x480 image.jpg
-r 指定图片的分辨率,最后的是照片保存的路径。
fswebcam -S 10 image.jpg: -S 参数来跳过前面几帧解决。

四、源码及步骤

由于翔云人脸识别次数有限,无法通过每个一段时间拍一次照片,而是采用语音控制开启摄像头线程。
camera.c
拍照、并将照片通过翔云平台进行比对。

#include "contrlDevices.h"			//自定义设备类的文件
#include <curl/curl.h>
#include <fcntl.h>


char ocrRetBuf[256];
size_t readData(void *ptr, size_t size, size_t nmemb, void *stream)
//回调函数,把从后台的数据拷贝给ocrRetBuf
{
    strncpy(ocrRetBuf,ptr,1024);
    //printf("===============================readdata========================\n");
	//printf("%s\n", ocrRetBuf);
}

char *getBase64FromFile(char * filePath){

    char *baseBuff =NULL;
    char cmd[256] = {'\0'};
    sprintf(cmd,"base64 %s >tmpFile",filePath);
    system(cmd);

    int fp = open("./tmpFile",O_RDWR);
    int fileLen = lseek(fp,0,SEEK_END);
    baseBuff = (char *)malloc(fileLen+8);
    lseek(fp,0,SEEK_SET);
    memset(baseBuff,'\0',fileLen+8);
    read(fp,baseBuff,fileLen+8);

    close(fp);
    system("rm -rf tmpFile");
    return baseBuff;
}

char* getFace()
{
	printf("人脸数据采集中...\n");
	system("fswebcam --no-banner -r 640x480 image.jpg");//关键命令
	
	while(access("./image.jpg",F_OK) != 0); //判断是否拍照完毕
	
	printf("数据采集完毕\n");
	
	char* base64BufFaceRec = getBase64FromFile("./image.jpg");
	system("rm image.jpg");  //采集完成删除,防止占内存
	
	return base64BufFaceRec;   //返回刚才拍照的base64
}

void postUrl()
{
    CURL *curl;
    CURLcode res;

    //分开定义,然后字符串拼接
    char* key    = "xxx";
    char* secret = "xxx";
    int   typeId = 21;
    char* format = "xml";

    char* base64BufPic1 = getFace();//摄像头拍照获取的照片
    char* base64BufPic2 = getBase64FromFile("./image2.jpg");//个人照片

    int len = strlen(key)+strlen(secret)+strlen(base64BufPic1)+strlen(base64BufPic2)+128;//分配空间不够会>导致栈溢出
    char* postString = (char* )malloc(len);
    memset(postString,'\0',len);//因为postString是一个指针,不能用sizeof来计算其指向的大小

    sprintf(postString,"img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",base64BufPic1,base64BufPic2,key,secret,typeId,format);//根据平台的传参格式编写

    curl = curl_easy_init();

    if(curl){
            curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postString);  //指定post内容,传入参数  
            curl_easy_setopt(curl, CURLOPT_URL, "https://netocr.com/api/faceliu.do");// 指定url
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,readData);  //回调函数readDate读取返回值
            res = curl_easy_perform(curl);          //类似于状态码
            printf("OK:%d\n",res);

            if(strstr(ocrRetBuf,"否") != NULL){    //判断翔云后台返回的字符串中有没有“是”
                    printf("不是同一个人\n");
            }
            else{
                    printf("是同一个人\n");//这里识别成功,去开锁!
            }
            curl_easy_cleanup(curl);
    }
}

struct Devices camera = {
	.devicesName = "camera",
	.justDoOnce = postUrl,
    .next = NULL
};

struct Devices* addCameraToDeviceLink(struct Devices *phead)		//摄像头加入设备链表函数
{
	if(phead == NULL){
		return &camera;
	}else{
		camera.next = phead;  //以前的头变成.next
		return &camera;
	}
}

在语音识别线程中,根据识别到“请进行人脸识别”语句后,创建摄像头线程。

case 'W':
                    printf("open camera\n");
                    findDevice = findDeviceByName("camera", pdeviceHead);
                    if(findDevice != NULL) {
                        pthread_t cameraThread;
                        pthread_create(&cameraThread,NULL,cameraThread_func,NULL);
                    }
                    else {
                        printf("camera = NULL!\n");
                    }
                    findDevice = NULL;
                    break;

启动摄像头线程。进行拍照并人脸识别

void *cameraThread_func(void* data)//起线程的函数有格式要求
{
	struct Devices *cameraTemp;
	cameraTemp = findDeviceByName("camera", pdeviceHead);

	if(cameraTemp == NULL){  //防止段错误的必需判断
		printf("find camera error\n");
		pthread_exit(NULL); //在线程中不用return
	}

	cameraTemp->justDoOnce(); //调用设备的justDoOnce函数
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值