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

Side by Side Diff: gm/rebaseline_server/imagediffdb.py

Issue 169943002: rebaseline_server: fail fast if skpdiff binary is not available (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: retry after "error: old chunk mismatch" Created 6 years, 10 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 """ 3 """
4 Copyright 2013 Google Inc. 4 Copyright 2013 Google Inc.
5 5
6 Use of this source code is governed by a BSD-style license that can be 6 Use of this source code is governed by a BSD-style license that can be
7 found in the LICENSE file. 7 found in the LICENSE file.
8 8
9 Calulate differences between image pairs, and store them in a database. 9 Calulate differences between image pairs, and store them in a database.
10 """ 10 """
(...skipping 13 matching lines...) Expand all
24 raise ImportError('Requires PIL to be installed; see ' 24 raise ImportError('Requires PIL to be installed; see '
25 + 'http://www.pythonware.com/products/pil/') 25 + 'http://www.pythonware.com/products/pil/')
26 26
27 # Set the PYTHONPATH to include the tools directory. 27 # Set the PYTHONPATH to include the tools directory.
28 sys.path.append( 28 sys.path.append(
29 os.path.join( 29 os.path.join(
30 os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, 30 os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir,
31 'tools')) 31 'tools'))
32 import find_run_binary 32 import find_run_binary
33 33
34 SKPDIFF_BINARY_NAME = 'skpdiff' 34 SKPDIFF_BINARY = find_run_binary.find_path_to_program('skpdiff')
35 35
36 DEFAULT_IMAGE_SUFFIX = '.png' 36 DEFAULT_IMAGE_SUFFIX = '.png'
37 DEFAULT_IMAGES_SUBDIR = 'images' 37 DEFAULT_IMAGES_SUBDIR = 'images'
38 38
39 DISALLOWED_FILEPATH_CHAR_REGEX = re.compile('[^\w\-]') 39 DISALLOWED_FILEPATH_CHAR_REGEX = re.compile('[^\w\-]')
40 40
41 DIFFS_SUBDIR = 'diffs' 41 DIFFS_SUBDIR = 'diffs'
42 WHITEDIFFS_SUBDIR = 'whitediffs' 42 WHITEDIFFS_SUBDIR = 'whitediffs'
43 43
44 VALUES_PER_BAND = 256 44 VALUES_PER_BAND = 256
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 bands = diff_image.split() 108 bands = diff_image.split()
109 graydiff_image = ImageChops.lighter(ImageChops.lighter( 109 graydiff_image = ImageChops.lighter(ImageChops.lighter(
110 bands[0], bands[1]), bands[2]) 110 bands[0], bands[1]), bands[2])
111 whitediff_image = (graydiff_image.point(lambda p: p > 0 and VALUES_PER_BAND) 111 whitediff_image = (graydiff_image.point(lambda p: p > 0 and VALUES_PER_BAND)
112 .convert('1', dither=Image.NONE)) 112 .convert('1', dither=Image.NONE))
113 113
114 # Calculate the perceptual difference percentage. 114 # Calculate the perceptual difference percentage.
115 skpdiff_csv_dir = tempfile.mkdtemp() 115 skpdiff_csv_dir = tempfile.mkdtemp()
116 try: 116 try:
117 skpdiff_csv_output = os.path.join(skpdiff_csv_dir, 'skpdiff-output.csv') 117 skpdiff_csv_output = os.path.join(skpdiff_csv_dir, 'skpdiff-output.csv')
118 skpdiff_binary = find_run_binary.find_path_to_program(SKPDIFF_BINARY_NAME)
119 expected_img = os.path.join(storage_root, expected_images_subdir, 118 expected_img = os.path.join(storage_root, expected_images_subdir,
120 str(expected_image_locator) + image_suffix) 119 str(expected_image_locator) + image_suffix)
121 actual_img = os.path.join(storage_root, actual_images_subdir, 120 actual_img = os.path.join(storage_root, actual_images_subdir,
122 str(actual_image_locator) + image_suffix) 121 str(actual_image_locator) + image_suffix)
123 find_run_binary.run_command( 122 find_run_binary.run_command(
124 [skpdiff_binary, '-p', expected_img, actual_img, 123 [SKPDIFF_BINARY, '-p', expected_img, actual_img,
125 '--csv', skpdiff_csv_output, '-d', 'perceptual']) 124 '--csv', skpdiff_csv_output, '-d', 'perceptual'])
126 with contextlib.closing(open(skpdiff_csv_output)) as csv_file: 125 with contextlib.closing(open(skpdiff_csv_output)) as csv_file:
127 for row in csv.DictReader(csv_file): 126 for row in csv.DictReader(csv_file):
128 perceptual_similarity = float(row[' perceptual'].strip()) 127 perceptual_similarity = float(row[' perceptual'].strip())
129 if not 0 <= perceptual_similarity <= 1: 128 if not 0 <= perceptual_similarity <= 1:
130 # skpdiff outputs -1 if the images are different sizes. Treat any 129 # skpdiff outputs -1 if the images are different sizes. Treat any
131 # output that does not lie in [0, 1] as having 0% perceptual 130 # output that does not lie in [0, 1] as having 0% perceptual
132 # similarity. 131 # similarity.
133 perceptual_similarity = 0 132 perceptual_similarity = 0
134 # skpdiff returns the perceptual similarity, convert it to get the 133 # skpdiff returns the perceptual similarity, convert it to get the
(...skipping 30 matching lines...) Expand all
165 0 and 100 (inclusive).""" 164 0 and 100 (inclusive)."""
166 return ((float(self._num_pixels_differing) * 100) / 165 return ((float(self._num_pixels_differing) * 100) /
167 (self._width * self._height)) 166 (self._width * self._height))
168 167
169 def get_perceptual_difference(self): 168 def get_perceptual_difference(self):
170 """Returns the perceptual difference percentage.""" 169 """Returns the perceptual difference percentage."""
171 return self._perceptual_difference 170 return self._perceptual_difference
172 171
173 def get_weighted_diff_measure(self): 172 def get_weighted_diff_measure(self):
174 """Returns a weighted measure of image diffs, as a float between 0 and 100 173 """Returns a weighted measure of image diffs, as a float between 0 and 100
175 (inclusive).""" 174 (inclusive).
175
176 TODO(epoger): Delete this function, now that we have perceptual diff?
177 """
176 return self._weighted_diff_measure 178 return self._weighted_diff_measure
177 179
178 def get_max_diff_per_channel(self): 180 def get_max_diff_per_channel(self):
179 """Returns the maximum difference between the expected and actual images 181 """Returns the maximum difference between the expected and actual images
180 for each R/G/B channel, as a list.""" 182 for each R/G/B channel, as a list."""
181 return self._max_diff_per_channel 183 return self._max_diff_per_channel
182 184
183 def as_dict(self): 185 def as_dict(self):
184 """Returns a dictionary representation of this DiffRecord, as needed when 186 """Returns a dictionary representation of this DiffRecord, as needed when
185 constructing the JSON representation.""" 187 constructing the JSON representation."""
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 return self._diff_dict[key] 260 return self._diff_dict[key]
259 261
260 262
261 # Utility functions 263 # Utility functions
262 264
263 def _calculate_weighted_diff_metric(histogram, num_pixels): 265 def _calculate_weighted_diff_metric(histogram, num_pixels):
264 """Given the histogram of a diff image (per-channel diff at each 266 """Given the histogram of a diff image (per-channel diff at each
265 pixel between two images), calculate the weighted diff metric (a 267 pixel between two images), calculate the weighted diff metric (a
266 stab at how different the two images really are). 268 stab at how different the two images really are).
267 269
270 TODO(epoger): Delete this function, now that we have perceptual diff?
271
268 Args: 272 Args:
269 histogram: PIL histogram of a per-channel diff between two images 273 histogram: PIL histogram of a per-channel diff between two images
270 num_pixels: integer; the total number of pixels in the diff image 274 num_pixels: integer; the total number of pixels in the diff image
271 275
272 Returns: a weighted diff metric, as a float between 0 and 100 (inclusive). 276 Returns: a weighted diff metric, as a float between 0 and 100 (inclusive).
273 """ 277 """
274 # TODO(epoger): As a wild guess at an appropriate metric, weight each 278 # TODO(epoger): As a wild guess at an appropriate metric, weight each
275 # different pixel by the square of its delta value. (The more different 279 # different pixel by the square of its delta value. (The more different
276 # a pixel is from its expectation, the more we care about it.) 280 # a pixel is from its expectation, the more we care about it.)
277 # In the long term, we will probably use some metric generated by
278 # skpdiff anyway.
279 assert(len(histogram) % VALUES_PER_BAND == 0) 281 assert(len(histogram) % VALUES_PER_BAND == 0)
280 num_bands = len(histogram) / VALUES_PER_BAND 282 num_bands = len(histogram) / VALUES_PER_BAND
281 max_diff = num_pixels * num_bands * (VALUES_PER_BAND - 1)**2 283 max_diff = num_pixels * num_bands * (VALUES_PER_BAND - 1)**2
282 total_diff = 0 284 total_diff = 0
283 for index in xrange(len(histogram)): 285 for index in xrange(len(histogram)):
284 total_diff += histogram[index] * (index % VALUES_PER_BAND)**2 286 total_diff += histogram[index] * (index % VALUES_PER_BAND)**2
285 return float(100 * total_diff) / max_diff 287 return float(100 * total_diff) / max_diff
286 288
287 def _max_per_band(histogram): 289 def _max_per_band(histogram):
288 """Given the histogram of an image, return the maximum value of each band 290 """Given the histogram of an image, return the maximum value of each band
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 400
399 Args: 401 Args:
400 expected_image_locator: locator string pointing at expected image 402 expected_image_locator: locator string pointing at expected image
401 actual_image_locator: locator string pointing at actual image 403 actual_image_locator: locator string pointing at actual image
402 404
403 Returns: already-sanitized locator where the diffs between expected and 405 Returns: already-sanitized locator where the diffs between expected and
404 actual images can be found 406 actual images can be found
405 """ 407 """
406 return "%s-vs-%s" % (_sanitize_locator(expected_image_locator), 408 return "%s-vs-%s" % (_sanitize_locator(expected_image_locator),
407 _sanitize_locator(actual_image_locator)) 409 _sanitize_locator(actual_image_locator))
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698