Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: webrtc/tools/barcode_tools/barcode_decoder.py

Issue 2965593002: Move webrtc/{tools => rtc_tools} (Closed)
Patch Set: Adding back root changes Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/tools/barcode_tools/README ('k') | webrtc/tools/barcode_tools/barcode_encoder.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 #
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
6 # tree. An additional intellectual property rights grant can be found
7 # in the file PATENTS. All contributing project authors may
8 # be found in the AUTHORS file in the root of the source tree.
9
10 import optparse
11 import os
12 import sys
13
14 if __name__ == '__main__':
15 # Make sure we always can import helper_functions.
16 sys.path.append(os.path.dirname(__file__))
17
18 import helper_functions
19
20 # Chrome browsertests will throw away stderr; avoid that output gets lost.
21 sys.stderr = sys.stdout
22
23
24 def ConvertYuvToPngFiles(yuv_file_name, yuv_frame_width, yuv_frame_height,
25 output_directory, ffmpeg_path):
26 """Converts a YUV video file into PNG frames.
27
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.
30
31 Args:
32 yuv_file_name(string): The name of the YUV file.
33 yuv_frame_width(int): The width of one YUV frame.
34 yuv_frame_height(int): The height of one YUV frame.
35 output_directory(string): The output directory where the PNG frames will be
36 stored.
37 ffmpeg_path(string): The path to the ffmpeg executable. If None, the PATH
38 will be searched for it.
39
40 Return:
41 (bool): True if the conversion was OK.
42 """
43 size_string = str(yuv_frame_width) + 'x' + str(yuv_frame_height)
44 output_files_pattern = os.path.join(output_directory, 'frame_%04d.png')
45 if not ffmpeg_path:
46 ffmpeg_path = 'ffmpeg.exe' if sys.platform == 'win32' else 'ffmpeg'
47 command = [ffmpeg_path, '-s', '%s' % size_string, '-i', '%s'
48 % yuv_file_name, '-f', 'image2', '-vcodec', 'png',
49 '%s' % output_files_pattern]
50 try:
51 print 'Converting YUV file to PNG images (may take a while)...'
52 print ' '.join(command)
53 helper_functions.RunShellCommand(
54 command, fail_msg='Error during YUV to PNG conversion')
55 except helper_functions.HelperError, err:
56 print 'Error executing command: %s. Error: %s' % (command, err)
57 return False
58 except OSError:
59 print 'Did not find %s. Have you installed it?' % ffmpeg_path
60 return False
61 return True
62
63
64 def DecodeFrames(input_directory, zxing_path):
65 """Decodes the barcodes overlaid in each frame.
66
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
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.
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
73 format: 11 digits content + one check digit).
74
75 Args:
76 input_directory(string): The input directory from where the PNG frames are
77 read.
78 zxing_path(string): The path to the zxing binary. If specified as None,
79 the PATH will be searched for it.
80 Return:
81 (bool): True if the decoding succeeded.
82 """
83 if not zxing_path:
84 zxing_path = 'zxing.exe' if sys.platform == 'win32' else 'zxing'
85 print 'Decoding barcodes from PNG files with %s...' % zxing_path
86 return helper_functions.PerformActionOnAllFiles(
87 directory=input_directory, file_pattern='frame_',
88 file_extension='png', start_number=1, action=_DecodeBarcodeInFile,
89 command_line_decoder=zxing_path)
90
91
92 def _DecodeBarcodeInFile(file_name, command_line_decoder):
93 """Decodes the barcode in the upper left corner of a PNG file.
94
95 Args:
96 file_name(string): File name of the PNG file.
97 command_line_decoder(string): The ZXing command-line decoding tool.
98
99 Return:
100 (bool): True upon success, False otherwise.
101 """
102 command = [command_line_decoder, '--try-harder', '--dump-raw', file_name]
103 try:
104 out = helper_functions.RunShellCommand(
105 command, fail_msg='Error during decoding of %s' % file_name)
106 text_file = open('%s.txt' % file_name[:-4], 'w')
107 text_file.write(out)
108 text_file.close()
109 except helper_functions.HelperError, err:
110 print 'Barcode in %s cannot be decoded.' % file_name
111 print err
112 return False
113 except OSError:
114 print 'Did not find %s. Have you installed it?' % command_line_decoder
115 return False
116 return True
117
118
119 def _GenerateStatsFile(stats_file_name, input_directory='.'):
120 """Generate statistics file.
121
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
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.
126 """
127 file_prefix = os.path.join(input_directory, 'frame_')
128 stats_file = open(stats_file_name, 'w')
129
130 print 'Generating stats file: %s' % stats_file_name
131 for i in range(1, _CountFramesIn(input_directory=input_directory) + 1):
132 frame_number = helper_functions.ZeroPad(i)
133 barcode_file_name = file_prefix + frame_number + '.txt'
134 png_frame = file_prefix + frame_number + '.png'
135 entry_frame_number = helper_functions.ZeroPad(i-1)
136 entry = 'frame_' + entry_frame_number + ' '
137
138 if os.path.isfile(barcode_file_name):
139 barcode = _ReadBarcodeFromTextFile(barcode_file_name)
140 os.remove(barcode_file_name)
141
142 if _CheckBarcode(barcode):
143 entry += (helper_functions.ZeroPad(int(barcode[0:11])) + '\n')
144 else:
145 entry += 'Barcode error\n' # Barcode is wrongly detected.
146 else: # Barcode file doesn't exist.
147 entry += 'Barcode error\n'
148
149 stats_file.write(entry)
150 os.remove(png_frame)
151
152 stats_file.close()
153
154
155 def _ReadBarcodeFromTextFile(barcode_file_name):
156 """Reads the decoded barcode for a .txt file.
157
158 Args:
159 barcode_file_name(string): The name of the .txt file.
160 Return:
161 (string): The decoded barcode.
162 """
163 barcode_file = open(barcode_file_name, 'r')
164 barcode = barcode_file.read()
165 barcode_file.close()
166 return barcode
167
168
169 def _CheckBarcode(barcode):
170 """Check weather the UPC-A barcode was decoded correctly.
171
172 This function calculates the check digit of the provided barcode and compares
173 it to the check digit that was decoded.
174
175 Args:
176 barcode(string): The barcode (12-digit).
177 Return:
178 (bool): True if the barcode was decoded correctly.
179 """
180 if len(barcode) != 12:
181 return False
182
183 r1 = range(0, 11, 2) # Odd digits
184 r2 = range(1, 10, 2) # Even digits except last
185 dsum = 0
186 # Sum all the even digits
187 for i in r1:
188 dsum += int(barcode[i])
189 # Multiply the sum by 3
190 dsum *= 3
191 # Add all the even digits except the check digit (12th digit)
192 for i in r2:
193 dsum += int(barcode[i])
194 # Get the modulo 10
195 dsum = dsum % 10
196 # If not 0 substract from 10
197 if dsum != 0:
198 dsum = 10 - dsum
199 # Compare result and check digit
200 return dsum == int(barcode[11])
201
202
203 def _CountFramesIn(input_directory='.'):
204 """Calculates the number of frames in the input directory.
205
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.
208 The numbers should start from 1 and should be consecutive.
209
210 Args:
211 input_directory(string): The input directory.
212 Return:
213 (int): The number of frames.
214 """
215 file_prefix = os.path.join(input_directory, 'frame_')
216 file_exists = True
217 num = 1
218
219 while file_exists:
220 file_name = (file_prefix + helper_functions.ZeroPad(num) + '.png')
221 if os.path.isfile(file_name):
222 num += 1
223 else:
224 file_exists = False
225 return num - 1
226
227
228 def _ParseArgs():
229 """Registers the command-line options."""
230 usage = "usage: %prog [options]"
231 parser = optparse.OptionParser(usage=usage)
232
233 parser.add_option('--zxing_path', type='string',
234 help=('The path to where the zxing executable is located. '
235 'If omitted, it will be assumed to be present in the '
236 'PATH with the name zxing[.exe].'))
237 parser.add_option('--ffmpeg_path', type='string',
238 help=('The path to where the ffmpeg executable is located. '
239 'If omitted, it will be assumed to be present in the '
240 'PATH with the name ffmpeg[.exe].'))
241 parser.add_option('--yuv_frame_width', type='int', default=640,
242 help='Width of the YUV file\'s frames. Default: %default')
243 parser.add_option('--yuv_frame_height', type='int', default=480,
244 help='Height of the YUV file\'s frames. Default: %default')
245 parser.add_option('--yuv_file', type='string', default='output.yuv',
246 help='The YUV file to be decoded. Default: %default')
247 parser.add_option('--stats_file', type='string', default='stats.txt',
248 help='The output stats file. Default: %default')
249 parser.add_option('--png_working_dir', type='string', default='.',
250 help=('The directory for temporary PNG images to be stored '
251 'in when decoding from YUV before they\'re barcode '
252 'decoded. If using Windows and a Cygwin-compiled '
253 'zxing.exe, you should keep the default value to '
254 'avoid problems. Default: %default'))
255 options, _ = parser.parse_args()
256 return options
257
258
259 def main():
260 """The main function.
261
262 A simple invocation is:
263 ./webrtc/tools/barcode_tools/barcode_decoder.py
264 --yuv_file=<path_and_name_of_overlaid_yuv_video>
265 --yuv_frame_width=640 --yuv_frame_height=480
266 --stats_file=<path_and_name_to_stats_file>
267 """
268 options = _ParseArgs()
269
270 # Convert the overlaid YUV video into a set of PNG frames.
271 if not ConvertYuvToPngFiles(options.yuv_file, options.yuv_frame_width,
272 options.yuv_frame_height,
273 output_directory=options.png_working_dir,
274 ffmpeg_path=options.ffmpeg_path):
275 print 'An error occurred converting from YUV to PNG frames.'
276 return -1
277
278 # Decode the barcodes from the PNG frames.
279 if not DecodeFrames(input_directory=options.png_working_dir,
280 zxing_path=options.zxing_path):
281 print 'An error occurred decoding barcodes from PNG frames.'
282 return -2
283
284 # Generate statistics file.
285 _GenerateStatsFile(options.stats_file,
286 input_directory=options.png_working_dir)
287 print 'Completed barcode decoding.'
288 return 0
289
290 if __name__ == '__main__':
291 sys.exit(main())
OLDNEW
« no previous file with comments | « webrtc/tools/barcode_tools/README ('k') | webrtc/tools/barcode_tools/barcode_encoder.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698