基于图像的火灾检测
个人情况及相关技术
双非普通本科,2017届软件工程移动设备应用开发方向,毕设所用技术:Qt、SQLite、OpenCV、树莓派
毕业设计题目是自己选定的,导师负责审核,由于学校学习嵌入式软件开发的同学较少,所以审核很容易
本博客为分享备忘性质,旨在为需要的同学提供思路,不喜勿喷
开发环境
软件平台
- 开发平台:Ubuntu 18
- Qt版本:5.1.2
- SQLite3
硬件平台
- 树莓派3b
- LED
- 蜂鸣器
- USB摄像头
树莓派配置OpenCV教程可查看我另一篇博客:树莓派安装OpenCV
由于学校对毕设的要求并不高,因此火焰识别部分的代码是随手摘抄的代码,参考链接如下:OpenCV火焰识别
系统存在的问题
- 图像传输过程有失败现象,导致上位机无法正常显示
- 检测结果展示模块使用的是假数据,没有进行数据库读取操作
- 系统设置并未实现,仅界面
- 网络按钮未实现
系统架构
系统基本工作流程
系统运行效果
- 识别到火焰
- 未识别到火焰
代码实现
上位机代码
下位机代码
下位机详细代码如下:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <time.h>
#include <stdio.h>
#include <wiringPi.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
#include <pthread.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
using namespace std;
using namespace cv;
#define LED 1 //LED 引脚
#define BUZZER 29 //BUZZER 引脚
#define MAXSIZE 1024*1024 //图片最大尺寸
int sockfd; //全局变量
int count = 0; //LED、BUZZER报警次数
char pic_Name[128] = {}; //照片名称
bool ledSwitch = false; //LED开关
bool buzzerSwitch = false; //BUZZER开关
void *camera(void *arg) //采集图像并报存
{
VideoCapture cap;
cap.open(0);
if(!cap.isOpened())
{
cout << "The camera open failed!" << endl;
}
Mat frame;
time_t nowTime;
tm* now;
while(1)
{
//cout << "This is camera !!!" << endl;
cap >> frame;
if(frame.empty())
break;
time(&nowTime);
now = localtime(&nowTime);
sprintf(pic_Name,"photo/%d-%d-%d %d:%d:%d.jpg",now->tm_year + 1900, now->tm_mon + 1, now->tm_mday,
now->tm_hour+8, now->tm_min, now->tm_sec);
cout << "This timenow is:" << now->tm_year + 1900 << "-" << now->tm_mon + 1 << "-" << now->tm_mday
<< " " << now->tm_hour + 7 << ":" << now->tm_min << ":" << now->tm_sec << endl;
imwrite(pic_Name, frame);
//每30秒采集一次图像数据
if(waitKey(30000) >= 0)
break;
}
}
void *sendPicture(void *arg) //发送图像到上位机
{
int len;
char buffer[MAXSIZE];
struct sockaddr_in their_addr;
FILE *fq;
//cout << "This is sendPicture !!!" << endl;
while((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1);
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(8888);
their_addr.sin_addr.s_addr=inet_addr("172.20.10.4");
bzero(&(their_addr.sin_zero), 8);
while(connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)) == -1);
sleep(10); //延时十秒确保图像数据已采集完毕
while(1)
{
string fileName(pic_Name);
if((fq = fopen(fileName.c_str(),"rb") ) == NULL ){
printf("File open failed.\n");
close(sockfd);
exit(1);
}
string str = "fileName:" + fileName;
send(sockfd, str.c_str(), str.length(), 0);
sleep(1);
fseek(fq,0,SEEK_END);
int length = ftell(fq);
printf("The Picture's len is : %d\n", length);
string str_Len = "fileLen:" + to_string(length);
send(sockfd, str_Len.c_str(), str_Len.length(), 0);
fseek(fq,0,SEEK_SET);
while(!feof(fq)){
len = fread(buffer, 1, sizeof(buffer), fq);
if(len != write(sockfd, buffer, len)){
break;
}
}
sleep(30);
}
close(sockfd);
fclose(fq);
}
void *ledCtrol(void *arg) //控制LED
{
while(1)
{
//cout << "This is LED !!!" << endl;
if(ledSwitch)
{
for (int i = 0; i < 5; i++)
{
digitalWrite(LED,HIGH);
delay(1000);
digitalWrite(LED,LOW);
delay(1000);
}
ledSwitch = !ledSwitch;
}
sleep(1);
}
}
void *buzzerCtrol(void *arg) //控制蜂鸣器
{
while(1)
{
//cout << "This is Buzzer !!!" << endl;
if(buzzerSwitch)
{
for (int i = 0; i < 5; i++)
{
digitalWrite(BUZZER,HIGH);
delay(1000);
digitalWrite(BUZZER,LOW);
delay(1000);
}
buzzerSwitch = !buzzerSwitch;
}
sleep(1);
}
}
void parseData(String str)
{
//解析上位机控制命令
char strBuf[] = {0};
strcpy(strBuf, str.c_str());
if(strBuf[0] == 'L')
{
if(strBuf[1] == '1')
{
ledSwitch = true;
}else
{
ledSwitch = false;
}
}else if(strBuf[0] == 'B')
{
if(strBuf[1] == '1')
{
buzzerSwitch = true;
}else
{
buzzerSwitch = false;
}
}
}
void *recDevStatus(void *arg)
{
char buffer[128];
//定时接收硬件状态
int bufferLen = 0;
while(1)
{
memset(buffer, 0, sizeof(buffer));
//cout << "This is recDevStatus !!!" << endl;
bufferLen = recv(sockfd, buffer, sizeof(buffer), 0);
if(bufferLen != -1)
{
cout << buffer;
parseData(buffer);
}
//解析收到的数据
sleep(1);
}
}
int main()
{
if(wiringPiSetup() == -1)
{
printf("setup wiringPi failed!!!\n");
}
pinMode(LED, OUTPUT);
pinMode(BUZZER, OUTPUT);
signal(SIGPIPE,SIG_IGN);
pthread_t camera_t, led_t, buzzer_t, sendPicture_t, revDevStatus_t;
//线程1:定时采集图像数据
pthread_create(&camera_t, NULL, camera, NULL);
//线程2:LED灯控制
pthread_create(&led_t, NULL, ledCtrol, NULL);
//线程3:蜂鸣器控制
pthread_create(&buzzer_t, NULL, buzzerCtrol, NULL);
//线程4:定时发送图像
pthread_create(&sendPicture_t, NULL, sendPicture, NULL);
//线程5:接受上位机发送的硬件状态
//pthread_create(&revDevStatus_t, NULL, recDevStatus, NULL);
pthread_join(camera_t, NULL);
pthread_join(led_t, NULL);
pthread_join(buzzer_t, NULL);
pthread_join(sendPicture_t, NULL);
pthread_join(revDevStatus_t, NULL);
return 0;
}
下位机编译命令
g++ -o Fireldentify Fireldentify.cpp -lpthread `pkg-config --cflags --libs opencv` -lwiringPi