mirror of https://github.com/GNOME/gimp.git
app/base/Makefile.am renamed to siox.[ch].
2005-07-13 Sven Neumann <sven@gimp.org> * app/base/Makefile.am * app/base/segmentator.[ch]: renamed to siox.[ch]. * app/base/siox.[ch]: added API docs and a link to the algorithm's new homepage. Removed unused code. * app/core/gimpdrawable-foreground-extract.c: changed accordingly.
This commit is contained in:
parent
65e26d5b30
commit
70aa10cef7
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2005-07-13 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/base/Makefile.am
|
||||
* app/base/segmentator.[ch]: renamed to siox.[ch].
|
||||
|
||||
* app/base/siox.[ch]: added API docs and a link to the algorithm's
|
||||
new homepage. Removed unused code.
|
||||
|
||||
* app/core/gimpdrawable-foreground-extract.c: changed accordingly.
|
||||
|
||||
2005-07-13 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
* app/core/gimppalette.c (gimp_palette_add_entry): actually return
|
||||
|
|
|
@ -36,8 +36,8 @@ libappbase_a_SOURCES = \
|
|||
pixel-region.h \
|
||||
pixel-surround.c \
|
||||
pixel-surround.h \
|
||||
segmentator.c \
|
||||
segmentator.h \
|
||||
siox.c \
|
||||
siox.h \
|
||||
temp-buf.c \
|
||||
temp-buf.h \
|
||||
threshold.c \
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* The GIMP Foreground Extraction Utility
|
||||
* segmentator.c - main algorithm.
|
||||
*
|
||||
* For algorithm documentation refer to:
|
||||
* G. Friedland, K. Jantz, L. Knipping, R. Rojas:
|
||||
* "Image Segmentation by Uniform Color Clustering
|
||||
* -- Approach and Benchmark Results",
|
||||
* Technical Report B-05-07, Department of Computer Science,
|
||||
* Freie Universitaet Berlin, June 2005.
|
||||
* http://www.inf.fu-berlin.de/inst/pubs/tr-b-05-07.pdf
|
||||
*
|
||||
* Algorithm idea by Gerald Friedland.
|
||||
* This implementation is Copyright (C) 2005
|
||||
* by Gerald Friedland <fland@inf.fu-berlin.de>
|
||||
* and Kristian Jantz <jantz@inf.fu-berlin.de>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SEGMENTATOR_H__
|
||||
#define __SEGMENTATOR_H__
|
||||
|
||||
|
||||
/* Amount of color dimensions in one point */
|
||||
#define DIMS 3
|
||||
|
||||
|
||||
void foreground_extract (TileManager *tiles,
|
||||
TileManager *trimap,
|
||||
gfloat limits[DIMS],
|
||||
gint smoothness);
|
||||
|
||||
|
||||
#endif /* __SEGMENTATOR_H__ */
|
311
app/base/siox.c
311
app/base/siox.c
|
@ -10,6 +10,8 @@
|
|||
* Freie Universitaet Berlin, June 2005.
|
||||
* http://www.inf.fu-berlin.de/inst/pubs/tr-b-05-07.pdf
|
||||
*
|
||||
* See http://www.siox.org/ for more information.
|
||||
*
|
||||
* Algorithm idea by Gerald Friedland.
|
||||
* This implementation is Copyright (C) 2005
|
||||
* by Gerald Friedland <fland@inf.fu-berlin.de>
|
||||
|
@ -42,7 +44,7 @@
|
|||
#include "paint-funcs/paint-funcs.h"
|
||||
|
||||
#include "pixel-region.h"
|
||||
#include "segmentator.h"
|
||||
#include "siox.h"
|
||||
#include "tile-manager.h"
|
||||
|
||||
|
||||
|
@ -214,7 +216,7 @@ stageone (lab *points,
|
|||
int dims,
|
||||
int depth,
|
||||
ArrayList *clusters,
|
||||
float limits[DIMS],
|
||||
float limits[SIOX_DIMS],
|
||||
int length)
|
||||
{
|
||||
int curdim = depth % dims;
|
||||
|
@ -329,7 +331,7 @@ stagetwo (lab *points,
|
|||
int dims,
|
||||
int depth,
|
||||
ArrayList *clusters,
|
||||
float limits[DIMS],
|
||||
float limits[SIOX_DIMS],
|
||||
int length,
|
||||
int total,
|
||||
float threshold)
|
||||
|
@ -483,7 +485,7 @@ euklid (const lab p,
|
|||
static lab *
|
||||
create_signature (lab *input,
|
||||
int length,
|
||||
float limits[DIMS],
|
||||
float limits[SIOX_DIMS],
|
||||
int *returnlength)
|
||||
{
|
||||
ArrayList *clusters1;
|
||||
|
@ -504,7 +506,7 @@ create_signature (lab *input,
|
|||
|
||||
clusters1 = g_new0 (ArrayList, 1);
|
||||
|
||||
stageone (input, DIMS, 0, clusters1, limits, length);
|
||||
stageone (input, SIOX_DIMS, 0, clusters1, limits, length);
|
||||
clusters1size = list_size (clusters1);
|
||||
centroids = g_new (lab, clusters1size);
|
||||
curelem = clusters1;
|
||||
|
@ -536,7 +538,7 @@ create_signature (lab *input,
|
|||
|
||||
clusters2 = g_new0 (ArrayList, 1);
|
||||
|
||||
stagetwo (centroids, DIMS, 0, clusters2, limits, clusters1size, length, 0.1);
|
||||
stagetwo (centroids, SIOX_DIMS, 0, clusters2, limits, clusters1size, length, 0.1);
|
||||
|
||||
/* see paper by tomasi */
|
||||
rval = list_to_array (clusters2, returnlength);
|
||||
|
@ -776,7 +778,7 @@ find_max_blob (TileManager *mask,
|
|||
|
||||
/* Returns squared clustersize */
|
||||
static gfloat
|
||||
getclustersize (const float limits[DIMS])
|
||||
getclustersize (const float limits[SIOX_DIMS])
|
||||
{
|
||||
float sum = (limits[0] - (-limits[0])) * (limits[0] - (-limits[0]));
|
||||
|
||||
|
@ -787,25 +789,22 @@ getclustersize (const float limits[DIMS])
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Call this method:
|
||||
* rgbs - the picture
|
||||
* confidencematrix - a confidencematrix with values <=0.1 is sure background,
|
||||
* >=0.9 is sure foreground, rest unknown
|
||||
* xres, yres - the dimensions of the picture and the confidencematrix
|
||||
* limits - a three dimensional float array specifing the accuracy
|
||||
* a good value is: {0.66,1.25,2.5}
|
||||
* int smoothness - specifies how smooth the boundaries of a picture should
|
||||
* be made (value greater or equal to 0).
|
||||
* More smooth = fault tolerant,
|
||||
* less smooth = exact boundaries - try 3 for a first guess.
|
||||
* returns and writes into the confidencematrix the resulting segmentation
|
||||
/**
|
||||
* siox_foreground_extract:
|
||||
* @pixels: the tiles to extract the foreground from
|
||||
* @mask: a trimap indicating sure foreground, sure background and
|
||||
* undecided regions
|
||||
* @limits: a three dimensional float array specifing the accuracy,
|
||||
* a good value is: { 0.66, 1.25, 2.5 }
|
||||
* @smoothness: boundary smoothness (a good value is 3)
|
||||
*
|
||||
* Writes the resulting segmentation into @mask.
|
||||
*/
|
||||
void
|
||||
foreground_extract (TileManager *pixels,
|
||||
TileManager *mask,
|
||||
gfloat limits[DIMS],
|
||||
gint smoothness)
|
||||
siox_foreground_extract (TileManager *pixels,
|
||||
TileManager *mask,
|
||||
gfloat limits[SIOX_DIMS],
|
||||
gint smoothness)
|
||||
{
|
||||
gfloat clustersize = getclustersize (limits);
|
||||
gint surebgcount = 0;
|
||||
|
@ -1013,267 +1012,3 @@ foreground_extract (TileManager *pixels,
|
|||
/* Now dilate, to fill up boundary pixels killed by erode */
|
||||
dilate_mask (mask, 0, 0, width, height);
|
||||
}
|
||||
|
||||
|
||||
/************ Unused functions, for reference ***************/
|
||||
|
||||
/* calculates alpha \times Confidencematrix */
|
||||
static void
|
||||
premultiply_matrix (float alpha,
|
||||
float *cm,
|
||||
int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
cm[i] = alpha * cm[i];
|
||||
}
|
||||
|
||||
/* Normalizes a confidencematrix */
|
||||
static void
|
||||
normalize_matrix (float *cm,
|
||||
int length)
|
||||
{
|
||||
float max = 0.0;
|
||||
float alpha = 0.0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
if (max < cm[i])
|
||||
max = cm[i];
|
||||
}
|
||||
|
||||
if (max <= 0.0)
|
||||
return;
|
||||
if (max == 1.00)
|
||||
return;
|
||||
|
||||
alpha = 1.00f / max;
|
||||
premultiply_matrix (alpha, cm, length);
|
||||
}
|
||||
|
||||
/* A confidence matrix eroder */
|
||||
static void
|
||||
erode2 (float *cm,
|
||||
int xres,
|
||||
int yres)
|
||||
{
|
||||
int idx, x, y;
|
||||
|
||||
/* From right */
|
||||
for (y = 0; y < yres; y++)
|
||||
{
|
||||
for (x = 0; x < xres - 1; x++)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] = MIN (cm[idx], cm[idx + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* From left */
|
||||
for (y = 0; y < yres; y++)
|
||||
{
|
||||
for (x = xres - 1; x >= 1; x--)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] = MIN (cm[idx - 1], cm[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
/* From down */
|
||||
for (y = 0; y < yres - 1; y++)
|
||||
{
|
||||
for (x = 0; x < xres; x++)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] = MIN (cm[idx], cm[((y + 1) * xres) + x]);
|
||||
}
|
||||
}
|
||||
|
||||
/* From up */
|
||||
for (y = yres - 1; y >= 1; y--)
|
||||
{
|
||||
for (x = 0; x < xres; x++)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] = MIN (cm[((y - 1) * xres) + x], cm[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* A confidence matrix dilater */
|
||||
static void
|
||||
dilate2 (float *cm,
|
||||
int xres,
|
||||
int yres)
|
||||
{
|
||||
int x, y, idx;
|
||||
|
||||
/* From right */
|
||||
for (y = 0; y < yres; y++)
|
||||
{
|
||||
for (x = 0; x < xres - 1; x++) {
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] = MAX (cm[idx], cm[idx + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* From left */
|
||||
for (y = 0; y < yres; y++)
|
||||
{
|
||||
for (x = xres - 1; x >= 1; x--)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] = MAX (cm[idx - 1], cm[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
/* From down */
|
||||
for (y = 0; y < yres - 1; y++)
|
||||
{
|
||||
for (x = 0; x < xres; x++)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] = MAX (cm[idx], cm[((y + 1) * xres) + x]);
|
||||
}
|
||||
}
|
||||
|
||||
/* From up */
|
||||
for (y = yres - 1; y >= 1; y--)
|
||||
{
|
||||
for (x = 0; x < xres; x++)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] = MAX (cm[((y - 1) * xres) + x], cm[idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Smoothes the confidence matrix */
|
||||
static void
|
||||
smoothcm (float *cm,
|
||||
int xres,
|
||||
int yres,
|
||||
float f1,
|
||||
float f2,
|
||||
float f3)
|
||||
{
|
||||
int y, x, idx;
|
||||
|
||||
/* Smoothright */
|
||||
for (y = 0; y < yres; y++)
|
||||
{
|
||||
for (x = 0; x < xres - 2; x++)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] =
|
||||
f1 * cm[idx] +
|
||||
f2 * cm[idx + 1] +
|
||||
f3 * cm[idx + 2];
|
||||
}
|
||||
}
|
||||
|
||||
/* Smoothleft */
|
||||
for (y = 0; y < yres; y++)
|
||||
{
|
||||
for (x = xres - 1; x >= 2; x--)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] =
|
||||
f3 * cm[idx - 2] +
|
||||
f2 * cm[idx - 1] +
|
||||
f1 * cm[idx];
|
||||
}
|
||||
}
|
||||
|
||||
/* Smoothdown */
|
||||
for (y = 0; y < yres - 2; y++)
|
||||
{
|
||||
for (x = 0; x < xres; x++)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] =
|
||||
f1 * cm[idx] +
|
||||
f2 * cm[((y + 1) * xres) + x] +
|
||||
f3 * cm[((y + 2) * xres) + x];
|
||||
}
|
||||
}
|
||||
|
||||
/* Smoothup */
|
||||
for (y = yres - 1; y >= 2; y--)
|
||||
{
|
||||
for (x = 0; x < xres; x++)
|
||||
{
|
||||
idx = (y * xres) + x;
|
||||
cm[idx] =
|
||||
f3 * cm[((y - 2) * xres) + x] +
|
||||
f2 * cm[((y - 1) * xres) + x] +
|
||||
f1 * cm[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* region growing */
|
||||
static void
|
||||
findmaxblob (float *cm,
|
||||
guint *image,
|
||||
int xres,
|
||||
int yres)
|
||||
{
|
||||
int i;
|
||||
int curlabel = 1;
|
||||
int maxregion = 0;
|
||||
int maxblob = 0;
|
||||
int regioncount = 0;
|
||||
int pos = 0;
|
||||
int length = xres * yres;
|
||||
int *labelfield = g_new0 (int, length);
|
||||
GQueue *q = g_queue_new ();
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
regioncount = 0;
|
||||
|
||||
if (labelfield[i] == 0 && cm[i] >= 0.5)
|
||||
g_queue_push_tail (q, GINT_TO_POINTER (i));
|
||||
|
||||
while (! g_queue_is_empty (q))
|
||||
{
|
||||
pos = GPOINTER_TO_INT (g_queue_pop_head (q));
|
||||
|
||||
if (pos < 0 || pos >= length)
|
||||
continue;
|
||||
|
||||
if (labelfield[pos] == 0 && cm[pos] >= 0.5f)
|
||||
{
|
||||
labelfield[pos] = curlabel;
|
||||
|
||||
regioncount++;
|
||||
|
||||
g_queue_push_tail (q, GINT_TO_POINTER (pos + 1));
|
||||
g_queue_push_tail (q, GINT_TO_POINTER (pos - 1));
|
||||
g_queue_push_tail (q, GINT_TO_POINTER (pos + xres));
|
||||
g_queue_push_tail (q, GINT_TO_POINTER (pos - xres));
|
||||
}
|
||||
}
|
||||
|
||||
if (regioncount > maxregion)
|
||||
{
|
||||
maxregion = regioncount;
|
||||
maxblob = curlabel;
|
||||
}
|
||||
|
||||
curlabel++;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
/* Kill everything that is not biggest blob! */
|
||||
if (labelfield[i] != 0 && labelfield[i] != maxblob)
|
||||
cm[i] = 0.0;
|
||||
}
|
||||
|
||||
g_queue_free (q);
|
||||
g_free (labelfield);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
* Freie Universitaet Berlin, June 2005.
|
||||
* http://www.inf.fu-berlin.de/inst/pubs/tr-b-05-07.pdf
|
||||
*
|
||||
* See http://www.siox.org/ for more information.
|
||||
*
|
||||
* Algorithm idea by Gerald Friedland.
|
||||
* This implementation is Copyright (C) 2005
|
||||
* by Gerald Friedland <fland@inf.fu-berlin.de>
|
||||
|
@ -37,13 +39,13 @@
|
|||
|
||||
|
||||
/* Amount of color dimensions in one point */
|
||||
#define DIMS 3
|
||||
#define SIOX_DIMS 3
|
||||
|
||||
|
||||
void foreground_extract (TileManager *tiles,
|
||||
TileManager *trimap,
|
||||
gfloat limits[DIMS],
|
||||
gint smoothness);
|
||||
void siox_foreground_extract (TileManager *tiles,
|
||||
TileManager *trimap,
|
||||
gfloat limits[SIOX_DIMS],
|
||||
gint smoothness);
|
||||
|
||||
|
||||
#endif /* __SEGMENTATOR_H__ */
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "core-types.h"
|
||||
|
||||
#include "base/pixel-region.h"
|
||||
#include "base/segmentator.h"
|
||||
#include "base/siox.h"
|
||||
#include "base/tile-manager.h"
|
||||
|
||||
#include "gimpchannel.h"
|
||||
|
@ -39,7 +39,7 @@ gimp_drawable_foreground_extract (GimpDrawable *drawable,
|
|||
GimpDrawable *mask)
|
||||
{
|
||||
GimpImage *gimage;
|
||||
gfloat limits[DIMS] = { 0.66, 1.25, 2.5 };
|
||||
gfloat limits[SIOX_DIMS] = { 0.66, 1.25, 2.5 };
|
||||
|
||||
g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
|
||||
g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)));
|
||||
|
@ -49,9 +49,9 @@ gimp_drawable_foreground_extract (GimpDrawable *drawable,
|
|||
|
||||
gimage = gimp_item_get_image (GIMP_ITEM (drawable));
|
||||
|
||||
foreground_extract (gimp_drawable_data (drawable),
|
||||
gimp_drawable_data (mask),
|
||||
limits, 3);
|
||||
siox_foreground_extract (gimp_drawable_data (drawable),
|
||||
gimp_drawable_data (mask),
|
||||
limits, 3);
|
||||
|
||||
gimp_drawable_update (mask,
|
||||
0, 0,
|
||||
|
|
Loading…
Reference in New Issue