1 #include "BlobDetectorBFS.hh"
2 #include <Base/ImageUtils/ImageDraw.hh>
3 #include <Base/Image/ImageConvert.hh>
4 #include <Base/Image/ImageIO.hh>
11 template <
class StorageType>
14 UL_[0] = UL_[1] = LR_[0] = LR_[1] = 0;
19 eraseBelowMinWeight_=
false;
25 template <
class StorageType>
37 template <
class StorageType>
40 std::vector<BIAS::BIASBlob> &blobs){
43 BIASERR(
"Blob detection only for 1 channel images, please convert!");
52 if(UL_[0] == 0 && UL_[1] == 0 && LR_[0] == 0 && LR_[1] == 0){
59 markerBackup_.Init(w,h,1);
61 markerBackup_.FillImageWithConstValue((
unsigned char)0);
62 unsigned char **idaMark = markerBackup_.GetImageDataArray();
63 for (
unsigned int y=UL_[1];y<LR_[1];y++) {
64 idaMark[y][UL_[0] ]=255;
65 idaMark[y][LR_[0]-1]=255;
67 for (
unsigned int x=UL_[0];x<LR_[0];x++) {
68 idaMark[UL_[1] ][x]=255;
69 idaMark[LR_[1]-1][x]=255;
73 marker_.CopyIn_NoInit(markerBackup_.GetImageData());
77 if (gaussSigma_!= 0.0) {
78 smoothFilter_.SetSigma(gaussSigma_);
79 smoothFilter_.Filter(image, imageSmooth_);
80 idaIn = ( StorageType**)imageSmooth_.GetImageDataArray();
84 unsigned int maxcornerweight = 0;
86 maxCorners_ = cornersCurrent;
89 StorageType **idaOrig;
90 if (eraseBelowMinWeight_) {
91 if (gaussSigma_ != 0.0) {
98 for (
unsigned int y=UL_[1];y<LR_[1];y++) {
99 for (
unsigned int x=UL_[0];x<LR_[0];x++) {
101 StorageType val = idaIn[y][x];
102 unsigned char mar = idaMark[y][x];
103 if (val > threshold_) {
105 if ((ClusterDescent_(x,y,w,h, idaIn, idaMark, cornersCurrent, idaOrig) == 0) &&
106 (cornersCurrent.
weight > minWeight_) && (cornersCurrent.
weight < maxWeight_)) {
108 corners_.push_back(cornersCurrent);
109 if (cornersCurrent.
weight > maxcornerweight) {
110 maxCorners_ = cornersCurrent;
111 maxcornerweight = cornersCurrent.
weight;
117 if (idaOrig != NULL) {
124 for(
unsigned k=0;k<corners_.size();k++){
125 blobs.push_back(corners_[k]);
143 template <
class StorageType>
146 const unsigned int w,
const unsigned int h,
147 StorageType **idaIn,
unsigned char **idaMark,
153 queue.push_back(start);
155 while (!queue.empty()) {
158 if (cluster.size() > w*h)
161 cluster.push_back(cur);
163 n[0] = n[2] = n[4] = cur[0]-1;
164 n[6] = n[8] = cur[0];
165 n[10] = n[12] = n[14] = cur[0]+1;
166 n[1] = n[7] = n[11] = cur[1]-1;
167 n[3] = n[13] = cur[1];
168 n[5] = n[9] = n[15] = cur[1]+1;
171 for (
unsigned int i=0;i<16;i+=2) {
173 if (idaMark[ y ][ x ] == 0) {
174 idaMark[ y ][ x ] = 255;
175 if (idaIn[ y ][ x ] > threshold_) {
176 start[0]=x; start[1]=y;
177 cluster.push_back(start);
178 queue.push_back(start);
277 corners.
weight = cluster.size();
278 if (corners.
weight > minWeight_ && corners.
weight < maxWeight_) {
279 corners.
UL[0] = cluster[0][0];
280 corners.
UL[1] = cluster[0][1];
281 corners.
LR[0] = cluster[0][0];
282 corners.
LR[1] = cluster[0][1];
285 for (
unsigned int i=1;i<corners.
weight;i++) {
289 if (cur[0] > corners.
LR[0])
290 corners.
LR[0] = cur[0];
291 if (cur[0] < corners.
UL[0])
292 corners.
UL[0] = cur[0];
293 if (cur[1] > corners.
LR[1])
294 corners.
LR[1] = cur[1];
295 if (cur[1] < corners.
UL[1])
296 corners.
UL[1] = cur[1];
303 if (idaOrig != NULL) {
304 for (
unsigned int i=0;i<cluster.size();i++) {
305 idaOrig[ cluster[i][1] ][ cluster[i][0] ] = 0;
319 template <
class StorageType>
322 StorageType green[3] = { 0,255,0 };
323 StorageType red[3] = { 255,0,0 };
332 for (
unsigned int i=0; i<corners_.size();i++) {
335 (
unsigned)c.
UL[1], (
unsigned)c.
LR[0],
336 (
unsigned)c.
LR[1], green);
340 if (GetLargestBoundingBox(c) == 0) {
342 (
unsigned)c.
UL[0], (
unsigned)c.
UL[1],
343 (
unsigned)c.
LR[0], (
unsigned)c.
LR[1], red);
345 (
unsigned)c.
UL[0]-1, (
unsigned)c.
UL[1]-1,
346 (
unsigned)c.
LR[0]+1, (
unsigned)c.
LR[1]+1, red);
348 (
unsigned)c.
UL[0]+1, (
unsigned)c.
UL[1]+1,
349 (
unsigned)c.
LR[0]-1, (
unsigned)c.
LR[1]-1, red);
359 #ifdef BUILD_IMAGE_INT
362 #ifdef BUILD_IMAGE_CHAR
365 #ifdef BUILD_IMAGE_SHORT
367 #ifdef BUILD_IMAGE_USHORT
370 #ifdef BUILD_IMAGE_UINT
372 #ifdef BUILD_IMAGE_DOUBLE
void CopyIn_NoInit(void *data)
Take some data and fill it into the Image.
BIAS::Vector2< double > LR
static int CircleCenterFilled(Image< StorageType > &im, unsigned int CenterX, unsigned int CenterY, unsigned int Radius, const StorageType Value[])
draws a filled circle using Value
unsigned int GetWidth() const
int Detect(BIAS::Image< StorageType > &image, std::vector< BIAS::BIASBlob > &blobs)
Detect and return blobs in an image.
static int RectangleCorners(Image< StorageType > &im, const int minx, const int miny, const int maxx, const int maxy, const StorageType value[])
rectangles
Helper class to store blob corners.
int ClusterDescent_(const unsigned int x, const unsigned int y, const unsigned int w, const unsigned int h, StorageType **idaIn, unsigned char **idaMark, BIAS::BIASBlob &corners, StorageType **idaOrig)
protected blobDetection function
BIAS::Vector2< double > centerofmass
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
unsigned int GetHeight() const
The image template class for specific storage types.
BlobDetectorBFS()
standard constructor
BIAS::Vector2< double > UL
int DrawInImage(BIAS::Image< StorageType > &image)
draws the detected blobs in image
virtual ~BlobDetectorBFS()
standard destructor
static int ToRGB(const Image< StorageType > &source, Image< StorageType > &dest)
Create a RGB converted copy of source image in this.
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase