CommunitySecurityProject
基于OpenCV的社区安防系统

CommunitySecurityProject - By Wild_Pointer

CommunitySecurityProject是一套基于OpenCV的社区安防系统,旨在通过开源的方式,帮助更多人了解社区安防系统,帮助更多人了解社区安防系统的实现原理,帮助更多人了解社区安防系统的应用场景。
源码可自由下载使用,更多信息参考个人博客:
在使用CommunitySecurityProject进行二次开发(策略、模块等)的过程中有任何疑问,可通过QQ邮箱或者谷歌邮箱,也欢迎在分享你的使用心得或者使用中产生的bug,方便作者后续更新迭代!
CommunitySecurityProject介绍
社区安防系统(CommunitySecurityProject)是一个创新的、响应迅速的安全解决方案,专为社区环境量身定制。它利用OpenCV的前沿技术,如人脸识别,通过直观的接口与用户需求紧密结合。系统核心包括用户注册和人脸检测功能,旨在快速实现个性化安全应用的构建。
系统采用成熟的客户端/服务器架构,保障了应用的稳健运行和未来的扩展潜力。数据存储采用SqlLite数据库,确保数据的安全性和高效的数据管理。客户端之间的通信通过JSON格式进行,这种格式不仅简洁,而且提高了信息交换的效率。同时,系统利用TCP协议确保数据传输的可靠性和稳定性,为社区安防提供了坚实的技术支撑。
项目技术栈:
数据库
- SqlLite
技术栈
C++11
Qt5
多线程
TCP协议
OpenCV
JSON格式
- 模块设计概述:
- 数据传输:
- 通过QTcpSocket使用TCP协议对客户端与服务端之间的数据进行传输,并且使用JSON格式对传递的数据进行格式化操作。
- 线程模块:
- 针对CommunitySecurityProject项目,作者采用QThread模块,在服务端定义了多线程模块。更快的处理人脸数据的捕获以及检测功能
- 检测模块:
- 作者使用了OpenCV自带的特征分类器对摄像头捕获的对象进行检测,检测人脸的物体上传至服务器识别
- 网络模块:
- 通过定义定时器对象,为客户端定义了心跳包,防止网络等原因导致与服务端失去连接
- 识别模块:
- 通过调用开源识别模型SeetaFace,加载级联分类器后,对客户端上传的图片进行识别
环境准备
- 推荐使用Qt5.14版本进行部署
- 支持的数据库版本:SqlLite
- 支持的系统版本:Ubuntu
- 支持的C++版本:C++ 11/64位(推荐使用C++ 11)
Qt模块准备
下载源码后,需要在Pro文件导入以下模块:
sqlnetwork注意:源码中的Pro文件以及列举了Qt6所需的所有模块
代码示例
CommunitySecurityProject采用了统一的命名和注释格式,具体可参考以下代码:
/* 打开摄像头操作*/void registerWidget::on_open_But_clicked(){ if(ui->open_But->text() == "打开摄像头"){ //捕获摄像头图片 if(capture_Obj.open("/dev/video0")){ ui->open_But->setText("关闭摄像头"); timer_ID = startTimer(100); //启动定时器 } }else{ killTimer(timer_ID); //关闭定时器 capture_Obj.release(); //关闭摄像头 ui->open_But->setText("打开摄像头"); }}其中函数命名使用驼峰法,并且注释中带有函数参数以及默认返回值int,方便后续对异常的捕获进行诊断
运行示例

作者留言
个人博客:wild-pointer.top
通过QQ邮箱联系我:3020922258@qq.com
通过谷歌邮箱联系我:wildpointer794@gmail.com
语言组成
- C++
- 89.3%
- QMake
- 10.7%
文件结构
查看完整文件清单(34 个文件)
CommunitySecurityClient/ClassifierFile/haarcascade_frontalface_alt2.xml CommunitySecurityClient/CommunitySecurityClient.pro CommunitySecurityClient/Icons.qrc CommunitySecurityClient/Icons/crc.png CommunitySecurityClient/Icons/yes.png CommunitySecurityClient/communitysecurityclient.cpp CommunitySecurityClient/communitysecurityclient.h CommunitySecurityClient/communitysecurityclient.ui CommunitySecurityClient/main.cpp CommunitySecurityServer/CommunitySecurityServer.pro CommunitySecurityServer/communitysecurityserver.cpp CommunitySecurityServer/communitysecurityserver.h CommunitySecurityServer/communitysecurityserver.ui CommunitySecurityServer/main.cpp CommunitySecurityServer/model/fd_2_00.dat CommunitySecurityServer/model/fr_2_10.dat CommunitySecurityServer/model/pd_2_00_pts5.dat CommunitySecurityServer/model/pd_2_00_pts81.dat CommunitySecurityServer/seletewidget.cpp CommunitySecurityServer/seletewidget.h CommunitySecurityServer/seletewidget.ui CommunitySecurityServer/srcFile/detection.cpp CommunitySecurityServer/srcFile/detection.h CommunitySecurityServer/srcFile/sql.cpp CommunitySecurityServer/srcFile/sql.h CommunitySecurityServer/uiFile/registerwidget.cpp CommunitySecurityServer/uiFile/registerwidget.h CommunitySecurityServer/uiFile/registerwidget.ui CommunitySecurityServer/uiFile/seletewidget.cpp CommunitySecurityServer/uiFile/seletewidget.h CommunitySecurityServer/uiFile/seletewidget.ui README.md README_IMG/1.gif README_IMG/logo.png
关键源码
CommunitySecurityServer/srcFile/detection.h
#ifndef DETECTION_H#define DETECTION_H#include <QObject>#include <opencv.hpp>#include <seeta/FaceEngine.h>//检测模块class Detection : public QObject{ Q_OBJECTpublic: explicit Detection(QObject *parent = nullptr); ~Detection();public slots: //用户注册 int64_t handle_UserRegister(cv::Mat& imgdata); //查询用户信息 void handle_SeleteUserData(cv::Mat& imgdata);signals: //返回检测到的人脸ID void return_QueryFaceId(int64_t id);signals:private: seeta::FaceEngine* faceEngine_Obj;};#endif // DETECTION_HCommunitySecurityServer/srcFile/detection.cpp
#include "detection.h"#include <QDebug>Detection::Detection(QObject *parent) : QObject(parent){ seeta::ModelSetting fd_Model("../CommunitySecurityServer/model/fd_2_00.dat",seeta::ModelSetting::CPU,0); seeta::ModelSetting fr_Model("../CommunitySecurityServer/model/fr_2_10.dat",seeta::ModelSetting::CPU,0); seeta::ModelSetting pd_Model("../CommunitySecurityServer/model/pd_2_00_pts5.dat",seeta::ModelSetting::CPU,0); faceEngine_Obj = new seeta::FaceEngine(fd_Model,pd_Model,fr_Model); faceEngine_Obj->Load("./facedata.db");}Detection::~Detection(){ delete faceEngine_Obj;}/* 用户注册 * imgdata:注册的图像数据 * 返回值:int64_t(用户ID)*/int64_t Detection::handle_UserRegister(cv::Mat &imgdata){ //将Mat数据转换为SeeraFace数据 SeetaImageData faceImg; faceImg.data = imgdata.data; faceImg.width = imgdata.cols; faceImg.height = imgdata.rows; faceImg.channels = imgdata.channels(); int64_t id = faceEngine_Obj->Register(faceImg); if(id >= 0){ faceEngine_Obj->Save("./facedata.db"); } return id;}/* 查询用户信息 * imgdata:图像数据 * 返回值:int(用户ID)*/void Detection::handle_SeleteUserData(cv::Mat& imgdata){ //将Mat数据转换为SeeraFace数据 SeetaImageData faceImg; faceImg.data = imgdata.data; faceImg.width = imgdata.cols; faceImg.height = imgdata.rows; faceImg.channels = imgdata.channels(); float similarity = 0; int64_t faceId = faceEngine_Obj->Query(faceImg,&similarity); if(similarity > 0.7){ //查询到对应的用户信息 emit return_QueryFaceId(faceId); }else{ //未查询到信息 emit return_QueryFaceId(-1); }}CommunitySecurityServer/communitysecurityserver.cpp
#include "communitysecurityserver.h"#include "ui_communitysecurityserver.h"CommunitySecurityServer::CommunitySecurityServer(QWidget *parent) : QMainWindow(parent) , ui(new Ui::CommunitySecurityServer){ ui->setupUi(this); data_Size = 0; register_Obj = nullptr; sqlTable_Obj.setTable("UserInfo"); //绑定表格 handle_InitThread(); //初始化线程 handle_InitTcpServer(); //初始化TcpServer}CommunitySecurityServer::~CommunitySecurityServer(){ delete ui;}////--------------------------------------------------线程操作模块--------------------------------------------------------/* 初始化线程*/void CommunitySecurityServer::handle_InitThread(){ QThread* thread_Obj = new QThread(); //将检测操作放到线程中处理 faceDetection_Obj.moveToThread(thread_Obj); thread_Obj->start(); //启动线程 connect(this,&CommunitySecurityServer::request_QueryInfo,&faceDetection_Obj,&Detection::handle_SeleteUserData); connect(&faceDetection_Obj,&Detection::return_QueryFaceId,this,&CommunitySecurityServer::handle_QueryFaceInfo);}////--------------------------------------------------识别操作模块--------------------------------------------------------/* 请求数据库查询制定的个人信息 * faceId:人脸ID*/void CommunitySecurityServer::handle_QueryFaceInfo(int64_t faceId){ QString str = ""; if(faceId < 0){ str = QString("{\"employeeID\":,\"name\":,\"department\":,\"time\":}"); client_Obj->write(str.toUtf8()); return; } //设置过滤器 sqlTable_Obj.setFilter(QString("faceID=%1").arg(faceId)); //查询数据 sqlTable_Obj.select(); if(sqlTable_Obj.rowCount() == 1){ //查询到数据 QSqlRecord record = sqlTable_Obj.record(0); str = QString("{\"ID\":\"%1\",\"name\":\"%2\",\"department\":\"软件\",\"time\":\"%3\"}") .arg(record.value("ID").toString()).arg(record.value("name").toString()) .arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh::mm::ss")); QString sqlCode = QString("INSERT INTO AttendanceInfo (employeeID) VALUES ('%1');") .arg(record.value("ID").toString()); if(sql_Obj.handle_InsertAttendanceInfo(sqlCode)){ //插入考勤信息 client_Obj->write(str.toUtf8()); //发送数据至客户端 } }}/* 识别人脸 * data:接收到的数据 * 返回值:int(用户ID)*/void CommunitySecurityServer::handle_IdentifyFace(QByteArray data){ cv::Mat readImg; //接收到的图像数据 std::vector<uchar> decode; decode.resize(data.size()); memcpy(decode.data(),data.data(),data.size()); //格式转换 readImg = cv::imdecode(decode,cv::IMREAD_COLOR); emit request_QueryInfo(readImg);}////--------------------------------------------------TCP操作模块--------------------------------------------------------/* 初始化TcpServer*/void CommunitySecurityServer::handle_InitTcpServer(){ //新的客户端连接操作 connect(&server_Obj,&QTcpServer::newConnection,this,&CommunitySecurityServer::handle_NewClientConnect); server_Obj.listen(QHostAddress::Any,13020);}/* 新的客户端连接申请*/void CommunitySecurityServer::handle_NewClientConnect(){ //获取当前新的客户端连接套接字 client_Obj = server_Obj.nextPendingConnection(); //客户端发送数据操作 connect(client_Obj,&QTcpSocket::readyRead,this,&CommunitySecurityServer::handle_ClientSendingData);}/* 处理客户端发送的数据*/void CommunitySecurityServer::handle_ClientSendingData(){ QDataStream stream(client_Obj); //绑定套接字到数据流中 stream.setVersion(QDataStream::Qt_5_14); if(data_Size == 0){ //读取数据大小 if(client_Obj->bytesAvailable() < (qint64)sizeof(data_Size)){ //读取的字节数小于8字节 return; } stream >> data_Size; }else{ if(client_Obj->bytesAvailable() < data_Size){ //图片数据未发送 return; } //读取到图片数据 QByteArray buffer; stream >> buffer; data_Size = 0; if(buffer.size() == 0){ //读取数据失败 return; } handle_ShowReceiveImg(buffer); //显示接收到的图片 handle_IdentifyFace(buffer); //识别人脸 }}/* 显示接收到的图片 * data:接收到的数据*/void CommunitySecurityServer::handle_ShowReceiveImg(const QByteArray &data){ QPixmap pixmap; pixmap.loadFromData(data,"jpg"); pixmap = pixmap.scaled(ui->show_Img->size()); //设置图像大小 ui->show_Img->setPixmap(pixmap);}////--------------------------------------------------界面操作模块--------------------------------------------------------/* 注册用户操作*/void CommunitySecurityServer::on_pushButton_clicked(){ if(register_Obj != nullptr){ delete register_Obj; register_Obj = nullptr; } register_Obj = new registerWidget(nullptr); register_Obj->show(); connect(register_Obj,®isterWidget::request_SqlSaveUserInfo,&sql_Obj,&sql::handle_AddUserInfo);}/* 查询数据操作*/void CommunitySecurityServer::on_pushButton_2_clicked(){ if(selete_Obj != nullptr){ delete selete_Obj; selete_Obj = nullptr; } selete_Obj = new seleteWidget(nullptr); selete_Obj->show();}CommunitySecurityServer/srcFile/sql.cpp
#include "sql.h"#include <QDebug>sql::sql(QObject *parent) : QObject(parent){ handle_InitSqlDataBase(); //初始化数据库 handle_CreateUserInfoTable();//创建员工信息表 handle_CreateAttendanceInfoTable(); //创建考勤表}sql::~sql(){}/* 初始化数据库*/void sql::handle_InitSqlDataBase(){ QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("server.db"); if(!db.open()){ //数据库打开失败 qDebug() << db.lastError().text(); return; }}/* 创建员工信息表*/void sql::handle_CreateUserInfoTable(){ QString sqlCode = "create table if not exists UserInfo(" " ID integer primary key autoincrement," " name varchar(256)," " sex varchar(32)," " birthday text," " address text," " phone text," " faceID integer unique," " headfile text);"; QSqlQuery query; if(!query.exec(sqlCode)){ QMessageBox::warning(nullptr, "警告", query.lastError().text(), QMessageBox::Ok); return; }}/* 创建考勤信息表*/void sql::handle_CreateAttendanceInfoTable(){ QString sqlCode = "create table if not exists AttendanceInfo(" " attendaceID integer primary key autoincrement," " employeeID integer," " attendaceTime TimeStamp NOT NULL DEFAULT CURRENT_TIMESTAMP);"; QSqlQuery query; if(!query.exec(sqlCode)){ QMessageBox::warning(nullptr, "警告", query.lastError().text(), QMessageBox::Ok); return; }}/* 插入考勤信息 * sqlCode:执行的Sql语句*/bool sql::handle_InsertAttendanceInfo(QString sqlCode){ QSqlQuery query; if(!query.exec(sqlCode)){ QString str = QString("考勤信息插入失败:%1").arg(query.lastError().text()); QMessageBox::warning(nullptr, "警告", str, QMessageBox::Ok); return false; }else{ return true; }}/* 添加用户信息 * sqlCode:执行的Sql语句*/void sql::handle_AddUserInfo(QString sqlCode){ QSqlQuery query; if(!query.exec(sqlCode)){ QString str = QString("添加信息失败:%1").arg(query.lastError().text()); QMessageBox::warning(nullptr, "警告", str, QMessageBox::Ok); return; }else{ QMessageBox::information(nullptr,"提示","添加用户信息成功!!!",QMessageBox::Ok); }}CommunitySecurityClient/communitysecurityclient.cpp
#include "communitysecurityclient.h"#include "ui_communitysecurityclient.h"#include <QDebug>CommunitySecurityClient::CommunitySecurityClient(QWidget *parent) : QMainWindow(parent) , ui(new Ui::CommunitySecurityClient){ ui->setupUi(this); faceFlag_Obj = 0; handle_InitCamera();//初始化摄像头 handle_InitClassifier();//初始化级联分类器对象 handle_InitTcpConnect();//初始化TCP链接槽函数 handle_InitHeartBea(); //初始化心跳包}CommunitySecurityClient::~CommunitySecurityClient(){ delete ui;}////--------------------------------------------------摄像头操作模块--------------------------------------------------------/* 初始化摄像头*/void CommunitySecurityClient::handle_InitCamera(){ Capture_Obj.open("/dev/video0"); startTimer(100); //启动定时器}////--------------------------------------------------级联分类器操作模块-----------------------------------------------------/* 人脸检测 * image:识别的图像数据*/void CommunitySecurityClient::handle_FaceDetection(Mat& image){ Mat grayImage; cvtColor(image,grayImage,COLOR_BGR2GRAY); //转化为灰度图提高效率 //检测人脸位置 std::vector<Rect> faceRect; classifier_Obj.detectMultiScale(grayImage,faceRect); if((faceRect.size() > 0) && (faceFlag_Obj >= 0)){ //读取到人脸数据 Rect rect = faceRect.at(0); rectangle(image,rect,Scalar(0,0,255)); handle_MatConvertInJpg(image); } if(faceRect.size() == 0){ faceFlag_Obj = 0; }}/* 将Mat类型数据转化为Jpg存储 * image:转化的Mat数据*/void CommunitySecurityClient::handle_MatConvertInJpg(const Mat &image){ if(faceFlag_Obj > 2){ vector<uchar> buffer; imencode(".jpg",image,buffer); //格式转换 //发送检测数据至服务器 handle_SendingDatainServer(QByteArray::fromRawData(reinterpret_cast<const char*>(buffer.data()), buffer.size())); } faceFlag_Obj++;}/* 初始化级联分类器对象*/void CommunitySecurityClient::handle_InitClassifier(){ classifier_Obj.load("../CommunitySecurityClient/ClassifierFile/haarcascade_frontalface_alt2.xml");}////--------------------------------------------------定时器操作模块---------------------------------------------------------/* 定时器事件 * event:事件*/void CommunitySecurityClient::timerEvent(QTimerEvent *event){ Q_UNUSED(event); Mat imageData; //捕获的图像数据 if(Capture_Obj.grab()){ Capture_Obj.read(imageData); } if(imageData.data == nullptr){ //未捕获到图像 return; } handle_FaceDetection(imageData);//人脸检测 cvtColor(imageData,imageData,COLOR_BGR2RGB); //将捕获的图像格式转化 QImage showImage(imageData.data,imageData.cols,imageData.rows,imageData.step1(),QImage::Format_RGB888); QPixmap pixmap = QPixmap::fromImage(showImage); ui->show_Img->setPixmap(pixmap);}////--------------------------------------------------心跳包操作模块---------------------------------------------------------/* 初始化心跳包*/void CommunitySecurityClient::handle_InitHeartBea(){ heartbea_Obj.start(4000); //启动定时器 //定时发起连接 connect(&heartbea_Obj,&QTimer::timeout,this,&CommunitySecurityClient::handle_TcpConnect);}/* 发起TCP连接*/void CommunitySecurityClient::handle_TcpConnect(){ tcpSocket_Obj.connectToHost("127.0.0.1",13020); //连接服务器}/* 暂停心跳包*/void CommunitySecurityClient::handle_StopHeartBea(){ qDebug() << "链接服务器成功"; heartbea_Obj.stop(); //暂停定时器}/* 启动心跳包*/void CommunitySecurityClient::handle_StateHeartBea(){ qDebug() << "服务器断开"; heartbea_Obj.start(4000); //启动定时器}////--------------------------------------------------TCP操作模块---------------------------------------------------------/* 初始化TCP链接槽函数*/void CommunitySecurityClient::handle_InitTcpConnect(){ //TCP连接成功操作 connect(&tcpSocket_Obj,&QTcpSocket::connected,this,&CommunitySecurityClient::handle_StopHeartBea); //TCP连接断开操作 connect(&tcpSocket_Obj,&QTcpSocket::disconnected,this,&CommunitySecurityClient::handle_StateHeartBea); //接送服务器数据操作 connect(&tcpSocket_Obj,&QTcpSocket::readyRead,this,&CommunitySecurityClient::handle_ReadyDatainServer);}/* 处理服务器发送的数据*/void CommunitySecurityClient::handle_ReadyDatainServer(){ QString str = tcpSocket_Obj.readAll(); QJsonDocument jsonDoc = QJsonDocument::fromJson(str.toUtf8()); QJsonObject jsonObj = jsonDoc.object(); //从JSON文档中获取JSON对象 ui->numbe_Show->setText(jsonObj.value("ID").toString()); ui->name_Show->setText(jsonObj.value("name").toString()); ui->date_Show->setText(jsonObj.value("time").toString());}/* 发送数据至服务器 * data:发送的数据*/void CommunitySecurityClient::handle_SendingDatainServer(QByteArray data){ quint64 dataSize = data.size(); QByteArray sendingData; QDataStream stream(&sendingData,QIODevice::WriteOnly); stream.setVersion(QDataStream::Qt_5_14); //设置数据流的版本 stream << dataSize << data; tcpSocket_Obj.write(sendingData); faceFlag_Obj = -2;}CommunitySecurityServer/main.cpp
#include "communitysecurityserver.h"#include <opencv.hpp>#include <QApplication>int main(int argc, char *argv[]){ QApplication a(argc, argv); //注册自定义类型 qRegisterMetaType<cv::Mat>("cv::Mat"); qRegisterMetaType<cv::Mat>("cv::Mat&"); qRegisterMetaType<int64_t>("int64_t"); CommunitySecurityServer w; w.show(); return a.exec();}