其实OpenCV已经提供了写视频的接口,但是编码和文件后缀的对应真是让人头疼,动不动就不支持。经过尝试,总结出目前两种可以正常写入视频的对应关系:
- MJPG --> .avi
- mp4v -->.mp4
一、编码MJPG、后缀.avi
MJPG是大写!!!
# coding=utf-8
from
__future__
import
absolute_import
,
division
,
print_function
import
cv2
import
warnings
import
numpy
as
np
warnings
.
simplefilter
(
"always"
)
class
VideoWriter
:
def
__init__
(
self
,
name
,
width
,
height
,
fps
=
25
)
:
# type: (str, int, int, int) -> None
if
not
name
.
endswith
(
'.avi'
)
:
# 保证文件名的后缀是.avi
name
+=
'.avi'
warnings
.
warn
(
'video name should ends with ".avi"'
)
self
.
__name
=
name
# 文件名
self
.
__height
=
height
# 高
self
.
__width
=
width
# 宽
fourcc
=
cv2
.
VideoWriter_fourcc
(
*
'MJPG'
)
# 如果是avi视频,编码需要为MJPG
self
.
__writer
=
cv2
.
VideoWriter
(
name
,
fourcc
,
fps
,
(
width
,
height
)
)
def
write
(
self
,
frame
)
:
if
frame
.
dtype
!=
np
.
uint8
:
# 检查frame的类型
raise
ValueError
(
'frame.dtype should be np.uint8'
)
# 检查frame的大小
row
,
col
,
_
=
frame
.
shape
if
row
!=
self
.
__height
or
col
!=
self
.
__width
:
warnings
.
warn
(
'长和宽不等于创建视频写入时的设置,此frame不会被写入视频'
)
return
self
.
__writer
.
write
(
frame
)
def
close
(
self
)
:
self
.
__writer
.
release
(
)
def
main
(
)
:
width
=
512
height
=
256
vw
=
VideoWriter
(
'test.avi'
,
width
,
height
)
for
i
in
range
(
25
*
50
)
:
# 随机生成一幅图像
frame
=
np
.
random
.
randint
(
0
,
255
,
(
height
,
width
,
3
)
,
dtype
=
np
.
uint8
)
# 写入图像
vw
.
write
(
frame
)
# 关闭
vw
.
close
(
)
if
__name__
==
'__main__'
:
main
(
)
二、编码mp4v、后缀.mp4
mp4v是小写!!!
# coding=utf-8
from
__future__
import
absolute_import
,
division
,
print_function
import
cv2
import
warnings
import
numpy
as
np
warnings
.
simplefilter
(
"always"
)
class
VideoWriter
:
def
__init__
(
self
,
name
,
width
,
height
,
fps
=
25
)
:
# type: (str, int, int, int) -> None
if
not
name
.
endswith
(
'.mp4'
)
:
# 保证文件名的后缀是.mp4
name
+=
'.mp4'
warnings
.
warn
(
'video name should ends with ".mp4"'
)
self
.
__name
=
name
# 文件名
self
.
__height
=
height
# 高
self
.
__width
=
width
# 宽
fourcc
=
cv2
.
VideoWriter_fourcc
(
*
'mp4v'
)
# 如果是mp4视频,编码需要为mp4v
self
.
__writer
=
cv2
.
VideoWriter
(
name
,
fourcc
,
fps
,
(
width
,
height
)
)
def
write
(
self
,
frame
)
:
if
frame
.
dtype
!=
np
.
uint8
:
# 检查frame的类型
raise
ValueError
(
'frame.dtype should be np.uint8'
)
# 检查frame的大小
row
,
col
,
_
=
frame
.
shape
if
row
!=
self
.
__height
or
col
!=
self
.
__width
:
warnings
.
warn
(
'长和宽不等于创建视频写入时的设置,此frame不会被写入视频'
)
return
self
.
__writer
.
write
(
frame
)
def
close
(
self
)
:
self
.
__writer
.
release
(
)
def
main
(
)
:
width
=
512
height
=
256
vw
=
VideoWriter
(
'test.mp4'
,
width
,
height
)
for
i
in
range
(
25
*
50
)
:
# 随机生成一幅图像
frame
=
np
.
random
.
randint
(
0
,
255
,
(
height
,
width
,
3
)
,
dtype
=
np
.
uint8
)
# 写入图像
vw
.
write
(
frame
)
# 关闭
vw
.
close
(
)
if
__name__
==
'__main__'
:
main
(
)
三、视频写入失败的原因
-
不支持对应的编码和后缀。目前我知道支持的是:
* mp4v–>.mp4
* MJPG–>.avi - frame的值类型不是uint8。
- frame的高或者宽和新建cv2.VideoWriter设置的高或宽不对应。