Skip to main content

Python[Module] Opencv 读取摄像头数据

如果做监控,经常会遇到读取摄像头的数据。如何在python中读取摄像头数据,并显示呢?

双码流

一般高清摄像头产品编码器可同时产生两个不同的编码格式,统称主码流和子码流,双码流技术兼顾了高质量图像传输和窄
带宽传输。

主码流用于本地存储,子码流适用于图像在低带宽网络上传输。
双码流采用一路高码率的码流用于本地高清存储,例如QCIF/CIF/D1编码,一路低码率的码流用于网络传输,例如QCIF/CIF编
码,同时兼顾本地存储和远程网络传输。双码流能实现本地传输和远程传输两种不同的带宽码流需要,本地传输采用高码
流可以获得更高的高清录像存储,远程传输采用较低的码流以适应CDMA/ADSL等各种网络而获得更高的图像流畅度。

SDK方式读取数据

一般主流的厂商,会提供SDK来访问摄像头的数据,比如海康,大华。我们可以直接下载SDK,加载Dll去读取数据

RSTP方式读取数据

如果不想利用SDK来读取数据,我们可以通过RSTP协议来读取视频流数据。比如:

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

例如,请求海康摄像机通道1的主码流,Url如下
主码流:
rtsp://admin:12345@192.0.0.64:554/h264/ch1/main/av_stream
rtsp://admin:12345@192.0.0.64:554/MPEG-4/ch1/main/av_stream

子码流:
rtsp://admin:12345@192.0.0.64/mpeg4/ch1/sub/av_stream
rtsp://admin:12345@192.0.0.64/h264/ch1/sub/av_stream

大华:
rtsp://username:password@ip:port/cam/realmonitor?channel=1&subtype=0
说明:
username: 用户名。例如admin。
password: 密码。例如admin。
ip: 为设备IP。例如 10.7.8.122。
port: 端口号默认为554,若为默认可不填写。
channel: 通道号,起始为1。例如通道2,则为channel=2。
subtype: 码流类型,主码流为0(即subtype=0),辅码流为1(即subtype=1)

例子

[python]
import wx
import cv2

class MainWindow(wx.Panel):
def __init__(self, parent, capture):
wx.Panel.__init__(self, parent)
mainSizer = wx.BoxSizer(wx.VERTICAL)

self.inputBox = wx.TextCtrl(self)
mainSizer.Add(self.inputBox, 0, wx.ALL, 5)

# video
videoWarper = wx.StaticBox(self, label="Video", size=(640, 480))
videoBoxSizer = wx.StaticBoxSizer(videoWarper, wx.VERTICAL)
videoFrame = wx.Panel(self, -1, size=(640, 480))
cap = ShowCapture(videoFrame, capture)
videoBoxSizer.Add(videoFrame, 0)
mainSizer.Add(videoBoxSizer, 0)

parent.Centre()
self.Show()
self.SetSizerAndFit(mainSizer)

class ShowCapture(wx.Panel):
def __init__(self, parent, capture, fps=30):
wx.Panel.__init__(self, parent, wx.ID_ANY, (0, 0), (640, 480))

self.capture = capture
ret, frame = self.capture.read()

height, width = frame.shape[:2]

parent.SetSize((width, height))

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

self.bmp = wx.BitmapFromBuffer(width, height, frame)

self.timer = wx.Timer(self)
self.timer.Start(1000. / fps)

self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_TIMER, self.NextFrame)

def OnPaint(self, evt):
dc = wx.BufferedPaintDC(self)
dc.DrawBitmap(self.bmp, 0, 0)

def NextFrame(self, event):
ret, frame = self.capture.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.bmp.CopyFromBuffer(frame)
self.Refresh()

rstp = ‘rtsp://admin:admin2018@192.168.1.180:554/MPEG-4/ch1/main/av_stream’
capture = cv2.VideoCapture(rstp)
# capture = cv2.open(rstp)
app = wx.App(False)
frame = wx.Frame(None, -1, ‘HGA Count’, size=(400, 400))
panel = MainWindow(frame, capture)
frame.Show()
app.MainLoop()

[/python]

微信截图_20180128155408

Python[Module] struct 数据格式转换

Python对于数据类型的表示,不像其他语言预定义了许多类型,它只定义了六种基本类型:字符串,整数,浮点数,元组,列表,字典。通过这六种数据类型,我们可以完成基本工作,但是与C/C++交互时,就会发现数据类型转换的问题。Struct 模块就是提供了C类型与python类型的转化。

主要的方法:
struct.pack
struct.pack用于将Python的值根据格式符,转换为字符串(因为Python中没有字节(Byte)类型,可以把这里的字符串理解为字节流,或字节数组)。其函数原型为:struct.pack(fmt, v1, v2, …),参数fmt是格式字符串,关于格式字符串的相关信息在下面有所介绍。v1, v2, …表示要转换的python值。

struct.unpack
struct.unpack做的工作刚好与struct.pack相反,用于将字节流转换成python数据类型。它的函数原型为:struct.unpack(fmt, string),该函数返回一个元组。 下面是一个简单的例子:
[python]
str = struct.pack("ii", 20, 400)
a1, a2 = struct.unpack("ii", str)
print ‘a1:’, a1
print ‘a2:’, a2

#—- result:
#a1: 20
#a2: 400

[/python]
pack_into
struct.pack_into(fmt, buffer, offset, v1, v2, …) 和pack 很类似,就是把结果放到一个buffer里
unpack_from
struct.unpack_from(fmt, buffer, offset=0)
pack_info 的反操作,根据format取出对应的数据
[python]
buffer = bytearray(16)
pack_into(‘!LLLL’, buffer, 0, 10, 20, 30, 40)
print(buffer)

unbuffer = unpack_from(‘!LLLL’, buffer, 0)
print(unbuffer)
[/python]

格式
struct_format

例子:
[python]
from struct import *

print(pack(‘hhl’, 1, 2, 3))
print(unpack(‘!LLLL’, b’\x00\x00\xad\xc5\x00\x00\x00\x02\x00\x00\x17\xf2\x00\x00\xad\xb9′))
print(unpack(‘!L’, b’\x77\xab\x77\xab’))
print(pack(‘!L’, 2007725995))
print(unpack(‘!L’, b’w\xabw\xab’))
print(pack(‘!L’, 44485))
print(unpack(‘!L’, b’\x00\x00\xad\xc5′))

str = pack("ii", 20, 1)
print(repr(str))
print(str)

[/python]

Python Struct

存储模式 Big-Endian和Little-Endian

大端模式Big-Endian就是高位字节排放在内存的低地址端,低位字节排放在内存的高地址端。
小端模式Little-Endian就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

为什么会有大小端模式之分
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。例如一个16bit的short型x,在内存中的地址为0x0010,x的值为0x1122,那么0x11为高字节,0x22为低字节。对于大端模式,就将0x11放在低地址中,即0x0010中,0x22放在高地址中,即0x0011中。小端模式,刚好相反。

例:32bit宽的数0x12345678在Little-endian模式以及Big-endian模式在内存中的存放方式为(假设从地址0x4000开始存放):
20180122002326

Linux 实例创建 FTP 站点

vsftpd 是 Linux 下的一款小巧轻快、安全易用的 FTP 服务器软件,是一款在各个 Linux 发行版中最受推崇的 FTP 服务器软件。本文以 CentOS 7.2 64位操作系统为例,说明如何在 Linux 实例上安装 vsftpd。

  • 安装 vsftpd
  • 配置 vsftpd
  • 设置安全组
  • 客户端测试

一: 安装 vsftpd
远程连接并登录到 Linux 实例。

运行以下命令安装 vsftpd。
yum install -y vsftpd
图片20

出现下图表示安装成功。
图片21

运行以下命令打开及查看etc/vsftpd。

cd /etc/vsftpd
ls
图片22

说明:
/etc/vsftpd/vsftpd.conf是核心配置文件。
/etc/vsftpd/ftpusers 是黑名单文件,此文件里的用户不允许访问 FTP 服务器。
/etc/vsftpd/user_list是白名单文件,是允许访问 FTP 服务器的用户列表。

运行以下命令设置开机自启动。
systemctl enable vsftpd.service
运行以下命令启动 FTP 服务。
systemctl start vsftpd.service
运行以下命令查看 FTP 服务端口。

netstat -antup | grep ftp
图片23

二: 配置 vsftpd

vsftpd 安装后默认开启了匿名 FTP 的功能,使用匿名 FTP,用户无需输入用户名密码即可登录 FTP 服务器,但没有权限修改或上传文件。
文本介绍了以下几个配置 vsftpd 的方法以及相关的参数说明,您可以根据具体需要进行参考。

配置匿名用户上传文件权限
配置本地用户登录
vsftpd.conf 的配置文件参数说明
配置匿名用户上传文件权限

修改 vsftpd.conf 的配置文件的选项,可以赋予匿名 FTP 更多的权限。
修改/etc/vsftpd/vsftpd.conf:
运行vim /etc/vsftpd/vsftpd.conf。
按键 “i” 进入编辑模式。
将写权限修改为write_enable=YES。
将匿名上传权限修改为anon_upload_enable=YES。
按键 “Esc” 退出编辑模式,然后按键“:wq” 保存并退出文件。
图片28

运行以下命令更改 /var/ftp/pub 目录的权限,为 FTP 用户添加写权限,并重新加载配置文件。

chmod o+w /var/ftp/pub/
systemctl restart vsftpd.service
图片29

配置本地用户登录

本地用户登录就是指用户使用 Linux 操作系统中的用户账号和密码登录 FTP 服务器。
vsftpd 安装后默只支持匿名 FTP 登录,用户如果试图使用 Linux 操作系统中的账号登录服务器,将会被 vsftpd 拒绝,但可以在 vsftpd 里配置用户账号和密码登录。具体步骤如下:

运行以下命令创建 ftptest 用户。
useradd ftptest
运行以下命令修改 ftptest 用户密码。
passwd ftptest
修改 ftptest 用户密码
图片31
修改/etc/vsftpd/vsftpd.conf:

运行vim /etc/vsftpd/vsftpd.conf。

按键 “i” 进入编辑模式。
将是否允许匿名登录 FTP 的参数修改为anonymous enable=NO。
将是否允许本地用户登录 FTP 的参数修改为local_enable=YES。
按键 “Esc” 退出编辑模式,然后按键“:wq” 保存并退出文件。
图片32

修改/etc/vsftpd/vsftpd.conf

vsftpd.conf 的配置文件参数说明

运行命令 cat /etc/vsftpd/vsftpd.conf 查看配置文件内容。

用户登录控制

参数 说明
anonymous_enable=YES 接受匿名用户
no_anon_password=YES 匿名用户login时不询问口令
anon_root=(none) 匿名用户主目录
local_enable=YES 接受本地用户
local_root=(none) 本地用户主目录
用户权限控制

参数 说明
write_enable=YES 可以上传(全局控制)
local_umask=022 本地用户上传文件的umask
file_open_mode=0666 上传文件的权限配合umask使用
anon_upload_enable=NO 匿名用户可以上传
anon_mkdir_write_enable=NO 匿名用户可以建目录
anon_other_write_enable=NO 匿名用户修改删除
chown_username=lightwiter 匿名上传文件所属用户名
三: 设置安全组

搭建好 FTP 站点后,您需要在实例的安全组的入方向添加一条放行 FTP 端口的规则,具体步骤参见 添加安全组规则,具体配置可以参考 安全组规则的典型应用_FTP。

四: 客户端测试
打开客户端的计算机,在路径栏输入ftp://服务器 IP 地址:FTP 端口(如果不填端口则默认访问21端口),例如:ftp://0.0.0.0:20。弹出输入用户名和密码的对话框表示配置成功,正确的输入用户名和密码后,即可对 FTP 文件进行相应权限的操作。

阿里云配置
python ftp