diff options
Diffstat (limited to 'src/trace/siox.h')
-rw-r--r-- | src/trace/siox.h | 654 |
1 files changed, 654 insertions, 0 deletions
diff --git a/src/trace/siox.h b/src/trace/siox.h new file mode 100644 index 0000000..10eb62b --- /dev/null +++ b/src/trace/siox.h @@ -0,0 +1,654 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#ifndef SEEN_SIOX_H +#define SEEN_SIOX_H +/* + * Copyright 2005, 2006 by Gerald Friedland, Kristian Jantz and Lars Knipping + * + * Conversion to C++ for Inkscape by Bob Jamison + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +/* + * Note by Bob Jamison: + * After translating the siox.org Java API to C++ and receiving an + * education into this wonderful code, I began again, + * and started this version using lessons learned. This version is + * an attempt to provide an dependency-free SIOX engine that anyone + * can use in their project with minimal effort. + * + * Many thanks to the fine people at siox.org. + */ + +#include <string> +#include <vector> + +#define HAVE_GLIB + +#ifdef HAVE_GLIB +#include <glib.h> +#include <gdk-pixbuf/gdk-pixbuf.h> +#endif + + +namespace org +{ + +namespace siox +{ + + +//######################################################################## +//# C L A B +//######################################################################## + +/** + * + */ +class CieLab +{ +public: + + /** + * + */ + CieLab() + { + init(); + C = 0; + L = A = B = 0.0f; + } + + + /** + * + */ + CieLab(unsigned long rgb); + + + /** + * + */ + CieLab(float lArg, float aArg, float bArg) + { + init(); + C = 0; + L = lArg; + A = aArg; + B = bArg; + } + + + /** + * + */ + CieLab(const CieLab &other) + { + init(); + C = other.C; + L = other.L; + A = other.A; + B = other.B; + } + + + /** + * + */ + CieLab &operator=(const CieLab &other) + { + init(); + C = other.C; + L = other.L; + A = other.A; + B = other.B; + return *this; + } + + /** + * + */ + virtual ~CieLab() + = default; + + /** + * Retrieve a CieLab value via index. + */ + virtual float operator()(unsigned int index) + { + if (index==0) return L; + else if (index==1) return A; + else if (index==2) return B; + else return 0; + } + + + /** + * + */ + virtual void add(const CieLab &other) + { + C += other.C; + L += other.L; + A += other.A; + B += other.B; + } + + + /** + * + */ + virtual void mul(float scale) + { + L *= scale; + A *= scale; + B *= scale; + } + + + /** + * + */ + virtual unsigned long toRGB(); + + /** + * Approximate cube roots + */ + double cbrt(double x); + + /** + * + */ + double qnrt(double x); + + /** + * Raise to the 2.4 power + */ + double pow24(double x); + + /** + * Squared Euclidean distance between this and another color + */ + float diffSq(const CieLab &other); + + /** + * Computes squared euclidean distance in CieLab space for two colors + * given as RGB values. + */ + static float diffSq(unsigned int rgb1, unsigned int rgb2); + + /** + * Computes squared euclidean distance in CieLab space for two colors + * given as RGB values. + */ + static float diff(unsigned int rgb0, unsigned int rgb1); + + + unsigned int C; + float L; + float A; + float B; + +private: + + /** + * + */ + void init(); + + +}; + + +//######################################################################## +//# S I O X I M A G E +//######################################################################## + +/** + * This is a generic image type that provides a consistent interface + * to Siox, so that developers will not need to worry about data arrays. + */ +class SioxImage +{ +public: + + /** + * Create an image with the given width and height + */ + SioxImage(unsigned int width, unsigned int height); + + /** + * Copy constructor + */ + SioxImage(const SioxImage &other); + + /** + * Assignment + */ + SioxImage &operator=(const SioxImage &other); + + /** + * Clean up after use. + */ + virtual ~SioxImage(); + + /** + * Returns true if the previous operation on this image + * was successful, else false. + */ + virtual bool isValid(); + + /** + * Sets whether an operation was successful, and whether + * this image should be considered a valid one. + * was successful, else false. + */ + virtual void setValid(bool val); + + /** + * Set a pixel at the x,y coordinates to the given value. + * If the coordinates are out of range, do nothing. + */ + virtual void setPixel(unsigned int x, + unsigned int y, + unsigned int pixval); + + /** + * Set a pixel at the x,y coordinates to the given r, g, b values. + * If the coordinates are out of range, do nothing. + */ + virtual void setPixel(unsigned int x, unsigned int y, + unsigned int a, + unsigned int r, + unsigned int g, + unsigned int b); + + /** + * Get a pixel at the x,y coordinates given. If + * the coordinates are out of range, return 0 + */ + virtual unsigned int getPixel(unsigned int x, unsigned int y); + + + /** + * Return the image data buffer + */ + virtual unsigned int *getImageData(); + + /** + * Set a confidence value at the x,y coordinates to the given value. + * If the coordinates are out of range, do nothing. + */ + virtual void setConfidence(unsigned int x, + unsigned int y, + float conf); + + /** + * Get a confidence value at the x,y coordinates given. If + * the coordinates are out of range, return 0 + */ + virtual float getConfidence(unsigned int x, unsigned int y); + + /** + * Return the confidence data buffer + */ + virtual float *getConfidenceData(); + + /** + * Return the width of this image + */ + virtual int getWidth(); + + /** + * Return the height of this image + */ + virtual int getHeight(); + + /** + * Saves this image as a simple color PPM + */ + bool writePPM(const std::string &fileName); + + + +#ifdef HAVE_GLIB + + /** + * Special constructor to create an image from a GdkPixbuf. + */ + SioxImage(GdkPixbuf *buf); + + /** + * Creates a GdkPixbuf from this image. The user must + * remember to destroy the image when no longer needed. + * with g_free(pixbuf) + */ + GdkPixbuf *getGdkPixbuf(); + +#endif + +private: + + SioxImage() + = default; + + /** + * Assign values to that of another + */ + void assign(const SioxImage &other); + + /** + * Initialize values. Used by constructors + */ + void init(unsigned int width, unsigned int height); + + bool valid; + + unsigned int width; + + unsigned int height; + + unsigned long imageSize; + + /** + * Pixel data + */ + unsigned int *pixdata; + + /** + * Confidence matrix data + */ + float *cmdata; + +private: + + /** + * Error logging + */ + void error(const char *fmt, ...) G_GNUC_PRINTF(2,3); + +}; + + + +//######################################################################## +//# S I O X O B S E R V E R +//######################################################################## +class Siox; + +/** + * This is a class for observing the progress of a Siox engine. Overload + * the methods in your subclass to get the desired behaviour. + */ +class SioxObserver +{ +public: + + /** + * Constructor. Context can point to anything, and is usually + * used to point to a C++ object or C state object, to delegate + * callback processing to something else. Use NULL to ignore. + */ + SioxObserver(void *contextArg) : context(nullptr) + { context = contextArg; } + + /** + * Destructor + */ + virtual ~SioxObserver() + = default; + + /** + * Informs the observer how much has been completed. + * Return false if the processing should be aborted. + */ + virtual bool progress(float /*percentCompleted*/) + { + return true; + } + + /** + * Send an error string to the Observer. Processing will + * be halted. + */ + virtual void error(const std::string &/*msg*/) + { + } + +protected: + + void *context; + +}; + + + +//######################################################################## +//# S I O X +//######################################################################## + +/** + * + */ +class Siox +{ +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; + + /** + * Construct a Siox engine + */ + Siox(); + + /** + * Construct a Siox engine. Use null to ignore + */ + Siox(SioxObserver *observer); + + /** + * + */ + virtual ~Siox(); + + /** + * Extract the foreground of the original image, according + * to the values in the confidence matrix. If the operation fails, + * sioxImage.isValid() will be false. + * backgroundFillColor is any ARGB color, such as 0xffffff (white) + * or 0x000000 (black) + */ + virtual SioxImage extractForeground(const SioxImage &originalImage, + unsigned int backgroundFillColor); + +private: + + SioxObserver *sioxObserver; + + /** + * Progress reporting + */ + bool progressReport(float percentCompleted); + + /** + * Flag this as false during processing to abort + */ + bool keepGoing; + + /** + * Image width + */ + unsigned int width; + + /** + * Image height + */ + unsigned int height; + + /** + * Image size in pixels + */ + unsigned long pixelCount; + + /** + * Image data + */ + unsigned int *image; + + /** + * Image confidence matrix + */ + float *cm; + + /** + * Markup for image editing + */ + int *labelField; + + + /** + * Our signature limits + */ + float limits[3]; + + /** + * Maximum distance of two lab values. + */ + float clusterSize; + + /** + * Initialize the Siox engine to its 'pristine' state. + * Performed at the beginning of extractForeground(). + */ + void init(); + + /** + * Clean up any debris from processing. + */ + void cleanup(); + + /** + * Error logging + */ + void error(const char *fmt, ...) G_GNUC_PRINTF(2,3); + + /** + * Trace logging + */ + void trace(const char *fmt, ...) G_GNUC_PRINTF(2,3); + + /** + * Stage 1 of the color signature work. 'dims' will be either + * 2 for grays, or 3 for colors + */ + void colorSignatureStage1(CieLab *points, + unsigned int leftBase, + unsigned int rightBase, + unsigned int recursionDepth, + unsigned int *clusters, + const unsigned int dims); + + /** + * Stage 2 of the color signature work + */ + void colorSignatureStage2(CieLab *points, + unsigned int leftBase, + unsigned int rightBase, + unsigned int recursionDepth, + unsigned int *clusters, + const float threshold, + const unsigned int dims); + + /** + * Main color signature method + */ + bool colorSignature(const std::vector<CieLab> &inputVec, + std::vector<CieLab> &result, + const unsigned int dims); + + + /** + * + */ + void keepOnlyLargeComponents(float threshold, + double sizeFactorToKeep); + + /** + * + */ + int depthFirstSearch(int startPos, float threshold, int curLabel); + + + /** + * + */ + void fillColorRegions(); + + /** + * Applies the morphological dilate operator. + * + * Can be used to close small holes in the given confidence matrix. + */ + void dilate(float *cm, int xres, int yres); + + /** + * Applies the morphological erode operator. + */ + void erode(float *cm, int xres, int yres); + + /** + * Normalizes the matrix to values to [0..1]. + */ + void normalizeMatrix(float *cm, int cmSize); + + /** + * Multiplies matrix with the given scalar. + */ + void premultiplyMatrix(float alpha, float *cm, int cmSize); + + /** + * Blurs confidence matrix with a given symmetrically weighted kernel. + */ + void smooth(float *cm, int xres, int yres, + float f1, float f2, float f3); + + /** + * Squared Euclidean distance of p and q. + */ + float sqrEuclideanDist(float *p, int pSize, float *q); + +}; + + + + +} // namespace siox +} // namespace org + +#endif // SEEN_SIOX_H +//######################################################################## +//# E N D O F F I L E +//######################################################################## |