summaryrefslogtreecommitdiffstats
path: root/src/trace/siox.h
blob: 5d36a71f660e13540fdbe80fc84ca506d58f0266 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
#ifndef __SIOX_SEGMENTATOR_H__
#define __SIOX_SEGMENTATOR_H__
/*
   Copyright 2005, 2006 by Gerald Friedland, Kristian Jantz and Lars Knipping

   Conversion to C++ for Inkscape by Bob Jamison

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

#include <map>
#include <vector>

namespace org
{
namespace siox
{

/**
 * Image segmentator based on
 *<em>SIOX: Simple Interactive Object Extraction</em>.
 * <P>
 * To segmentate an image one has to perform the following steps.
 * <OL><LI>Construct an instance of <code>SioxSegmentator</code>.
 * </LI><LI>Create a confidence matrix, where each entry marks its
 *      corresponding image pixel to belong to the foreground, to the
 *      background, or being of unknown type.
 * </LI><LI>Call <code>segmentate</code> on the image with the confidence
 *       matrix. This stores the result as new foreground confidence into
 *       the confidence matrix, with each entry being either
 *       zero (<code>CERTAIN_BACKGROUND_CONFIDENCE</code>) or one
 *       (<code>CERTAIN_FOREGROUND_CONFIDENCE</code>).
 * </LI><LI>Optionally call <code>subpixelRefine</code> to areas
 *      where pixels contain both foreground and background (e.g.
 *      object borders or highly detailed features like flowing hairs).
 *      The pixel are then assigned confidence values bwetween zero and
 *      one to give them a measure of "foregroundness".
 *      This step may be repeated as often as needed.
 * </LI></OL>
 * <P>
 * For algorithm documentation refer to
 * G. Friedland, K. Jantz, L. Knipping, R. Rojas:<i>
 * Image Segmentation by Uniform Color Clustering
 *  -- Approach and Benchmark Results</i>,
 * <A HREF="http://www.inf.fu-berlin.de/inst/pubs/tr-b-05-07.pdf">Technical Report B-05-07</A>,
 * Department of Computer Science, Freie Universitaet Berlin, June 2005.<br>
 * <P>
 * See <A HREF="http://www.siox.org/" target="_new">http://www.siox.org</A> for more information.<br>
 * <P>
 * Algorithm idea by Gerald Friedland.
 *
 * @author Gerald Friedland, Kristian Jantz, Lars Knipping
 * @version 1.12
 */

/**
 * Helper class for storing the minimum distances to a cluster centroid
 * in background and foreground and the index to the centroids in each
 * signature for a given color.
 */
class Tupel {
public:

    Tupel()
        {
        minBgDist  = 0.0f;
        indexMinBg = 0;
        minFgDist  = 0.0f;
        indexMinFg = 0;
        }
    Tupel(float minBgDistArg, long indexMinBgArg,
          float minFgDistArg, long indexMinFgArg)
        {
	minBgDist  = minBgDistArg;
	indexMinBg = indexMinBgArg;
	minFgDist  = minFgDistArg;
	indexMinFg = indexMinFgArg;
        }
    Tupel(const Tupel &other)
        {
	minBgDist  = other.minBgDist;
	indexMinBg = other.indexMinBg;
	minFgDist  = other.minFgDist;
	indexMinFg = other.indexMinFg;
        }
    Tupel &operator=(const Tupel &other)
        {
	minBgDist  = other.minBgDist;
	indexMinBg = other.indexMinBg;
	minFgDist  = other.minFgDist;
	indexMinFg = other.indexMinFg;
	return *this;
        }
    virtual ~Tupel()
        {}

    float minBgDist;
    long  indexMinBg;
    float minFgDist;
    long  indexMinFg;

 };


class CLAB
{
public:
    CLAB()
        {
        C = L = A = B = 0.0f;
        }
    CLAB(float lArg, float aArg, float bArg)
        {
        C = 0.0f;
        L = lArg;
        A = aArg;
        B = bArg;
        }
    CLAB(const CLAB &other)
        {
        C = other.C;
        L = other.L;
        A = other.A;
        B = other.B;
        }
    CLAB &operator=(const CLAB &other)
        {
        C = other.C;
        L = other.L;
        A = other.A;
        B = other.B;
        return *this;
        }
    virtual ~CLAB()
        {}

    float C;
    float L;
    float A;
    float B;
};


class SioxSegmentator
{
public:

    /** Confidence corresponding to a certain foreground region (equals one). */
    static const float CERTAIN_FOREGROUND_CONFIDENCE;  //=1.0f;

    /** Confidence for a region likely being foreground.*/
    static const float FOREGROUND_CONFIDENCE;  //=0.8f;

    /** Confidence for foreground or background type being equally likely.*/
    static const float UNKNOWN_REGION_CONFIDENCE;  //=0.5f;

    /** Confidence for a region likely being background.*/
    static const float BACKGROUND_CONFIDENCE;  //=0.1f;

    /** Confidence corresponding to a certain background reagion (equals zero). */
    static const float CERTAIN_BACKGROUND_CONFIDENCE;  //=0.0f;


    /**
     * Constructs a SioxSegmentator Object to be used for image segmentation.
     *
     * @param w X resolution of the image to be segmentated.
     * @param h Y resolution of the image to be segmentated.
     * @param limits Size of the cluster on LAB axises.
     *        If <code>null</code>, the default value {0.64f,1.28f,2.56f}
     *        is used.
     */
    SioxSegmentator(int w, int h, float *limitsArg, int limitsSize);

    /**
     * Destructor
     */
    virtual ~SioxSegmentator();


    /**
     * Segmentates the given image with information from the confidence
     * matrix.
     * <P>
     * The confidence entries  of <code>BACKGROUND_CONFIDENCE</code> or less
     * are mark known background pixel for the segmentation, those
     * of at least <code>FOREGROUND_CONFIDENCE</code> mark known
     * foreground pixel for the segmentation. Any other entry is treated
     * as region of unknown affiliation.
     * <P>
     * As result, each pixel is classified either as foregroound or
     * background, stored back into its <code>cm</code> entry as confidence
     * <code>CERTAIN_FOREGROUND_CONFIDENCE</code> or
     * <code>CERTAIN_BACKGROUND_CONFIDENCE</code>.
     *
     * @param image Pixel data of the image to be segmentated.
     *        Every integer represents one ARGB-value.
     * @param cm Confidence matrix specifying the probability of an image
     *        belonging to the foreground before and after the segmentation.
     * @param smoothness Number of smoothing steps in the post processing.
     *        Both arrays should be width * height in size.
     * @param sizeFactorToKeep Segmentation retains the largest connected
     *        foreground component plus any component with size at least
     *        <CODE>sizeOfLargestComponent/sizeFactorToKeep</CODE>.
     * @return <CODE>true</CODE> if the segmentation algorithm succeeded,
     *         <CODE>false</CODE> if segmentation is impossible
     */
    bool segmentate(unsigned long *image, float *cm,
                    int smoothness, double sizeFactorToKeep);

    /**
     * Clears given confidence matrix except entries for the largest connected
     * component and every component with
     * <CODE>size*sizeFactorToKeep >= sizeOfLargestComponent</CODE>.
     *
     * @param cm  Confidence matrix to be analysed
     * @param threshold Pixel visibility threshold.
     *        Exactly those cm entries larger than threshold are considered
     *        to be a "visible" foreground pixel.
     * @param sizeFactorToKeep This method keeps the largest connected
     *        component plus any component with size at least
     *        <CODE>sizeOfLargestComponent/sizeFactorToKeep</CODE>.
     */
    void keepOnlyLargeComponents(float *cm,
                                 float threshold,
                                 double sizeFactorToKeep);

    /**
     * Depth first search pixels in a foreground component.
     *
     * @param cm confidence matrix to be searched.
     * @param i starting position as index to confidence matrix.
     * @param threshold defines the minimum value at which a pixel is
     *        considered foreground.
     * @param curlabel label no of component.
     * @return size in pixel of the component found.
     */
    int depthFirstSearch(float *cm, int i, float threshold, int curLabel);

    /**
     * Refines the classification stored in the confidence matrix by modifying
     * the confidences for regions which have characteristics to both
     * foreground and background if they fall into the specified square.
     * <P>
     * The can be used in displaying the image by assigning the alpha values
     * of the pixels according to the confidence entries.
     * <P>
     * In the algorithm descriptions and examples GUIs this step is referrered
     * to as <EM>Detail Refinement (Brush)</EM>.
     *
     * @param x Horizontal coordinate of the squares center.
     * @param y Vertical coordinate of the squares center.
     * @param brushmode Mode of the refinement applied, <CODE>ADD_EDGE</CODE>
     *        or <CODE>SUB_EDGE</CODE>. Add mode only modifies pixels
     *        formerly classified as background, sub mode only those
     *        formerly classified as foreground.
     * @param threshold Threshold for the add and sub refinement, deciding
     *        at the confidence level to stop at.
     * @param cf The confidence matrix to modify, generated by
     *        <CODE>segmentate</CODE>, possibly already refined by privious
     *        calls to <CODE>subpixelRefine</CODE>.
     * @param brushsize Halfed diameter of the square shaped brush.
     *
     * @see #segmentate
     */
    void subpixelRefine(int x, int y, int brushmode,
                             float threshold, float *cf, int brushsize);

    /**
     * Refines the classification stored in the confidence matrix by modifying
     * the confidences for regions which have characteristics to both
     * foreground and background if they fall into the specified area.
     * <P>
     * The can be used in displaying the image by assigning the alpha values
     * of the pixels according to the confidence entries.
     * <P>
     * In the algorithm descriptions and examples GUIs this step is referrered
     * to as <EM>Detail Refinement (Brush)</EM>.
     *
     * @param area Area in which the reworking of the segmentation is
     *        applied to.
     * @param brushmode Mode of the refinement applied, <CODE>ADD_EDGE</CODE>
     *        or <CODE>SUB_EDGE</CODE>. Add mode only modifies pixels
     *        formerly classified as background, sub mode only those
     *        formerly classified as foreground.
     * @param threshold Threshold for the add and sub refinement, deciding
     *        at the confidence level to stop at.
     * @param cf The confidence matrix to modify, generated by
     *        <CODE>segmentate</CODE>, possibly already refined by privious
     *        calls to <CODE>subpixelRefine</CODE>.
     *
     * @see #segmentate
     */
    bool subpixelRefine(int xa, int ya, int dx, int dy,
                                     int brushmode,
                                     float threshold, float *cf);
    /**
     * A region growing algorithms used to fill up the confidence matrix
     * with <CODE>CERTAIN_FOREGROUND_CONFIDENCE</CODE> for corresponding
     * areas of equal colors.
     * <P>
     * Basically, the method works like the <EM>Magic Wand<EM> with a
     * tolerance threshold of zero.
     *
     * @param cm confidence matrix to be searched
     * @param image image to be searched
     */
    void fillColorRegions(float *cm, unsigned long *image);

private:

    /**
     * Prevent this from being used
     */
    SioxSegmentator();

    /** error logging **/
    void error(char *format, ...);

    /** trace logging **/
    void trace(char *format, ...);

    typedef enum
        {
        ADD_EDGE, /** Add mode for the subpixel refinement. */
        SUB_EDGE  /** Subtract mode for the subpixel refinement. */
        } BrushMode;

    // instance fields:

    /** Horizontal resolution of the image to be segmentated. */
    int imgWidth;

    /** Vertical resolution of the image to be segmentated. */
    int imgHeight;

    /** Number of pixels and/or confidence matrix values to process.
        equal to imgWidth * imgHeight
    */
    long pixelCount;

    /** Stores component label (index) by pixel it belongs to. */
    int *labelField;

    /**
     * LAB color values of pixels that are definitly known background.
     * Entries are of form {l,a,b}.
     */
    std::vector<CLAB> knownBg;

    /**
     * LAB color values of pixels that are definitly known foreground.
     * Entries are of form {l,a,b}.
     */
    std::vector<CLAB> knownFg;

    /** Holds background signature (a characteristic subset of the bg.) */
    std::vector<CLAB> bgSignature;

    /** Holds foreground signature (a characteristic subset of the fg).*/
    std::vector<CLAB> fgSignature;

    /** Size of cluster on lab axis. */
    float *limits;

    /** Maximum distance of two lab values. */
    float clusterSize;

    /**
     * Stores Tupels for fast access to nearest background/foreground pixels.
     */
    std::map<unsigned long, Tupel> hs;

    /** Size of the biggest blob.*/
    int regionCount;

    /** Copy of the original image, needed for detail refinement. */
    long *origImage;
    long origImageSize;

    /** A flag that stores if the segmentation algorithm has already ran.*/
    bool segmentated;

};

} //namespace siox
} //namespace org

#endif /* __SIOX_SEGMENTATOR_H__ */