千寻的第二篇博客
自己写的博客,自己都搜不到,忧桑。
话不多说,记录供大家分享。
2.行人检测程序
功能:打开电脑摄像头,判断行人的移动方向并向服务器发送数据,控制小车移动。
扩展:当行人停止时,检测手势信息,进行识别控制。
原理:opencv中自带了行人检测模型,通过检测行人在图像中的位置信息变化,记作行人的移动方向。通过socket网络向服务器发送控制指令。
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/objdetect/objdetect.hpp>
#include<iostream>
#include <winsock2.h>
#include <process.h>
#define _PORT_NUM_ 6666
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
using namespace std;
using namespace cv;
unsigned _stdcall ThreadProc( void * lpvoid); //线程函数,要不太卡了
//图意省事,设为全局变量,若怕不安全,可以进行封装
SOCKET sock;
int Compare=0;
vector<Rect> found;
VideoCapture capture(0);
Mat frame;
int High;
int bjHigh=0;
int buf[4]={0};
int main()
{
VideoCapture capture(0);
if(!capture.isOpened())
{
cout<<"摄像头打开失败!"<<endl;
return -1;
}
char key;
char filename[200];
int count = 0;
//创建线程
HANDLE m_hThread = (HANDLE)_beginthreadex(NULL,0,&ThreadProc,0,0,0);
while(1)
{
capture>>frame; //实时捕捉摄像头图片
}
}
unsigned _stdcall ThreadProc( void * lpvoid)
{
//创建Socket网络
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return 1;
}
else
printf("The Winsock 2.2 dll was found okay\n");
sock =socket(AF_INET ,SOCK_STREAM ,IPPROTO_TCP);
if(sock==INVALID_SOCKET )
{
WSACleanup();
return 1;
}
sockaddr_in TCPServer;
TCPServer.sin_addr.S_un.S_addr=inet_addr("123.206.24.164");/*换成服务器的IP*/
TCPServer.sin_family=AF_INET;
TCPServer.sin_port=htons(6666);
if(connect(sock,(const sockaddr*)&TCPServer,sizeof(TCPServer)) ==SOCKET_ERROR)
{
WSACleanup();
closesocket(sock);
cout<<"连接服务器失败,请检查网络代码"<<endl;
waitKey(0);
return 1;
}
while(1)
{
if (frame.empty())
continue;
HOGDescriptor defaultHog; //opencv中自带的行人检测模型
defaultHog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
//默认模型,这个模型数据在OpenCV源码中是一堆常量数字,
//这些数字是通过原作者提供的行人样本INRIAPerson.tar训练得到的
defaultHog.detectMultiScale(frame, found);
// 画出长方形,框出人
for (int i = 0; i < found.size(); i++)
{
Rect r = found[i];
rectangle(frame, r.tl(), r.br(), Scalar(0, 0, 255), 3);
}
//判断函数,通过图像大小,人物移动来控制小车移动
if(found.size())
{
Rect r = found[0]; //图片位置信息数据保存在found数组中
//判断图片大小
High=r.br().y-r.tl().y; //根据高度的变化判断前后移动
if(bjHigh==0)
{
bjHigh=High;
}
if(Compare==0) //根据宽度的变化判断左右
{
Compare=r.tl().x;
}
if(r.tl().x-Compare>20||Compare-r.tl().x>20) //变化范围较大的,默认检测误差,不做处理
continue;
else
{
if(Compare<r.tl().x-10)
{
//小车往右走
cout<<"人物像右走"<<endl;
buf[3]=1;
if(send(sock,(char*)buf,sizeof(buf),0)==SOCKET_ERROR)
{
WSACleanup();
closesocket(sock);
cout<<"发送数据失败,请检查发送端代码"<<endl;
waitKey(0);
return 1;
}
buf[3]=0;
}
if(Compare>r.tl().x+10)
{
//小车往左走
cout<<"人物像左走"<<endl;
buf[2]=1;
if(send(sock,(char*)buf,sizeof(buf),0)==SOCKET_ERROR)
{
WSACleanup();
closesocket(sock);
cout<<"发送数据失败,请检查发送端代码"<<endl;
waitKey(0);
return 1;
}
buf[2]=0;
}
if(High-bjHigh>20||bjHigh-High>20)
{
if(High>bjHigh+5)
{
cout<<"人物像后移动"<<endl;
buf[1]=1;
if(send(sock,(char*)buf,sizeof(buf),0)==SOCKET_ERROR)
{
WSACleanup();
closesocket(sock);
cout<<"发送数据失败,请检查发送端代码"<<endl;
waitKey(0);
return 1;
}
buf[1]=0;
}
else if(High<bjHigh-5)
{
cout<<"人物像前移动"<<endl;
buf[0]=1;
if(send(sock,(char*)buf,sizeof(buf),0)==SOCKET_ERROR)
{
WSACleanup();
closesocket(sock);
cout<<"发送数据失败,请检查发送端代码"<<endl;
waitKey(0);
return 1;
}
buf[0]=0;
}
else
{
cout<<"人物保持不变"<<endl;
//可以在此处添加手势识别代码
/*
Demo
手势识别与行人检测上
*/
}
bjHigh=High;
}
}
Compare=r.tl().x;
}
namedWindow("Detect pedestrain", WINDOW_AUTOSIZE);
imshow("Detect pedestrain", frame);
waitKey(10);
}
return 0;
}