文章目录

  • 1 摘要
  • 2 概述
  • 3 客户端的设计与实现
    • 3.1 OpenCV图像处理
      • 3.1.1 cv::VideoCapture类
      • 3.1.2 图像压缩编码
    • 3.2 Socket 网络通信
  • 4 服务器端的设计与实现
    • 4.1 Socket网络通信
    • 4.2 OpenCV图像处理
  • 5 MFC界面的设计与分析
    • 5.1 MFC简介
    • 5.2 客户端及服务器端的MFC界面
    • 5.3 细节分析
  • 6 程序测试
    • 6.1 本机回环测试
    • 6.2 局域网下两台PC的测试
  • 7 优缺点分析
    • 7.1 本项目的优势
    • 7.2 改进空间

1 摘要

OpenCV作为一个广为人知的跨平台计算机视觉库,应用于各种领域,但在网络视频监控方面的应用还很少。本项目将OpenCV与Socket结合,采用TCP协议以MFC为UI界面实现了从客户端到服务器端的实时图像传输。

本文将从OpenCV图像处理和Socket网络连接两方面分别介绍客户端和服务器端的设计和实现。随后,本文介绍该项目的MFC界面设计以及在本机和局域网下的程序测试结果。最后,本文分析了本项目的优缺点。

2 概述

该项目分为客户端和服务器端两部分,其整体框架如图所示。客户端的作用是采集实时图像信息并实时显示到MFC的Picture Control控件图像,再利用OpenCV压缩编码,再将图像数据流通过Socket发送到服务器端。服务器端的作用是接收数据流,再将收到的数据流进行解码并显示出来。

接下来本文将主要从客户端、服务器端以及MFC界面设计端分别做详细的说明。

3 客户端的设计与实现

客户端的主要作用是从摄像头获取图像流,压缩编码,发起TCP连接,发送数据流。下面将从OpenCV图像处理和Socket网络通信来进一步说明如何实现。

3.1 OpenCV图像处理

客户端的OpenCV图像处理流程图如图所示。

3.1.1 cv::VideoCapture类

cv::VideoCapture类既支持从视频文件读取,也支持从摄像头中读取图像流。在此之前,须先创建一个VideoCapture对象,此对象调用成员函数isOpened()来检查是否打开成功,成功则返回true。

cv::VideoCapture对象调用视频文件(.mpg或.avi格式)读取视频的格式为:

//从视频文件读取
cv::VideoCapture capture(const string& filename);
cv::VideoCapture capture("路径");

cv::VideoCapture对象调用摄像头读取实时视频格式为:

//从摄像头读取
cv::VideoCapture capture(int device);

其中,device是摄像头的标识符。如果只有一个摄像头,则device赋值为0。如果计算机有多个摄像头,将其逐渐增加即可。

打开默认摄像头,并从中读取图像流,将图像流赋给cv:Mat image,其代码块为:

Mat image;
VideoCapture capture;
while(capture.isOpened()){capture.open(0);
capture >> image;
imshow(image);
waitKey(3);
}

3.1.2 图像压缩编码

对于图像传输,很多方案都是基于像素的传输,即传输的数据大小直接与图像分辨率和通道数对等。以640480分辨率为例,若传输单通道灰度图,一张图像传输的数据量是307200个字节;若传输三通道RGB图像,则一张图像需要传输921600个字节。一张图像九十多万字节的数据量,这显然是极大地浪费了网络资源。若采用这种基于像素的图像传输,很容易造成视频卡顿。这时我们引入OpenCV的imencode和imdecode两个函数,分别对像素进行二进制压缩编码及解码。

imencode()的定义格式为:

bool imencode(
const String& ext,
InputArray img,
vector<uchar>& buf,
const vector<int>& params=vector<int>())

各参数解释如表所示。

参数 解释
ext 定义输出文件格式的扩展名
img 待编码的图像
buf 输出的缓存区
params 被编码的格式和压缩率

在本项目中,编码成jpg格式,压缩率为50%。

3.2 Socket 网络通信

网络通信方面,本项目客户端采用继承于CAsyncSocket类的自定义ClientSocket类。程序流程图如下图所示。

用户从MFC界面输入目的IP及端口号,点击“连接”按键,ClientSocket类的对象调用Create()创建套接字,Connect()发起TCP连接,连接成功后Send()向服务器端发送数据流。用户点击“断开连接”按键,Close()关闭套接字,capture.release()关闭摄像头。

4 服务器端的设计与实现

服务器端的作用是先与客户端实现TCP连接,再接收来自客户端的数据流,然后进行解码并将实时图像显示出来。所以,接下来笔者将从Socket网络通信及OpenCV图像处理两方面来介绍服务器端。

4.1 Socket网络通信

服务器端网络通信,本项目采用继承于CAsyncSocket类的自定义ListenSocket类和ServerSocket类,二者分别用于监听和连接服务。

服务端Socket网络通信部分的程序流程图如图所示。

用户点击“本地回环测试”设置IP地址为127.0.0.1,点击“获取本机IP”及自动获取并设置本机的IP地址。本项目自动获取本机IP的方法为:引用winsock2.h库,调用其中gethostname()函数获取本机的主机名,然后用gethostbyname()函数利用主机名获取IP。设置IP地址后将其显示在MFC的IP控件上。

设置好IP地址及端口号后点击“打开监控”,ListenSocket类的对象调用Create()创建监听套接字。Listen()进入监听状态,然后检测是否有来自客户端的连接请求,如果没有请求则继续监听,如果接收到请求则OnAccept()接收请求实现TCP连接。然后用ServerSocket类的对象调用Create()创建服务套接字,OnReceive()接收来自客户端的数据流,客户端没有断开连接则持续接收实时图像数据流,如果客户端断开连接,则OnClose()断开连接。

如果服务器端主动断开连接,即用户在TCP连接状态下点击“断开连接”,ListenSocket类和ServerSocket类的对象将调用Close()关闭套接字,断开与客户端的连接。

4.2 OpenCV图像处理

服务器端的图像处理部分很简单,将接受到的数据流进行imdecode()解码,然后将解码出来的Mat类型图像实时地显示到窗口内。

imdecode()是OpenCV中图像解码函数,与imencode()成对使用,前面已经介绍了压缩编码的imencode()函数,下面来介绍一下imdecode()。
imencode()有两个重载:

Mat imdecode(InputArray buf, int flags)
Mat imdecode(InputArray buf, int flags, Mat* dst)
  • buf:解压的内存空间;
  • flags:色彩空间,常用的有CV_LOAD_IMOSE_COLOR指三通道彩色图像,CV_LOAD_IMAGE_GRAYSCALE指的是单通道灰度图;dst:解码矩阵的可选输出占位符,不填则是NULL。

5 MFC界面的设计与分析

5.1 MFC简介

本项目的UI界面采用的是MFC(Microsoft Foundation Classes,微软基础类),同VCL类似,是一种应用程序框架。该类库提供一组通用的可重用的类库供开发人员使用,大部分类均从CObject直接或间接派生。

MFC应用程序的总体结构通常由开发人员从MFC类派生的几个类和一个CWinApp类对象(应用程序对象)组成。MFC提供了MFC AppWizard自动生成框架。Windows 应用程序中,MFC的主包含文件为Afxwin.h。

5.2 客户端及服务器端的MFC界面

客户端的MFC界面:

服务器端的MFC界面:

5.3 细节分析

为提升程序的实用性及鲁棒性,下面介绍三点有关本项目MFC界面设计上的细节。

第一,显示图片的功能是利用OpenCV的imshow()完成的,但显示的窗口一般会独立出一个子窗口,这样不仅很不美观,使用起来还很不方便。所以,这里本项目是把OpenCV的窗口和MFC的Picture控件绑定在一起,实现图像显示窗口嵌入到主窗口。相关代码块为:

//将MFC的IDC_PIC1与OpenCV的src1绑定
CRect rect1;
CWnd* pWnd1 = GetDlgItem(IDC_PIC1);
pWnd1->GetClientRect(&rect1);
namedWindow("src1", WINDOW_AUTOSIZE);
resizeWindow("src1", Size(rect1.Width(), rect1.Height()));
HWND hWnd1 = (HWND)cvGetWindowHandle("src1");
HWND hParent1 = ::GetParent(hWnd1);
::SetParent(hWnd1, GetDlgItem(IDC_PIC1)->m_hWnd);
::ShowWindow(hParent1, SW_HIDE);

第二,为了能实时反映当前程序运行状态,在界面上加了列表控件。例如,当IP/端口号为空时点击“连接”按键,列表中会提示“IP地址为空,请输入目标IP地址”,摄像头打开则提示“摄像头打开成功”,服务端开始监听会输出地址和端口号并提示“等待用户连接”,等等。

第三,为了提升程序的鲁棒性,防止程序出错,本项目利用控件变量调用函数EnableWindow(FALSE/TRUE)来使控件有效或无效,对输入进行严格的控制。以客户端界面为例,初始界面中可以输入IP地址和端口号,可点击“连接”按键,但“断开”连接按键是灰色的,不可点击。但如果IP/端口号为空,列表栏会提示“IP地址为空,请输入目标IP地址”,发起TCP连接后,IP控件、端口号控件及“连接”按键会变灰,而“断开连接”按键有效,可以点击。

6 程序测试

6.1 本机回环测试

服务器端点击“本地回环测试”,即设置IP地址为“127.0.0.1”,实现TCP连接后,实时视频传输正常,网络监控的基本功能实现,某一时刻测试结果如图所示。

6.2 局域网下两台PC的测试

将两台计算机连接同一个WIFI,组成一个无线局域网。

一台计算机运行服务器端程序,一台计算机运行客户端程序。服务器端点击“获取本机IP”,获取到的IP地址为“192.168.0.103”,与客户端PC实现TCP连接后,测试得出实时视频传输正常,即局域网下也可实现网络监控的基本功能,某一时刻测试结果为:

局域网下,客户端测试某一时刻结果:

局域网下,服务器端测试某一时刻结果:

7 优缺点分析

7.1 本项目的优势

整体来说,本项目最大的创新点在于实现了OpenCV图像处理与Socket网络通信的结合。所以本项目的优势基本源于OpenCV的优势。

第一,在本项目的图传的预处理中采用了OpenCV的图像编码与解码功能替代了传统的基于像素的图像传输,这极大地压缩了传输数据量,释放了网络资源,使得实时视频更流畅。

第二,由于OpenCV中有丰富的图像分析处理及机器视觉的函数库,所以在智能化图传方面,本项目提供了非常便利的OpenCV接口进行二次开发。例如,在客户端图像采集后可以搭载OpenCV人脸识别方面的函数库,再与人员信息数据库结合起来就可以很快开发出一个适用于上班打卡或场所出入口的具备实时登记流动人员信息的网络视频监控系统。

7.2 改进空间

由于笔者编程能力有限,本项目还有很多缺陷有待改进。

第一,传输视频的时候,接收端(服务器端)偶尔会出现花屏现象。这是因为本项目采用的是TCP网络传输协议。
TCP协议提供的是面向连接的可靠传输,通常应用于文件传输、文字传输、电子邮件等这些对精确性要求较高而且对实时性要求不高的场景。而UDP协议提供的是无连接的不可靠的网络传输,通常应用于数据量大但精确度要求不高的数据传输,比如网站上看视频、多人网络游戏等场景。

通过TCP与UDP的对比,我们发现网络视频监控更适合用UDP协议。

第二,项目没能实现双向视频传输,如果实现双向视频、音频传输,在加上视频音频同步及多线程技术,就可以实现网络视频通话。

基于Socket、OpenCV和MFC实现的网络实时视频监控相关推荐

  1. .NET(C#)基于Socket编程实现平行主机之间网络通讯有图片传输的Demo演示

    本文讲下C#通过Socket编程实现平行主机之间网络通讯的详细讲解,非常不错的博文,一起来看下吧.      在程序设计中,涉及数据存储和数据交换的时候,不管是B/S还是C/S模式 ,都有这样一个概念 ...

  2. linux点对点聊天室的实现与设计心得,基于Socket接口的Linux与Windows网络聊天室设计与实现...

    陈洁 孟晓景 摘要:为了实现Linux与Windows跨平台通信,及时共享信息,构建了一个适用于跨平台的网络聊天室通信程序.先搭建跨平台通信环境,然后使用Socket套接字网络编程接口实现通信.整个系 ...

  3. 树莓派+电脑 opencv实时网络图像监控

    概述 本文实现了一种基于树莓派+python3+opencv3方法实现实时网络视频监控(局域网内).现将实现过程中才过的坑(对我这个新手来说是坑)与大家分享,我将在代码实现章节进行详细说明. 功能实现 ...

  4. socket recv 服务端阻塞 python_网络编程(基于socket编程)

    网络编程(基于socket编程) socket套接字:应用程序通常通过socket"套接字"向网络发送请求或应答网络请求,是主机间或同一计算机中的进程间相互通讯 socket是介于 ...

  5. Flex与.NET互操作(一):基于Socket的网络连接

    Flash/Flex也支持基于Socket的网络连接 ,服务器端可以是C++,VB,C#,Java等任一语言开发.监听一个网络端口便可以接收到Flash/Flex开发的客户端的连接. ActionSc ...

  6. 基于socket网络编程技术实现TCP和UDP的流程详解及实例

    具体函数讲解太多,根据程序自行分析. 可以参考这篇文章: https://blog.csdn.net/qq_41687938/article/details/119102328?spm=1001.20 ...

  7. 基于opencv和mfc的摄像头采集代码(GOMFCTemplate2)持续更新

            编写带界面的图像处理程序,选择opencv+mfc是一种很好的选择:在读取摄像头数据方面,网上的方法很多,其中shiqiyu的camerads的方法是较好的.       基于现有资料 ...

  8. eBPF技术应用云原生网络实践系列之基于socket的service | 龙蜥技术

    简介:如何使用 socket eBPF进一步提升Service 网络的转发性能? 背景介绍 Kubernetes 中的网络功能,主要包括 POD 网络,service 网络和网络策略组成.其中 POD ...

  9. 网络编程(基于socket接口技术的进程间通信)接上一篇文章补充

    目录 一.网络编程(基于socket接口技术) 1.基于TCP协议的网络通信 编程模型: 2.基于UDP通信协议的网络通信 编程模型: 3.新增函数: 大小端数据转换函数: ip地址转换函数: TCP ...

最新文章

  1. ARM的cache和写缓冲器(write buffer)
  2. 使用ln -s解决库冲突的问题
  3. [iOS]服务器使用php时多图片上传AFNetworking的设置
  4. Vue 中 slot插槽 的使用
  5. MySQL社区版的下载和安装
  6. docker添加jar包_docker配置容器运行jar包
  7. linux静默删除文件夹,Linux常用命令10 - unzip
  8. Android设计模式之——模板方法模式
  9. 原生js实现jquery库中选择器的功能(jquery库封装一)
  10. iOS中 openGL常用函数记录(部分)
  11. [jQuery基础] jQuery对象 -- 属性操作
  12. (49)FPGA面试题2-4译码器实现
  13. WinEdt10注册码
  14. cocos2dx 交叉编译 iconv库 protobuf库
  15. android编译framework架包运行报错 (转)
  16. 计算机数字雨教程视频,股票配资火爆cmd什么意思(cmd命令数字雨)
  17. PHP-Web聊天室 一天即可打造自己的聊天室-严双双-专题视频课程
  18. 税法18个税种全总结附记忆小口诀
  19. 【今日头条2017内推】调度问题
  20. 照片后期制作计算机配置,追求色彩真实还原,图片后期处理电脑配置推荐

热门文章

  1. FINDSTR 命令使用详解
  2. Word插入图片后随着文字的增多图片会到下一页的解决方法
  3. xinetd(安装及配置xinetd)
  4. FlinkSql中表的创建及查询
  5. mycat 分表分库
  6. 可汗学院金融学笔记系列
  7. Android USB HID整理
  8. singleTask vs singleInstance
  9. matlab的tfdata函数_MATLAB 主要函数指令表(按功能分类)
  10. 自编码器,变分自编码器和生成对抗网络异同