3
# Foreground Extraction Benchmark
4
# Copyright 2005 Sven Neumann <sven@gimp.org>
6
# This is a from-scratch implementation of the benchmark proposed in
7
# "GrabCut": interactive foreground extraction using iterated graph
8
# cuts published in the Proceedings of the 2004 SIGGRAPH Conference.
10
# No guarantee is made that this benchmark produces the same results
11
# as the cited benchmark but the goal is that it does. So if you find
12
# any bugs or inaccuracies in this code, please let us know.
14
# The benchmark has been adapted work with the SIOX algorithm
15
# (http://www.siox.org). which is (currently) the only
16
# implementation of gimp_drawable_foreground_extract(). If other
17
# implementations are being added, this benchmark should be changed
20
# You will need a set of test images to run this benchmark, preferably
21
# the original set of 50 images. Some of these images are from the
22
# Berkeley Segmentation Dataset
23
# (http://www.cs.berkeley.edu/projects/vision/grouping/segbench/).
24
# See also http://www.siox.org/details.html for trimaps.
26
# This program is free software; you can redistribute it and/or modify
27
# it under the terms of the GNU General Public License as published by
28
# the Free Software Foundation; either version 2 of the License, or
29
# (at your option) any later version.
31
# This program is distributed in the hope that it will be useful,
32
# but WITHOUT ANY WARRANTY; without even the implied warranty of
33
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
# GNU General Public License for more details.
36
# You should have received a copy of the GNU General Public License
37
# along with this program; if not, write to the Free Software
38
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41
import os, re, struct, sys, time
46
def benchmark (folder, save_output):
47
folder = os.path.abspath (folder)
48
if not os.path.exists (folder):
49
gimp.message("Folder '" + folder + "' doesn't exist.\n")
52
total_unclassified = 0
53
total_misclassified = 0
56
images = os.path.join (folder, "images")
57
for name in os.listdir (images):
60
gimp.delete (image_display)
61
gimp.delete (mask_display)
62
except UnboundLocalError:
65
image_name = os.path.join (images, name)
67
# FIXME: improve this!
68
name = re.sub (r'\.jpg$', '', name)
69
name = re.sub (r'\.JPG$', '', name)
70
name = re.sub (r'\.bmp$', '', name)
72
mask_name = os.path.join (folder, "cm_bmp", name + '.png')
73
truth_name = os.path.join (folder, "truth", name + '.bmp')
75
image = pdb.gimp_file_load (image_name, image_name)
76
image_layer = image.active_layer;
78
mask = pdb.gimp_file_load (mask_name, mask_name)
79
convert_grayscale (mask)
80
mask_layer = mask.active_layer;
82
truth = pdb.gimp_file_load (truth_name, truth_name)
83
convert_grayscale (truth)
84
truth_layer = truth.active_layer;
86
unclassified = unclassified_pixels (mask_layer, truth_layer)
88
sys.stderr.write (os.path.basename (image_name))
91
pdb.gimp_drawable_foreground_extract (image_layer,
92
FOREGROUND_EXTRACT_SIOX,
96
sys.stderr.write (" ")
100
# Ignore errors when creating image displays;
101
# allows us to be used without a display.
103
image_display = pdb.gimp_display_new (image)
104
mask_display = pdb.gimp_display_new (mask)
106
gimp.displays_flush ()
113
misclassified = misclassified_pixels (mask_layer, truth_layer)
115
sys.stderr.write ("%d %d %.2f%% %.3fs\n" %
116
(unclassified, misclassified,
117
(misclassified * 100.0 / unclassified),
120
total_unclassified += unclassified
121
total_misclassified += misclassified
122
total_time += end - start
127
filename = os.path.join (folder, "output", name + '.png')
128
pdb.gimp_file_save (mask, mask_layer, filename, filename)
135
gimp.delete (image_display)
136
gimp.delete (mask_display)
137
except UnboundLocalError:
140
sys.stderr.write ("Total: %d %d %.2f%% %.3fs\n" %
141
(total_unclassified, total_misclassified,
142
(total_misclassified * 100.0 / total_unclassified),
145
def convert_grayscale (image):
146
if image.base_type != GRAY:
147
pdb.gimp_image_convert_grayscale (image)
150
def unclassified_pixels (mask, truth):
151
(mean, std_dev, median, pixels,
152
count, percentile) = pdb.gimp_histogram (mask, HISTOGRAM_VALUE, 1, 254)
157
def misclassified_pixels (mask, truth):
160
copy = pdb.gimp_layer_new_from_drawable (mask, image)
161
copy.name = "Difference"
162
copy.mode = DIFFERENCE_MODE
164
image.add_layer (copy, -1)
166
# The assumption made here is that the output of
167
# foreground_extract is a strict black and white mask. The truth
168
# however may contain unclassified pixels. These are considered
169
# unknown, a strict segmentation isn't possible here.
171
# The result of using the Difference mode as done here is that
172
# pure black pixels in the result can be considered correct.
173
# White pixels are wrong. Gray values were unknown in the truth
174
# and thus are not counted as wrong.
176
(mean, std_dev, median, pixels,
177
count, percentile) = pdb.gimp_histogram (image.flatten (),
178
HISTOGRAM_VALUE, 255, 255)
184
"python-fu-benchmark-foreground-extract",
185
"Benchmark and regression test for the SIOX algorithm",
190
"Foreground Extraction",
192
[ (PF_FILE, "image-folder", "Image folder",
193
"~/segmentation/msbench/imagedata"),
194
(PF_TOGGLE, "save-output", "Save output images", False) ],
196
benchmark, menu="<Toolbox>/Xtns/Benchmark")