|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tropcm.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzCore includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tpalette.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "trop_borders.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "pixelselectors.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "runsmap.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#define INCLUDE_HPP
|
|
Toshihiro Shimizu |
890ddd |
#include "raster_edge_iterator.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "borders_extractor.h"
|
|
Toshihiro Shimizu |
890ddd |
#define INCLUDE_HPP
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// STL includes
|
|
Toshihiro Shimizu |
890ddd |
#include <deque></deque>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*============================================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
Explanation
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Despeckling is a noise-removal procedure which aims at eliminating small blots
|
|
Shinya Kitaoka |
120a6e |
of color
|
|
Toshihiro Shimizu |
890ddd |
from an image.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
We will assume that speckles are recognized with uniform color (which means -
|
|
Shinya Kitaoka |
120a6e |
image
|
|
Toshihiro Shimizu |
890ddd |
discretization should be externally performed).
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
We will currently assume that the despeckling procedure works only on the ink
|
|
Shinya Kitaoka |
120a6e |
or paint plane of a
|
|
Toshihiro Shimizu |
890ddd |
TRasterCM32 instance, not both (should be extended in the future).
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
The image is traversed to isolate regions with the same color and, if their
|
|
Shinya Kitaoka |
120a6e |
area is
|
|
Toshihiro Shimizu |
890ddd |
below the specified threshold, they get removed or changed of color.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Color change looks at the area's neighbouring pixels for the most used color
|
|
Shinya Kitaoka |
120a6e |
to use for
|
|
Shinya Kitaoka |
120a6e |
replacement. If NO neighbouring color can be found, the area is made
|
|
Shinya Kitaoka |
120a6e |
transparent.
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
==============================================================================================*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace TRop::borders;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Pixel Selectors
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class InkSelectorCM32 {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef TPixelCM32 pixel_type;
|
|
Shinya Kitaoka |
120a6e |
typedef TUINT32 value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
InkSelectorCM32() {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
value_type transparent() const { return 0; }
|
|
Shinya Kitaoka |
120a6e |
bool transparent(const pixel_type &pix) const { return value(pix) == 0; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
value_type value(const pixel_type &pix) const { return pix.getInk(); }
|
|
Shinya Kitaoka |
120a6e |
bool equal(const pixel_type &a, const pixel_type &b) const {
|
|
Shinya Kitaoka |
120a6e |
return value(a) == value(b);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool skip(const value_type &prevLeftValue,
|
|
Shinya Kitaoka |
120a6e |
const value_type &leftValue) const {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename channel="" pixel,="" typename=""></typename>
|
|
Shinya Kitaoka |
120a6e |
class InkSelectorRGBM {
|
|
Shinya Kitaoka |
120a6e |
bool m_transparentIsWhite;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef PIXEL pixel_type;
|
|
Shinya Kitaoka |
120a6e |
typedef CHANNEL value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
InkSelectorRGBM(bool transparentIsWhite)
|
|
Shinya Kitaoka |
120a6e |
: m_transparentIsWhite(transparentIsWhite) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
value_type transparent() const { return 0; }
|
|
Shinya Kitaoka |
120a6e |
bool transparent(const pixel_type &pix) const { return value(pix) == 0; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
value_type value(const pixel_type &pix) const {
|
|
Shinya Kitaoka |
120a6e |
if (m_transparentIsWhite)
|
|
Shinya Kitaoka |
120a6e |
return (pix == PIXEL::White) ? 0 : 1;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
return (pix.m == 0) ? 0 : 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
bool equal(const pixel_type &a, const pixel_type &b) const {
|
|
Shinya Kitaoka |
120a6e |
return value(a) == value(b);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool skip(const value_type &prevLeftValue,
|
|
Shinya Kitaoka |
120a6e |
const value_type &leftValue) const {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename channel="" pixel,="" typename=""></typename>
|
|
Shinya Kitaoka |
120a6e |
class InkSelectorGR {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef PIXEL pixel_type;
|
|
Shinya Kitaoka |
120a6e |
typedef CHANNEL value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
InkSelectorGR() {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
value_type transparent() const { return PIXEL::maxChannelValue; }
|
|
Shinya Kitaoka |
120a6e |
bool transparent(const pixel_type &pix) const { return value(pix) == 0; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
value_type value(const pixel_type &pix) const {
|
|
Shinya Kitaoka |
120a6e |
return (pix.value == PIXEL::maxChannelValue) ? 0 : 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
bool equal(const pixel_type &a, const pixel_type &b) const {
|
|
Shinya Kitaoka |
120a6e |
return value(a) == value(b);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool skip(const value_type &prevLeftValue,
|
|
Shinya Kitaoka |
120a6e |
const value_type &leftValue) const {
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Border class
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct Border {
|
|
Shinya Kitaoka |
120a6e |
std::vector<tpoint> m_points;</tpoint>
|
|
Shinya Kitaoka |
120a6e |
int m_x0, m_y0, m_x1, m_y1;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
Border()
|
|
Shinya Kitaoka |
120a6e |
: m_x0((std::numeric_limits<int>::max)())</int>
|
|
Shinya Kitaoka |
120a6e |
, m_y0(m_x0)
|
|
Shinya Kitaoka |
120a6e |
, m_x1(-m_x0)
|
|
Shinya Kitaoka |
120a6e |
, m_y1(m_x1) {}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void addPoint(const TPoint &p) {
|
|
Shinya Kitaoka |
120a6e |
// Update the region box
|
|
Shinya Kitaoka |
120a6e |
if (p.x < m_x0) m_x0 = p.x;
|
|
Shinya Kitaoka |
120a6e |
if (p.x > m_x1) m_x1 = p.x;
|
|
Shinya Kitaoka |
120a6e |
if (p.y < m_y0) m_y0 = p.y;
|
|
Shinya Kitaoka |
120a6e |
if (p.y > m_y1) m_y1 = p.y;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// Add the vertex
|
|
Shinya Kitaoka |
120a6e |
m_points.push_back(p);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void clear() {
|
|
Shinya Kitaoka |
120a6e |
m_points.clear();
|
|
Shinya Kitaoka |
120a6e |
m_x0 = (std::numeric_limits<int>::max)(), m_y0 = m_x0, m_x1 = -m_x0,</int>
|
|
Shinya Kitaoka |
120a6e |
m_y1 = m_x1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Base classes
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
// Borders Painter
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Shinya Kitaoka |
120a6e |
class BordersPainter {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef Pix pixel_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Shinya Kitaoka |
120a6e |
TRasterPT<pixel_type> m_ras;</pixel_type>
|
|
Shinya Kitaoka |
120a6e |
RunsMapP m_runsMap;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
BordersPainter(const TRasterPT<pixel_type> &ras) : m_ras(ras) {}</pixel_type>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const TRasterPT<pixel_type> &ras() { return m_ras; }</pixel_type>
|
|
Shinya Kitaoka |
120a6e |
RunsMapP &runsMap() { return m_runsMap; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void paintLine(int x, int y0, int y1) const;
|
|
Shinya Kitaoka |
120a6e |
void paintBorder(const Border &border) const;
|
|
Shinya Kitaoka |
120a6e |
void paintBorders(const std::deque<border *=""> &borders) const {</border>
|
|
Shinya Kitaoka |
120a6e |
size_t i, size = borders.size();
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < size; ++i) paintBorder(*borders[i]);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Shinya Kitaoka |
120a6e |
virtual void paintPixel(pixel_type *pix) const = 0;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void BordersPainter<pix>::paintBorder(const Border &border) const {</pix>
|
|
Shinya Kitaoka |
120a6e |
const std::vector<tpoint> &points = border.m_points;</tpoint>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
size_t i, size_1 = points.size() - 1;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < size_1; ++i) {
|
|
Shinya Kitaoka |
120a6e |
const TPoint &p = points[i];
|
|
Shinya Kitaoka |
120a6e |
paintLine(p.x, p.y, points[i + 1].y);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
paintLine(points[size_1].x, points[size_1].y, points[0].y);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void BordersPainter<pix>::paintLine(int x, int y0, int y1) const {</pix>
|
|
Shinya Kitaoka |
120a6e |
for (int j = y0; j < y1; ++j) {
|
|
Shinya Kitaoka |
120a6e |
TPixelGR8 *runPix = m_runsMap->pixels(j) + x;
|
|
Shinya Kitaoka |
120a6e |
int l, runLength = 0, hierarchy = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
do {
|
|
Shinya Kitaoka |
120a6e |
if (runPix->value & TRop::borders::_HIERARCHY_INCREASE) ++hierarchy;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Update vars
|
|
Shinya Kitaoka |
120a6e |
runLength += l = m_runsMap->runLength(runPix);
|
|
Shinya Kitaoka |
120a6e |
runPix += l;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if ((runPix - 1)->value & TRop::borders::_HIERARCHY_DECREASE) --hierarchy;
|
|
Shinya Kitaoka |
120a6e |
} while (hierarchy > 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
pixel_type *pix = m_ras->pixels(j) + x, *pixEnd = pix + runLength;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
for (; pix < pixEnd; ++pix) paintPixel(pix);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
// Despeckling Reader
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class DespecklingReader {
|
|
Toshihiro Shimizu |
890ddd |
protected:
|
|
Shinya Kitaoka |
120a6e |
std::deque<border *=""> m_borders;</border>
|
|
Shinya Kitaoka |
120a6e |
Border m_border;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int m_sizeTol;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
DespecklingReader(int sizeTol) : m_sizeTol(sizeTol) {}
|
|
Shinya Kitaoka |
120a6e |
~DespecklingReader();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int sizeTol() const { return m_sizeTol; }
|
|
Shinya Kitaoka |
120a6e |
bool isSpeckle(const Border &border) {
|
|
Shinya Kitaoka |
120a6e |
return border.m_x1 - border.m_x0 <= m_sizeTol &&
|
|
Shinya Kitaoka |
120a6e |
border.m_y1 - border.m_y0 <= m_sizeTol;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void openContainer(const TPoint &pos);
|
|
Shinya Kitaoka |
120a6e |
void addElement(const TPoint &pos);
|
|
Shinya Kitaoka |
120a6e |
virtual void closeContainer();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const std::deque<border *=""> &borders() const { return m_borders; }</border>
|
|
Shinya Kitaoka |
120a6e |
std::deque<border *=""> &borders() { return m_borders; }</border>
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DespecklingReader::~DespecklingReader() {
|
|
otakuto |
675691 |
std::for_each(m_borders.begin(), m_borders.end(), std::default_delete<border>());</border>
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void DespecklingReader::openContainer(const TPoint &pos) {
|
|
Shinya Kitaoka |
120a6e |
m_border.clear();
|
|
Shinya Kitaoka |
120a6e |
m_border.addPoint(pos);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void DespecklingReader::addElement(const TPoint &pos) {
|
|
Shinya Kitaoka |
120a6e |
m_border.addPoint(pos);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void DespecklingReader::closeContainer() {
|
|
Shinya Kitaoka |
120a6e |
if (isSpeckle(m_border)) m_borders.push_back(new Border(m_border));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Specialized classes
|
|
Toshihiro Shimizu |
890ddd |
//************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
// Replace Painters
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Shinya Kitaoka |
d1f6c4 |
class ReplacePainter final : public BordersPainter<pix> {</pix>
|
|
Shinya Kitaoka |
120a6e |
typename ReplacePainter::pixel_type m_color;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter(const TRasterPT<typename replacepainter::pixel_type=""> &ras)</typename>
|
|
Shinya Kitaoka |
120a6e |
: BordersPainter<pix>(ras) {}</pix>
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter(const TRasterPT<typename replacepainter::pixel_type=""> &ras,</typename>
|
|
Shinya Kitaoka |
120a6e |
const typename ReplacePainter::pixel_type &color)
|
|
Shinya Kitaoka |
120a6e |
: BordersPainter<pix>(ras), m_color(color) {}</pix>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
const typename ReplacePainter::pixel_type &color() const { return m_color; }
|
|
Shinya Kitaoka |
120a6e |
typename ReplacePainter::pixel_type &color() { return m_color; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void paintPixel(typename ReplacePainter::pixel_type *pix) const override {
|
|
Shinya Kitaoka |
120a6e |
*pix = m_color;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <>
|
|
Shinya Kitaoka |
d1f6c4 |
class ReplacePainter<tpixelcm32> final : public BordersPainter<tpixelcm32> {</tpixelcm32></tpixelcm32>
|
|
Shinya Kitaoka |
120a6e |
TUINT32 m_value;
|
|
Shinya Kitaoka |
120a6e |
TUINT32 m_keepMask;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter(const TRasterPT<pixel_type> &ras)</pixel_type>
|
|
Shinya Kitaoka |
120a6e |
: BordersPainter<tpixelcm32>(ras), m_value(0), m_keepMask(0) {}</tpixelcm32>
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter(const TRasterPT<pixel_type> &ras, TUINT32 value,</pixel_type>
|
|
Shinya Kitaoka |
120a6e |
TUINT32 keepMask)
|
|
Shinya Kitaoka |
120a6e |
: BordersPainter<tpixelcm32>(ras), m_value(value), m_keepMask(keepMask) {}</tpixelcm32>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const TUINT32 &value() const { return m_value; }
|
|
Shinya Kitaoka |
120a6e |
TUINT32 &value() { return m_value; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
const TUINT32 &keepMask() const { return m_keepMask; }
|
|
Shinya Kitaoka |
120a6e |
TUINT32 &keepMask() { return m_keepMask; }
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
473e70 |
void paintPixel(pixel_type *pix) const override {
|
|
Shinya Kitaoka |
120a6e |
*pix = TPixelCM32(m_value | (pix->getValue() & m_keepMask));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
// Isolated Despeckling
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Shinya Kitaoka |
d1f6c4 |
class IsolatedReader final : public DespecklingReader {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef typename PixelSelector::pixel_type pixel_type;
|
|
Shinya Kitaoka |
120a6e |
typedef typename PixelSelector::value_type value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
const PixelSelector &m_selector;
|
|
Shinya Kitaoka |
120a6e |
bool m_ok;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
IsolatedReader(const PixelSelector &selector, int sizeTol);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void openContainer(const RasterEdgeIterator<pixelselector> &it);</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
void addElement(const RasterEdgeIterator<pixelselector> &it);</pixelselector>
|
|
Shinya Kitaoka |
473e70 |
void closeContainer() override;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Shinya Kitaoka |
120a6e |
IsolatedReader<pixelselector>::IsolatedReader(const PixelSelector &selector,</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
int sizeTol)
|
|
Shinya Kitaoka |
120a6e |
: DespecklingReader(sizeTol), m_selector(selector) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void IsolatedReader<pixelselector>::openContainer(</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
const RasterEdgeIterator<pixelselector> &it) {</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
m_ok = (it.leftColor() == m_selector.transparent());
|
|
Shinya Kitaoka |
120a6e |
if (!m_ok) return;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DespecklingReader::openContainer(it.pos());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void IsolatedReader<pixelselector>::addElement(</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
const RasterEdgeIterator<pixelselector> &it) {</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
if (!m_ok) return;
|
|
Shinya Kitaoka |
120a6e |
m_ok = (it.leftColor() == m_selector.transparent());
|
|
Shinya Kitaoka |
120a6e |
if (!m_ok) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
DespecklingReader::addElement(it.pos());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void IsolatedReader<pixelselector>::closeContainer() {</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
if (m_ok) DespecklingReader::closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*********************************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Despeckling Mains
|
|
Toshihiro Shimizu |
890ddd |
//*********************************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Shinya Kitaoka |
120a6e |
Applies despeckling (paint or removal of small blots of uniform color) to the
|
|
Shinya Kitaoka |
120a6e |
image.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename channel="" pixel,="" typename=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void doDespeckleRGBM(const TRasterPT<pixel> &ras, int sizeThreshold,</pixel>
|
|
Shinya Kitaoka |
120a6e |
bool transparentIsWhite) {
|
|
Shinya Kitaoka |
120a6e |
InkSelectorRGBM<pixel, channel=""> selector(transparentIsWhite);</pixel,>
|
|
Shinya Kitaoka |
120a6e |
IsolatedReader<inkselectorrgbm<pixel, channel="">> reader(selector,</inkselectorrgbm<pixel,>
|
|
Shinya Kitaoka |
120a6e |
sizeThreshold);
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter<pixel> painter(</pixel>
|
|
Shinya Kitaoka |
120a6e |
ras, transparentIsWhite ? PIXEL::White : PIXEL::Transparent);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRop::borders::readBorders(ras, selector, reader, &painter.runsMap());
|
|
Shinya Kitaoka |
120a6e |
painter.paintBorders(reader.borders());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename channel="" pixel,="" typename=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void doDespeckleGR(const TRasterPT<pixel> &ras, int sizeThreshold) {</pixel>
|
|
Shinya Kitaoka |
120a6e |
InkSelectorGR<pixel, channel=""> selector;</pixel,>
|
|
Shinya Kitaoka |
120a6e |
IsolatedReader<inkselectorgr<pixel, channel="">> reader(selector, sizeThreshold);</inkselectorgr<pixel,>
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter<pixel> painter(ras, PIXEL::maxChannelValue);</pixel>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRop::borders::readBorders(ras, selector, reader, &painter.runsMap());
|
|
Shinya Kitaoka |
120a6e |
painter.paintBorders(reader.borders());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//----------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Campbell Barton |
8c6c57 |
static void doDespeckleCM32(const TRasterPT<tpixelcm32> &ras, int sizeThreshold,</tpixelcm32>
|
|
Campbell Barton |
8c6c57 |
bool check) {
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P rasCM(ras);
|
|
Shinya Kitaoka |
120a6e |
rasCM->lock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
InkSelectorCM32 selector;
|
|
Shinya Kitaoka |
120a6e |
IsolatedReader<inkselectorcm32> reader(selector, sizeThreshold);</inkselectorcm32>
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter<tpixelcm32> painter(</tpixelcm32>
|
|
Shinya Kitaoka |
120a6e |
rasCM, check ? 0xffffff00 : 0x000000ff,
|
|
Shinya Kitaoka |
120a6e |
0); // 0xffffff00 is a special non-mapped full ink pixel
|
|
Shinya Kitaoka |
120a6e |
// 0x000000ff is a full transparent paint pixel
|
|
Shinya Kitaoka |
120a6e |
TRop::borders::readBorders(rasCM, selector, reader, &painter.runsMap());
|
|
Shinya Kitaoka |
120a6e |
painter.paintBorders(reader.borders());
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
rasCM->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRop::despeckle(const TRasterP &ras, int sizeThreshold, bool check,
|
|
Shinya Kitaoka |
120a6e |
bool transparentIsWhite) {
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (TRasterCM32P(ras)) {
|
|
Shinya Kitaoka |
120a6e |
doDespeckleCM32(ras, sizeThreshold, check);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (TRaster32P(ras)) {
|
|
Shinya Kitaoka |
120a6e |
doDespeckleRGBM<tpixel32, uchar="">(ras, sizeThreshold, transparentIsWhite);</tpixel32,>
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (TRaster64P(ras)) {
|
|
Shinya Kitaoka |
120a6e |
doDespeckleRGBM<tpixel64, ushort="">(ras, sizeThreshold, transparentIsWhite);</tpixel64,>
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (TRasterGR8P(ras)) {
|
|
Shinya Kitaoka |
120a6e |
doDespeckleGR<tpixelgr8, uchar="">(ras, sizeThreshold);</tpixelgr8,>
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (TRasterGR16P(ras)) {
|
|
Shinya Kitaoka |
120a6e |
doDespeckleGR<tpixelgr16, ushort="">(ras, sizeThreshold);</tpixelgr16,>
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
/*!
|
|
Toshihiro Shimizu |
890ddd |
Performs a copy of rin and then applies despeckling.
|
|
Toshihiro Shimizu |
890ddd |
*/
|
|
Shinya Kitaoka |
120a6e |
void TRop::despeckle(const TRasterP &rout, const TRasterP &rin,
|
|
Shinya Kitaoka |
120a6e |
int sizeThreshold, bool check) {
|
|
Shinya Kitaoka |
120a6e |
TRop::copy(rout, rin);
|
|
Shinya Kitaoka |
120a6e |
TRop::despeckle(rout, sizeThreshold, check);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*********************************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Majority Despeckling
|
|
Toshihiro Shimizu |
890ddd |
//*********************************************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Shinya Kitaoka |
d1f6c4 |
class FillingReader final : public DespecklingReader {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
typedef typename PixelSelector::pixel_type pixel_type;
|
|
Shinya Kitaoka |
120a6e |
typedef typename PixelSelector::value_type value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
private:
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter<tpixelgr8> m_painter;</tpixelgr8>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
FillingReader(const TRasterGR8P &rasGR, int sizeTol)
|
|
Shinya Kitaoka |
120a6e |
: DespecklingReader(sizeTol), m_painter(rasGR, TPixelGR8::Black) {}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void openContainer(const RasterEdgeIterator<pixelselector> &it);</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
void addElement(const RasterEdgeIterator<pixelselector> &it);</pixelselector>
|
|
Shinya Kitaoka |
473e70 |
void closeContainer() override;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
RunsMapP &runsMap() { return m_painter.runsMap(); }
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void FillingReader<pixelselector>::openContainer(</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
const RasterEdgeIterator<pixelselector> &it) {</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
DespecklingReader::openContainer(it.pos());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void FillingReader<pixelselector>::addElement(</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
const RasterEdgeIterator<pixelselector> &it) {</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
DespecklingReader::addElement(it.pos());
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixelselector=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void FillingReader<pixelselector>::closeContainer() {</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
if (isSpeckle(m_border)) m_painter.paintBorder(m_border);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
DespecklingReader::closeContainer();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
inline TPoint direction(const TPoint &a, const TPoint &b) {
|
|
Shinya Kitaoka |
120a6e |
return TPoint((b.x > a.x) ? 1 : (b.x < a.x) ? -1 : 0,
|
|
Shinya Kitaoka |
120a6e |
(b.y > a.y) ? 1 : (b.y < a.y) ? -1 : 0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pixel,="" pixelselector="" typename=""></typename>
|
|
Toshihiro Shimizu |
890ddd |
bool majority(const TRasterPT<pixel> ras, const TRasterGR8P &rasGR,</pixel>
|
|
Shinya Kitaoka |
120a6e |
const PixelSelector &selector, const Border &border,
|
|
Shinya Kitaoka |
120a6e |
typename PixelSelector::value_type &color) {
|
|
Shinya Kitaoka |
120a6e |
typedef typename PixelSelector::value_type value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Build a histogram of all found colors around the border
|
|
Shinya Kitaoka |
120a6e |
std::map<value_type, int=""> histogram;</value_type,>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
Pixel *pix, *basePix = ras->pixels(0);
|
|
Shinya Kitaoka |
120a6e |
TPixelGR8 *grPix;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int diff, x, y, lx = ras->getLx(), ly = ras->getLy(), wrap = ras->getWrap();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
assert(border.m_points[1].y > border.m_points[0].y);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Iterate the raster along the border
|
|
Shinya Kitaoka |
120a6e |
const std::vector<tpoint> &points = border.m_points;</tpoint>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
RasterEdgeIterator<pixelselector> start(ras, selector, points[0],</pixelselector>
|
|
Shinya Kitaoka |
120a6e |
direction(points[0], points[1])),
|
|
Shinya Kitaoka |
120a6e |
it(start);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
size_t next = 1, size = points.size();
|
|
Shinya Kitaoka |
120a6e |
do {
|
|
Shinya Kitaoka |
120a6e |
while (it.pos() != points[next]) {
|
|
Shinya Kitaoka |
120a6e |
pix = it.leftPix();
|
|
Shinya Kitaoka |
120a6e |
diff = pix - basePix;
|
|
Shinya Kitaoka |
120a6e |
x = diff % wrap;
|
|
Shinya Kitaoka |
120a6e |
y = diff / wrap;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (x >= 0 && y >= 0 && x < lx && y < ly) {
|
|
Shinya Kitaoka |
120a6e |
grPix = rasGR->pixels(y) + x;
|
|
Shinya Kitaoka |
120a6e |
if (grPix->value) ++histogram[it.leftColor()];
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
it.setEdge(it.pos() + it.dir(), it.dir());
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
next = (next + 1) % size;
|
|
Shinya Kitaoka |
120a6e |
it.setEdge(it.pos(), direction(it.pos(), points[next]));
|
|
Shinya Kitaoka |
120a6e |
} while (it != start);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
if (!histogram.empty()) {
|
|
Shinya Kitaoka |
120a6e |
// Return the most found color
|
|
Shinya Kitaoka |
120a6e |
color = histogram.begin()->first;
|
|
Shinya Kitaoka |
120a6e |
return true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
return false;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
template <typename pix=""></typename>
|
|
Shinya Kitaoka |
120a6e |
void majorityDespeckle(const TRasterPT<pix> &ras, int sizeThreshold) {</pix>
|
|
Shinya Kitaoka |
120a6e |
typedef typename TRop::borders::PixelSelector<pix> pixel_selector;</pix>
|
|
Shinya Kitaoka |
120a6e |
typedef typename pixel_selector::pixel_type pixel_type;
|
|
Shinya Kitaoka |
120a6e |
typedef typename pixel_selector::value_type value_type;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
ras->lock();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Use a temporary bitmap (well, a bytemap - for now?) to store the found
|
|
Shinya Kitaoka |
120a6e |
// speckles
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P rasGR(ras->getSize());
|
|
Shinya Kitaoka |
120a6e |
rasGR->fill(TPixelGR8::White);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Find the speckles and draw them on the bitmap
|
|
Shinya Kitaoka |
120a6e |
pixel_selector selector;
|
|
Shinya Kitaoka |
120a6e |
FillingReader<pixel_selector> reader(rasGR, sizeThreshold);</pixel_selector>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TRop::borders::readBorders(ras, selector, reader, &reader.runsMap());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Now, operate each speckle. Try to apply a majority color to the speckle
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter<pixel_type> painter(ras);</pixel_type>
|
|
Shinya Kitaoka |
120a6e |
painter.runsMap() = reader.runsMap();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
ReplacePainter<tpixelgr8> painterGR(rasGR, TPixelGR8::White);</tpixelgr8>
|
|
Shinya Kitaoka |
120a6e |
painterGR.runsMap() = reader.runsMap();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
std::deque<border *=""> borders =</border>
|
|
Shinya Kitaoka |
120a6e |
reader.borders(); // Note that the DEEP copy is NEEDED
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
int processedCount = 1;
|
|
Shinya Kitaoka |
120a6e |
while (processedCount > 0 && !borders.empty()) {
|
|
Shinya Kitaoka |
120a6e |
processedCount = 0;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Traverse the speckles list. Try to apply majority.
|
|
Shinya Kitaoka |
120a6e |
Border *current, *last = borders.back();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
do {
|
|
Shinya Kitaoka |
120a6e |
current = borders.front();
|
|
Shinya Kitaoka |
120a6e |
borders.pop_front();
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
value_type color;
|
|
Shinya Kitaoka |
120a6e |
if (majority(ras, rasGR, selector, *current, color)) {
|
|
Shinya Kitaoka |
120a6e |
++processedCount;
|
|
Shinya Kitaoka |
120a6e |
painter.color() = color;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
painter.paintBorder(*current);
|
|
Shinya Kitaoka |
120a6e |
painterGR.paintBorder(*current);
|
|
Shinya Kitaoka |
120a6e |
} else
|
|
Shinya Kitaoka |
120a6e |
borders.push_back(current);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} while (current != last);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
// Speckles may remain. In this case, fill with transparent.
|
|
Shinya Kitaoka |
120a6e |
painter.color() = selector.transparent();
|
|
Shinya Kitaoka |
120a6e |
while (!borders.empty()) {
|
|
Shinya Kitaoka |
120a6e |
Border *current = borders.front();
|
|
Shinya Kitaoka |
120a6e |
painter.paintBorder(*current);
|
|
Shinya Kitaoka |
120a6e |
borders.pop_front();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
ras->unlock();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//================================================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void TRop::majorityDespeckle(const TRasterP &ras, int sizeThreshold) {
|
|
Shinya Kitaoka |
120a6e |
TRaster32P ras32(ras);
|
|
Shinya Kitaoka |
120a6e |
if (ras32) {
|
|
Shinya Kitaoka |
120a6e |
::majorityDespeckle(ras32, sizeThreshold);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRaster64P ras64(ras);
|
|
Shinya Kitaoka |
120a6e |
if (ras64) {
|
|
Shinya Kitaoka |
120a6e |
::majorityDespeckle(ras64, sizeThreshold);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterGR8P rasGR8(ras);
|
|
Shinya Kitaoka |
120a6e |
if (rasGR8) {
|
|
Shinya Kitaoka |
120a6e |
::majorityDespeckle(rasGR8, sizeThreshold);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterGR16P rasGR16(ras);
|
|
Shinya Kitaoka |
120a6e |
if (rasGR16) {
|
|
Shinya Kitaoka |
120a6e |
::majorityDespeckle(rasGR16, sizeThreshold);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TRasterCM32P rasCM32(ras);
|
|
Shinya Kitaoka |
120a6e |
if (rasCM32) {
|
|
Shinya Kitaoka |
120a6e |
// Not yet implemented
|
|
Shinya Kitaoka |
120a6e |
assert(false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
//::majorityDespeckleCM(rasCM32, sizeThreshold, toneTol);
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|