智能家居项目之树莓派+摄像头进行人脸识别

Posted Love小羽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了智能家居项目之树莓派+摄像头进行人脸识别相关的知识,希望对你有一定的参考价值。

目录

1、编辑Camera.c

2、编辑contrlDevices.h

3、编辑mainPro.c

4、进行编译:

5、运行结果: ./test1

6、项目图片演示


智能家居项目(七)之Libcurl库与HTTPS协议实现人脸识别_Love小羽的博客-CSDN博客

经过上一篇文章,写的代码是在Ubuntu系统中写的,这回把代码搬到树莓派上进行测试

直接上代码

1、编辑Camera.c

#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "contrlDevices.h"

#define true 1
#define false 0typedef 

typedef unsigned int bool;
char buf[10240] = '\\0';//全局变量,用来接收从OCR后台返回的数据
char* getFace1();
void postUrl();

char* getPicBase64FromFile(char *filePath); 
struct Devices *addCameraContrlToDeviceLink(struct Devices *phead);

size_t readData(void *ptr,size_t size,size_t nmemb,void *stream)  //回调函数
	
	strncpy(buf,ptr,1024);


char *getFace1()
	 
	printf("Taking pictures...\\n");	  
	system("raspistill -q 5 -t 1 -o image.jpg"); //-q 是图片质量,在0~100之间,我们调成5,压缩图片质量,生成的照片名字为imag.jpg 												//-t 是拍照延时,设定1s后拍照	 while (access("./image.jpg", F_OK) != 0)		 ; //判断是否拍照完毕	 printf("拍照完成\\n");	  char *base64BufFaceRec = getPicFromOCRBase641("./image.jpg");    // system("rm image.jpg");	 return base64BufFaceRec; //返回刚才拍照的base64
	
	while (access("./image.jpg", F_OK) != 0); //判断是否拍照完毕
	printf("Photo taking completed\\n");
	
	char *base64BufFaceRec = getPicBase64FromFile("./image.jpg");
	
	return base64BufFaceRec; //返回刚才拍照的base64


char* getPicBase64FromFile(char *filePath)    //获取图片的base64流
	
	char *bufPic;	
	char cmd[128] = '\\0';
	
	sprintf(cmd,"base64 %s > tmpFile",filePath);	
	system(cmd);

	int fd = open("./tmpFile",O_RDWR);	
	int filelen = lseek(fd,0,SEEK_END);	
	lseek(fd,0,SEEK_SET);	
	bufPic =(char *)malloc(filelen+2);	
	memset(bufPic,0,filelen+2);	
	read(fd,bufPic,filelen);	
	close(fd);
	system("rm -f tmpFile");	
	return bufPic;


void postUrl()
	
	CURL *curl;	
	CURLcode res;	
	char *postString;

	char* key    = "自行购买翔云平台购买人脸识别后的key";//翔云平台购买人脸识别后的key
    char* secret = "自行购买翔云平台购买人脸识别后的secret";//翔云平台购买人脸识别后的secret
    int   typeId = 21;
    char* format = "xml";
	
	char *bufPic1 = getFace1();	
	char *bufPic2 = getPicBase64FromFile("./5.jpg");
	int len = strlen(key)+strlen(secret)+strlen(bufPic1)+strlen(bufPic2)+124;	//分配空间不够会导致栈溢出
	postString = (char *)malloc(len);	//因为postString是一个指针,不能用sizeof来计算其指向的大小
	memset(postString,'\\0',len);

	sprintf(postString,"img1=%s&img2=%s&key=%s&secret=%s&typeId=%d&format=%s",			
		bufPic1,bufPic2,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); //将返回的http头输出到fp指向的文件		
		res = curl_easy_perform(curl);		//类似于状态码
		printf("OK:%d\\n",res);
		if(strstr(buf,"是") != NULL)    //判断翔云后台返回的字符串中有没有“是”
					
			printf("the same Person\\n");
		else			
			printf("diff Person\\n");		
		
		curl_easy_cleanup(curl);	
	


struct Devices cameraContrl = 	
	
	.deviceName = "camera",		
	.justDoOnce = postUrl,
	.getFace = getFace1,
	.getPicBase64FromFile = getPicBase64FromFile,
	.readData = readData,
	.next = NULL
;

struct Devices *addCameraContrlToDeviceLink(struct Devices *phead)
	
	
	if(phead == NULL)		
		return &cameraContrl;	
	else		
		cameraContrl.next = phead;		
		phead = &cameraContrl;
		
	return phead;

2、编辑contrlDevices.h

//设备工厂
#include <wiringPi.h>
#include <stdlib.h>

struct Devices


	char deviceName[128];

	int status;
	int pinNum;
	int (*open)(int pinNum);
	int (*close)(int pinNum);
	void (*justDoOnce)(); //用于摄像头
	char* (*getFace)(); //用于摄像头
	char* (*getPicBase64FromFile)(); //用于摄像头
	size_t (*readData)(); //用于摄像头
	
	int (*deviceInit)(int pinNum);
	int (*readStatus)(int pinNum);
	int (*changeStatus)(int status);

	struct Devices *next;
;

struct Devices* addBathroomLightToDeviceLink(struct Devices *phead);
struct Devices* addUpstairLightToDeviceLink(struct Devices *phead);
struct Devices* addLivingRoomLightToDeviceLink(struct Devices *phead);
struct Devices* addRestaurantLightToDeviceLink(struct Devices *phead);
struct Devices* addFireToDeviceLink(struct Devices *phead);
struct Devices* addCameraContrlToDeviceLink(struct Devices *phead);

3、编辑mainPro.c

#include "contrlDevices.h"
#include "InputCommand.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

struct Devices *pdeviceHead = NULL;          //设备工厂
struct InputCommander *pCommandHead = NULL;  //指令工厂
struct InputCommander *socketHandler = NULL;
int c_fd;
struct Devices *cameraThrad = NULL; 
typedef unsigned int bool;


struct Devices* findDeviceByName(char *name,struct Devices *phead)

	struct Devices *tmp = phead;
	if(phead == NULL)
		return NULL;
	else
		while(tmp != NULL)
			if(strcmp(tmp->deviceName,name) == 0)
				return tmp;
			
			tmp = tmp->next;
		
			return NULL;
	


struct InputCommander* findCommandByName(char *name,struct InputCommander *phead)


	struct InputCommander *tmp = phead;
	if(phead == NULL)
		return NULL;
	else
		while(tmp != NULL)
			if(strcmp(tmp->commandName,name) == 0)
				return tmp;
			
			tmp = tmp->next;
		
			return NULL;
	


void *voice_thread(void* datas)
	
	int nread;
	printf("voice_thread\\n");
	struct InputCommander *voiceHandler;
	voiceHandler = findCommandByName("voice",pCommandHead);
	if(voiceHandler == NULL)
		printf("find voiceHandler error\\n");
		pthread_exit(NULL);
	else
		if(voiceHandler->Init(voiceHandler,NULL,NULL) < 0)
			printf("voice init error\\n");
			pthread_exit(NULL);
			
		else
			printf("%s init success\\n",voiceHandler->commandName);
		
		while(1)
			nread = voiceHandler->getCommand(voiceHandler);
			if(nread == 0)
				printf("nodata form vocie\\n");
			else
				printf("do divece contrl:%s\\n",voiceHandler->command);
			
		
	


void *read_thread(void* datas)

	int n_read;
	printf("have user connect\\n");
	memset(socketHandler->command,'\\0',sizeof(socketHandler->command));
	while(1)
		n_read = read(c_fd,socketHandler->command,sizeof(socketHandler->command));
		if(n_read == -1)
			perror("read");
		else if(n_read > 0)
			printf("\\nget: %d,%s\\n",n_read,socketHandler->command);
			memset(socketHandler->command,'\\0',sizeof(socketHandler->command));
		else
			printf("client quit\\n");	
		
	


void *socket_thread(void* datas)

	
	int n_read = 0;
	printf("socket_thread\\n");
	pthread_t readThrad;
	
	struct sockaddr_in c_addr;
	memset(&c_addr,0,sizeof(struct sockaddr_in));
	int clen = sizeof(struct sockaddr_in);
	
	socketHandler = findCommandByName("socketServer",pCommandHead);
	if(socketHandler == NULL)
		printf("find socketServerHandler error\\n");
		pthread_exit(NULL);
	
	else
		printf("%s init success\\n",socketHandler->commandName);
	
	socketHandler->Init(socketHandler,NULL,NULL);
	while(1)
		
		c_fd = accept(socketHandler->sfd,(struct sockaddr *)&c_addr,&clen);
		pthread_create(&readThrad,NULL,read_thread,NULL);
	


void *cameraThread_func(void* data)//起线程的函数有格式要求

	struct Devices *cameraTemp;

	cameraTemp = findDeviceByName("camera", pdeviceHead); //摄像头的设备编号为c1

	if(cameraTemp == NULL)  //防止段错误的必需判断,当给指针赋值是,一定要考虑NULL的情况,否则后续操作都是空谈
		printf("find camera error\\n");
		pthread_exit(NULL); //在线程中不用return
	

	cameraTemp->justDoOnce(); //设备都要从工厂里面取出来.可不能camera.justDoOnce,谁认识你这个camera!


int main()

	char name[128];
	struct Devices *tmp = NULL;
	pthread_t voiceThread;
	pthread_t socketThread;
	pthread_t cameraThread;
	
	if(-1 == wiringPiSetup())
		return -1;
		

	//1、设备工厂初始化
	pdeviceHead = addBathroomLightToDeviceLink(pdeviceHead);
	pdeviceHead = addUpstairLightToDeviceLink(pdeviceHead);
	pdeviceHead = addLivingRoomLightToDeviceLink(pdeviceHead);
	pdeviceHead = addRestaurantLightToDeviceLink(pdeviceHead);
	pdeviceHead = addFireToDeviceLink(pdeviceHead);
	pdeviceHead = addCameraContrlToDeviceLink(pdeviceHead);       //摄像头

	pCommandHead = addvoiceContrlToInputCommandLink(pCommandHead);//声音
	pCommandHead = addSocketContrlToInputCommandLink(pCommandHead);

	//2、语音线程池建立
	
/*int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);*/

	pthread_create(&voiceThread,NULL,voice_thread,NULL);

	//3、socket线程池建立
	pthread_create(&socketThread,NULL,socket_thread,NULL);

	//4、 摄像头线程
	
	pthread_create(&cameraThread,NULL,cameraThread_func,NULL);
		
	//5、 火灾线程
	
	//线程等待
	pthread_join(voiceThread,NULL);
	pthread_join(socketThread,NULL);
	pthread_join(cameraThread,NULL);
	return 0;

4、进行编译:

gcc mainPro.c upstairLight.c bathroomLight.c fire.c livingroomLight.c socketContrl.c restaurantLight.c  camera.c voiceContrl.c -lwiringPi -lpthread  -I ./curl-7.71.1/_install/include/ -L ./curl-7.71.1/_install/lib/ -lcurl -o test1

5、运行结果: ./test1

 结果显示diff Person,说明人脸识别失败了,我也尝试了很多次,都没有成功,有可能是我放在树莓派里的本人照片和用摄像头拍的本人照片,差别较大的缘故吧,但是程序是可以正常运行的。

6、项目图片演示

 

 

 

以上是关于智能家居项目之树莓派+摄像头进行人脸识别的主要内容,如果未能解决你的问题,请参考以下文章

树莓派 --- 人脸口罩识别智能监控

人脸识别——树莓派+单片机+python+百度云aip

智能追录器——基于人脸识别,图像处理,机器人视觉交叉领域

树莓派——智能家居第一步

基于树莓派的智能魔镜,支持人脸识别情感监测热词唤醒语音交互,以及与手机APP交互的实现

基于树莓派的智能魔镜,支持人脸识别情感监测热词唤醒语音交互,以及与手机APP交互的实现