26 # pragma warning (disable: 4251) // STL MAP DLL warning noise (JW)
33 #include <Base/Image/ImageIO.hh>
34 #include <Base/Image/ImageConvert.hh>
38 #include <Base/Common/BIASpragma.hh>
39 #include <MathAlgo/Median1D.hh>
45 #define MAX_SEG UCHAR_MAX
46 #define MAX_LAB USHRT_MAX
57 LabelInitialized_=
false;
58 _FilterBorderHandling=TBH_same;
68 BIASDOUT(D_INIT,
"LabelInit_()");
69 unsigned int UpperLeftX, UpperLeftY, LowerRightX, LowerRightY;
70 Image.
GetROI()->
GetCorners(UpperLeftX, UpperLeftY, LowerRightX, LowerRightY);
71 LabelSumImage_.Init(LowerRightX - UpperLeftX, LowerRightY - UpperLeftY);
72 LabelResultImage_.Init(LowerRightX - UpperLeftX,
73 LowerRightY - UpperLeftY);
74 LabelInitialized_=
true;
102 BIASDOUT(D_INIT,
"LabelShortRelease_()");
103 LabelSumImage_.Release();
104 LabelResultImage_.Release();
105 LabelInitialized_=
false;
112 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Label::Label4Neighbour_\n");
113 int nx, ny, i, k, no_seg, lab_seg2, lab_segv, no_all, *seg_list = NULL;
114 register int value, lab_seg1;
115 register LABEL_CALC_TYPE *adr, *adr_out;
117 try { seg_list =
new int[MAX_LAB]; }
118 catch (bad_alloc) { BIASERR(
"new failed "); }
119 nx = LabelSumImage_.GetWidth();
120 ny = LabelSumImage_.GetHeight();
121 adr = LabelSumImage_.GetImageData();
122 adr_out = LabelResultImage_.GetImageData();
132 seg_list[0] = SEGDEF;
134 for ( k = nx-1 ; k > 0 ; k--)
136 if (*adr != *(adr-1))
139 seg_list[no_seg] = SEGDEF;
143 *adr_out++ = lab_seg1;
151 for ( i = ny-1 ; i > 0 ; i--)
161 if ( *(adr-nx) == value ) lab_seg1 = *(adr_out-nx);
163 if ( lab_seg1 == -1 )
166 seg_list[no_seg] = SEGDEF;
178 for ( k = nx-1 ; k > 0; k--)
181 lab_seg2 = *(adr_out-nx);
183 if ( *(adr-1) == value)
187 else if ( *(adr-nx) == value)
189 lab_seg1 = *(adr_out-nx);
199 seg_list[no_seg] = SEGDEF;
201 if (no_seg > MAX_LAB) {
202 BIASERR(
"error: too many blobs " << ERR_NOLB);
211 *(adr_out-1) = lab_segv;
219 if ( k != 1 && value == *(adr-nx) && lab_seg1 != lab_seg2)
222 seg_list[lab_seg2] = -lab_seg1-1;
223 for ( m = nx ; m > 0; m--)
225 if ( *(adr_out-m) == lab_seg2)
226 *(adr_out-m) = lab_seg1;
234 *(adr_out-1) = lab_segv;
243 for ( i = 0; i <= no_seg ; i++)
245 if (seg_list[i] == SEGDEF)
247 seg_list[i] = no_all;
257 for ( i = 0; i <= no_seg ; i++)
261 while (seg_list[ind] < 0 )
263 ind = -seg_list[ind]-1;
265 seg_list[i] = seg_list[ind];
273 adr_out = LabelResultImage_.GetImageData();
274 for ( i = nx*ny ; i > 0 ; i--)
276 *adr_out = seg_list[*adr_out];
289 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Label::Label4Neighbour\n");
291 if (!LabelInitialized_){
300 CornerCount = Label4Neighbour_();
302 DestinationImage.
Paste2ROI(LabelResultImage_);
311 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Label::Label4Neighbour\n");
314 if (!LabelInitialized_)
331 CornerCount = Label4Neighbour_();
333 if (CornerCount > MAX_SEG){
334 BIASERR(
"Label::Label4Neighbour() Segmentzahl "
335 << CornerCount <<
" der Label zu gross\n");
336 CornerCount = MAX_SEG;
339 DestinationImage.
Paste2ROI(LabelResultImage_);
346 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Label::Process\n");
347 if (!LabelInitialized_)
352 unsigned minx, miny, maxx, maxy;
358 if (!LabelResultImage_.SamePixelAndChannelCount(roiImg) ) {
366 width=LabelResultImage_.GetWidth();
367 height=LabelResultImage_.GetHeight();
368 BIASCDOUT(D_LABEL,
"image size: "<<width<<
"x"<<height<<endl);
371 int count = Label4Neighbour_();
374 BIASCDOUT(D_LABEL,
"found "<<count<<
" blobs\n");
380 MedianCenters_.clear();
383 BlobCount_.push_back(0);
387 BlobCount_.resize(count-1);
388 TopLefts_.resize(count-1);
389 BotRights_.resize(count-1);
390 Centers_.resize(count-1);
391 MedianCenters_.resize(count-1);
392 SortVec_.resize(count);
394 for (
int n=0; n<count; n++){
396 SortVec_[n].tl.Set(width, height);
397 SortVec_[n].br.Set(0, 0);
398 SortVec_[n].center.Set(0.0, 0.0);
399 SortVec_[n].x.clear();
400 SortVec_[n].y.clear();
403 LABEL_CALC_TYPE **ida=LabelResultImage_.GetImageDataArray();
406 for (
int y=0; y<height; y++){
407 for (
int x=0; x<width; x++){
411 while (i<Num_.size() && Num_[i]!=c) i++;
413 if (i==Num_.size()) Num_.push_back(c);
421 SortVec_[i].x.push_back(x);
422 SortVec_[i].y.push_back(y);
423 if (SortVec_[i].tl[0]>x) SortVec_[i].tl[0]=x;
424 if (SortVec_[i].tl[1]>y) SortVec_[i].tl[1]=y;
425 if (SortVec_[i].br[0]<x) SortVec_[i].br[0]=x;
426 if (SortVec_[i].br[1]<y) SortVec_[i].br[1]=y;
430 sort(SortVec_.begin(), SortVec_.end());
432 BIASCDOUT(D_LABEL,
"neglecting bg label: "<<SortVec_[0].center <<
"\t"
433 << (
double)SortVec_[0].bc <<
"\t"<<SortVec_[0].tl<<
"\t"
435 << (SortVec_[0].center / (
double)SortVec_[0].bc) <<
"\t"
439 for (
int i=1, j=0; i<count; i++, j++){
440 BlobCount_[j]=SortVec_[i].bc;
441 BlobMap_[i]=SortVec_[i].bc;
442 TopLefts_[j]=SortVec_[i].tl;
443 BotRights_[j]=SortVec_[i].br;
444 Centers_[j] = (SortVec_[i].center / (double)SortVec_[i].bc) + offset;
446 mx = (double)med.
GetMedian() + offset[0];
448 my = (double)med.
GetMedian() + offset[1];
451 BIASCDOUT(D_LABEL, SortVec_[i].center <<
"\t"
452 << (
double)SortVec_[i].bc <<
"\t"<<Centers_[j] <<
"\t"
453 << SortVec_[i].tl <<
"\t"<< SortVec_[i].br<<
"\t"
454 << (SortVec_[i].center / (
double)SortVec_[i].bc) <<
"\n");
462 BIASCDOUT(D_FILTERBASE_CALLSTACK,
"Label::Filter\n");
465 if (BlobCount_.size()>255) {
466 BIASERR(
"Label.Filter(): resulting image invalid, cause more than 255 "
469 bool UseLargeImage =
false;
471 if (!LabelResultImage_.SamePixelAndChannelCount(src)) {
473 unsigned int UpperLeftX, UpperLeftY, LowerRightX, LowerRightY;
475 LargeImage.
GetROI()->
SetCorners(UpperLeftX, UpperLeftY, LowerRightX, LowerRightY);
477 UseLargeImage =
true;
495 border_x = border_y = 0;
int GetCopyOfROI(ImageBase ©) const
returns a copy of ROI (a new image) lower right point excluded, only interleaved images ! ...
void Release()
reimplemented from ImageBase
void LabelInit_(const ImageBase &Image)
int SetCorners(unsigned UpperLeftX, unsigned UpperLeftY, unsigned LowerRightX, unsigned LowerRightY)
Sets a rectangular region of interest.
void GetCorners(unsigned &UpperLeftX, unsigned &UpperLeftY, unsigned &LowerRightX, unsigned &LowerRightY) const
Return the region of interest, by saving the coordinates within the variables defined by the paramete...
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
int Label4Neighbour(const BIAS::Image< unsigned char > &Image, BIAS::Image< unsigned char > &DestinationImage)
labels an unsigned short int using an 4er neighbourhood and returns it in DestinationImage if Destina...
int Process(const Image< unsigned char > &im)
call this if you don't need the output image, is faster than Filter
unsigned int GetWidth() const
virtual int Filter(const Image< unsigned char > &src, Image< unsigned char > &dst)
prototyp for filter computation function
ROI * GetROI()
Returns a pointer to the roi object.
static int ConvertST(const BIAS::ImageBase &source, BIAS::ImageBase &dest, ImageBase::EStorageType targetST)
Function to convert the storage type of images e.g.
unsigned int GetHeight() const
The image template class for specific storage types.
bool SamePixelAndChannelCount(const ImageBase &Image) const
checks if data area has same "size" as Image of other type
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
(8bit) unsigned char image storage type
int Paste2ROI(const ImageBase &Image)
paste Image to current ROI
This is the base class for images in BIAS.
virtual void GetBordersValid_(int &border_x, int &border_y) const