VLC+多线程+人脸识别+SQL(插入、更新、删除、select)

贴出来的代码是调不通的,只是为了自己记录需要
VLC和SQL以及人脸识别的环境配置就不写了,kernel部分就在这
因为项目的隐私性,所以人脸识别的内容保密
1. GeneralFun.h

#pragma once
#include <process.h>   
#include <windows.h>  
#include <vlc\vlc.h>
#include <vlc\libvlc.h>
#include "FaceRecognition.h"

#define VIDEO_WIDTH 960
#define VIDEO_HEIGHT 540

//初始化参数
const int THREAD_NUM = 2;
int house_number[THREAD_NUM] = { NULL };
char *windowname[THREAD_NUM] = { "Result0","Result1" };

//定义公有继承变量
DataBase database;
Recongnition face_recongnition;
LoadParaInsertDatabase paradata_insert_database;

//VLC结构
struct VlcData
{
    IplImage* image;
    HANDLE mutex;
    uchar* pixels;
    char buffer[40960000];
};

//多线程
unsigned int __stdcall Result(LPVOID  pM);

class GeneralFun
{
public:
    void LoadData();
private:
    void PlayVideo(int& i);
    static void *lock(void *data, void**p_pixels);
    static void display(void *data, void *id);
    static void unlock(void *data, void *id, void *const *p_pixels);
public:
    char* url[THREAD_NUM] = { NULL };
    libvlc_instance_t *     vlc_ins[THREAD_NUM] = { NULL };
    libvlc_media_player_t * vlc_player[THREAD_NUM] = { NULL };
    libvlc_media_t *        vlc_media[THREAD_NUM] = { NULL };
private:
    House_Info house_info;
    Person_Info person_info;
};

2. GeneralFun.cpp(算法多线程核心部分,vlc和人脸识别算法的多线程)
注意:在进行人脸识别的时候一定要加入互斥锁,锁的使用参见

https://www.cnblogs.com/fnlingnzb-learner/p/5829556.html

#include "GeneralFun.h"
#include "LoadParaInsertDatabase.h"

DataBase database;
Recongnition face_recongnition;
LoadParaInsertDatabase paradata_insert_database;

int house_number[THREAD_NUM] = {NULL};
char *windowname[THREAD_NUM] = { "Result0","Result1" };

//VLC参数定义
const char * vlc_args[] =
{
    "-I",
    "dummy",
    "--ignore-config",
};
struct VlcData* contexts[THREAD_NUM];

void* GeneralFun::lock(void *data, void**p_pixels)
{
    struct VlcData *VlcData = (struct VlcData*)data;
    WaitForSingleObject(VlcData->mutex, INFINITE); // 等待当前线程执行完毕
    memset(VlcData->buffer, 0, sizeof(*(VlcData->buffer)));
    *p_pixels = VlcData->buffer;
    return NULL;
}
void GeneralFun::display(void *data, void *id) {
    struct VlcData *VlcData = (struct VlcData*)data;
    WaitForSingleObject(VlcData->mutex, INFINITE); // 等待当前线程执行完毕
    VlcData->image->imageData = VlcData->buffer;
    assert(id == NULL);
}
void GeneralFun::unlock(void *data, void *id, void *const *p_pixels) {
    struct VlcData *VlcData = (struct VlcData*)data;
    ReleaseMutex(VlcData->mutex); // 释放由线程拥有的一个互斥体的控制权
}

void GeneralFun::PlayVideo(int& i)
{
    contexts[i] = (struct VlcData*)malloc(sizeof(*contexts[i]));
    contexts[i]->mutex = CreateMutex(NULL, FALSE, NULL);
    contexts[i]->image = cvCreateImage(cvSize(VIDEO_WIDTH, VIDEO_HEIGHT), IPL_DEPTH_8U, 4);
    contexts[i]->pixels = (unsigned char *)contexts[i]->image->imageData;
    //cvReleaseImage(&img);
    //step1:创建一个VLC实例
    vlc_ins[i] = libvlc_new(sizeof(vlc_args) / sizeof(vlc_args[0]), vlc_args);
    if (vlc_ins[i] == NULL)
        system("pause");
    vlc_player[i] = libvlc_media_player_new(vlc_ins[i]);
    if (vlc_player[i] == NULL)
        system("pause");
    //step2:通过文件路径或网络地址创建一个媒体实例
    if (url[i][1] == ':')
        vlc_media[i] = libvlc_media_new_path(vlc_ins[i], url[i]);
    else
        vlc_media[i] = libvlc_media_new_location(vlc_ins[i], url[i]);
    if (vlc_media[i] == NULL)
        system("pause");
    //step3:
    vlc_player[i] = libvlc_media_player_new_from_media(vlc_media[i]);
    libvlc_media_release(vlc_media[i]);
    //step4:视频解码回调函数
    libvlc_video_set_format(vlc_player[i], "RGBA", VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_WIDTH * 4);
    libvlc_video_set_callbacks(vlc_player[i], lock, unlock, display, contexts[i]);
    //step4:实时播放
    libvlc_media_player_set_hwnd(vlc_player[i],::GetDesktopWindow());   
    //step5:播放
    libvlc_media_player_play(vlc_player[i]);
}

void GeneralFun::LoadData()
{
    face_recongnition.LoadModel();//加载人脸识别model
    paradata_insert_database.LoadPara(house_info, person_info, true);//加载数据库参数
    face_recongnition.TrainModel(person_info, database, false);//训练人脸model
    for (int i = 0; i < THREAD_NUM; i++)
    {
        char* rtsp = new char[128]; strcpy(rtsp, house_info.rtsp[i].c_str());
        url[i] = rtsp;
        house_number[i] = house_info.houseNumber[i];
        PlayVideo(i);
    }
}

unsigned int __stdcall GeneralFun::Result(LPVOID  pM)
{
    int FaceNumber = 0;
    int index = *(int*)(pM);

    while (true)
    {
        try{
            clock_t starttime, endtime;
            starttime = clock();
            IplImage *src = cvCreateImage(cvSize(VIDEO_WIDTH, VIDEO_HEIGHT), IPL_DEPTH_8U, 3);
            cvCvtColor(contexts[index]->image, src, CV_RGB2BGR);
            cv::Mat frame(src);
            if (frame.empty())
                continue;
            cv::Rect rect;
            dlib::matrix<float, 0, 1 > face_descriptor_test;

            WaitForSingleObject(hMutex_GPU, INFINITE);
            face_recongnition.DetectionAlignmentFeature(frame, face_descriptor_test, rect, 0);//特征提取
            if (rect.width*rect.height != 0)
            {
                face_recongnition.Recongnize(frame, database, face_descriptor_test, house_number[index], paradata_insert_database, rect);
            }           
            cv::imshow(windowname[index], frame);
            cv::waitKey(50); //wait时间如果设计不合理会出现错误
            ReleaseMutex(hMutex_GPU);//互斥锁(防止GPU出现内存泄漏)

            cvReleaseImage(&src);
        }
        catch (std::exception& e)
        {
            WriteRunLog("错了");
            std::cout << e.what() << endl;
        }
    }
    return 0;
}

3.LoadParaInsertDatabase.h(SQL的使用)

#pragma once

#include <windows.h>
#include <mysql.h> 
#include "winsock.h" 
#include <iostream>
#include <vector>
#include<string>
using namespace std;

#pragma comment(lib, "libmysql.lib")
struct House_Info
{
    std::vector<string> rtsp;
    std::vector<int> houseNumber;
};
struct Person_Info
{
    std::vector<string> name;
    std::vector<string> imgPath;
    std::vector<int> houseNumber;
};
class LoadParaInsertDatabase
{
private:
    int UDP_Port;
    char rootpath[256];
    char *host; 
    char *user; 
    char *passwd;//你的mysql服务器密码 247密码12306. 本地密码123456
    char *db; 
    unsigned int port; //server port 
    MYSQL *sock;
    char szSqlText[500];
    BOOL Flag;

public:
    House_Info house_info;
    Person_Info person_info;
    Person_Info person_info_test;

public:
    LoadParaInsertDatabase(void);
    ~LoadParaInsertDatabase(void);
    void LoadPara(House_Info& house_info, Person_Info& person_info, bool UseVideo);
    int SelectSQLPersonInfo(Person_Info& person_info);//获取所有住户的信息
    int SelectSQLPersonInfoTest(Person_Info& person_info_test);//获取测试住户信息(单张图片)
    int SelectSQLHouseInfo(House_Info& house_info);//获取房屋信息
    int InsertDatabaseFace(int houseNumber, char* name, char* result, char* RecordTime, char* FaceImgPath);//插入
    int DeleteSQLPersonInfo(char *userName);//删除
    int UpdataSQLPersonInfo(char *userName);//更新
private:
    int ModifyDatabase(char* host,char* user, char* passwd, char* db, unsigned int port);
    int IsConnectToDatabase(void);
};

4.LoadParaInsertDatabase.cpp
注意:在使用select的时候,一定要使用do{}while();语句来mysql_free_result(result);要不然会出现数据库索引错误!

#include "LoadParaInsertDatabase.h"
void LoadParaInsertDatabase::LoadPara(House_Info& house_info, Person_Info& person_info, bool UseVideo)
{
    LPCWSTR strPath(TEXT("./Setting.ini"));
    LPCWSTR strTitle(TEXT("Parameter"));
    LPCWSTR strKey;

    const int BUFF_LEN = 128;//读取字符串的缓存
    TCHAR buff[BUFF_LEN];
    int iLength = 0;
    char buffer[BUFF_LEN];

    strKey = TEXT("Database_host");//数据库IP
    GetPrivateProfileString(strTitle, strKey, L"127.0.0.1", buff, BUFF_LEN, strPath);
    iLength = WideCharToMultiByte(CP_ACP, 0, buff, -1, NULL, 0, NULL, NULL);
    host = new char[iLength];
    WideCharToMultiByte(CP_ACP, 0, buff, -1, host, iLength, NULL, NULL);

    strKey = TEXT("Database_user");//数据库用户名
    GetPrivateProfileString(strTitle, strKey, L"root", buff, BUFF_LEN, strPath);
    iLength = WideCharToMultiByte(CP_ACP, 0, buff, -1, NULL, 0, NULL, NULL);
    user = new char[iLength];
    WideCharToMultiByte(CP_ACP, 0, buff, -1, user, iLength, NULL, NULL);

    strKey = TEXT("Database_passwd");//数据库密码
    GetPrivateProfileString(strTitle, strKey, L"123456", buff, BUFF_LEN, strPath);
    iLength = WideCharToMultiByte(CP_ACP, 0, buff, -1, NULL, 0, NULL, NULL);
    passwd = new char[iLength];
    WideCharToMultiByte(CP_ACP, 0, buff, -1, passwd, iLength, NULL, NULL);

    strKey = TEXT("Database_db");//数据库名称
    GetPrivateProfileString(strTitle, strKey, L"TV_HSGCC", buff, BUFF_LEN, strPath);
    iLength = WideCharToMultiByte(CP_ACP, 0, buff, -1, NULL, 0, NULL, NULL);
    db = new char[iLength];
    WideCharToMultiByte(CP_ACP, 0, buff, -1, db, iLength, NULL, NULL);

    strKey = TEXT("Database_port"); //数据库端口号
    port = GetPrivateProfileInt(strTitle, strKey, 3306, strPath);

    strKey = L"UDP_Port";
    UDP_Port = GetPrivateProfileInt(strTitle, strKey, 8888, strPath);

    strKey = TEXT("FilePath");//图片结果存储路径
    GetPrivateProfileString(strTitle, strKey, L"", buff, BUFF_LEN, strPath);
    iLength = WideCharToMultiByte(CP_ACP, 0, buff, -1, NULL, 0, NULL, NULL);
    WideCharToMultiByte(CP_ACP, 0, buff, -1, rootpath, iLength, NULL, NULL);

    ModifyDatabase(host, user, passwd, db, port);//mysql
    if (!Flag)
        IsConnectToDatabase();
    if (UseVideo)
    {
        SelectSQLPersonInfo(person_info);//获取所有住户的信息
        SelectSQLHouseInfo(house_info);
    }
    else
        SelectSQLPersonInfoTest(person_info);
}

int LoadParaInsertDatabase::InsertDatabaseFace(int houseNumber, char* name, char* result, char* RecordTime, char* FaceImgPath)
{
    sprintf_s(szSqlText, "insert into facerecord (houseNumber, name, result, recordTime, facePath) values('%d','%s','%s', '%s','%s')",
        houseNumber,name, result, RecordTime, FaceImgPath); //向表中插入数据 注意时间格式
    if (!Flag)
    {
        IsConnectToDatabase();
    }
    if (mysql_query(sock, szSqlText))
    {
        std::cout << "Can't insert data! " << mysql_error(sock) << std::endl;
        return FALSE;
    }
    else
    {
        std::cout << RecordTime << "Insert data to person table Success! " << std::endl;
        return TRUE;
    }
}
//更新
int LoadParaInsertDatabase::UpdataSQLPersonInfo(char *userName) {
    MYSQL myCont;
    MYSQL_RES *result;
    MYSQL_ROW sql_row;
    int res;
    mysql_init(&myCont);
    if (!Flag)
    {
        IsConnectToDatabase();
    }
    sprintf(szSqlText, "update user set UserPass='%s',ConnectionNum=%d,UseFor=%d where UserName='%s'", body.userPass, body.connection, body.type, body.userName);
    if (mysql_query(sock, szSqlText))
    {
        std::cout << "Can't insert data! " << mysql_error(sock) << std::endl;
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}
//删除
int LoadParaInsertDatabase::DeleteSQLPersonInfo(char *userName) {
    MYSQL myCont;
    MYSQL_RES *result;
    MYSQL_ROW sql_row;
    int res;
    mysql_init(&myCont);
    if (!Flag)
    {
        IsConnectToDatabase();
    }
    sprintf(szSqlText, "delete from user where UserName='%s'", userName);//这个未使用,想用的话需要修改
    if (mysql_query(sock, szSqlText))
    {
        std::cout << "Can't insert data! " << mysql_error(sock) << std::endl;
        return FALSE;
    }
    else
    {
        return TRUE;
    }
}
//select房屋信息
int LoadParaInsertDatabase::SelectSQLHouseInfo(House_Info& house_info)
{
    MYSQL myCont;
    MYSQL_RES *result;
    MYSQL_ROW sql_row;
    int res;
    mysql_init(&myCont);
    if (mysql_real_connect(&myCont, host, user, passwd, db, port, NULL, 0))
    {
        mysql_query(&myCont, "SET NAMES GBK"); //设置编码格式
        res = mysql_query(&myCont, "select houseNumber, rtsp from householdinfo");
        if (!res)
        {
            do {
                result = mysql_store_result(&myCont);
                if (result)
                {
                    while (sql_row = mysql_fetch_row(result))
                    {
                        for (int i = 0; i < mysql_num_fields(result); i++)
                        {
                            house_info.houseNumber.push_back(atoi(sql_row[i])); 
                            i++;
                            house_info.rtsp.push_back(sql_row[i]); 
                        }
                    }
                    mysql_free_result(result);
                }
            } while (!mysql_next_result(&myCont));
        }
        else
        {
            cout << "query sql failed!" << endl;
        }
    }
    return 1;
}
//select住户信息
int LoadParaInsertDatabase::SelectSQLPersonInfo(Person_Info& person_info)
{
    MYSQL myCont;
    MYSQL_RES *result;
    MYSQL_ROW sql_row;
    int res;
    mysql_init(&myCont);
    if (mysql_real_connect(&myCont, host, user, passwd, db, port, NULL, 0))
    {
        mysql_query(&myCont, "SET NAMES GBK"); //设置编码格式
        res = mysql_query(&myCont, "select houseNumber, name, imgPath from personinfo");//查询select camera_id,rtsp_high,rtsp_low from camera WHERE camera_type = 2
        if (!res)
        {
            do{
                result = mysql_store_result(&myCont);
                if (result)
                {
                    while (sql_row = mysql_fetch_row(result))
                    {
                        for (int i = 0; i < mysql_num_fields(result); i++)
                        {
                            person_info.houseNumber.push_back(atoi(sql_row[i])); 
                            i++;
                            person_info.name.push_back(sql_row[i]);
                            i++;
                            person_info.imgPath.push_back(sql_row[i]);
                        }
                    }
                    mysql_free_result(result);
                }
            } while (!mysql_next_result(&myCont));
        }
        else
        {
            cout << "query sql failed!" << endl;
        }
    }
    return 1;
}
//查找测试图片
int LoadParaInsertDatabase::SelectSQLPersonInfoTest(Person_Info& person_info_test)
{
    MYSQL myCont;
    MYSQL_RES *result;
    MYSQL_ROW sql_row;
    int res;
    mysql_init(&myCont);
    if (mysql_real_connect(&myCont, host, user, passwd, db, port, NULL, 0))
    {
        mysql_query(&myCont, "SET NAMES GBK"); //设置编码格式
        res = mysql_query(&myCont, "select houseNumber, imgPath from facerecord");
        if (!res)
        {
            do{
                result = mysql_store_result(&myCont);
                if (result)
                {
                    while (sql_row = mysql_fetch_row(result))//获取具体的数据
                    {
                        for (int i = 0; i < mysql_num_fields(result); i++)
                        {
                            person_info_test.houseNumber.push_back(atoi(sql_row[i]));
                            i++;
                            person_info_test.imgPath.push_back(sql_row[i]);
                        }
                    }
                    mysql_free_result(result);
                }
            } while (!mysql_next_result(&myCont));
        }
        else
        {
            cout << "query sql failed!" << endl;
        }
    }
    return 1;
}



LoadParaInsertDatabase::LoadParaInsertDatabase(void)
{
    this->host = "192.168.0.247";//sever
    this->user = "admin";
    this->passwd = "123456.";
    this->db = "tv_hsgcc";
    this->port = 3306; //server port 
    sock = mysql_init(0);
    Flag = 0;
}

LoadParaInsertDatabase::~LoadParaInsertDatabase(void)
{
    if (!Flag)
    {
        IsConnectToDatabase();//
    }
}

int LoadParaInsertDatabase::ModifyDatabase(char* host, char* user, char* passwd, char* db, unsigned int port)
{
    if (host != NULL)
    {
        this->host = host;
    }
    if (user != NULL)
    {
        this->user = user;
    }
    if (passwd != NULL)
    {
        this->passwd = passwd;
    }
    if (db != NULL)
    {
        this->db = db;
    }
    if (port != NULL)
    {
        this->port = port;
    }
    return 1;
}

int LoadParaInsertDatabase::IsConnectToDatabase(void)
{
    if (this->sock && mysql_real_connect(this->sock, this->host, this->user, this->passwd, this->db, this->port, NULL, 0))
    {
        mysql_query(sock, "SET NAMES GBK"); //设置编码格式,支持中文
        Flag = 1;
        return TRUE;
    }
    else//连接数据库出错 
    {
        std::cout << "cannot connect to the sock sever: " << mysql_error(sock) << std::endl;
        mysql_close(sock);//加上清除2017-9-27
        Flag = 0;
        return FALSE;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值