opencv+qt通过CGI读取网络摄像头

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

效果图


你可能感兴趣的:(qt,opencv,二次开发,网络监控摄像机)