看下效果图:
开发环境:QT5+BOOST+win7+vs2012+opencv2.8
服务器端:
只有使用到了QT(使用qtcreator)
客户端(采集webcam视频通过tcp发送到服务器端)
客户端的tcp用的是boost的,在VS2012里编写(ps.在qtcreator里怎么使用boost啊,boost是用vc11编译的)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
客户端:
采集webcam视频后用hog特征检测,如果图像中有人就发送到服务器端,同时控制台输出:send image finished ,如果没有,就不发送了。控制台输出:no image to send。
采集视频和HOG初始化
HOGDescriptor hog;
hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector()); /* 直接调用opencv里的HOG特征检测 */
VideoCapture cap(0); /* open webcam */
if(!cap.isOpened())
{
return -1;
}
Mat frame; //采集到的视频存在这个mat里
cap.set(CV_CAP_PROP_FRAME_WIDTH, 320); /* set width */
cap.set(CV_CAP_PROP_FRAME_HEIGHT, 240); /* set height */
设置连接服务器端的ip和端口
boost::asio::io_service io_service;
tcp::endpoint end_point(boost::asio::ip::address::from_string("127.0.0.1"), 3200);
tcp::socket socket(io_service);
socket.connect(end_point);
boost::system::error_code ignored_error;
hog检测和发送:
while (true)
{
vector<Rect> found, found_filtered;
size_t i, j;
cap>>frame;
hog.detectMultiScale(frame, found, 0, Size(4,4), Size(0,0), 1.05, 2);
imshow("client",frame);
char c=(char)waitKey(100);
if (c==27)
{
break;
}
if (found.size()>=1) {
frame = (frame.reshape(0,1)); // to make it continuous
std::string message((char *)frame.data,230400); /* the size of mat data is 320*240*3 */
socket.write_some(boost::asio::buffer(message), ignored_error);
cout<<"send image finished"<<endl;
}
else
{
cout<<"no image to send "<<endl;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
服务器端
qtcreator创建基于对话框的程序
MyTcpServer类用来与客户端通信
MyTcpServer::MyTcpServer(QObject *parent) :
QObject(parent)
{
server = new QTcpServer(this);//返回一个通信的socket
connect(server, SIGNAL(newConnection()),
this, SLOT(newConnection()));
if(!server->listen(QHostAddress::Any, 3200))
{
qDebug() << "Server could not start";
}
else
{
qDebug() << "Server started!";
}
}
监听新的连接
void MyTcpServer::newConnection()
{
socket = server->nextPendingConnection();
connect(socket, SIGNAL(readyRead()),
this, SLOT(readSlot()));
}
读取客户端发来的数据
void MyTcpServer::readSlot() { qint64 blockSize = 230400; //320*240*3 if (socket->bytesAvailable() < blockSize)//直到读到230400byte数据 { return; } QByteArray b1=socket->read(230400); std::vector<uchar> vectordata(b1.begin(),b1.end()); cv::Mat data_mat(vectordata,true); img= data_mat.reshape(3,240); /* reshape to 3 channel and 240 rows */ emit readyRead(); //重新运行readSlot }
对话框界面设置定时器更新客户端传来的图像:
timer = new QTimer(this);
timer->start(10); //1000为1秒,10毫秒去取一帧
connect(timer,SIGNAL(timeout()),this,SLOT(getFrame())); //超时就去取
void Dialog::getFrame(){
QImage image= QImage((uchar*) server->img.data, server->img.cols, server->img.rows, server->img.step, QImage::Format_RGB888).rgbSwapped();
ui->label->setPixmap(QPixmap::fromImage(image));
}
在github的代码:
https://github.com/wzyuliyang/streammat