目录

一、原始需求

二、环境安装

2.1 qt安装

2.2 opencv安装

三、系统设计

3.1、 整体流程设计

3.2 、数据传输交互流程

3.3 、数据库设计

四、关键代码

4.1、如何实现通信(TCP)

4.1.1 服务端

4.1.2 客户端

4.2、如何实现视频读取(V4L2)

4.3、如何实现图像处理(opencv)

4.4 登录验证

五、实现效果

5.1、服务端GUI

5.2、客户端GUI

六、参考文献


一、原始需求

Linux下基于qt的视频监控系统

  • 服务端: 用v4l2实现视频采集、视频传输,用tcp实现服务器端与客户端通信
  • 客户端:用qt实现

功能:

1、注册登录

2、暂停

3、截图

4、保存视频

5、视频上显示时间

6、可以对视频进行边缘检测、锐化、阈值分割

7、同时监控两个及以上个摄像头

二、环境安装

本人开发环境ubuntu 16.04 qt5.6.3 opencv3.4

2.1 qt安装

Index of /new_archive/qt/5.6/5.6.3

下载linux版本

修改可执行权限,Terminal中运行

一路傻瓜式安装即可

2.2 opencv安装

安装cmake

sudo apt-get install cmake

安装依赖环境

sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev
sudo apt-get install libgtk2.0-dev
sudo apt-get install pkg-config
 

下载opencv3.4版本

下载地址:Releases - OpenCV,点击Sources进行下载自己需要的版

下载完后解压文件,进入,当前位置打开Terminal

mkdir build
cd build
sudo cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local ..
sudo make -j4
sudo make install

到此所有依赖环境安装完毕

三、系统设计

3.1、 整体流程设计

3.2 、数据传输交互流程

3.3 、数据库设计

一张用户表记录注册信息即可

四、关键代码

4.1、如何实现通信(TCP)

4.1.1 服务端

在头文件里面定义一个server指针变量,一个socket指针变量

  QTcpServer *tcpserver;QTcpSocket *tcpsocket;

实例化server,监听的对象设成Any,端口号设置一个固定值,客户端与服务端端口号一致才能通信成功

  tcpserver = new QTcpServer(this);tcpserver->listen(QHostAddress::Any, 48797);

监听到有新连接接入时,连接到信号槽来处理连接的客户端

  connect(tcpserver, SIGNAL(newConnection()), this,SLOT(slotTcpNewConnection()));
void MainWindow::slotTcpNewConnection() {qDebug("NEW CONNECTION");tcpsocket = tcpserver->nextPendingConnection(); //获取监听到的socket/*获取对方IP和端口*/QString ip = tcpsocket->peerAddress().toString();quint16 port = tcpsocket->peerPort();QString str = QString("[%1:%2]成功连接").arg(ip).arg(port);ui->textBrowser->append(str); /*显示编辑区*///连接成功后我们再连接一个信号槽到准备接收信号槽函数中去connect(tcpsocket, SIGNAL(readyRead()), this, SLOT(slotTcpReadyRead()));//已连接套接字的断开信号与自身的稍后删除信号相连接connect(tcpsocket, SIGNAL(disconnected()), this, SLOT(slotDisconnect()));
}
 

当收客户端发来的信息后,开启读取摄像头数据线程

void MainWindow::slotTcpReadyRead() {QByteArray recvbuf = tcpsocket->readAll();qDebug("recv:");qDebug(recvbuf);vapi.start();
}

V4l2Api为线程,启动线程后,会发送sendImage信号,关联slotSendImage

V4l2Api vapi;
connect(&vapi, &V4l2Api::sendImage, this, &MainWindow::slotSendImage);
void MainWindow::slotSendImage(QImage image) {qDebug("send image:");QImage tempimage = image;tempimage =tempimage.scaled(800, 480, Qt::KeepAspectRatio, Qt::FastTransformation).scaled(400, 240, Qt::KeepAspectRatio, Qt::SmoothTransformation);QPixmap pixmap =QPixmap::fromImage(tempimage); //把img转成位图,我们要转成jpg格式QByteArray ba;QBuffer buf(&ba); //把ba绑定到buf上,操作buf就等于操作bapixmap.save(&buf, "jpg", 50); //把pixmap保存成jpg,压缩质量50 数据保存到buf//先写大小过去,告诉主机我们要传输的数据有多大tcpsocket->write(QString("size=%1").arg(ba.size()).toLocal8Bit().data());tcpsocket->waitForReadyRead(); //等待主机响应“ok”tcpsocket->write(ba);          //把图像数据写入传输给主机tcpsocket->waitForReadyRead();
}
 

4.1.2 客户端

接收消息封装成线程,重写run

void RecvThread::run() {isRunning = true;QTcpSocket tcpsocket;connect(&tcpsocket, SIGNAL(disconnected()), this, SIGNAL(disconnectSlot()));tcpsocket.connectToHost(ip, port);if (!tcpsocket.waitForConnected(3000)) {qDebug() << "连接失败:" << tcpsocket.errorString();emit disconnectSlot();return;} else {qDebug() << "连接成功!";}//发送HTTP请求tcpsocket.write("\r\n\r\n");if (tcpsocket.waitForBytesWritten(3000)) {qDebug() << "发送Http Request成功!";} else {qDebug() << "发送Http Request失败!";return;}cv::VideoWriter videowriter;  //录屏int recvtimes=0;  //接收次数QByteArray jpgArr; //存储图片int totalsize;     //总大小while (isRunning) {if (tcpsocket.waitForReadyRead()) {QByteArray buf = tcpsocket.readAll();qDebug() << "recv buf: " << buf << "\n";if (buf.contains("size=")) {buf = buf.replace("size=", "");totalsize = buf.toInt();jpgArr.clear();tcpsocket.write("ok");           //发送一个响应给客户机tcpsocket.waitForBytesWritten(); //等待数据写入} else {//如果不是图片大小数据,就是图片数据,图片数据追加写到数组里面jpgArr.append(buf);}if (jpgArr.length() == totalsize) {QImage img_qt;img_qt.loadFromData(jpgArr, "JPG");cv::Mat src_img_cv;   //源数据src_img_cv = Util::QImage2cvMat(img_qt);  //QImage转mat...其他图像处理img_qt = Util::cvMat2QImage(src_img_cv);  //mat转QImageemit transmitData(img_qt);jpgArr.clear();tcpsocket.write("ok");}}
}
 

4.2、如何实现视频读取(V4L2)

把v4l2封装在线程里,支持yuyv、jpeg格式转rgb算法

v4l2api.h

#ifndef V4L2API_H
#define V4L2API_H
#include <QImage>
#include <QObject>
#include <QThread>
#include <exception>
#include <fcntl.h>
#include <iostream>
#include <linux/videodev2.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <vector>
using namespace std;const int WIDTH = 640;
const int HEIGHT = 480;//异常类
class VideoException : public exception {
public:VideoException(string err) : errStr(err) {}~VideoException() {}const char *what() const noexcept { return errStr.c_str(); }private:string errStr;
};struct VideoFrame {char *start; //保存内核空间映射到用户空间的空间首地址int length;  //空间长度
};// v4l2封装成线程
class V4l2Api : public QThread {Q_OBJECT
public:V4l2Api(const char *dname = "/dev/video0", int count = 4);~V4l2Api();/*** @brief open 打开摄像头*/void open();/*** @brief close 关闭摄像头*/void close();/*** @brief grapImage* @param imageBuffer* @param length*/void grapImage(char *imageBuffer, int *length);/*** @brief yuyv_to_rgb888 yuyv转rgb算法* @param yuyvdata* @param rgbdata* @param picw* @param pich* @return*/bool yuyv_to_rgb888(unsigned char *yuyvdata, unsigned char *rgbdata,int picw = WIDTH, int pich = HEIGHT);/*** @brief jpeg_to_rgb888   jpeg转rgb算法* @param jpegData* @param size* @param rgbdata*/void jpeg_to_rgb888(unsigned char *jpegData, int size,unsigned char *rgbdata);inline void setRunning(bool running);/*** @brief run定义run函数*/void run();private:/*** @brief video_init*/void video_init();/*** @brief video_mmap*/void video_mmap();private:string deviceName; //摄像头名称int vfd;           //保存文件描述符int count;         //缓冲区个数vector<struct VideoFrame> framebuffers;volatile bool isRunning; //是否运行signals:/*** @brief sendImage  发送图片*/void sendImage(QImage);
};
void V4l2Api::setRunning(bool running) { this->isRunning = running; }#endif // V4

v4l2api.cpp

#include "v4l2api.h"
#include <QDebug>
#include <QImage>
#include <jpeglib.h>
V4l2Api::V4l2Api(const char *dname, int count): deviceName(dname), count(count) {this->open();
}V4l2Api::~V4l2Api() { this->close(); }void V4l2Api::open() {video_init();video_mmap();
#if 1//开始采集enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;int ret = ioctl(this->vfd, VIDIOC_STREAMON, &type);if (ret < 0) {perror("start fail");}
#endif
}void V4l2Api::close() {enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;int ret = ioctl(this->vfd, VIDIOC_STREAMOFF, &type);if (ret < 0) {perror("stop fail");}//释放映射for (int i = 0; i < this->framebuffers.size(); i++) {munmap(framebuffers.at(i).start, framebuffers.at(i).length);}
}void V4l2Api::grapImage(char *imageBuffer, int *length) {// select (rfds, wfds, efds, time)struct v4l2_buffer readbuf;readbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;readbuf.memory = V4L2_MEMORY_MMAP;// perror("read");if (ioctl(this->vfd, VIDIOC_DQBUF, &readbuf) < 0) //取一针数据{perror("read image fail");}printf("%ld\n", readbuf.length);*length = readbuf.length;memcpy(imageBuffer, framebuffers[readbuf.index].start,framebuffers[readbuf.index].length);//把用完的队列空间放回队列中重复使用if (ioctl(vfd, VIDIOC_QBUF, &readbuf) < 0) {perror("destroy fail");exit(1);}
}void V4l2Api::video_init() {// 1.打开设备this->vfd = ::open(deviceName.c_str(), O_RDWR);if (this->vfd < 0) {perror("open fail");VideoException vexp("open fail"); //创建异常对象//抛异常throw vexp;}// 2.配置采集属性struct v4l2_format vfmt;vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; //vfmt.fmt.pix.width = WIDTH;vfmt.fmt.pix.height = HEIGHT;vfmt.fmt.pix.pixelformat =V4L2_PIX_FMT_JPEG; //(设置视频输出格式,但是要摄像头支持4:2:2)//通过ioctl把属性写入设备int ret = ioctl(this->vfd, VIDIOC_S_FMT, &vfmt);if (ret < 0) {perror("set fail");//        VideoException vexp("set fail");//创建异常对象//        throw vexp;}//通过ioctl从设备获取属性memset(&vfmt, 0, sizeof(vfmt));vfmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;ret = ioctl(this->vfd, VIDIOC_G_FMT, &vfmt);if (ret < 0) {perror("get fail");//        VideoException vexp("get fail");//创建异常对象//        throw vexp;}if (vfmt.fmt.pix.width == WIDTH && vfmt.fmt.pix.height == HEIGHT &&vfmt.fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG) {} else {//        VideoException vexp("set error 2");//创建异常对象//        throw vexp;}
}void V4l2Api::video_mmap() {// 1申请缓冲区队列struct v4l2_requestbuffers reqbuffer;reqbuffer.count = this->count; //申请缓冲区队列长度reqbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;reqbuffer.memory = V4L2_MEMORY_MMAP;int ret = ioctl(this->vfd, VIDIOC_REQBUFS, &reqbuffer);if (ret < 0) {perror("req buffer fail");//        VideoException vexp("req buffer fail");//创建异常对象//        throw vexp;}// 2.映射for (int i = 0; i < this->count; i++) {struct VideoFrame frame;struct v4l2_buffer mapbuffer;mapbuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;mapbuffer.index = i;mapbuffer.memory = V4L2_MEMORY_MMAP;//从队列中拿到内核空间ret = ioctl(this->vfd, VIDIOC_QUERYBUF, &mapbuffer);if (ret < 0) {perror("query fail");}//映射frame.length = mapbuffer.length;frame.start = (char *)mmap(NULL, mapbuffer.length, PROT_READ | PROT_WRITE,MAP_SHARED, this->vfd, mapbuffer.m.offset);//空间放回队列中(内核空间)ret = ioctl(this->vfd, VIDIOC_QBUF, &mapbuffer);//把frame添加到容器framebuffersframebuffers.push_back(frame);}
}bool V4l2Api::yuyv_to_rgb888(unsigned char *yuyvdata, unsigned char *rgbdata,int picw, int pich) {int i, j;unsigned char y1, y2, u, v;int r1, g1, b1, r2, g2, b2;//确保所转的数据或要保存的地址有效if (yuyvdata == NULL || rgbdata == NULL) {return false;}int tmpw = picw / 2;for (i = 0; i < pich; i++) {for (j = 0; j < tmpw; j++) // 640/2  == 320{// yuv422// R = 1.164*(Y-16) + 1.159*(V-128);// G = 1.164*(Y-16) - 0.380*(U-128)+ 0.813*(V-128);// B = 1.164*(Y-16) + 2.018*(U-128));//下面的四个像素为:[Y0 U0 V0] [Y1 U1 V1] -------------[Y2 U2 V2] [Y3 U3// V3]//存放的码流为:    Y0 U0 Y1 V1------------------------Y2 U2 Y3 V3//映射出像素点为:  [Y0 U0 V1] [Y1 U0 V1]--------------[Y2 U2 V3] [Y3 U2// V3]//获取每个像素yuyv数据   YuYvy1 = *(yuyvdata + (i * tmpw + j) * 4);    // yuv像素的Yu = *(yuyvdata + (i * tmpw + j) * 4 + 1); // yuv像素的Uy2 = *(yuyvdata + (i * tmpw + j) * 4 + 2);v = *(yuyvdata + (i * tmpw + j) * 4 + 3);//把yuyv数据转换为rgb数据r1 = y1 + 1.042 * (v - 128);g1 = y1 - 0.34414 * (u - 128);b1 = y1 + 1.772 * (u - 128);r2 = y2 + 1.042 * (v - 128);g2 = y2 - 0.34414 * (u - 128);b2 = y2 + 1.772 * (u - 128);if (r1 > 255)r1 = 255;else if (r1 < 0)r1 = 0;if (g1 > 255)g1 = 255;else if (g1 < 0)g1 = 0;if (b1 > 255)b1 = 255;else if (b1 < 0)b1 = 0;if (r2 > 255)r2 = 255;else if (r2 < 0)r2 = 0;if (g2 > 255)g2 = 255;else if (g2 < 0)g2 = 0;if (b2 > 255)b2 = 255;else if (b2 < 0)b2 = 0;//把rgb值保存于rgb空间 数据为反向rgbdata[((pich - 1 - i) * tmpw + j) * 6] = (unsigned char)b1;rgbdata[((pich - 1 - i) * tmpw + j) * 6 + 1] = (unsigned char)g1;rgbdata[((pich - 1 - i) * tmpw + j) * 6 + 2] = (unsigned char)r1;rgbdata[((pich - 1 - i) * tmpw + j) * 6 + 3] = (unsigned char)b2;rgbdata[((pich - 1 - i) * tmpw + j) * 6 + 4] = (unsigned char)g2;rgbdata[((pich - 1 - i) * tmpw + j) * 6 + 5] = (unsigned char)r2;}}return true;
}void V4l2Api::jpeg_to_rgb888(unsigned char *jpegData, int size,unsigned char *rgbdata) {//解码jpeg图片// 1.定义解码对象struct jpeg_decompress_struct 错误处理对象struct// jpeg_error_mgr;struct jpeg_decompress_struct cinfo;struct jpeg_error_mgr err;// 2.初始化错误jpeg_std_error(err),创建初始化解码对象jpeg_create_decompress();cinfo.err = jpeg_std_error(&err);jpeg_create_decompress(&cinfo);// 3.加载源数据jpeg_mem_src()jpeg_mem_src(&cinfo, jpegData, size);// 4.获取jpeg图片头数据jpeg_read_header(&cinfo, true);// 5.开始解码jpeg_start_decompress(&cinfo);// 6.分配存储一行像素所需要的空间//---RGB数据// 640--cinfo.output_width, 480--cinfo.output_heightchar *rowFrame = (char *)malloc(cinfo.output_width * 3);int pos = 0;// 7.一行一行循环读取(一次读取一行,要全部读完)while (cinfo.output_scanline < cinfo.output_height) {//读取一行数据--解码一行jpeg_read_scanlines(&cinfo, (JSAMPARRAY)&rowFrame, 1);//把rgb像素显示在lcd上 mmpmemcpy(rgbdata + pos, rowFrame, cinfo.output_width * 3);pos += cinfo.output_width * 3;}free(rowFrame);// 8.解码完成jpeg_finish_decompress(&cinfo);// 9.销毁解码对象jpeg_destroy_decompress(&cinfo);
}void V4l2Api::run() {isRunning = true;char buffer[WIDTH*HEIGHT*3];char rgbbuffer[WIDTH*HEIGHT*3];int times = 0;int len;while(isRunning){grapImage(buffer, &len);//yuyv_to_rgb888((unsigned char *)buffer, (unsigned char *)rgbbuffer);jpeg_to_rgb888((unsigned char *)buffer, len, (unsigned char *)rgbbuffer);//把RGB数据转为QImageQImage image((uchar*)rgbbuffer, WIDTH, HEIGHT, QImage::Format_RGB888);emit sendImage(image);qDebug()<<"(("<<times++<<"))";msleep(200);}
/*//模拟视频,用于测试int times = 0;while (isRunning) {qDebug("send image:");static int count = 1;QString path = tr("/home/shenjun/Pictures/speaker/img/%1.png").arg(count);qDebug() << path;QImage image(path);count++;if (count == 4) {count = 1;}emit sendImage(image);qDebug() << "((" << times <<"))";
}

4.3、如何实现图像处理(opencv)

pro文件中加入

INCLUDEPATH += /usr/local/include \/usr/local/include/opencv \/usr/local/include/opencv2 \LIBS += /usr/local/lib/libopencv_*.so \

引入头文件

#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;

边缘检测

        if(isEdgeDetect){  //边缘检测cv::Mat dstPic, edge, grayImage;//创建与src同类型和同大小的矩阵dstPic.create(src_img_cv.size(), src_img_cv.type());//将原始图转化为灰度图cvtColor(src_img_cv, grayImage, COLOR_BGR2GRAY);//先使用3*3内核来降噪blur(grayImage, edge, Size(3, 3));//运行canny算子Canny(edge, edge, 3, 9, 3);src_img_cv = edge;}

锐化

        if(isSharpen){ //锐化cv::Mat blur_img, usm;GaussianBlur(src_img_cv, blur_img, Size(0, 0), 25);//高斯滤波addWeighted(src_img_cv, 1.5, blur_img, -0.5, 0, usm);src_img_cv = usm;}

阈值分割

        if(isThreshold){ //阈值分割double the = 150;//阈值cv::Mat threshold_dst;threshold(src_img_cv, threshold_dst, the, 255, THRESH_BINARY);//手动设置阈值src_img_cv = threshold_dst;}

4.4 登录验证

使用sqlite数据库,封装成单例模式

sqlitesingleton.h

#ifndef SQLITESINGLETON_H
#define SQLITESINGLETON_H#include <QDebug>
#include <QMutex>
#include <QMutexLocker>
#include <QObject>
#include <QSharedPointer>
#include <QSqlDatabase>class SQLiteSingleton {public:static SQLiteSingleton &getInstance();/*** @brief initDB  初始化数据库* @param db_type*/void initDB(QString db_type = "QSQLITE");/*** @brief createTable 创建数据库表*/void createTable();/*** @brief insertUserTable  添加用户* @param username 用户名* @param pwd  密码*/bool insertUserTable(QString username, QString pwd);/*** @brief queryUserExist 查询用户是否存在* @param username* @param pwd* @return*/bool queryUserExist(QString username, QString pwd);private:SQLiteSingleton();~SQLiteSingleton();QSqlDatabase db;
};#endif // SQLITESINGLETO

sqlitesingleton.cpp

#include "sqlitesingleton.h"#include <QMessageBox>
#include <QSqlError>
#include <QSqlQuery>SQLiteSingleton &SQLiteSingleton::getInstance() {static SQLiteSingleton tSQLiteSingleton;return tSQLiteSingleton;
}void SQLiteSingleton::initDB(QString db_type) {qDebug() << "初始化数据库";if (db_type == "QSQLITE") {db = QSqlDatabase::addDatabase("QSQLITE");db.setDatabaseName("UserInfo.dat");if (!db.open()) {QSqlError lastError = db.lastError();QMessageBox::warning(0, QObject::tr("Database Error"),"数据库打开失败," + lastError.driverText());return;}}
}void SQLiteSingleton::createTable() {QSqlQuery query(db);bool ret = query.exec("create table user_info (username varchar(40) primary ""key, password varchar(40))");qDebug() << "create user_info " << ret;
}bool SQLiteSingleton::insertUserTable(QString username, QString pwd) {QSqlQuery query(db);bool ret = query.exec(QObject::tr("insert into user_info values('%1', '%2')").arg(username).arg(pwd));qDebug() << "insertUserTable" << ret;return ret;
}bool SQLiteSingleton::queryUserExist(QString username, QString pwd) {bool isExist = false;QSqlQuery query(db);bool ret = query.exec(QObject::tr("select * from user_info where username='%1' and password='%2'").arg(username).arg(pwd));qDebug() << "queryUserExist" << ret;while (query.next()) {isExist = true;}return isExist;
}SQLiteSingleton::SQLiteSingleton() {}
SQLiteSingleton::~SQLiteSingleto

使用方法

初始化

  SQLiteSingleton::getInstance().initDB();SQLiteSingleton::getInstance().createTable();

注册

SQLiteSingleton::getInstance().insertUserTable(username, pwd1);

查询

isLoginSuccess = SQLiteSingleton::getInstance().queryUserExist(username, pwd);

五、实现效果

5.1、服务端GUI

5.2、客户端GUI

六、参考文献

  • Opencv安装教程 解决opencv测试时OpenCV Error: Unspecified error (The function is not implemented.的问题_陶陶name-CSDN博客
  • 基于QT的网络视频监控系统 https://github.com/muxiaozi/LiveCamera
  • V4L2示例 https://github.com/justdoit-mqr/V4L2VideoProcess
  • QT使用TCP传输图像或者数据的方法QT使用TCP传输图像或者数据的方法_ALong_Lj的博客-CSDN博客_qt tcp传输图片
  • Opencv-锐化增强算法(USM)Opencv-锐化增强算法(USM)_lovefive55的博客-CSDN博客_opencv usm锐化
  • OpenCV —— 阈值分割(直方图技术法,熵算法,Otsu,自适应阈值算法)OpenCV —— 阈值分割(直方图技术法,熵算法,Otsu,自适应阈值算法)_学无止境-CSDN博客_otsu阈值分割算法

Linux下基于qt的视频监控系统相关推荐

  1. 嵌入式项目实战——基于QT的视频监控系统设计(四)

    嵌入式项目实战--基于QT的视频监控系统设计(四) 进入到五一假期的第四天,通过前三天的分享,相信你应该已经掌握了QT的基本使用.UDP网络编程.v4l2视频处理模块.多线程编程等基本的知识点.其实昨 ...

  2. 嵌入式项目实战——基于QT的视频监控系统设计(三)

    嵌入式项目实战--基于QT的视频监控系统设计(三) 进入到五一假期第三天,继续我们的项目.本来五一假期还是想好好休息一下的,因为最近学习的状态不太好,刷题都没有思路了,但是身边的同学太卷了,不过我还是 ...

  3. 嵌入式项目实战——基于QT的视频监控系统设计(一)

    嵌入式项目实战--基于QT的视频监控系统设计(一) 这个五一因为疫情,只能待在家里,想了想不如将我之前做的一个小的嵌入式的练习项目分享出来,供入门嵌入式的同学们学习.基于QT的视频监控系统设计虽然是个 ...

  4. 嵌入式Linux下基于FFmpeg的视频硬件编解码

    嵌入式Linux下基于FFmpeg的视频硬件编解码[图] http://www.c114.net ( 2012/3/1 15:41 ) 摘要: 对FFmpeg多媒体解决方案中的视频编解码流程进行研究. ...

  5. 嵌入式项目实战——基于QT的视频监控系统设计(二)

    嵌入式项目实战--基于QT的视频监控系统设计(二) 昨天我分享了关于QT的基本使用方法,掌握了这些基本的方法就可以设计一个简单的视频监控界面.下面我们开始分享完成这个嵌入式项目同样重要的知识点--UD ...

  6. 嵌入式Linux下基于FFmpeg的视频硬件编解码[图]

    转自:http://tech.c114.net/167/a674033.html 摘要: 对FFmpeg多媒体解决方案中的视频编解码流程进行研究.结合对S3C6410处理器视频硬件编解码方法的分析,阐 ...

  7. Qt编写视频监控系统70-OSD标签和图形信息(支持写入到文件)

    一.前言 作为一个完整的视频监控系统,用户还需要自定义一些OSD标签信息显示在对应通道上面,而且不止一个OSD标签信息,位置可以在四个角或者指定坐标显示.最开始本系统设计的时候,由于本人擅长的是pai ...

  8. linux搭建天地伟业easy7,easy7视频监控系统客户端|天地伟业easy7监控客户端简洁版(Easy7 Smart Client Express)下载 V7.12 官方版 - 比克尔下载...

    Easy7 Smart Client Express就是天地伟业简洁版的easy7视频监控系统客户端,支持天地伟业的DVR.NVR.网络视频编码器.网络摄像机.高清编码器等设备,该软件属于单机版软件, ...

  9. 基于ARM的视频监控系统的设计与实现

    http://61ic.com/Technology/embed/201111/39092.html 摘要: 提出一种基于ARM 嵌入式开发平台视频监控的实现方案.通过V4L2 在Linux 下构建视 ...

最新文章

  1. 深入理解Netty-从偶现宕机看Netty流量控制
  2. 第22天学习Java的笔记-继承
  3. git/码云上关于项目的一些操作:初始化、克隆、上传修改等
  4. The underlying provider failed on open 问题解决
  5. hpunix下11gRac的安装
  6. java 动态代理范例 InvocationHandler与Proxy
  7. 高甜预警|甜齁你的情人节促销海报设计模板
  8. OpenShift 4 之Service Mesh教程(6)- 根据Header路由请求
  9. TCP、UDP及IP协议总结
  10. 年末阿里百度等大厂技术面试题汇总,不可思议!
  11. html设置渐变色背景图片,css中渐变色作为背景图来使用总结
  12. java中有无穷大吗_Java语言中有无穷大
  13. CentOS6.x定制~修改CentOS字样
  14. 怎么关闭计算机的端口服务,怎么关闭和打开电脑的端口?
  15. CGLib动态代理详解
  16. jszip 解压压缩包_一文彻底弄懂jszip中的压缩与解压
  17. 轻松实现页面提交时,显示“提交中..”
  18. 开启虚拟机的时候出现不支持虚拟化的Intel VT-x/EPT
  19. 【游戏客户端开发】Unity3D 学习笔记2——了解U3D引擎的操作面板和各种工具
  20. word如何去除表格中高亮部分(表格属性-边框和底纹)

热门文章

  1. Gartner首次发布中国超融合市场竞争格局报告,ZETTAKIT泽塔云的差异化优势成重点关注对象
  2. [渗透教程]-001-信息收集-第三方软件
  3. 传统产业数字化转型四个发展阶段
  4. 任务分配到每个工作日
  5. 1. NETSDK1141    无法解析位于  global.json 中指定的 .NET SDK 版本
  6. AVAudioPlayer和AVAudioPlayerDelegate-iOS音频播放器
  7. 神经网络中epoch、batch、batchsize
  8. 蓝牙技术基础知识总结笔记1 - 蓝牙版本及 4.0 和 BLE 的关系等
  9. Tecohoo VD-182U 全高清视频会议摄像机
  10. bitset(位图)原理与用法