/
HDF5_to_AVI.py
executable file
·165 lines (129 loc) · 5.05 KB
/
HDF5_to_AVI.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#!/usr/bin/env python
"""
Notes:
* VideoWriter expects dimensions (x,y,3) and will fail otherwise, writing a tiny file perhaps
* VLC has a long-standing bug where files under about 3fps don't playback
* the isColor parameter of VideoWriter works on Linux too
Example:
python HDF5_to_AVI.py extracted.h5 /tmp/out.avi
"""
import logging
from pathlib import Path
import h5py
import numpy as np
from typing import Sequence, Tuple
from argparse import ArgumentParser
# from scipy.signal import wiener
from pyimagevideo import sixteen2eight
from pyimagevideo.videowriter import VideoWriter
usecolor = False
PTILE = [5, 99.95]
SUFFIXES = (".mkv", ".ogv", ".avi")
"""
all of these codecs worked for me on Ubuntu 14.04 and 16.04
'MJPG' Motion JPEG
'XVID' MPEG-4
'FFV1' Lossless
'FMP4' MPEG-4
** maybe works somewhat
'THEO' ext='.ogv' #must name file .ogv, NOT .avi -- somewhat broken, per messages in ffplay
*** NOT working for me on Ubuntu 16.04 ***
'YV12'
'IYUV'
'Y41P' #silent error, no write
'YUV9' #silent error, no write -- 15.04 writes but nobody knows how to play
'DIB ' # silent error, no write
'CVID' #encoder not found
'MJ2C' #segmentation fault -- 15.04 blank video
"""
def hdf2avi(
infn: Path, outfn: Path, h5key: str, cc4: str, minmax: Tuple[int, int] = None, fps: float = None, ptile=PTILE, step: int = 1
):
"""
Parameters
----------
infn: pathlib.Path
HDF5 file containing video to read
outfn: pathlib.Path
video file to write
h5key: str
HDF5 path to video. Assuming shape Nframe x Y x X x 3 (RGB color) or Nframe x Y x X (gray)
cc4: str
CC4 code of codec
minmax: tuple of int
min, max to scale contrast
"""
window = step * 100 # number of frames over which to auto contrast
infn = Path(infn).expanduser()
outfn = Path(outfn).expanduser()
if outfn.suffix not in SUFFIXES:
raise ValueError(f"output filename should have suffix of {SUFFIXES}")
if cc4 == "THEO":
assert outfn.suffix == ".ogv"
if outfn.is_file():
raise FileExistsError(outfn)
# %% open HDF5 video for parameters
with h5py.File(infn, "r") as f:
N, y, x = f[h5key].shape[:3]
Next = N // step
print(f"converting {Next} / {N} frames sized {x} x {y} from {infn} to {outfn}")
# %% initialize OpenCV video writer
if N < 100:
print(f"picking FPS=4 due to small amount Nframe {N}")
fps = 4
window = step * Next // 10
elif fps is None:
fps = 20
if fps <= 3:
logging.warning("FPS<=3 might not work with some AVI players e.g. VLC")
with VideoWriter(outfn, cc4, (x, y), fps, usecolor) as h:
# %% loop over HDF5 video
for i in range(0, N, step):
if not i % window:
if minmax is None:
minmax = np.percentile(f[h5key][i : i + window : step, :, :], ptile, interpolation="nearest")
if minmax[0] != minmax[1]:
print(f"{i/N*100:.1f} % min/max {minmax}\r", end="")
else:
logging.error(f"{i/N*100:.1f} % Min==max no input image contrast")
im = f[h5key][i, :, :]
# im = wiener(im,wienernhood)
img = sixteen2eight(im, minmax)
h.write(img)
def getprc(fn: Path, key: str, stride: int = 60, ptile: Sequence[float] = PTILE):
"""plot some file statistics to help decide min/max"""
fn = Path(fn).expanduser()
fGB = fn.stat().st_size / 1e9
print(f"sampling {ptile} percentiles {fn}, reading {1/stride*fGB:.1f} of {fGB:.1f} GB")
with h5py.File(fn, "r") as f:
prc = np.percentile(f[key][::stride, ...], ptile, interpolation="nearest")
print(f"percentiles {ptile}: {prc}")
def findvidvar(fn: Path) -> str:
"""
assumes which variable is video in an HDF5 file
by finding variable of larget size (number of elements) in an HDF5 file that's 3-D or 4-D
"""
fn = Path(fn).expanduser()
x = {}
with h5py.File(fn, "r") as f:
for v in f:
if f[v].ndim in (3, 4):
x[v] = f[v].size
vid = max(x, key=x.get)
print(f'using "{vid}" as video variable in {fn}')
return vid
if __name__ == "__main__":
p = ArgumentParser()
p.add_argument("infn", help="HDF5 video file to read")
p.add_argument("outfn", help="video file to write e.g. cool.avi")
p.add_argument("-k", "--h5key", help="key to HDF5 video (variable in HDF5 file)")
p.add_argument("-cc4", help="video codec CC4 code", default="FMP4")
p.add_argument("-minmax", help="minimum, maximum values. Automatic if not specified.")
p.add_argument("-fps", help="frames/sec of output video", type=int, default=None)
p.add_argument("-s", "--step", help="take every Nth frame (default 1)", type=int, default=1)
P = p.parse_args()
h5key = findvidvar(P.infn) if not P.h5key else P.h5key
if not P.outfn:
getprc(P.infn, h5key)
else:
hdf2avi(P.infn, P.outfn, h5key, P.cc4, P.minmax, P.fps, step=P.step)