工程代码: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
#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; }