12
12
import ffmpeg
13
13
import re
14
14
15
+ global N
16
+ global N_WIDTH
17
+ global N_HEIGHT
18
+ global THRESHOLD
19
+
15
20
N = 16
16
21
N_WIDTH = N // 2
17
22
N_HEIGHT = N
20
25
CHARS = ['W' , '#' , 'R' , 'E' , '8' , 'x' , 's' , 'i' , ';' , ',' , '.' , ' ' ]
21
26
PALETTE = np .arange (len (CHARS ))
22
27
23
- parser = argparse .ArgumentParser (
24
- description = 'This program converts videos to texts.' )
25
-
26
- parser .add_argument ('input' , help = 'input video' )
27
- parser .add_argument ('output' , help = 'output text' )
28
- parser .add_argument ('-s' , '--size' , type = int )
29
- parser .add_argument ('-m' , '--mode' , type = str , help = 'choose WHITE or BLACK' )
30
- parser .add_argument ('-t' , '--threshold' , type = int ,
31
- help = 'threshold between white and black' )
32
-
33
28
34
29
def cover_multiple (current_length , multiple ):
35
30
"""
@@ -54,58 +49,68 @@ def slicer(a, chunk_i, chunk_j, two_d=True):
54
49
return c
55
50
56
51
57
- def frameToText (frame , opts ):
52
+ def frameToText (frame , chars , palette , n_height , n_width , mode = None , threshold = 110 ):
58
53
text = ''
59
54
60
55
frame_gray = cv2 .cvtColor (frame , cv2 .COLOR_BGR2GRAY )
61
- if not opts [ ' mode' ] :
62
- if frame_gray .mean () < opts [ 'THRESHOLD' ] :
56
+ if mode is None :
57
+ if frame_gray .mean () < threshold :
63
58
text = 'BLACK\n '
64
- chars = np .array (list (reversed (opts [ 'CHARS' ] )), dtype = '<U1' )
59
+ chars = np .array (list (reversed (chars )), dtype = '<U1' )
65
60
else :
66
61
text = 'WHITE\n '
67
- chars = np .array (opts [ 'CHARS' ] , dtype = '<U1' )
62
+ chars = np .array (chars , dtype = '<U1' )
68
63
else :
69
- if opts [ ' mode' ] == 'WHITE' :
64
+ if mode == 'WHITE' :
70
65
text = 'WHITE\n '
71
- chars = np .array (opts [ 'CHARS' ] , dtype = '<U1' )
66
+ chars = np .array (chars , dtype = '<U1' )
72
67
else :
73
68
text = 'BLACK\n '
74
- chars = np .array (list (reversed (opts [ 'CHARS' ] )), dtype = '<U1' )
69
+ chars = np .array (list (reversed (chars )), dtype = '<U1' )
75
70
76
71
tmp = np .nanmean (
77
- slicer (frame_gray , opts [ 'N_HEIGHT' ], opts [ 'N_WIDTH' ] ), axis = (2 , 3 ))
72
+ slicer (frame_gray , n_height , n_width ), axis = (2 , 3 ))
78
73
tmp = tmp / 256 * len (chars )
79
74
tmp = tmp .astype (int )
80
- ind = np .digitize (tmp .ravel (), opts [ ' PALETTE' ] , right = True )
75
+ ind = np .digitize (tmp .ravel (), PALETTE , right = True )
81
76
tmp2 = '' .join (chars [ind ].tolist ())
82
- chunk_size = ceil (frame_gray .shape [1 ]/ opts [ 'N_WIDTH' ] )
77
+ chunk_size = ceil (frame_gray .shape [1 ]/ n_width )
83
78
84
79
tmp3 = [tmp2 [i :i + chunk_size ] for i in range (0 , len (tmp2 ), chunk_size )]
85
80
86
81
text += '\n ' .join (tmp3 )
87
82
return text
88
83
89
84
90
- def loadFrame (path ):
91
- return cv2 .imread ( path )
85
+ def loadFrame (bytes ):
86
+ return cv2 .imdecode ( np . fromstring ( bytes , dtype = 'uint8' ), cv2 . IMREAD_UNCHANGED )
92
87
93
88
94
- def loadFrameAndConvertToText (data ):
89
+ def loadFrameFileAndConvertToText (data ):
95
90
path = data [0 ]
96
91
opts = data [1 ]
97
- return frameToText (loadFrame (path ), opts )
92
+ with open (path , 'rb' ) as f :
93
+ return frameToText (loadFrame (f .read ()), ** opts )
94
+
95
+
96
+ if __name__ == "__main__" :
97
+ parser = argparse .ArgumentParser (
98
+ description = 'This program converts videos to texts.' )
98
99
100
+ parser .add_argument ('input' , help = 'input video' )
101
+ parser .add_argument ('output' , help = 'output text' )
102
+ parser .add_argument ('-s' , '--size' , type = int )
103
+ parser .add_argument ('-m' , '--mode' , type = str , help = 'choose WHITE or BLACK' )
104
+ parser .add_argument ('-t' , '--threshold' , type = int ,
105
+ help = 'threshold between white and black' )
106
+
107
+ args = parser .parse_args ()
99
108
100
- def main (args ):
101
109
if args .size :
102
- global N
103
110
N = args .size
104
111
if args .threshold :
105
- global THRESHOLD
106
112
THRESHOLD = args .threshold
107
113
108
- global N_WIDTH , N_HEIGHT
109
114
N_WIDTH = N // 2
110
115
N_HEIGHT = N
111
116
@@ -114,11 +119,11 @@ def main(args):
114
119
115
120
texts = []
116
121
opts = {}
117
- opts ['THRESHOLD ' ] = THRESHOLD
118
- opts ['CHARS ' ] = CHARS
119
- opts ['N_HEIGHT ' ] = N_HEIGHT
120
- opts ['N_WIDTH ' ] = N_WIDTH
121
- opts ['PALETTE ' ] = PALETTE
122
+ opts ['threshold ' ] = THRESHOLD
123
+ opts ['chars ' ] = CHARS
124
+ opts ['n_height ' ] = N_HEIGHT
125
+ opts ['n_width ' ] = N_WIDTH
126
+ opts ['palette ' ] = PALETTE
122
127
opts ['mode' ] = args .mode
123
128
124
129
with tempfile .TemporaryDirectory () as tmpdir :
@@ -128,7 +133,7 @@ def main(args):
128
133
files .sort (key = lambda f : int (re .sub ('\D' , '' , f )))
129
134
with mp .Pool (mp .cpu_count ()) as pool :
130
135
with tqdm (total = len (files )) as t :
131
- for res in pool .imap (loadFrameAndConvertToText , zip (list (map (lambda f : os .path .join (tmpdir , f ), files )), repeat (opts ))):
136
+ for res in pool .imap (loadFrameFileAndConvertToText , zip (list (map (lambda f : os .path .join (tmpdir , f ), files )), repeat (opts ))):
132
137
texts .append (res )
133
138
t .update ()
134
139
@@ -148,8 +153,3 @@ def main(args):
148
153
filepath , fps , int (width ), int (height ), origwidth , origheight ))
149
154
f .write ('=====\n ' )
150
155
f .write ('\n ' .join (texts ))
151
-
152
-
153
- if __name__ == "__main__" :
154
- args = parser .parse_args ()
155
- main (args )
0 commit comments