Chromium Code Reviews| 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 |