GPU端到端目标检测YOLOV3全过程(中)








总结了一下自己在计算机视觉初级部分的知识框架,整理如下。
个人所学并不全面(比如图像频域方面了解就比较少),仅做参考。
图像点(pixel值)运算
1. 直方图;
2. 线性/非线性变换;
3. 灰度均衡化/规定化;
4. H-S直方图
图像几何变换
1. 平移、旋转、镜像、缩放(图像金字塔,图像多尺度表达的一种方法,高斯金字塔、拉普拉斯金字塔);
2. 仿射变换
空间域滤波
1. 线性滤波
2. 均值滤波、高斯滤波
3. 非线性滤波
4. 中值滤波、双边滤波
频域图像处理
傅里叶变换
形态学处理
腐蚀、膨胀、开运算、闭运算
边缘检测
Canny;sobel算子(求梯度)、LoG和DoG(DoG是LoG的一种简化算法)
hough变换
适用于直线、圆等其他具有解析式的简单形状
阈值
1. 自适应阈值;
2. 双阈值(Canny中有使用);
3. 非极大值抑制(应用广泛,如目标检测)
轮廓
寻找轮廓、存储轮廓、多边形包围、轮廓的矩
局部特征
1. 特征检测
2. blob detection
3. SIFT(尺度不变性、旋转不变性)、SURF(可用于不同帧间的匹配)
4. corner detection
5. Harris(单帧图像中)、Shi-Tomasi、亚像素级
6. 特征描述
7. 梯度统计直方图
8. SIFT、SURF、HOG、KAZE
9. 二进制字符串特征描述子(使用汉明距离匹配)
10. ORB、LBP、BRIEF、BRISK、FREAK
11. 应用
12. 寻找已知物体(匹配,模板匹配)、透视变换
相机几何模型与相机标定
2D-to-3D reconstruction
1. single image
2. 2-image
3. 3-image
4. N-image
5. bundle adjustment approach
6. Kalman Filter
Novel sensors
1. Structured light(Kinect)
2. Time of flight laser
视频采集的基本流程
2、 打开视频设备
在V4L2中,视频设备被看做一个文件。使用open函数打开这个设备:
// 用非阻塞模式打开摄像头设备
int cameraFd;
cameraFd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0);
// 如果用阻塞模式打开摄像头设备,上述代码变为:
//cameraFd = open("/dev/video0", O_RDWR, 0);
关于阻塞模式和非阻塞模式:应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。
3、 设定属性及采集方式
打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:
extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;
__fd:设备的ID,例如刚才用open函数打开视频通道后返回的cameraFd;
__request:具体的命令标志符。
在进行V4L2开发中,一般会用到以下的命令标志符:
VIDIOC_REQBUFS:分配内存
VIDIOC_QUERYBUF:把VIDIOC_REQBUFS中分配的数据缓存转换成物理地址
VIDIOC_QUERYCAP:查询驱动功能
VIDIOC_ENUM_FMT:获取当前驱动支持的视频格式
VIDIOC_S_FMT:设置当前驱动的频捕获格式
VIDIOC_G_FMT:读取当前驱动的频捕获格式
VIDIOC_TRY_FMT:验证当前驱动的显示格式
VIDIOC_CROPCAP:查询驱动的修剪能力
VIDIOC_S_CROP:设置视频信号的边框
VIDIOC_G_CROP:读取视频信号的边框
VIDIOC_QBUF:把数据从缓存中读取出来
VIDIOC_DQBUF:把数据放回缓存队列
VIDIOC_STREAMON:开始视频显示函数
VIDIOC_STREAMOFF:结束视频显示函数
VIDIOC_QUERYSTD:检查当前视频设备支持的标准,例如PAL或NTSC。
这些IO调用,有些是必须的,有些是可选择的。
4、 检查当前视频设备支持的标准
在亚洲,一般使用PAL(720X576)制式的摄像头,而欧洲一般使用NTSC(720X480),使用VIDIOC_QUERYSTD来检测:
v4l2_std_id std;
do {
ret = ioctl(fd, VIDIOC_QUERYSTD, &std);
} while (ret == -1 && errno == EAGAIN);
switch (std) {
case V4L2_STD_NTSC:
//……
case V4L2_STD_PAL:
//……
}
5、 设置视频捕获格式
当检测完视频设备支持的标准后,还需要设定视频捕获格式:
struct v4l2_format fmt;
memset ( &fmt, 0, sizeof(fmt) );
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 720;
fmt.fmt.pix.height = 576;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) {
return -1;
}
v4l2_format结构体定义如下:
struct v4l2_format
{
enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
union
{
struct v4l2_pix_format pix;
struct v4l2_window win;
struct v4l2_vbi_format vbi;
__u8 raw_data[200];
} fmt;
};
struct v4l2_pix_format
{
__u32 width; // 宽,必须是16的倍数
__u32 height; // 高,必须是16的倍数
__u32 pixelformat; // 视频数据存储类型,例如是YUV4:2:2还是RGB
enum v4l2_field field;
__u32 bytesperline;
__u32 sizeimage;
enum v4l2_colorspace colorspace;
__u32 priv;
};
6、 分配内存
接下来可以为视频捕获分配内存:
struct v4l2_requestbuffers req;
if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) {
return -1;
}
v4l2_requestbuffers定义如下:
struct v4l2_requestbuffers
{
__u32 count; // 缓存数量,也就是说在缓存队列里保持多少张照片
enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE
enum v4l2_memory memory; // V4L2_MEMORY_MMAP 或 V4L2_MEMORY_USERPTR
__u32 reserved[2];
};
7、 获取并记录缓存的物理空间
使用VIDIOC_REQBUFS,获取了req.count个缓存,下一步通过调用VIDIOC_QUERYBUF命令来获取这些缓存的地址,然后使用mmap函数转换成应用程序中的绝对地址,最后把这段缓存放入缓存队列:
typedef struct VideoBuffer {
void *start;
size_t length;
} VideoBuffer;
VideoBuffer* buffers = calloc( req.count, sizeof(*buffers) );
struct v4l2_buffer buf;
for (numBufs = 0; numBufs < req.count; numBufs++) {
memset( &buf, 0, sizeof(buf) );
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = numBufs;
// 读取缓存
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) {
return -1;
}
buffers[numBufs].length = buf.length;
// 转换成相对地址
buffers[numBufs].start = mmap(NULL, buf.length,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd, buf.m.offset);
if (buffers[numBufs].start == MAP_FAILED) {
return -1;
}
// 放入缓存队列
if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) {
return -1;
}
}
8、 关于视频采集方式
操作系统一般把系统使用的内存划分成用户空间和内核空间,分别由应用程序管理和操作系统管理。应用程序可以直接访问内存的地址,而内核空间存放的是 供内核访问的代码和数据,用户不能直接访问。v4l2捕获的数据,最初是存放在内核空间的,这意味着用户不能直接访问该段内存,必须通过某些手段来转换地址。
一共有三种视频采集方式:
1)使用read、write方式:直接使用 read 和 write 函数进行读写。这种方式最简单,但是这种方式会在 用户空间和内核空间不断拷贝数据 ,同时在用户空间和内核空间占用 了 大量内存,效率不高。
2)内存映射方式(mmap):把设备里的内存映射到应用程序中的内存控件,直接处理设备内存,这是一种有效的方式。上面的mmap函数就是使用这种方式。
3)用户指针模式:内存由用户空间的应用程序分配,并把地址传递到内核中的驱动程序,然后由 v4l2 驱动程序直接将数据填充到用户空间的内存中。这点需要在v4l2_requestbuffers里将memory字段设置成V4L2_MEMORY_USERPTR。
第一种方式效率是最低的,后面两种方法都能提高执行的效率,但是对于mmap 方式,文档中有这样一句描述 --Remember the buffers are allocated in physical memory, as opposed to virtual memory which can be swapped out to disk. Applications should free the buffers as soon as possible with the munmap () function .(使用mmap方法的时候,buffers相当于是在内核空间中分配的,这种情况下,这些buffer是不能被交换到虚拟内存中,虽然这种方法不怎么影响读写效率,但是它一直占用着内核空间中的内存,当系统的内存有限的时候,如果同时运行有大量的进程,则对系统的整体性能会有一定的影响。)
所以,对于三种视频采集方式的选择,推荐的顺序是 userptr 、 mmap 、 read-write 。当使用 mmap 或 userptr 方式的时候,有一个环形缓冲队列的概念,这个队列中,有 n 个 buffer ,驱动程序采集到的视频帧数据,就是存储在每个 buffer 中。在每次用 VIDIOC_DQBUF 取出一个 buffer ,并且处理完数据后,一定要用 VIDIOC_QBUF 将这个 buffer 再次放回到环形缓冲队列中。环形缓冲队列,也使得这两种视频采集方式的效率高于直接 read/write 。
9、 处理采集数据
V4L2有一个数据缓存,存放req.count数量的缓存数据。数据缓存采用FIFO的方式,当应用程序调用缓存数据时,缓存队列将最先采集到的 视频数据缓存送出,并重新采集一张视频数据。这个过程需要用到两个ioctl命令,VIDIOC_DQBUF和VIDIOC_QBUF:
struct v4l2_buffer buf;
memset(&buf,0,sizeof(buf));
buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory=V4L2_MEMORY_MMAP;
buf.index=0;
//读取缓存
if (ioctl(cameraFd, VIDIOC_DQBUF, &buf) == -1)
{
return -1;
}
//…………视频处理算法
//重新放入缓存队列
if (ioctl(cameraFd, VIDIOC_QBUF, &buf) == -1) {
return -1;
}
10、 关闭视频设备
使用close函数关闭一个视频设备
close(cameraFd)
linux FFMPEG 摄像头采集数据推流
环境vmware14
Ubuntu14
1)
搭建推流服务器Nginx-rtmp
下载源码
1.
2. mkdir /home/ffmpeg
3. cd /home/ffmpeg
4. wget http://nginx.org/download/nginx-1.7.5.tar.gz
5. wget https://github.com/arut/nginx-rtmp-module/archive/master.zip
6.
解压两个源码包
cd nginx-1.7.5
./configure --with-http_ssl_module --add-module=../nginx-rtmp-module-master
1. make
2. make install
1. wget https://raw.github.com/JasonGiedymin/nginx-init-ubuntu/master/nginx -O /etc/init.d/nginx
2. chmod +x /etc/init.d/nginx
3. update-rc.d nginx defaults
推流:ffmpeg -re -i /home/ffmpeg
配置 nginx-rtmp 服务器
打开 /usr/local/nginx/conf/nginx.conf
1. rtmp {
2. server {
3. listen 1935;
4. chunk_size 4096;
5.
6. application live {
7. live on;
8. record off;
9. exec ffmpeg -i rtmp://localhost/live/$name -threads 1 -c:v libx264 -profile:v baseline -b:v 350K -s 640x360 -f flv -c:a aac -ac 1 -strict -2 -b:a 56k rtmp://localhost/live360p/$name;
10. }
11. application live360p {
12. live on;
13. record off;
14. }
15. }
16. }
到这里服务器安装成功
2)安装ffmpeg
下载源码
wget http://ffmpeg.org/releases/ffmpeg-3.4.4.tar.bz2
关于这个的安装教程很多暂且略过
安装VLC media player
在虚拟机准备一个MP4文件然后进行推流
推流命令:ffmpeg -re -i /home/ffmpeg/test1.mp4 -vcodec copy -acodec copy -f flv "rtmp://127.0.0.1:1935/live/test1"
后面尝试外接摄像头进行推流,发现ffmpeg一些功能还未编译进去,在虚拟机启用v4l2的时候报错误
重新配置编译
./configure --prefix=/usr/local/ffmpeg --enable-gpl --enable-shared --enable-nonfree --enable-libx264 --enable-libxcb --enable-libv4l2
使能libx264 libv4l2等功能,
在执行上面这个配置命令可能会报not found x264 v4l2等错误
(具体可参考https://blog.csdn.net/fgf00/article/details/78203399?locationNum=5&fps=1)
apt-get install libx264-dev
apt-get install libv4l-dev
即可解决
make
make install
到安装目录下执行推流命令
./ffmpeg -f video4linux2 -s 640x480 -i /dev/video0 -f flv rtmp://127.0.0.1:1935/live/live
附上常用命令
ffmpeg常用命令
-f 强迫采用格式fmt
-i filename 输入文件
-s size 设置帧大小 默认是160x128
-r 设置帧频,默认25 (待验证,确认非标准桢率会导致音画不同步,所以只能设定为15或者29.97)
-qscale:v n(q:v n) n表示视频质量级别1-31(待验证值越小,质量越好)
-ab bitrate设置音频码率
-ar freq 设置音频采样率
-ac channels设置通道,默认为1
-vd device 设置视频捕获设备 eg:/dev/video0
-av device 设置音频设备 eg:/dev/dsp
-vcodec
opencv—视频和图片的相互转换
视频分解成图片
**
"""
视频分解成图片
1.load读取视频
2.读取视频的info信息
3.parse解码,拿到单针视频
4.展示imshow 保存imwrite
"""
import cv2
cap=cv2.VideoCapture("1.mp4")# 获取视频打开的句柄
isOpen=cap.isOpened# 判断是否能打开成功
print(isOpen)
fps=cap.get(cv2.CAP_PROP_FPS)# 帧率,视频每秒展示多少张图片
width=int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))# 获取宽度信息
height=int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))# 获取高度信息
print(fps,width,height)
# 15.0 272 480
i=0
while(isOpen):
ifi==10:
break
else:
i=i+1
(flag,frame)=cap.read()# 读取每一张图片 flag表示是否读取成功,frame是图片
fileName='image'+str(i)+'.jpg'
ifflag==True:
cv2.imwrite(fileName,frame,[cv2.IMWRITE_JPEG_QUALITY,100])# 最后一个list是质量控制
print("end")
图片合成视频
import cv2
img=cv2.imread("image1.jpg")
imgInfo=img.shape
size = (imgInfo[1],imgInfo[0])
#文件名称 可以使用的编码器 选择帧率5帧,size视频的大小
videoWrite = cv2.VideoWriter("2.mp4",-1,5,size) # 创建一个对象
for i in range(1,10):
fileName = "image" + str(i) + ".jpg"
img = cv2.imread(fileName)
videoWrite.write(img) # 写入
print("end")
opencv-python将视频转为图片,将图片转为视频
视频转为图片
import cv2
import os
defvideo2imgs(videoPath,imgPath):
ifnotos.path.exists(imgPath):
os.makedirs(imgPath)# 目标文件夹不存在,则创建
cap=cv2.VideoCapture(videoPath)# 获取视频
judge=cap.isOpened()# 判断是否能打开成功
print(judge)
fps=cap.get(cv2.CAP_PROP_FPS)# 帧率,视频每秒展示多少张图片
print('fps:',fps)
frames=1# 用于统计所有帧数
count=1# 用于统计保存的图片数量
while(judge):
flag,frame=cap.read()# 读取每一张图片 flag表示是否读取成功,frame是图片
ifnotflag:
print(flag)
print("Process finished!")
break
else:
ifframes%10==0:# 每隔10帧抽一张
imgname='jpgs_'+str(count).rjust(3,'0')+".jpg"
newPath=imgPath+imgname
print(imgname)
cv2.imwrite(newPath,frame,[cv2.IMWRITE_JPEG_QUALITY,100])
# cv2.imencode('.jpg', frame)[1].tofile(newPath)
count+=1
frames+=1
cap.release()
print("共有 %d 张图片"%(count-1))
video2imgs('/home/jim/Documents/document_fly/10_9/111.webm','./jpgs/')


GPU端到端目标检测YOLOV3全过程(中)的更多相关文章
- GPU端到端目标检测YOLOV3全过程(下)
GPU端到端目标检测YOLOV3全过程(下) Ubuntu18.04系统下最新版GPU环境配置 安装显卡驱动 安装Cuda 10.0 安装cuDNN 1.安装显卡驱动 (1)这里采用的是PPA源的安装 ...
- GPU端到端目标检测YOLOV3全过程(上)
GPU端到端目标检测YOLOV3全过程(上) Basic Parameters: Video: mp4, webM, avi Picture: jpg, png, gif, bmp Text: doc ...
- 目标检测算法(1)目标检测中的问题描述和R-CNN算法
目标检测(object detection)是计算机视觉中非常具有挑战性的一项工作,一方面它是其他很多后续视觉任务的基础,另一方面目标检测不仅需要预测区域,还要进行分类,因此问题更加复杂.最近的5年使 ...
- 第三十五节,目标检测之YOLO算法详解
Redmon, J., Divvala, S., Girshick, R., Farhadi, A.: You only look once: Unified, real-time object de ...
- 利用ImageAI库只需几行python代码超简实现目标检测
目录 什么是目标检测 目标检测算法 Two Stages One Stage python实现 依赖 安装 使用 附录 什么是目标检测 目标检测关注图像中特定的物体目标,需要同时解决解决定位(loca ...
- 小白也能弄懂的目标检测YOLO系列之YOLOV1 - 第二期
上期给大家展示了用VisDrone数据集训练pytorch版YOLOV3模型的效果,介绍了什么是目标检测.目标检测目前比较流行的检测算法和效果比较以及YOLO的进化史,这期我们来讲解YOLO最原始V1 ...
- 不带Anchors和NMS的目标检测
前言: 目标检测是计算机视觉中的一项传统任务.自2015年以来,人们倾向于使用现代深度学习技术来提高目标检测的性能.虽然模型的准确性越来越高,但模型的复杂性也增加了,主要是由于在训练和NMS后处理过 ...
- 目标检测之YOLO V2 V3
YOLO V2 YOLO V2是在YOLO的基础上,融合了其他一些网络结构的特性(比如:Faster R-CNN的Anchor,GooLeNet的\(1\times1\)卷积核等),进行的升级.其目的 ...
- CVPR2019目标检测方法进展综述
CVPR2019目标检测方法进展综述 置顶 2019年03月20日 14:14:04 SIGAI_csdn 阅读数 5869更多 分类专栏: 机器学习 人工智能 AI SIGAI 版权声明:本文为 ...
随机推荐
- Oracle 数据库裸设备扩容处理
前段时间,我管理的一台Oracle数据库表空间容量不足了,由于本人以前没有接触过Oracle的使用所以,就自己查资料来研究如何扩容,网上的文档多数都是在物理机上扩容,而偏偏我的数据文件是存储在裸设备上 ...
- Linux系统登录相关
whoami:查看当前用户 who:查看当前登录系统的所有用户 tty指的是主机的图形化界面的面板 pts/x指的是远程ssh连接的窗口 who -b:主机的上一次启动时间 w:显示已经登陆系统的用户 ...
- WideCharToMultiByte 与 MultiByteToWideChar
先看看这篇关于Windows编码的文章:http://blog.csdn.net/shyboy_nwpu/article/details/4431668 再看看这篇关于两个函数参数和用法的说明:htt ...
- 2020腾讯Android岗初级到高级面试真题收录解析
前言 马上就要到金九银十面试季了,需要找工作的小伙伴可以开始刷题复习了. 今天给大家分享的是博主腾讯面试的面经以及对腾讯2020上半年Android开发岗面经真题收录,希望可以帮助到大家,喜欢的朋友可 ...
- java的继承和组合
继承和组合是java中非常常用的两种创建新类型的方法,两者都能提高代码的复用率. 继承主要是想让子类继承父类的基本特性:组合技术通常用于想在新类中使用现有类的功能,而非它的接口.两者的分别是" ...
- ERROR: Pool overlaps with other one on this address space
出现问题 配置了两个不同的docker-compose.yml,使用了相同的网段,导致了在运行第二个yml文件时命令行报错目标网段已存在,报错如下: Creating network "v2 ...
- 如何在centos上配置802.1Q VLAN标记,linux单网卡多vlan多网段Ip配置案例
介绍 VLAN使将大型网络分成较小且易于管理的网络成为可能.802.1Q是所有供应商都在其网络设备中实施的标准.某些交换机能够将多个VLAN分配给单个网络端口.使用此功能,您可以将多个VLAN分配给单 ...
- 5分钟,教你用Python每天跟女朋友说1000遍土味情话!
- BUAA-OO-第四单元总结——终章
面向对象第四单元博客总结--终章 第四单元作业设计 第13次作业设计 类和对应方法属性设计 类设计如下图所示 本次作业主要涉及六个类,其中包括主类 Main ,通用Map类 UmlElementIdM ...
- Dart 2.13 版现已发布
作者 / Kevin Moore & Michael Thomsen Dart 2.13 版现已发布,其中新增了类型别名功能,这是目前用户呼声第二高的语言功能.Dart 2.13 还改进了 D ...