贴出来的代码是调不通的,只是为了自己记录需要
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和人脸识别算法的多线程)
注意:在进行人脸识别的时候一定要加入互斥锁,锁的使用参见
#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;
}
}