智能家居语音控制及摄像头人脸识别
1、使用的软件及过程
2、python 人脸代码讲解
3、主函数代码讲解
1.使用的软件及过程
使用到的软件有secureSRT,filezilla,Visual Srudio
secureSRT 是负责树莓派的代码烧入,与编程(树莓派的文件存储位置)
Visual Studio 是负责 代码的编写,与快速的编写,代码文件存储
filezilla 这个软件是负责把 visual srudio的代码上传到SecureCRT 好编译
接下来简单说一下过程
第一步先在VS中编写好代码
第二步在filezilla传输文件到树莓派,也就是CRT中
传输完成后,便可以到CRT中编译了,但编译时先编译Python的摄像头代码先
1、先找到
2、编译代码
3、先运行代码将第一张图片存进里面(raspistill -o file1.jpg)
运行完就可以树莓派的主函数
(gcc mainPro.c bathroomLight.c upstairLight.c livingroom.c Restaurant.c voiceContrl.c socketContrl.c -lwiringPi -lpthread -o c)
运行成功
2、python 人脸代码讲解
#coding=UTF-8
import sys
reload(sys)
sys.setdefaultencoding('utf8')
import requests #导包并设置字符编码,因为在py中,出现中文默认会报错
url = r'https://netocr.com/api/facerecog.do' #翔云api的接口地址
key = r'用户个人的key码,可在个人中心查看' 如下张图
secret = r'用户个人的secret码,可在个人中心查看'
typeId = 21 #服务类型
rFormat = r'xml'
file1 = {'file1': open('file1.jpg', 'rb'),'file2':open('file2.jpg','rb')}
#要比对的两张图片,file1.jpg,file2.jpg,注意照片的文件是可以自定义的,但要和树莓派上的主代码一致
data = {'key':key, 'secret':secret, 'typeId':typeId, 'format':rFormat}
#其他参数的字典
r = requests.post(url, files=file1,data = data) #发起http请求,传参,比对后返回的信息存入r
print(r.text) //用来显示输出结果,方便调试,调试后删除
if str(r.text).find('是')!=-1:
print(1)
else:
print(0)
#如果返回的信息中带有“是”,则表示比对成功(向缓冲区输出1,方便被popen函数调用时捕获到运行结果),否则表示比对失败(向缓冲区输出0,方便被popen函数调用时捕获到运行结果)
3、主函数代码讲解
1,设计模式(工厂模式)
智能家居的整体代码架构,我用的是工厂模式设计,(工厂模式是java中的一种常用的设计模式之一,
我们在创建对象是不会对客户端暴露创建逻辑,并通过接口来指向新 的创建对象)
创建的对象比较多,具体用到的代码可参考树莓派中编译的个数
2主函数(main)
#include<stdio.h>
#include<string.h>
#include"contrlDevics.h"
#include"lnputCommand.h"
#include<pthread.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<wiringPi.h>
struct Devices* pdeviceHead1 = NULL;
struct Devices* pdeviceHead2 = NULL;
struct Devices* pdeviceHead3 = NULL;
struct Devices* pdeviceHead4 = NULL;
struct InputCommander* pCommandHead = NULL;
struct Devices* pdeviceHead = NULL;
struct InputCommander* socketHandler = NULL;
int c_fd;
struct InputCommander* pConmmandHead = NULL;
struct InputCommander* voiceHandler;
int shexian(void) //摄像头人脸识别函数。
{
int init = wiringPiSetup();
if (init == -1)
{
printf("init error\n");
}
char ch[1];
FILE* p;
pinMode(22, OUTPUT);
digitalWrite(22, HIGH);
char a;
for(int g=0;g<5;g++)
{
printf("Turning on face recognition...\n");
memset(ch, '0', 1);
printf("Please do not move while taking photos........\n");//正在拍照不要移动
system("raspistill -o file2.jpg"); //通过system函数,驱动摄像头拍照
printf("Photo taken successfully, comparing results, please wait....\n"); //正在拍照请等一下
p = popen("python shexian.py", "r"); //通过popen函数,运行py文件访问接口,获取 到人脸识别后程序的结果存入文件流p(1表示识别成功)
fread(ch, 1, 1, p); //读取到p文件流中的信息,存入字符数组ch
if (ch[0] == '1') //如果比对后的结果为1,则比对成功,开锁
{
printf("Identify success! The lock okokokokokokokokokokok++++++\n"); //拍照成功
digitalWrite(22, HIGH);
sleep(2);
digitalWrite(22, LOW);
break;
}
else {
printf("Error recognition! Illegal visitor nononononononononno\n");
sleep(2);
digitalWrite(22, HIGH);
}
}
}
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;
printf("%s*******\n", tmp->next->commandName);
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;
voiceHandler = findCommandByName("voice", pConmmandHead); //寻找语音设备
printf("%s555\n", voiceHandler->commandName);
if (voiceHandler == NULL) { //判断是否有数据读取
printf("find voiceHandler error haha\n");
pthread_exit(NULL);
}
else {
printf("1111111111111\n");
if (voiceHandler->Init(voiceHandler,NULL,NULL) == -1) { //串口初始化失败
printf("voice init error\n");
pthread_exit(NULL);
}
else {
printf("%s init success\n", voiceHandler->commandName); //串口初始化成功,并打印出语音模块获取到的数据
}
printf("22222\n");
while (1) {
nread = voiceHandler->getCommand(voiceHandler); //读取到的数据
if (nread == 0) {
printf("nodata form voice\n");
}
else {
printf("do divece contrl:%s", voiceHandler->command);
if (strcmp(voiceHandler->command,"0") ==0)
{
printf("peijiafeng\n");
shexian();
}
else if (strcmp(voiceHandler->command, "1") == 0)
{
printf("peijiafeng\n");
pdeviceHead2->deviceInit(pdeviceHead2->pinNum);
pdeviceHead2->open(pdeviceHead2->pinNum);
}
else if (strcmp(voiceHandler->command, "2") == 0)
{
printf("peijiafeng\n");
pdeviceHead3->deviceInit(pdeviceHead3->pinNum);
pdeviceHead3->open(pdeviceHead3->pinNum);
}
else if (strcmp(voiceHandler->command, "3") == 0)
{
printf("peijiafeng\n");
pdeviceHead4->deviceInit(pdeviceHead4->pinNum);
pdeviceHead4->open(pdeviceHead4->pinNum);
}
else if (strcmp(voiceHandler->command, "4") == 0)
{
printf("peijiafeng\n");
pdeviceHead1->open(pdeviceHead1->pinNum);
pdeviceHead1->deviceInit(pdeviceHead1->pinNum);
}
else if (strcmp(voiceHandler->command, "5") == 0)
{
printf("peijiafeng\n");
pdeviceHead2->open(pdeviceHead2->pinNum);
pdeviceHead2->deviceInit(pdeviceHead2->pinNum);
}
else if (strcmp(voiceHandler->command, "6") == 0)
{
printf("peijiafeng\n");
pdeviceHead3->open(pdeviceHead3->pinNum);
pdeviceHead3->deviceInit(pdeviceHead3->pinNum);
}
else if (strcmp(voiceHandler->command, "7") == 0)
{
printf("peijiafeng\n");
pdeviceHead4->open(pdeviceHead4->pinNum);
pdeviceHead4->deviceInit(pdeviceHead4->pinNum);
}
}
}
}
}
void * read_thread(void* datas) {
int n_read;
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);
}
else {
printf("client quit\n");
}
}
void* socket_thread(void* datas) {
int n_read = 0;
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 voiceHandler error\n");
pthread_exit(NULL);
}
socketHandler->Init(socketHandler, NULL, NULL);
while (1) {
c_fd = accept(socketHandler->sfd, (struct sockaddr*)&c_addr, &clen);
pthread_create(&readThrad, NULL, read_thread, NULL);
}
}
int main() {
char name[128];
struct Devices* tmp=NULL;
pthread_t voiceThread;
pthread_t socketThread;
//1.指令工厂初始话
if (-1 == wiringPiSetup()) {
return -1;
}
//2.设备控制工厂初始化
pdeviceHead1 = addBathroomLightToDeviceLink(pdeviceHead1); //通过头节点存储方便调用
pdeviceHead2 = addUpstairLightToDeviceLink(pdeviceHead2);
pdeviceHead3 = livingLightToDeviceLink(pdeviceHead3);
pdeviceHead4 = restaurantLightToDeviceLink(pdeviceHead4);
pConmmandHead = addvoiceContrlTolnputCommandLink(pConmmandHead);
pConmmandHead = addsocketTolnputCommandLink(pConmmandHead);
int a;
//3.线程池的建立
//3.1语音
while(1){
printf("**************** 1.语音控制 ******** ");
printf("**************** 2.摄像头人脸识别 **");
printf("yu ying\n");
pthread_create(&voiceThread, NULL, voice_thread, NULL); //调用语音线程
pthread_join(voiceThread, NULL);
printf("do divece contrl*****:%s", voiceHandler->command);
}
//3.2 SOCKET线程
//pthread_create(&socketThread, NULL, socket_thread, NULL);
while (1) {
printf("qing shu ru :\n");
scanf("%s", &name);
tmp = findDeviceByName(name, pdeviceHead);
if (tmp != NULL) {
tmp->deviceInit(tmp->pinNum);
tmp->open(tmp->pinNum);
}
}
return 0;
}
3 路灯对象代码
#include"contrlDevics.h"
int upstairLightOpen(int pinNum) { //电平拉低
digitalWrite(pinNum, LOW);
}
int upstairLightClose(int pinNum) { //电平拉高
digitalWrite(pinNum, HIGH);
}
int upstairLightCloseInit(int pinNum) { //串口初始化
pinMode(pinNum, OUTPUT);
digitalWrite(pinNum, HIGH);
}
int upstairLightCloseStatus(int status) {
}
struct Devices upstairLight = { //通过结构体函数将上面的实现函数,和初始化函数一并联立起来 用结构体来表示 路灯的结构体函数
.deviceName = "upstairLight",
.pinNum = 27,
.open = upstairLightOpen,
.close = upstairLightClose,
.deviceInit = upstairLightCloseInit,
.changeStatus = upstairLightCloseStatus
};
struct Devices* addUpstairLightToDeviceLink(struct Devices* phead) { //使用头插法将函数串联起来
if (phead == NULL) {
return &upstairLight;
}
else {
upstairLight.next = phead;
phead = &upstairLight;
}
}
4 语音控制对象代码
#include"lnputCommand.h"
#include<unistd.h>
#include<stdlib.h>
#include<wiringSerial.h>
int voiceGetCommand(struct InputCommander* voicer) { //语音串口的数据读取函数
int nread = 0;
nread = read(voicer->fd, voicer->command, sizeof(voicer->command)); //读取数据
if (nread == 0) { //判断是否有数据读入
printf("voice no datas\n");
}
else {
return nread;
}
}
int voicelnit(struct InputCommander* voicer1, char* ipAdress, char* port) { //声音相关初始话
int fd;
printf("3333\n");
if ((fd = serialOpen(voicer1->deviceName,9600)) == -1) //初始化串口,波特率9600
{
printf("4444\n");
printf("%d\n", fd);
exit(-1);
}
voicer1->fd = fd;
printf("%d\n", fd);
return fd; //失败的话是为-1
}
struct InputCommander voiceContrl = { ///语音串口函数结构初始化
.commandName = "voice", //语音名字
.deviceName = "/dev/ttyAMA0",//打开的串口
.command = {'\0'},
.Init = voicelnit,
.getCommand = voiceGetCommand,
.log = {'\0'},
.next = NULL
};
struct InputCommander* addvoiceContrlTolnputCommandLink(struct InputCommander* phead) {
if (phead == NULL) {
return &voiceContrl;
}
else {
voiceContrl.next = phead;
phead = &voiceContrl;//一定要注意这里加个return;不然程序可能段错误
}
}