Image Component Library (ICL)
|
Complex utility class for detection of connected image components. More...
#include <RegionDetector.h>
Public Member Functions | |
RegionDetector (bool createRegionGraph, const std::string &configurableID=Configurable::create_default_ID("region-detector-")) | |
first constructor with given flag for creation of the region graph | |
RegionDetector (int minSize=1, int maxSize=400000000, int minVal=0, int maxVal=255, bool createRegionGraph=false, const std::string &configurableID=Configurable::create_default_ID("region-detector-")) | |
2nd constructor with given constraints and region-graph creation flag | |
virtual | ~RegionDetector () |
Destructor. | |
void | setConstraints (int minSize, int maxSize, int minVal, int maxVal) |
set up new constraints | |
void | setCreateGraph (bool on) |
set up the region-graph creation flag | |
void | setCSSParams (float angle_thresh=162., float rc_coeff=1.5, float sigma=3., float curvature_cutoff=100., float straight_line_thresh=0.1) |
sets the internally used parameters for CSS-based corner detection | |
const std::vector< ImageRegion > & | detect (const core::ImgBase *image) |
main apply function that is used to detect an images image-regions | |
const ImageRegion | click (const utils::Point &pos) |
Utility function that returns the image regions that contains a given position (e.g. from mouse input) | |
Private Member Functions | |
void | useImage (const core::ImgBase *image) throw (utils::ICLException) |
Internally used utility function that extracts the input images ROI if necessary. | |
void | analyseRegions () |
creates region-parts | |
void | joinRegions () |
combines ImageRegionParts | |
void | linkRegions () |
detects region neighbours | |
void | setUpBorders () |
detects border regions | |
void | filterRegions () |
filters regions by given size and value constraints | |
Private Attributes | |
Data * | m_data |
internal data structure |
Complex utility class for detection of connected image components.
The RegionDetector extracts all connected components from a given input image
Currently, only a 4-Neighbourhood for pixels is supported. This means, that Image-Regions have to be adjacent either horizontally or vertically. Pixels with an identical value, that are only connected diagonally are not connected.
As internally, adjacent pixels are compared using the default '==' processing of float- or double-images is currently not supported. Furthermore, it is also very uncommon to search for connected components on floating-point images.
In short: multi-channel images are not supported at all. Strictly speaking only the channel with index 0 is used, all other remain untouched.
ROI support is provided by the internally used instance of class RunLengthEncoder. The RunLengthEncoder has only a very small overhead for ROI-images. If an image with set ROI is passed to the RegionDetectors detect- function, only the images ROI is process internally. All other pixels will not be processed at all. In this case, regions, that are adjacent to the image ROI are set to be border-regions and image regions that intersect the ROI are cut at the ROI-boundaries. In other words, the detection behaves as if the image-ROI is extracted before the detection step.
The RegionDetector instance does not take ownership of the given input image. However, the input image needs to remain unchanged as long as the result of the RegionDetector::detect-function is used. Currently, only the ImageRegions's ImageRegion::getBoundary() and variants of this method actually demand the image to be unchanged, however, future implementations of other feature functions of ImageRegion do not guarantee this.
The ImageRegion structure that is returned by the RegionDetector::detect-function Is a utility wrapper around it's data structure that is called ImageRegionData. Please do not use ImageRegionData directly, but only by using the ImageRegion interface. ImageRegions can easily be copied (just a single pointer copy) -- the internal data is always managed by the parent RegionDetector instance.
There are two direct constraints, that can be defined for filtering the set of all image regions:
Note: Internally, all regions are always detected and automatically filtered afterwards. By this means, RegionDetector::detect only returns regions, that match the given size and value constraints but also all neighbours and sub-regions of these are also available even if they do not match the filter criterion.
RegionDetector provides the functionality to perform a simple connected component analysis as well as to compute higher level information about the region structure. In particular, it can be set up to create a so called region graph. Which defines basically, which regions are adjacent. This information can then be used to compute a region hierarchy that defines which regions do contain which other regions. The most expensive step is to define the region neighbours of each region. Therefore, the creation of this additinal information has to be activated explicitly. If the RegionDetector was not set up to create the region graph (either via a constructor argument or using the function RegionDetector::setCreateGraph(bool)), this information is not available, and the following region-information are not available: region neighbours sub-regions parent regions
We use a custom designed and highly optimized algorithm for connected component analysis. In a first step: The image is run-length encoded. All further steps are performed on the resulting LineSegment representation.
The Algorithm is split into 6 parts:
In a first preprocessing step, the input image is run length encoded. Each image line is then no longer represented as a set of width pixel values but as a sequence of so called LineSegments each defined by pixel value, x,y, and xend. For this step a RunLengthEncoder instances is used. Note, that run length encoding is highly optimized in case of using icl8u-images. Here, the most essential step (search for the first pixel value that is different from the current one) is accelerated by checking 4 next pixels at once.
In this processing step, each 2 successive image lines (represented as sequences of LineSegments) are processed. Internally, we used a utility structure called WorkingLineSegment for run length encoding. This utility class can also hold additinal information which is a pointer to an ImageRegionPart in this step. If two line segments A and B with identical values are adjacent (using 4-neighbourhood), they are both added to A's ImageRegionPart and B's ImageRegionPart is set to A's ImageRegionPart. Occasionally, A and B are already set up with an ImageRegionPart. In this case, B's ImageRegionPart is added to A's ImageRegionPart and B's ImageRegionPart is set to be no longer on top level. Only top level ImageRegionParts are transformed to complete image regions in the next step.
After this step, we have a set of ImageRegionParts. Some of this parts are still top level, others are not and need to be added to their top-most ImageRegionPart.
Here, a ImageRegion (stricly speaking ImageRegionData-structure) is created from each top level ImageRegionParts T. During the creation process, all WorkingLineSegments of T and all contained ImageRegionParts are collected recursively. Furthermore, the internally used WorkingLineSegments do no longer need information about their parent ImageRegionPart. Therefore, their data pointer is set to their parent ImageRegionData structure.
After this step, we already have a set of all image regions.
If a region graph needs to be created, this step is used to detect which regions are adjacent. Again, we use the internal WorkingLineSegment representation. For each pair adjacent WorkingLineSegments A and B (4-neighbourhood) A's linked ImageRegionData is set to be a neighbour of B's ImageRegionData and vice versa. After this step, each ImageRegionData contains a set of all of it's adjacent ImageRegionData structures.
For the computation of region containment, regions that are adjacent to the image borders are special as these regions are not contained by other regions. Here, we again use the internal WorkingLineSegment representation to set up the isBorder-flag of all ImageRegionData structures that touch the image border to true.
Lastly, all ImageRegionData structures are filtered w.r.t. the given size and value constraints.
icl::cv::RegionDetector::RegionDetector | ( | bool | createRegionGraph, |
const std::string & | configurableID = Configurable::create_default_ID("region-detector-") |
||
) |
first constructor with given flag for creation of the region graph
Note: at default, the region graph is not created
icl::cv::RegionDetector::RegionDetector | ( | int | minSize = 1 , |
int | maxSize = 400000000 , |
||
int | minVal = 0 , |
||
int | maxVal = 255 , |
||
bool | createRegionGraph = false , |
||
const std::string & | configurableID = Configurable::create_default_ID("region-detector-") |
||
) |
2nd constructor with given constraints and region-graph creation flag
virtual icl::cv::RegionDetector::~RegionDetector | ( | ) | [virtual] |
Destructor.
void icl::cv::RegionDetector::analyseRegions | ( | ) | [private] |
creates region-parts
see Region Analysis
const ImageRegion icl::cv::RegionDetector::click | ( | const utils::Point & | pos | ) |
Utility function that returns the image regions that contains a given position (e.g. from mouse input)
click always refers to the last detect call. If no region contains the given point (e.g. because it is outside the image rectangle), a null-region is returned.
const std::vector<ImageRegion>& icl::cv::RegionDetector::detect | ( | const core::ImgBase * | image | ) |
main apply function that is used to detect an images image-regions
As explained in Supported Image Depths, this function is only valid for icl8u, icl16s and icl32s images
void icl::cv::RegionDetector::filterRegions | ( | ) | [private] |
filters regions by given size and value constraints
void icl::cv::RegionDetector::joinRegions | ( | ) | [private] |
combines ImageRegionParts
see Region Joining
void icl::cv::RegionDetector::linkRegions | ( | ) | [private] |
detects region neighbours
see Region Linking
void icl::cv::RegionDetector::setConstraints | ( | int | minSize, |
int | maxSize, | ||
int | minVal, | ||
int | maxVal | ||
) |
set up new constraints
void icl::cv::RegionDetector::setCreateGraph | ( | bool | on | ) |
set up the region-graph creation flag
void icl::cv::RegionDetector::setCSSParams | ( | float | angle_thresh = 162. , |
float | rc_coeff = 1.5 , |
||
float | sigma = 3. , |
||
float | curvature_cutoff = 100. , |
||
float | straight_line_thresh = 0.1 |
||
) |
sets the internally used parameters for CSS-based corner detection
The internal corner detector is used if ImageRegion::getBoundaryCorners is called on detected regions. Note, this can also be adjusted by the Configurable interface
void icl::cv::RegionDetector::setUpBorders | ( | ) | [private] |
detects border regions
void icl::cv::RegionDetector::useImage | ( | const core::ImgBase * | image | ) | throw (utils::ICLException) [private] |
Internally used utility function that extracts the input images ROI if necessary.
Data* icl::cv::RegionDetector::m_data [private] |
internal data structure
internal data pointer