OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 # Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 # | 3 # |
4 # Use of this source code is governed by a BSD-style license | 4 # Use of this source code is governed by a BSD-style license |
5 # that can be found in the LICENSE file in the root of the source | 5 # that can be found in the LICENSE file in the root of the source |
6 # tree. An additional intellectual property rights grant can be found | 6 # tree. An additional intellectual property rights grant can be found |
7 # in the file PATENTS. All contributing project authors may | 7 # in the file PATENTS. All contributing project authors may |
8 # be found in the AUTHORS file in the root of the source tree. | 8 # be found in the AUTHORS file in the root of the source tree. |
9 | 9 |
10 import optparse | 10 import optparse |
11 import os | 11 import os |
12 import sys | 12 import sys |
13 | 13 |
14 if __name__ == '__main__': | 14 if __name__ == '__main__': |
15 # Make sure we always can import helper_functions. | 15 # Make sure we always can import helper_functions. |
16 sys.path.append(os.path.dirname(__file__)) | 16 sys.path.append(os.path.dirname(__file__)) |
17 | 17 |
18 import helper_functions | 18 import helper_functions |
19 | 19 |
20 # Chrome browsertests will throw away stderr; avoid that output gets lost. | 20 # Chrome browsertests will throw away stderr; avoid that output gets lost. |
21 sys.stderr = sys.stdout | 21 sys.stderr = sys.stdout |
22 | 22 |
23 | 23 |
24 def convert_yuv_to_png_files(yuv_file_name, yuv_frame_width, yuv_frame_height, | 24 def ConvertYuvToPngFiles(yuv_file_name, yuv_frame_width, yuv_frame_height, |
25 output_directory, ffmpeg_path): | 25 output_directory, ffmpeg_path): |
26 """Converts a YUV video file into PNG frames. | 26 """Converts a YUV video file into PNG frames. |
27 | 27 |
28 The function uses ffmpeg to convert the YUV file. The output of ffmpeg is in | 28 The function uses ffmpeg to convert the YUV file. The output of ffmpeg is in |
29 the form frame_xxxx.png, where xxxx is the frame number, starting from 0001. | 29 the form frame_xxxx.png, where xxxx is the frame number, starting from 0001. |
30 | 30 |
31 Args: | 31 Args: |
32 yuv_file_name(string): The name of the YUV file. | 32 yuv_file_name(string): The name of the YUV file. |
33 yuv_frame_width(int): The width of one YUV frame. | 33 yuv_frame_width(int): The width of one YUV frame. |
34 yuv_frame_height(int): The height of one YUV frame. | 34 yuv_frame_height(int): The height of one YUV frame. |
(...skipping 19 matching lines...) Expand all Loading... | |
54 command, fail_msg='Error during YUV to PNG conversion') | 54 command, fail_msg='Error during YUV to PNG conversion') |
55 except helper_functions.HelperError, err: | 55 except helper_functions.HelperError, err: |
56 print 'Error executing command: %s. Error: %s' % (command, err) | 56 print 'Error executing command: %s. Error: %s' % (command, err) |
57 return False | 57 return False |
58 except OSError: | 58 except OSError: |
59 print 'Did not find %s. Have you installed it?' % ffmpeg_path | 59 print 'Did not find %s. Have you installed it?' % ffmpeg_path |
60 return False | 60 return False |
61 return True | 61 return True |
62 | 62 |
63 | 63 |
64 def decode_frames(input_directory, zxing_path): | 64 def DecodeFrames(input_directory, zxing_path): |
65 """Decodes the barcodes overlaid in each frame. | 65 """Decodes the barcodes overlaid in each frame. |
66 | 66 |
67 The function uses the Zxing command-line tool from the Zxing C++ distribution | 67 The function uses the Zxing command-line tool from the Zxing C++ distribution |
68 to decode the barcode in every PNG frame from the input directory. The frames | 68 to decode the barcode in every PNG frame from the input directory. The frames |
69 should be named frame_xxxx.png, where xxxx is the frame number. The frame | 69 should be named frame_xxxx.png, where xxxx is the frame number. The frame |
70 numbers should be consecutive and should start from 0001. | 70 numbers should be consecutive and should start from 0001. |
71 The decoding results in a frame_xxxx.txt file for every successfully decoded | 71 The decoding results in a frame_xxxx.txt file for every successfully decoded |
72 barcode. This file contains the decoded barcode as 12-digit string (UPC-A | 72 barcode. This file contains the decoded barcode as 12-digit string (UPC-A |
73 format: 11 digits content + one check digit). | 73 format: 11 digits content + one check digit). |
74 | 74 |
75 Args: | 75 Args: |
76 input_directory(string): The input directory from where the PNG frames are | 76 input_directory(string): The input directory from where the PNG frames are |
77 read. | 77 read. |
78 zxing_path(string): The path to the zxing binary. If specified as None, | 78 zxing_path(string): The path to the zxing binary. If specified as None, |
79 the PATH will be searched for it. | 79 the PATH will be searched for it. |
80 Return: | 80 Return: |
81 (bool): True if the decoding succeeded. | 81 (bool): True if the decoding succeeded. |
82 """ | 82 """ |
83 if not zxing_path: | 83 if not zxing_path: |
84 zxing_path = 'zxing.exe' if sys.platform == 'win32' else 'zxing' | 84 zxing_path = 'zxing.exe' if sys.platform == 'win32' else 'zxing' |
85 print 'Decoding barcodes from PNG files with %s...' % zxing_path | 85 print 'Decoding barcodes from PNG files with %s...' % zxing_path |
86 return helper_functions.perform_action_on_all_files( | 86 return helper_functions.perform_action_on_all_files( |
87 directory=input_directory, file_pattern='frame_', | 87 directory=input_directory, file_pattern='frame_', |
88 file_extension='png', start_number=1, action=_decode_barcode_in_file, | 88 file_extension='png', start_number=1, action=_DecodeBarcodeInFile, |
89 command_line_decoder=zxing_path) | 89 command_line_decoder=zxing_path) |
90 | 90 |
91 | 91 |
92 def _decode_barcode_in_file(file_name, command_line_decoder): | 92 def _DecodeBarcodeInFile(file_name, command_line_decoder): |
93 """Decodes the barcode in the upper left corner of a PNG file. | 93 """Decodes the barcode in the upper left corner of a PNG file. |
94 | 94 |
95 Args: | 95 Args: |
96 file_name(string): File name of the PNG file. | 96 file_name(string): File name of the PNG file. |
97 command_line_decoder(string): The ZXing command-line decoding tool. | 97 command_line_decoder(string): The ZXing command-line decoding tool. |
98 | 98 |
99 Return: | 99 Return: |
100 (bool): True upon success, False otherwise. | 100 (bool): True upon success, False otherwise. |
101 """ | 101 """ |
102 command = [command_line_decoder, '--try-harder', '--dump-raw', file_name] | 102 command = [command_line_decoder, '--try-harder', '--dump-raw', file_name] |
103 try: | 103 try: |
104 out = helper_functions.run_shell_command( | 104 out = helper_functions.run_shell_command( |
105 command, fail_msg='Error during decoding of %s' % file_name) | 105 command, fail_msg='Error during decoding of %s' % file_name) |
106 text_file = open('%s.txt' % file_name[:-4], 'w') | 106 text_file = open('%s.txt' % file_name[:-4], 'w') |
107 text_file.write(out) | 107 text_file.write(out) |
108 text_file.close() | 108 text_file.close() |
109 except helper_functions.HelperError, err: | 109 except helper_functions.HelperError, err: |
110 print 'Barcode in %s cannot be decoded.' % file_name | 110 print 'Barcode in %s cannot be decoded.' % file_name |
111 print err | 111 print err |
112 return False | 112 return False |
113 except OSError: | 113 except OSError: |
114 print 'Did not find %s. Have you installed it?' % command_line_decoder | 114 print 'Did not find %s. Have you installed it?' % command_line_decoder |
115 return False | 115 return False |
116 return True | 116 return True |
117 | 117 |
118 | 118 |
119 def _generate_stats_file(stats_file_name, input_directory='.'): | 119 def _GenerateStatsFile(stats_file_name, input_directory='.'): |
120 """Generate statistics file. | 120 """Generate statistics file. |
121 | 121 |
122 The function generates a statistics file. The contents of the file are in the | 122 The function generates a statistics file. The contents of the file are in the |
123 format <frame_name> <barcode>, where frame name is the name of every frame | 123 format <frame_name> <barcode>, where frame name is the name of every frame |
124 (effectively the frame number) and barcode is the decoded barcode. The frames | 124 (effectively the frame number) and barcode is the decoded barcode. The frames |
125 and the helper .txt files are removed after they have been used. | 125 and the helper .txt files are removed after they have been used. |
126 """ | 126 """ |
127 file_prefix = os.path.join(input_directory, 'frame_') | 127 file_prefix = os.path.join(input_directory, 'frame_') |
128 stats_file = open(stats_file_name, 'w') | 128 stats_file = open(stats_file_name, 'w') |
129 | 129 |
130 print 'Generating stats file: %s' % stats_file_name | 130 print 'Generating stats file: %s' % stats_file_name |
131 for i in range(1, _count_frames_in(input_directory=input_directory) + 1): | 131 for i in range(1, _CountFramesIn(input_directory=input_directory) + 1): |
132 frame_number = helper_functions.zero_pad(i) | 132 frame_number = helper_functions.zero_pad(i) |
133 barcode_file_name = file_prefix + frame_number + '.txt' | 133 barcode_file_name = file_prefix + frame_number + '.txt' |
134 png_frame = file_prefix + frame_number + '.png' | 134 png_frame = file_prefix + frame_number + '.png' |
135 entry_frame_number = helper_functions.zero_pad(i-1) | 135 entry_frame_number = helper_functions.zero_pad(i-1) |
136 entry = 'frame_' + entry_frame_number + ' ' | 136 entry = 'frame_' + entry_frame_number + ' ' |
137 | 137 |
138 if os.path.isfile(barcode_file_name): | 138 if os.path.isfile(barcode_file_name): |
139 barcode = _read_barcode_from_text_file(barcode_file_name) | 139 barcode = _ReadBarcodeFromTextFile(barcode_file_name) |
140 os.remove(barcode_file_name) | 140 os.remove(barcode_file_name) |
141 | 141 |
142 if _check_barcode(barcode): | 142 if _CheckBarcode(barcode): |
143 entry += (helper_functions.zero_pad(int(barcode[0:11])) + '\n') | 143 entry += (helper_functions.zero_pad(int(barcode[0:11])) + '\n') |
144 else: | 144 else: |
145 entry += 'Barcode error\n' # Barcode is wrongly detected. | 145 entry += 'Barcode error\n' # Barcode is wrongly detected. |
146 else: # Barcode file doesn't exist. | 146 else: # Barcode file doesn't exist. |
147 entry += 'Barcode error\n' | 147 entry += 'Barcode error\n' |
148 | 148 |
149 stats_file.write(entry) | 149 stats_file.write(entry) |
150 os.remove(png_frame) | 150 os.remove(png_frame) |
151 | 151 |
152 stats_file.close() | 152 stats_file.close() |
153 | 153 |
154 | 154 |
155 def _read_barcode_from_text_file(barcode_file_name): | 155 def _ReadBarcodeFromTextFile(barcode_file_name): |
156 """Reads the decoded barcode for a .txt file. | 156 """Reads the decoded barcode for a .txt file. |
157 | 157 |
158 Args: | 158 Args: |
159 barcode_file_name(string): The name of the .txt file. | 159 barcode_file_name(string): The name of the .txt file. |
160 Return: | 160 Return: |
161 (string): The decoded barcode. | 161 (string): The decoded barcode. |
162 """ | 162 """ |
163 barcode_file = open(barcode_file_name, 'r') | 163 barcode_file = open(barcode_file_name, 'r') |
164 barcode = barcode_file.read() | 164 barcode = barcode_file.read() |
165 barcode_file.close() | 165 barcode_file.close() |
166 return barcode | 166 return barcode |
167 | 167 |
168 | 168 |
169 def _check_barcode(barcode): | 169 def _CheckBarcode(barcode): |
170 """Check weather the UPC-A barcode was decoded correctly. | 170 """Check weather the UPC-A barcode was decoded correctly. |
171 | 171 |
172 This function calculates the check digit of the provided barcode and compares | 172 This function calculates the check digit of the provided barcode and compares |
173 it to the check digit that was decoded. | 173 it to the check digit that was decoded. |
174 | 174 |
175 Args: | 175 Args: |
176 barcode(string): The barcode (12-digit). | 176 barcode(string): The barcode (12-digit). |
177 Return: | 177 Return: |
178 (bool): True if the barcode was decoded correctly. | 178 (bool): True if the barcode was decoded correctly. |
179 """ | 179 """ |
(...skipping 13 matching lines...) Expand all Loading... | |
193 dsum += int(barcode[i]) | 193 dsum += int(barcode[i]) |
194 # Get the modulo 10 | 194 # Get the modulo 10 |
195 dsum = dsum % 10 | 195 dsum = dsum % 10 |
196 # If not 0 substract from 10 | 196 # If not 0 substract from 10 |
197 if dsum != 0: | 197 if dsum != 0: |
198 dsum = 10 - dsum | 198 dsum = 10 - dsum |
199 # Compare result and check digit | 199 # Compare result and check digit |
200 return dsum == int(barcode[11]) | 200 return dsum == int(barcode[11]) |
201 | 201 |
202 | 202 |
203 def _count_frames_in(input_directory='.'): | 203 def _CountFramesIn(input_directory='.'): |
204 """Calculates the number of frames in the input directory. | 204 """Calculates the number of frames in the input directory. |
205 | 205 |
206 The function calculates the number of frames in the input directory. The | 206 The function calculates the number of frames in the input directory. The |
207 frames should be named frame_xxxx.png, where xxxx is the number of the frame. | 207 frames should be named frame_xxxx.png, where xxxx is the number of the frame. |
208 The numbers should start from 1 and should be consecutive. | 208 The numbers should start from 1 and should be consecutive. |
209 | 209 |
210 Args: | 210 Args: |
211 input_directory(string): The input directory. | 211 input_directory(string): The input directory. |
212 Return: | 212 Return: |
213 (int): The number of frames. | 213 (int): The number of frames. |
214 """ | 214 """ |
215 file_prefix = os.path.join(input_directory, 'frame_') | 215 file_prefix = os.path.join(input_directory, 'frame_') |
216 file_exists = True | 216 file_exists = True |
217 num = 1 | 217 num = 1 |
218 | 218 |
219 while file_exists: | 219 while file_exists: |
220 file_name = (file_prefix + helper_functions.zero_pad(num) + '.png') | 220 file_name = (file_prefix + helper_functions.zero_pad(num) + '.png') |
221 if os.path.isfile(file_name): | 221 if os.path.isfile(file_name): |
222 num += 1 | 222 num += 1 |
223 else: | 223 else: |
224 file_exists = False | 224 file_exists = False |
225 return num - 1 | 225 return num - 1 |
226 | 226 |
227 | 227 |
228 def _parse_args(): | 228 def _ParseArgs(): |
229 """Registers the command-line options.""" | 229 """Registers the command-line options.""" |
230 usage = "usage: %prog [options]" | 230 usage = "usage: %prog [options]" |
231 parser = optparse.OptionParser(usage=usage) | 231 parser = optparse.OptionParser(usage=usage) |
232 | 232 |
233 parser.add_option('--zxing_path', type='string', | 233 parser.add_option('--zxing_path', type='string', |
234 help=('The path to where the zxing executable is located. ' | 234 help=('The path to where the zxing executable is located. ' |
235 'If omitted, it will be assumed to be present in the ' | 235 'If omitted, it will be assumed to be present in the ' |
236 'PATH with the name zxing[.exe].')) | 236 'PATH with the name zxing[.exe].')) |
237 parser.add_option('--ffmpeg_path', type='string', | 237 parser.add_option('--ffmpeg_path', type='string', |
238 help=('The path to where the ffmpeg executable is located. ' | 238 help=('The path to where the ffmpeg executable is located. ' |
(...skipping 10 matching lines...) Expand all Loading... | |
249 parser.add_option('--png_working_dir', type='string', default='.', | 249 parser.add_option('--png_working_dir', type='string', default='.', |
250 help=('The directory for temporary PNG images to be stored ' | 250 help=('The directory for temporary PNG images to be stored ' |
251 'in when decoding from YUV before they\'re barcode ' | 251 'in when decoding from YUV before they\'re barcode ' |
252 'decoded. If using Windows and a Cygwin-compiled ' | 252 'decoded. If using Windows and a Cygwin-compiled ' |
253 'zxing.exe, you should keep the default value to ' | 253 'zxing.exe, you should keep the default value to ' |
254 'avoid problems. Default: %default')) | 254 'avoid problems. Default: %default')) |
255 options, _ = parser.parse_args() | 255 options, _ = parser.parse_args() |
256 return options | 256 return options |
257 | 257 |
258 | 258 |
259 def _main(): | 259 def main(): |
260 """The main function. | 260 """The main function. |
261 | 261 |
262 A simple invocation is: | 262 A simple invocation is: |
263 ./webrtc/tools/barcode_tools/barcode_decoder.py | 263 ./webrtc/tools/barcode_tools/barcode_decoder.py |
264 --yuv_file=<path_and_name_of_overlaid_yuv_video> | 264 --yuv_file=<path_and_name_of_overlaid_yuv_video> |
265 --yuv_frame_width=640 --yuv_frame_height=480 | 265 --yuv_frame_width=640 --yuv_frame_height=480 |
266 --stats_file=<path_and_name_to_stats_file> | 266 --stats_file=<path_and_name_to_stats_file> |
267 """ | 267 """ |
268 options = _parse_args() | 268 options = _ParseArgs() |
269 | 269 |
270 # Convert the overlaid YUV video into a set of PNG frames. | 270 # Convert the overlaid YUV video into a set of PNG frames. |
271 if not convert_yuv_to_png_files(options.yuv_file, options.yuv_frame_width, | 271 if not ConvertYuvToPngFiles(options.yuv_file, options.yuv_frame_width, |
272 options.yuv_frame_height, | 272 options.yuv_frame_height, |
273 output_directory=options.png_working_dir, | 273 output_directory=options.png_working_dir, |
274 ffmpeg_path=options.ffmpeg_path): | 274 ffmpeg_path=options.ffmpeg_path): |
oprypin_webrtc
2017/03/09 08:41:49
Misaligned
kjellander_webrtc
2017/03/09 08:58:13
Done.
| |
275 print 'An error occurred converting from YUV to PNG frames.' | 275 print 'An error occurred converting from YUV to PNG frames.' |
276 return -1 | 276 return -1 |
277 | 277 |
278 # Decode the barcodes from the PNG frames. | 278 # Decode the barcodes from the PNG frames. |
279 if not decode_frames(input_directory=options.png_working_dir, | 279 if not DecodeFrames(input_directory=options.png_working_dir, |
280 zxing_path=options.zxing_path): | 280 zxing_path=options.zxing_path): |
281 print 'An error occurred decoding barcodes from PNG frames.' | 281 print 'An error occurred decoding barcodes from PNG frames.' |
282 return -2 | 282 return -2 |
283 | 283 |
284 # Generate statistics file. | 284 # Generate statistics file. |
285 _generate_stats_file(options.stats_file, | 285 _GenerateStatsFile(options.stats_file, |
286 input_directory=options.png_working_dir) | 286 input_directory=options.png_working_dir) |
oprypin_webrtc
2017/03/09 08:41:49
Misaligned here and above
kjellander_webrtc
2017/03/09 08:58:13
Done.
| |
287 print 'Completed barcode decoding.' | 287 print 'Completed barcode decoding.' |
288 return 0 | 288 return 0 |
289 | 289 |
290 if __name__ == '__main__': | 290 if __name__ == '__main__': |
291 sys.exit(_main()) | 291 sys.exit(main()) |
OLD | NEW |