1 #ifndef __FAST_AREA_OPENIN_MAX_TREE_T_HPP__
2 #define __FAST_AREA_OPENIN_MAX_TREE_T_HPP__
4 #include "Core/include/DCore.h"
42 #define CONNECTIVITY 4
46 #define PI 3.14159265358979323846
47 #define bzero(b, len) (memset((b), '\0', (len)), (void) 0)
49 typedef unsigned char ubyte;
50 typedef unsigned int uint;
51 typedef unsigned long ulong;
56 #define MIN(a, b) ((a <= b) ? (a) : (b))
60 #define MAX(a, b) ((a >= b) ? (a) : (b))
62 typedef struct ImageGray ImageGray;
89 #define ST_NotAnalyzed -1
90 #define ST_InTheQueue -2
96 ulong *NumPixelsBelowLevel;
97 ulong *NumNodesAtLevel;
99 void *(*NewAuxData)(ulong, ulong);
100 void (*AddToAuxData)(
void *, ulong, ulong);
101 void (*MergeAuxData)(
void *,
void *);
102 void (*DeleteAuxData)(
void *);
105 void MaxTreeDelete(
MaxTree *mt);
114 void *NewAreaData(SMIL_UNUSED ulong x, SMIL_UNUSED ulong y)
123 void DeleteAreaData(
void *areaattr)
128 void AddToAreaData(
void *areaattr, SMIL_UNUSED ulong x, SMIL_UNUSED ulong y)
130 AreaData *areadata = (AreaData *) areaattr;
135 void MergeAreaData(
void *areaattr,
void *childattr)
137 AreaData *areadata = (AreaData *) areaattr;
138 AreaData *childdata = (AreaData *) childattr;
140 areadata->Area += childdata->Area;
143 double AreaAttribute(
void *areaattr)
145 AreaData *areadata = (AreaData *) areaattr;
148 area = areadata->Area;
162 void *NewEnclRectData(ulong x, ulong y)
167 rectdata->MinX = rectdata->MaxX = x;
168 rectdata->MinY = rectdata->MaxY = y;
172 void DeleteEnclRectData(
void *rectattr)
177 void AddToEnclRectData(
void *rectattr, ulong x, ulong y)
179 EnclRectData *rectdata = (EnclRectData *) rectattr;
181 rectdata->MinX = MIN(rectdata->MinX, x);
182 rectdata->MinY = MIN(rectdata->MinY, y);
183 rectdata->MaxX = MAX(rectdata->MaxX, x);
184 rectdata->MaxY = MAX(rectdata->MaxY, y);
187 void MergeEnclRectData(
void *rectattr,
void *childattr)
189 EnclRectData *rectdata = (EnclRectData *) rectattr;
190 EnclRectData *childdata = (EnclRectData *) childattr;
192 rectdata->MinX = MIN(rectdata->MinX, childdata->MinX);
193 rectdata->MinY = MIN(rectdata->MinY, childdata->MinY);
194 rectdata->MaxX = MAX(rectdata->MaxX, childdata->MaxX);
195 rectdata->MaxY = MAX(rectdata->MaxY, childdata->MaxY);
198 double EnclRectAreaAttribute(
void *rectattr)
200 EnclRectData *rectdata = (EnclRectData *) rectattr;
203 area = (rectdata->MaxX - rectdata->MinX + 1) *
204 (rectdata->MaxY - rectdata->MinY + 1);
208 double EnclRectDiagAttribute(
void *rectattr)
211 EnclRectData *rectdata = (EnclRectData *) rectattr;
212 double minx, miny, maxx, maxy, l;
214 minx = rectdata->MinX;
215 miny = rectdata->MinY;
216 maxx = rectdata->MaxX;
217 maxy = rectdata->MaxY;
218 l = (maxx - minx + 1) * (maxx - minx + 1) +
219 (maxy - miny + 1) * (maxy - miny + 1);
228 double SumX, SumY, SumX2, SumY2;
231 void *NewInertiaData(ulong x, ulong y)
236 inertiadata->Area = 1;
237 inertiadata->SumX = x;
238 inertiadata->SumY = y;
239 inertiadata->SumX2 = x * x;
240 inertiadata->SumY2 = y * y;
241 return (inertiadata);
244 void DeleteInertiaData(
void *inertiaattr)
249 void AddToInertiaData(
void *inertiaattr, ulong x, ulong y)
251 InertiaData *inertiadata = (InertiaData *) inertiaattr;
254 inertiadata->SumX += x;
255 inertiadata->SumY += y;
256 inertiadata->SumX2 += x * x;
257 inertiadata->SumY2 += y * y;
260 void MergeInertiaData(
void *inertiaattr,
void *childattr)
262 InertiaData *inertiadata = (InertiaData *) inertiaattr;
263 InertiaData *childdata = (InertiaData *) childattr;
265 inertiadata->Area += childdata->Area;
266 inertiadata->SumX += childdata->SumX;
267 inertiadata->SumY += childdata->SumY;
268 inertiadata->SumX2 += childdata->SumX2;
269 inertiadata->SumY2 += childdata->SumY2;
272 double InertiaAttribute(
void *inertiaattr)
274 InertiaData *inertiadata = (InertiaData *) inertiaattr;
275 double area, inertia;
277 area = inertiadata->Area;
278 inertia = inertiadata->SumX2 + inertiadata->SumY2 -
279 (inertiadata->SumX * inertiadata->SumX +
280 inertiadata->SumY * inertiadata->SumY) /
286 double InertiaDivA2Attribute(
void *inertiaattr)
288 InertiaData *inertiadata = (InertiaData *) inertiaattr;
289 double inertia,
area;
291 area = (double) (inertiadata->Area);
292 inertia = inertiadata->SumX2 + inertiadata->SumY2 -
293 (inertiadata->SumX * inertiadata->SumX +
294 inertiadata->SumY * inertiadata->SumY) /
297 return (inertia * 2.0 * PI / (
area *
area));
300 double MeanXAttribute(
void *inertiaattr)
302 InertiaData *inertiadata = (InertiaData *) inertiaattr;
305 area = inertiadata->Area;
306 sumx = inertiadata->SumX;
307 return (sumx /
area);
310 double MeanYAttribute(
void *inertiaattr)
312 InertiaData *inertiadata = (InertiaData *) inertiaattr;
315 area = inertiadata->Area;
316 sumy = inertiadata->SumY;
317 return (sumy /
area);
322 ImageGray *ImageGrayCreate(ulong width, ulong height)
326 img = (ImageGray *) malloc(
sizeof(ImageGray));
330 img->Height = height;
331 img->Pixmap = (ubyte *) malloc(width * height);
332 if (img->Pixmap == NULL) {
339 void ImageGrayDelete(ImageGray *img)
345 void ImageGrayInit(ImageGray *img, ubyte h)
347 memset(img->Pixmap, h, (img->Width) * (img->Height));
352 HQueue *HQueueCreate(ulong imgsize, ulong *numpixelsperlevel)
357 hq = (HQueue *) calloc(NUMLEVELS,
sizeof(HQueue));
360 hq->Pixels = (ulong *) calloc(imgsize,
sizeof(ulong));
361 if (hq->Pixels == NULL) {
365 hq->Head = hq->Tail = 0;
366 for (i = 1; i < NUMLEVELS; i++) {
367 hq[i].Pixels = hq[i - 1].Pixels + numpixelsperlevel[i - 1];
368 hq[i].Head = hq[i].Tail = 0;
373 void HQueueDelete(HQueue *hq)
379 #define HQueueFirst(hq, h) (hq[h].Pixels[hq[h].Head++])
380 #define HQueueAdd(hq, h, p) hq[h].Pixels[hq[h].Tail++] = p
381 #define HQueueNotEmpty(hq, h) (hq[h].Head != hq[h].Tail)
383 int GetNeighbors(ubyte *shape, ulong imgwidth, ulong imgsize, ulong p,
390 if ((x < (imgwidth - 1)) && (shape[p + 1]))
392 if ((p >= imgwidth) && (shape[p - imgwidth]))
394 if ((x > 0) && (shape[p - 1]))
397 if ((p < imgsize) && (shape[p]))
402 int MaxTreeFlood(MaxTree *mt, HQueue *hq, ulong *numpixelsperlevel,
403 bool *nodeatlevel, ImageGray *img, ubyte *shape,
int h,
404 ulong *thisarea,
void **thisattr)
409 void *attr = NULL, *childattr;
410 ulong imgwidth, imgsize, p, q, idx, x, y;
411 ulong
area = *thisarea, childarea;
416 imgwidth = img->Width;
417 imgsize = imgwidth * (img->Height);
418 pixmap = img->Pixmap;
419 while (HQueueNotEmpty(hq, h)) {
421 p = HQueueFirst(hq, h);
425 mt->AddToAuxData(attr, x, y);
427 attr = mt->NewAuxData(x, y);
431 mt->MergeAuxData(attr, *thisattr);
433 mt->Status[p] = mt->NumNodesAtLevel[h];
434 numneighbors = GetNeighbors(shape, imgwidth, imgsize, p,
neighbors);
435 for (i = 0; i < numneighbors; i++) {
437 if (mt->Status[q] == ST_NotAnalyzed) {
438 HQueueAdd(hq, pixmap[q], q);
439 mt->Status[q] = ST_InTheQueue;
440 nodeatlevel[pixmap[q]] =
true;
441 if (pixmap[q] > pixmap[p]) {
446 m = MaxTreeFlood(mt, hq, numpixelsperlevel, nodeatlevel, img,
447 shape, m, &childarea, &childattr);
448 if (m >= NUMLEVELS) {
449 mt->DeleteAuxData(attr);
454 mt->MergeAuxData(attr, childattr);
459 mt->NumNodesAtLevel[h] = mt->NumNodesAtLevel[h] + 1;
461 while ((m >= 0) && (nodeatlevel[m] ==
false))
465 mt->Nodes + (mt->NumPixelsBelowLevel[h] + mt->NumNodesAtLevel[h] - 1);
466 node->Parent = mt->NumPixelsBelowLevel[m] + mt->NumNodesAtLevel[m];
468 idx = mt->NumPixelsBelowLevel[h];
469 node = mt->Nodes + idx;
473 node->Attribute = attr;
475 nodeatlevel[h] =
false;
481 MaxTree *MaxTreeCreate(ImageGray *img, ImageGray *templateImg,
482 void *(*newauxdata)(ulong, ulong),
483 void (*addtoauxdata)(
void *, ulong, ulong),
484 void (*mergeauxdata)(
void *,
void *),
485 void (*deleteauxdata)(
void *))
487 ulong numpixelsperlevel[NUMLEVELS];
488 bool nodeatlevel[NUMLEVELS];
491 ubyte *pixmap = img->Pixmap;
493 ulong imgsize, p, m = 0,
area = 0;
497 mt = (MaxTree *) malloc(
sizeof(MaxTree));
500 imgsize = (img->Width) * (img->Height);
501 mt->Status = (
long *) calloc((
size_t) imgsize,
sizeof(long));
502 if (mt->Status == NULL) {
506 mt->NumPixelsBelowLevel = (ulong *) calloc(NUMLEVELS,
sizeof(ulong));
507 if (mt->NumPixelsBelowLevel == NULL) {
512 mt->NumNodesAtLevel = (ulong *) calloc(NUMLEVELS,
sizeof(ulong));
513 if (mt->NumNodesAtLevel == NULL) {
514 free(mt->NumPixelsBelowLevel);
519 mt->Nodes = (MaxNode *) calloc((
size_t) imgsize,
sizeof(MaxNode));
520 if (mt->Nodes == NULL) {
521 free(mt->NumNodesAtLevel);
522 free(mt->NumPixelsBelowLevel);
529 for (p = 0; p < imgsize; p++)
530 mt->Status[p] = ST_NotAnalyzed;
531 bzero(nodeatlevel, NUMLEVELS *
sizeof(
bool));
532 bzero(numpixelsperlevel, NUMLEVELS *
sizeof(ulong));
535 for (p = 0; p < imgsize; p++)
536 numpixelsperlevel[pixmap[p]]++;
537 mt->NumPixelsBelowLevel[0] = 0;
538 for (l = 1; l < NUMLEVELS; l++) {
539 mt->NumPixelsBelowLevel[l] =
540 mt->NumPixelsBelowLevel[l - 1] + numpixelsperlevel[l - 1];
542 hq = HQueueCreate(imgsize, numpixelsperlevel);
545 free(mt->NumNodesAtLevel);
546 free(mt->NumPixelsBelowLevel);
553 for (p = 0; p < imgsize; p++) {
554 if (pixmap[p] < pixmap[m])
560 nodeatlevel[l] =
true;
562 mt->Status[m] = ST_InTheQueue;
565 mt->NewAuxData = newauxdata;
566 mt->AddToAuxData = addtoauxdata;
567 mt->MergeAuxData = mergeauxdata;
568 mt->DeleteAuxData = deleteauxdata;
569 l = MaxTreeFlood(mt, hq, numpixelsperlevel, nodeatlevel, img,
570 templateImg->Pixmap, l, &
area, &attr);
578 void MaxTreeDelete(MaxTree *mt)
584 for (h = 0; h < NUMLEVELS; h++) {
585 for (i = 0; i < mt->NumNodesAtLevel[h]; i++) {
586 attr = mt->Nodes[mt->NumPixelsBelowLevel[h] + i].Attribute;
588 mt->DeleteAuxData(attr);
592 free(mt->NumNodesAtLevel);
593 free(mt->NumPixelsBelowLevel);
598 void MaxTreeFilterMin(MaxTree *mt, ImageGray *img, ImageGray *templateImg,
599 ImageGray *out,
double (*attribute)(
void *),
602 MaxNode *node, *parnode;
603 ubyte *shape = templateImg->Pixmap;
604 ulong i, idx, parent;
607 for (l = 0; l < NUMLEVELS; l++) {
608 for (i = 0; i < mt->NumNodesAtLevel[l]; i++) {
609 idx = mt->NumPixelsBelowLevel[l] + i;
610 node = &(mt->Nodes[idx]);
611 parent = node->Parent;
612 parnode = &(mt->Nodes[parent]);
613 if ((idx != parent) && (((*attribute)(node->Attribute) < lambda) ||
614 (parnode->Level != parnode->NewLevel))) {
615 node->NewLevel = parnode->NewLevel;
617 node->NewLevel = node->Level;
620 for (i = 0; i < (img->Width) * (img->Height); i++) {
622 idx = mt->NumPixelsBelowLevel[img->Pixmap[i]] + mt->Status[i];
623 out->Pixmap[i] = mt->Nodes[idx].NewLevel;
628 void MaxTreeFilterDirect(MaxTree *mt, ImageGray *img, ImageGray *templateImg,
629 ImageGray *out,
double (*attribute)(
void *),
633 ubyte *shape = templateImg->Pixmap;
634 ulong i, idx, parent;
637 for (l = 0; l < NUMLEVELS; l++) {
638 for (i = 0; i < mt->NumNodesAtLevel[l]; i++) {
639 idx = mt->NumPixelsBelowLevel[l] + i;
640 node = &(mt->Nodes[idx]);
641 parent = node->Parent;
642 if ((idx != parent) && ((*attribute)(node->Attribute) < lambda)) {
643 node->NewLevel = mt->Nodes[parent].NewLevel;
645 node->NewLevel = node->Level;
648 for (i = 0; i < (img->Width) * (img->Height); i++) {
650 idx = mt->NumPixelsBelowLevel[img->Pixmap[i]] + mt->Status[i];
651 out->Pixmap[i] = mt->Nodes[idx].NewLevel;
656 void MaxTreeFilterMax(MaxTree *mt, ImageGray *img, ImageGray *templateImg,
657 ImageGray *out,
double (*attribute)(
void *),
661 ubyte *shape = templateImg->Pixmap;
662 ulong i, idx, parent;
665 for (l = 0; l < NUMLEVELS; l++) {
666 for (i = 0; i < mt->NumNodesAtLevel[l]; i++) {
667 idx = mt->NumPixelsBelowLevel[l] + i;
668 node = &(mt->Nodes[idx]);
669 parent = node->Parent;
670 if ((idx != parent) && ((*attribute)(node->Attribute) < lambda)) {
671 node->NewLevel = mt->Nodes[parent].NewLevel;
673 node->NewLevel = node->Level;
676 for (l = NUMLEVELS - 1; l > 0; l--) {
677 for (i = 0; i < mt->NumNodesAtLevel[l]; i++) {
678 idx = mt->NumPixelsBelowLevel[l] + i;
679 node = &(mt->Nodes[idx]);
680 parent = node->Parent;
681 if ((idx != parent) && (node->NewLevel == node->Level)) {
682 mt->Nodes[parent].NewLevel = mt->Nodes[parent].Level;
686 for (i = 0; i < (img->Width) * (img->Height); i++) {
688 idx = mt->NumPixelsBelowLevel[img->Pixmap[i]] + mt->Status[i];
689 out->Pixmap[i] = mt->Nodes[idx].NewLevel;
694 void MaxTreeFilterSubtractive(MaxTree *mt, ImageGray *img,
695 ImageGray *templateImg, ImageGray *out,
696 double (*attribute)(
void *),
double lambda)
698 MaxNode *node, *parnode;
699 ubyte *shape = templateImg->Pixmap;
700 ulong i, idx, parent;
703 for (l = 0; l < NUMLEVELS; l++) {
704 for (i = 0; i < mt->NumNodesAtLevel[l]; i++) {
705 idx = mt->NumPixelsBelowLevel[l] + i;
706 node = &(mt->Nodes[idx]);
707 parent = node->Parent;
708 parnode = &(mt->Nodes[parent]);
709 if ((idx != parent) && ((*attribute)(node->Attribute) < lambda)) {
710 node->NewLevel = parnode->NewLevel;
712 node->NewLevel = ((int) (node->Level)) + ((
int) (parnode->NewLevel)) -
713 ((int) (parnode->Level));
716 for (i = 0; i < (img->Width) * (img->Height); i++) {
718 idx = mt->NumPixelsBelowLevel[img->Pixmap[i]] + mt->Status[i];
719 out->Pixmap[i] = mt->Nodes[idx].NewLevel;
724 typedef struct AttribStruct AttribStruct;
728 void *(*NewData)(ulong, ulong);
729 void (*DeleteData)(
void *);
730 void (*AddToData)(
void *, ulong, ulong);
731 void (*MergeData)(
void *,
void *);
732 double (*Attribute)(
void *);
738 {
"Area", NewAreaData, DeleteAreaData, AddToAreaData, MergeAreaData,
740 {
"Area of min. enclosing rectangle", NewEnclRectData, DeleteEnclRectData,
741 AddToEnclRectData, MergeEnclRectData, EnclRectAreaAttribute},
742 {
"Square of diagonal of min. enclosing rectangle", NewEnclRectData,
743 DeleteEnclRectData, AddToEnclRectData, MergeEnclRectData,
744 EnclRectDiagAttribute},
745 {
"Moment of Inertia", NewInertiaData, DeleteInertiaData, AddToInertiaData,
746 MergeInertiaData, InertiaAttribute},
747 {
"(Moment of Inertia) / (area)^2", NewInertiaData, DeleteInertiaData,
748 AddToInertiaData, MergeInertiaData, InertiaDivA2Attribute},
749 {
"Mean X position", NewInertiaData, DeleteInertiaData, AddToInertiaData,
750 MergeInertiaData, MeanXAttribute},
751 {
"Mean Y position", NewInertiaData, DeleteInertiaData, AddToInertiaData,
752 MergeInertiaData, MeanYAttribute}};
754 typedef struct DecisionStruct DecisionStruct;
759 double (*attribute)(
void *),
double);
762 #define NUMDECISIONS 4
765 {
"Min", MaxTreeFilterMin},
766 {
"Direct", MaxTreeFilterDirect},
767 {
"Max", MaxTreeFilterMax},
768 {
"Subtractive", MaxTreeFilterSubtractive},
771 template <
class T1,
class T2>
775 ASSERT_ALLOCATED(&imIn)
776 ASSERT_SAME_SIZE(&imIn, &imOut)
782 int attrib = 0, decision = 2;
791 img.Pixmap = bufferIn;
795 out.Pixmap = bufferOut;
797 templateImg = ImageGrayCreate(img.Width, img.Height);
799 ImageGrayInit(templateImg, NUMLEVELS - 1);
801 mt = MaxTreeCreate(&img, templateImg, Attribs[attrib].NewData,
802 Attribs[attrib].AddToData, Attribs[attrib].MergeData,
803 Attribs[attrib].DeleteData);
804 Decisions[decision].Filter(mt, &img, templateImg, &out,
805 Attribs[attrib].Attribute, size);
807 ImageGrayDelete(templateImg);
812 template <
class T1,
class T2>
817 ASSERT_ALLOCATED(&imIn)
818 ASSERT_SAME_SIZE(&imIn, &imOut)
824 int attrib = 4, decision = 2;
833 img.Pixmap = bufferIn;
837 out.Pixmap = bufferOut;
839 templateImg = ImageGrayCreate(img.Width, img.Height);
841 ImageGrayInit(templateImg, NUMLEVELS - 1);
843 mt = MaxTreeCreate(&img, templateImg, Attribs[attrib].NewData,
844 Attribs[attrib].AddToData, Attribs[attrib].MergeData,
845 Attribs[attrib].DeleteData);
846 Decisions[decision].Filter(mt, &img, templateImg, &out,
847 Attribs[attrib].Attribute, size);
849 ImageGrayDelete(templateImg);
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:80
size_t getHeight() const
Get image height.
Definition: DBaseImage.h:85
Definition: DBaseImage.h:386
lineType getPixels() const
Get the pixels as a 1D array.
Definition: DImage.hpp:105
RES_T ImInertiaThinning_MaxTree(const Image< T1 > &imIn, double size, Image< T2 > &imOut)
Inertia thinning with a max tree algorithm (V4)
Definition: AreaOpeningMaxTree.hpp:813
RES_T ImAreaOpening_MaxTree(const Image< T1 > &imIn, int size, Image< T2 > &imOut)
Area opening with a max tree algorithm (V4)
Definition: AreaOpeningMaxTree.hpp:772
RES_T fill(Image< T > &imOut, const T &value)
fill() - Fill an image with a given value.
Definition: DImageArith.hpp:1456
RES_T neighbors(const Image< T1 > &imIn, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
neighbors() - Neighbors count
Definition: DMorphoLabel.hpp:1160
size_t area(const Image< T > &imIn)
area() - Area of an image
Definition: DMeasures.hpp:91
Definition: AreaOpeningMaxTree.hpp:110
Definition: AreaOpeningMaxTree.hpp:726
Definition: AreaOpeningMaxTree.hpp:756
Definition: AreaOpeningMaxTree.hpp:155
Definition: AreaOpeningMaxTree.hpp:70
Definition: AreaOpeningMaxTree.hpp:64
Definition: AreaOpeningMaxTree.hpp:226
Definition: AreaOpeningMaxTree.hpp:78
Definition: AreaOpeningMaxTree.hpp:94