工程代码:http://download.csdn.net/download/mjlsuccess/9461745
网络监控摄像头比普通摄像头的优势在于它有云台,可以调整角度。这两天老板让我买个网络摄像头看看效果如何,那么这就涉及到监控摄像头的二次开发问题,淘宝上买的大多支持二次开发。我买的这款使用的是CGI指令,简单点说是HTTP协议。查看手册发现它传输的图像数据流是jpeg类型的,在使用OpenCV读取图片时,我们一般使用imread,但是imread只能从硬盘度数据,而我们现在需要的是能够在内存中读数据的的函数,这时就要使用imdecode函数(OpenCV就是方便)。关于界面和HTTP通信使用Qt来搞定。
贴出代码:
#ifndef HTTP_TEST_H
#define HTTP_TEST_H
#include <QtWidgets/QMainWindow>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrl>
#include <QFile>
#include <QTextStream>
#include <opencv.hpp>
#include "ui_http_test.h"
using namespace cv;
class Http_test : public QMainWindow
{
Q_OBJECT
public:
Http_test(QWidget *parent = 0);
~Http_test();
public slots:
void httpReadyRead();
void startRequst();
void stopRequst();
void httpFinished();
private:
Ui::Http_testClass ui;
QNetworkAccessManager qnam;
QNetworkReply * reply;
QUrl url;
private:
int size;
bool flag;
Mat showImage;
Mat bufImage;
int count;
};
#endif // HTTP_TEST_H
http_test.cpp
#include <QByteArray>
#include <QPushButton>
#include <QMessageBox>
#include <QNetworkRequest>
#include "http_test.h"
Http_test::Http_test(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(ui.startHttp, &QPushButton::clicked, this, &Http_test::startRequst);
connect(ui.stopHttp, &QPushButton::clicked, this, &Http_test::stopRequst);
ui.startHttp->setEnabled(true);
ui.stopHttp->setEnabled(false);
size = 0;
flag = 1;
count = 0;
}
Http_test::~Http_test()
{
httpFinished();
}
/*
网络摄像头通过HTTP协议发送数据,而http是基于TCP协议的可以使用抓包软件Wireshark查看
发送的数据格式为 header + jpegstream (数据以byte为单位计数)
header为59个字节格式如下:
--This String Content-type:image/jpeg Content-Length:35716
header的最后5位 ,35716 表示接下来要传输数据的字节数
上面的header含义就是,接下来的一张jpeg图片有35716个字节
*/
void Http_test::httpReadyRead()
{
QByteArray jpegStream = reply->readAll();
QByteArray str = "Length:";
int header_cnt=0, stream_cnt = 0;
int index;
//header_cnt->表示已经解析了多少数据头, stream_cnt->表示已经解析了多少个bytes
while((59*header_cnt + stream_cnt) < jpegStream.size())
{
if(flag)
{
index = jpegStream.indexOf(str, 59*header_cnt + stream_cnt);
if(index != -1)
{
size = (jpegStream.mid(index+7, 5)).toInt();
bufImage.create(1, size, CV_8UC1);
ui.textEdit->setText(QString("%1").arg(size));
flag = 0;
header_cnt++;
}
}
else
{
for (int k=59*header_cnt + stream_cnt; k<jpegStream.size(); k++)
{
bufImage.at<uchar>(0, count) = jpegStream.at(k);
count++;
stream_cnt++;
if(count == size)
{
showImage = imdecode(bufImage, CV_LOAD_IMAGE_ANYCOLOR);
imshow("jpegWin", showImage);
flag = 1;
size = 0;
count = 0;
break;
}
}
}
}
}
void Http_test::startRequst()
{
QString str = "http://192.168.0.50:88/cgi-bin/CGIStream.cgi?cmd=GetMJStream&usr=poss&pwd=poss";
str+= ui.lineEdit->text();
url = str;
reply = qnam.get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &Http_test::httpFinished);
connect(reply, &QNetworkReply::readyRead, this, &Http_test::httpReadyRead);
ui.startHttp->setEnabled(false);
ui.stopHttp->setEnabled(true);
}
void Http_test::stopRequst()
{
reply->abort();
ui.startHttp->setEnabled(true);
ui.stopHttp->setEnabled(false);
}
void Http_test::httpFinished()
{
reply->deleteLater();
reply = 0;
}
效果图