OpenCV获取网络摄像头实时视频流
创始人
2025-05-30 20:49:20
0

参考文章:

  • [常用工具] OpenCV获取网络摄像头实时视频流_opencv网络摄像头
  • [常用工具] OpenCV获取网络摄像头实时视频流_opencv网络摄像头_落痕的寒假的博客-CSDN博客

 


方式一: 使用VideoCapture读取视频流

在使用OpenCv处理视频时,无论是视频文件还是摄像头画面,都要使用VideoCapture类来进行每一帧图像的处理。当我们使用视频文件作为参数时,OpenCv则打开视频文件,进行每一帧画面的读取。当我们传递摄像机编号时,OpenCv则打开相机,实时读取相机画面。
获取VideoCaptrue实例:

# 读取视频文件
cv2.VideoCapture('video.mp4')
# 打开摄像机
cv2.VideoCapture(0)

使用VideoCapture读取海康RTSP流

RTSP流

在使用OpenCv进行计算机视觉处理时,我们很多时候需要连接外部相机,如海康威视。监控相机的常见视频传输协议有:RTSP、RTMP(以RTSP为主)
RTSP与RTMP比较:

  •     RTSP:低时延,实现难度大,适合视频聊天和视频监控
  •     RTMP:低时延,实现难度大,适合视频聊天和视频监控

目前市面上的相机大多以RTSP流协议为主。
在读取海康相机时,需要使用VideoCapture读取RTSP流协议的内容,而不是通过相机编号直接读取。

"""
海康相机rtsp格式:rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_streamusername: 用户名。例如admin。password: 密码。例如12345。ip: 为设备IP。例如 192.0.0.64。port: 端口号默认为554,若为默认可不填写。codec:有h264、MPEG-4、mpeg4这几种。channel: 通道号,起始为1。例如通道1,则为ch1。subtype: 码流类型,主码流为main,辅码流为sub。
"""

使用VideoCapture读取RTSP流示例:

# 使用rtsp流打开相机
def open_camera(username: str, password: str, ip: str, port: int):"""使用rtsp流打开相机rtsp格式:rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_streamusername: 用户名。例如admin。password: 密码。例如12345。ip: 为设备IP。例如 192.0.0.64。port: 端口号默认为554,若为默认可不填写。codec:有h264、MPEG-4、mpeg4这几种。channel: 通道号,起始为1。例如通道1,则为ch1。subtype: 码流类型,主码流为main,辅码流为sub。:return:相机是否打开,相机"""try:# 使用rtsp流打开相机cam = cv2.VideoCapture(f'rtsp://{username}:{password}@{ip}:{port}/h264/ch1/main/av_stream')return True, camexcept cv2.error:# 捕获cv异常# 打开相机失败return False, None

优化后代码:

import queue
import threadingimport cv2class CameraThread(threading.Thread):# 保存实例化相机,通过实例化相机操作相机camera = None# 保存每一帧从rtsp流中读取到的画面queue_image = queue.Queue(maxsize=10)# 线程体是否循环执行标志flag_run = False# 相机线程调用函数def run(self) -> None:while self.flag_run:try:# 捕获异常,避免读取视频操作因异常而退出# 相机实例存在,判断相机是否打开if self.camera.is_opened():# 相机已打开,读取相机内容ret, frame = self.camera.read()if not ret or frame is None:# 读取相机内容失败breakif ret:# 将内容添加到队列中# 判断队列是否满if self.queue_image.full():# 队列满,队头出队self.queue_image.get()# 队尾添加数据self.queue_image.put(frame)else:# 队尾添加数据self.queue_image.put(frame)except cv2.error as error:# 捕获cv异常# 因为子线程会一直调用该程序,可对捕获到的异常不进行处理print(error)passexcept Exception as error:# 捕获Exception异常print(error)pass# setter:设置相机的camera对象def set_camera(self, camera):"""设置相机的camera对象"""# 设置相机的cameraself.camera = camera# 获取队列中的RGB图像def get_image(self):"""获取队列中的RGB图像:return: img: RGB图像"""# 读取队列中的图片img = self.queue_image.get()# img为None,读取失败,队列还未获取到图片while img is None:# 一直读取图片,直到读取图片成功img = self.queue_image.get()# 返回读取到的内容return img# 停止运行def run_stop(self):self.flag_run = False# 开始运行def run_start(self):self.flag_run = True


方式二: 所需要硬件及软件环境:

python 3/OpenCV3.4 or C++11/OpenCV3.4

1 RTSP协议

RTSP (Real Time Streaming Protocol),是一种语法和操作类似 HTTP 协议,专门用于音频和视频的应用层协议。 和 HTTP 类似,RTSP 也使用 URL 地址。同时我们也要了解到摄像机传输数据用的是码流,高清网络摄像机产品编码器都会产生两个编码格式,称为主码流和子码流。这就叫双码流技术。目的是用于解决监控录像的本地存储和网络传输的图像的质量问题。双码流能实现本地和远程传输的两种不同的带宽码流需求,本地传输可以用主码流,能获得更清晰的存储录像,远程传输就因为带宽限制的原因,而使用子码流来获得流畅的图像和录像。通过RTSP协议传输不同的码流,但是各大摄像头厂家的RTSP协议地址不大一样。通常你只要知道摄像头IP地址,用户名密码就行了。

海康的RTSP协议地址如下:

rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream
1) username  用户名,常用 admin
2) password  密码,常用 12345
3) ip        摄像头IP,如 192.0.0.64
4) port      端口号,默认为 554,可以不写
5) codec     视频编码模式,有 h264、MPEG-4、mpeg4 等,可以不写
6) channel   通道号,起始为1,例如通道1,则为 ch1
7) subtype   码流类型,主码流为 main,辅码流为 sub

大华的RTSP协议地址如下: 

rtsp://[username]:[password]@[ip]:[port]/cam/realmonitor?[channel=1]&[subtype=1] 
1) username、password、ip、port 同上
2) channel  通道号,起始为1,例如通道2,则为 channel=2
3) subtype  码流类型,主码流为0(即 subtype=0),辅码流为1(即 subtype=1)

宇视的RTSP协议地址如下:

rtsp://{用户名}:{密码}@{ip}:{port}/video1/2/3,
1)video1/2/3表示主码流,子码流,三码流(可以不用)
2)其他一样

2 OpenCV中读取网络摄像头

OpenCV读取网络摄像头很简单,直接用url设定rtsp地址,用VideoCapture读取视频就行了。但是RTSP有些许问题,所以在最后通过TCP传输协议上承载RTSP,保证稳定性。就在rtsp地址后面加?tcp

    String url = "rtsp://admin:123456@114.114.114.114/ch1-s1?tcp";//海康//"rtsp://admin:123456@114.114.114.114/ch1-s1?tcp"//大华//“rtsp://admin:123456@114.114.114.114/cam/realmonitor?channel=1&subtype=1?tcp”//宇视//"rtsp://admin:123456@114.114.114.114/video1?tcp"VideoCapture cap(url);Mat frame;cap>>frame;

但是直接按上面的方法来读取视频,会出问题,通常都是error while decoding,读不了码流,也就是读到一半就失败。这个会导致程序异常。

这是由于OpenCV中FFMPEG Lib对在rtsp协议中的H264 vidos不支持或者OpenCV版本太低,所以处理办法就是自己写两个不同的线程单独去处理接收每一帧的图像,然后另一个线程处理这每一帧的图像。思路如下:使用队列,基于pthread类采取先入先出策略,在一个线程中开始接收数据,在另一个线程中处理逐帧数据。

这样就可以实时获得网络摄像头数据啦,获得Mat格式图像,具体代码如下:

 C++代码:
 

 
//并行
#include 
//互斥访问
#include //是否打开视频
bool captureOpen = false;
//读取的每张图像
Mat image;
VideoCapture capture;//网络链接地址
String url = "rtsp://admin:123456@114.114.114.114/ch1-s1?tcp";//加锁器
mutex mtx;
//是否读图成功
bool imgready = false;/*** @brief 读图* * @return Mat */
Mat captureThread()
{if (captureOpen == false || image.empty()){//打开图像capture.open(url);}while (1){//加锁mtx.lock();capture >> image;//读图成功imgready = true;//解锁mtx.unlock();return image;}
}/*** @brief 处理函数* * @param image 输入图像*/
void processingThread(Mat image)
{//如果读图成功if (imgready){//如果图像为空if (image.empty()){return;}mtx.lock();//你的处理函数//your functionmtx.unlock();return;}
}int main()
{//读图thread t1(captureThread);t1.join();//已经读图captureOpen = true;//并行处理thread t2(processingThread, image);t2.join();return 0;
}

Python代码:

import cv2
import queue
import time
import threading
q=queue.Queue()def Receive():print("start Reveive")cap = cv2.VideoCapture("rtsp://admin:admin_123@172.0.0.0")ret, frame = cap.read()q.put(frame)while ret:ret, frame = cap.read()q.put(frame)def Display():print("Start Displaying")while True:if q.empty() !=True:frame=q.get()cv2.imshow("frame1", frame)if cv2.waitKey(1) & 0xFF == ord('q'):breakif __name__=='__main__':p1=threading.Thread(target=Receive)p2 = threading.Thread(target=Display)p1.start()p2.start()

相关内容

热门资讯

合同范本-技术培训合同样本 技... 委托方:_________??法定代表人或负责人:________??服务方:_______??法定...
合同范本-科技查新合同样本 房... 合同编号:查新项目名称中文:英文:委托单位名称:通信地址:邮政编码:电子信箱:负责人电话:传真:联系...
合同范本-软件外包合同范本样本... 甲方:_________乙方:_________(个人)身份证号码:________________...
Git 和 GitHub 超入... 工作流程 工作的流程应该遵循以下步骤: (1) 在 issue 跟踪系统中创建一个新的...
技术服务合同(含技术培训、技术... 项目名称:____________________________________________委...
转让技术秘密和补偿贸易合作生产... 甲方:____________________________________地址:________...
【Git】git环境如何搭建与... 搭建 Git 环境: 安装 Git 客户端:根据操作系统选择对应的版本进...
day36_jdbc 今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客...
与梦想有关的哲理说说短语 梦想...   01、 我就是我是颜色不一样的烟火天空海阔要做最坚强的泡沫。  02、 不论你在什么时候开始,重...
激励人生的励志签名致自己 激励...   01、 农村三驴子,进城。‰  02、 ≮问世间情为何物,一物降一物。≯  03、 上学的心情,...
青春励志个性签名正能量 励志个...   01、 还喜欢 还在意 但不渴望在一起  02、 努力吧一意孤行的公主  03、 让人耗尽心力的...
样本-合同范本-中外专有技术许... 中外专有技术许可合同签约时间:签字地点:合同号:中国,北京,×××公司(以下简称“受让方”)为一方,...
人生格言个性励志签名 微信励志...   01、 如果迩是棉花糖机,莪愿融化真心,旋转成手心旳云。  02、 人活着不是要用眼泪博得同情,...
2023年顶级编程语言趋势 对于开发人员和软件工程师来说,选择更优秀的编程语言使编写可以在任何地方运行的软件变得更...
[VUE 问题]crbug/1... [VUE 问题]crbug/1173575, non-JS module files depreca...
古风唯美诗意个性签名 古风个性...   01、 为了几世夙愿,踏过一程山水,寻你却终陌路难相见。  02、 浅墨淡彩,扉卷半开,痴儿叹。...
霸气励志个性签名女生 男人个性...   01、 我不怕苦不怕累不怕失败不怕鼻青脸肿不怕遍体鳞伤我只怕自己有梦却没从努力过。  02、 漫...
古风有诗意的说说短语 关于古风...   01、 灯火星星,人声杳杳,歌不尽乱世烽火。  02、 静水流深,沧笙踏歌;三生阴晴圆缺,一朝悲...
努力奋斗的励志说说短语 孩子努...   01、 如果自己不努力,谁也给不了你想要的生活;梦想不会逃跑,逃跑的永远是自己。  02、 相对...
Redis中的List列表 List 文章目录List常用命令lpush/rpush/lrangelpop/rpoplindex...