CommunitySecurityProject

基于OpenCV的社区安防系统

作者
WildPointer
更新
2026-09-16
类型
自有项目
仓库
2 stars / 0 forks(抓取快照)
CommunitySecurityProject 项目演示
项目 README 演示动图

CommunitySecurityProject - By Wild_Pointer

CommunitySecurityProject是一套基于OpenCV的社区安防系统,旨在通过开源的方式,帮助更多人了解社区安防系统,帮助更多人了解社区安防系统的实现原理,帮助更多人了解社区安防系统的应用场景。

源码可自由下载使用,更多信息参考个人博客:

在使用CommunitySecurityProject进行二次开发(策略、模块等)的过程中有任何疑问,可通过QQ邮箱或者谷歌邮箱,也欢迎在分享你的使用心得或者使用中产生的bug,方便作者后续更新迭代!

CommunitySecurityProject介绍

社区安防系统(CommunitySecurityProject)是一个创新的、响应迅速的安全解决方案,专为社区环境量身定制。它利用OpenCV的前沿技术,如人脸识别,通过直观的接口与用户需求紧密结合。系统核心包括用户注册和人脸检测功能,旨在快速实现个性化安全应用的构建。

系统采用成熟的客户端/服务器架构,保障了应用的稳健运行和未来的扩展潜力。数据存储采用SqlLite数据库,确保数据的安全性和高效的数据管理。客户端之间的通信通过JSON格式进行,这种格式不仅简洁,而且提高了信息交换的效率。同时,系统利用TCP协议确保数据传输的可靠性和稳定性,为社区安防提供了坚实的技术支撑。

  1. 项目技术栈:

    • 数据库

      • 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文件导入以下模块:

text
sql
text
network

注意:源码中的Pro文件以及列举了Qt6所需的所有模块

代码示例

CommunitySecurityProject采用了统一的命名和注释格式,具体可参考以下代码:

C++
/*  打开摄像头操作*/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
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_H
CommunitySecurityServer/srcFile/detection.cpp
CommunitySecurityServer/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
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,&registerWidget::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
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
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
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();}
WildPointer

专注系统编程、工程实践与底层技术,记录 C++、Qt、OpenCV 与 VTK 的学习和实践。