全局Haar-Like特徵圖像識別的C++實現

 cvdirectcascade.h:
#include "cv.h"

struct TWeakClassifier
{
    CvRect Rectangles[
2];
}
;

struct PtrWeakClassifier
{
    
long *tl0, *tr0, *bl0, *br0;
    
long *tl1, *tr1, *bl1, *br1;
    
int offset, size0, size1;
    
int Threshold;
}
;

struct ListObjectType
{
    
int x, y, width, height;
    
int w;
    
bool use;
    ListObjectType 
*next;
}
;

struct TLearnedObject
{
    TWeakClassifier 
*Classifiers;
    PtrWeakClassifier 
*ScaleClassifiers;
    
int ObjectWidth, ObjectHeight;
    
int NClassifiers;
}
;

struct TDetectSettings
{
    
double ScaleRatio, OffsetX, OffsetY;
    
int Ignore, MinW;
    
int StartSubWindow, EndSubWindow;
}
;

bool LoadDefaultSetting(char *FileName, TDetectSettings &DS);
void LearnClassifiers(unsigned char *IptImage, TLearnedObject &target, int IptWidth, int IptHeight);
int DetectObject(TLearnedObject &target, unsigned char *FrameImage, int Width, int Height, TDetectSettings &DS, CvRect *&Objects);

cvdirectcascade.cpp:
#include <iostream.h>
#include 
<stdio.h>
#include 
<math.h>
#include 
<string.h>
#include 
<ctype.h>
#include 
<stdlib.h>

#include 
"cv.h"
#include 
"cvdirectcascade.h"

bool Overlapped(ListObjectType *obj1, ListObjectType *obj2)
{
    
int cx = obj1->+ obj1->width / 2;
    
int cy = obj1->+ obj1->height / 2;
    
if ((cx > obj2->x) && (cx < obj2->+ obj2->width) && (cy > obj2->y) && (cy < obj2->+ obj2->height))
        
return true;
    cx 
= obj2->+ obj2->width / 2;
    cy 
= obj2->+ obj2->height / 2;
    
if ((cx > obj1->x) && (cx < obj1->+ obj1->width) && (cy > obj1->y) && (cy < obj1->+ obj1->height))
        
return true;
    
return false;
}


void RestoreImage(unsigned char *IptImage, long *&IntegralImage, int IptWidth, int IptHeight)
{
    IntegralImage 
= new long [(IptWidth + 1* (IptHeight + 1)];

    
long *pic = IntegralImage;
    
for (int i = 0; i < IptWidth + 1; i++)
    
{
        
*pic = 0; pic++;
    }

    
for (int j = 0; j < IptHeight; j++)
    
{
        
*pic = 0; pic+=IptWidth + 1;
    }


    unsigned 
char *pc = IptImage;
    
long *picx, *picy, *picxy;
    picxy 
= IntegralImage;
    pic 
= picxy + IptWidth + 2;
    picx 
= picxy + IptWidth + 1;
    picy 
= picxy + 1;
    
for (i = 0; i < IptHeight; i++)
    
{
        
for (j = 0; j < IptWidth; j++)
        
{
            
*pic = *pc + *picx + *picy - *picxy;
            pic
++; picx++; picy++; picxy++;
            pc
++;
        }

        pic
++; picx++; picy++; picxy++;
    }

}


int CalculateXBoundary(unsigned char *IptImage, int IptWidth, int IptHeight, int x, int y, int width, int height)
{
    
int T, NewT = width / 2, C1 = 0, C2 = 0, D1 = 0, D2 = 0;
    unsigned 
char *ptr, *oldptr;
    oldptr 
= IptImage + IptWidth * y + x;
    
int step = IptWidth - width;
    
do{
        T 
= NewT;
        C1 
= 0; C2 = 0; D1 = 0; D2 = 0;
        ptr 
= oldptr;
        
for (int j = y; j < y + height; j++)
        
{
            
for (int i = x; i < x + T; i++)
            
{
                C1 
+= (i - x) * *ptr;
                D1 
+= *ptr;
                ptr
++;
            }

            
for (i = x + T; i < x + width; i++)
            
{
                C2 
+= (i - x) * *ptr;
                D2 
+= *ptr;
                ptr
++;
            }

            ptr
+=step;
        }

        C1 
= C1 / D1; C2 = C2 / D2;
        NewT 
= (C1 + C2) / 2;
    }
while (NewT != T);
    
return T;
}


int CalculateYBoundary(unsigned char *IptImage, int IptWidth, int IptHeight, int x, int y, int width, int height)
{
    
int T, NewT = height / 2, C1 = 0, C2 = 0, D1 = 0, D2 = 0;
    unsigned 
char *ptr, *oldptr;
    oldptr 
= IptImage + IptWidth * y + x;
    
int step = IptWidth - width;
    
do{
        T 
= NewT;
        C1 
= 0; C2 = 0; D1 = 0; D2 = 0;
        ptr 
= oldptr;
        
for (int j = y; j < y + T; j++)
        
{
            
for (int i = x; i < x + width; i++)
            
{
                C1 
+= (j - y) * *ptr;
                D1 
+= *ptr;
                ptr
++;
            }

            ptr
+=step;
        }

        
for (j = y + T; j < y + height; j++)
        
{
            
for (int i = x; i < x + width; i++)
            
{
                C2 
+= (j - y) * *ptr;
                D2 
+= *ptr;
                ptr
++;
            }

            ptr
+=step;
        }

        C1 
= C1 / D1; C2 = C2 / D2;
        NewT 
= (C1 + C2) / 2;
    }
while (NewT != T);
    
return T;
}


void LearnClassifiers(unsigned char *IptImage, TLearnedObject &target, int IptWidth, int IptHeight)
{
    
long *IntegralImage = NULL;

    target.ObjectWidth 
= IptWidth; target.ObjectHeight = IptHeight;
    RestoreImage(IptImage, IntegralImage, IptWidth, IptHeight);
    CvRect 
*close, *open, *record;

    record 
= new CvRect [target.NClassifiers * 2];

    TWeakClassifier 
*cptr;
    cptr 
= target.Classifiers; int NowClassifiers = 0;
    close 
= record;    open = record;
    record
->= 0; record->= 0;
    record
->width = IptWidth; record->height = IptHeight;
    
do{
        
int T;
        
if (close->width > 1)
        
{
            T 
= CalculateXBoundary(IptImage, IptWidth, IptHeight, close->x, close->y, close->width, close->height);
            
if ((T > 0&& (T < close->width))
            
{
                cptr
->Rectangles[0].x = close->x;
                cptr
->Rectangles[0].y = close->y;
                cptr
->Rectangles[0].width = T;
                cptr
->Rectangles[0].height = close->height;
                cptr
->Rectangles[1].x = close->+ T;
                cptr
->Rectangles[1].y = close->y;
                cptr
->Rectangles[1].width = close->width - T;
                cptr
->Rectangles[1].height = close->height;
                NowClassifiers
++; cptr++;
                
if (NowClassifiers >= target.NClassifiers) break;
                open
++;
                open
->= close->x;    open->= close->y;
                open
->width = T; open->height = close->height;
                open
++;
                open
->= close->+ T; open->= close->y;
                open
->width = close->width - T; open->height = close->height;
            }

        }

        
if (close->height > 1)
        
{
            T 
= CalculateYBoundary(IptImage, IptWidth, IptHeight, close->x, close->y, close->width, close->height);
            
if ((T > 0&& (T < close->height))
            
{
                cptr
->Rectangles[0].x = close->x;
                cptr
->Rectangles[0].y = close->y;
                cptr
->Rectangles[0].width = close->width;
                cptr
->Rectangles[0].height = T;
                cptr
->Rectangles[1].x = close->x;
                cptr
->Rectangles[1].y = close->+ T;
                cptr
->Rectangles[1].width = close->width;
                cptr
->Rectangles[1].height = close->height - T;
                NowClassifiers
++; cptr++;
                
if (NowClassifiers >= target.NClassifiers) break;
                open
++;
                open
->= close->x;    open->= close->y;
                open
->width = close->width; open->height = T;
                open
++;
                open
->= close->x; open->= close->+ T;
                open
->width = close->width; open->height = close->height - T;
            }

        }

        close
++;
    }
while (close <= open);
    delete [] record;

    cptr 
= target.Classifiers;
    PtrWeakClassifier 
*scptr;
    scptr 
= target.ScaleClassifiers;
    
for (int i = 0; i < target.NClassifiers; i++)
    
{
        scptr
->tl0 = IntegralImage + cptr->Rectangles[0].y * (IptWidth + 1+ cptr->Rectangles[0].x;
        scptr
->tr0 = scptr->tl0 + cptr->Rectangles[0].width;
        scptr
->bl0 = IntegralImage + (cptr->Rectangles[0].y + cptr->Rectangles[0].height) * (IptWidth + 1+ cptr->Rectangles[0].x;
        scptr
->br0 = scptr->bl0 + cptr->Rectangles[0].width;
        scptr
->size0 =cptr->Rectangles[0].width * cptr->Rectangles[0].height;
        scptr
->tl1 = IntegralImage + cptr->Rectangles[1].y * (IptWidth + 1+ cptr->Rectangles[1].x;
        scptr
->tr1 = scptr->tl1 + cptr->Rectangles[1].width;
        scptr
->bl1 = IntegralImage + (cptr->Rectangles[1].y + cptr->Rectangles[1].height) * (IptWidth + 1+ cptr->Rectangles[1].x;
        scptr
->br1 = scptr->bl1 + cptr->Rectangles[1].width;
        scptr
->size1 =cptr->Rectangles[1].width * cptr->Rectangles[1].height;
        
int gray = (*(scptr->br0) - *(scptr->bl0) - *(scptr->tr0) + *(scptr->tl0)) / scptr->size0;
        gray 
-= (*(scptr->br1) - *(scptr->bl1) - *(scptr->tr1) + *(scptr->tl1)) / scptr->size1;
        scptr
->Threshold = gray;
        scptr
++; cptr++;
    }

  
    delete [] IntegralImage;
}


int DetectObject(TLearnedObject &target, unsigned char *FrameImage, int Width, int Height, TDetectSettings &DS, CvRect *&Objects)
{
    
long *IntegralImage = NULL;
    RestoreImage(FrameImage, IntegralImage, Width, Height);

    
bool smallenough = false;
    
int ObjectWindow;
    
if (target.ObjectWidth > target.ObjectHeight) ObjectWindow = target.ObjectWidth; else ObjectWindow = target.ObjectHeight;
    
double scale = (double)DS.StartSubWindow / (double)ObjectWindow;
    
double scale_ = 1 / scale, newscalex = scale * DS.OffsetX, newscaley = scale * DS.OffsetY;
    
int NewWidth = (int)(Width * scale_), NewHeight = (int)(Height * scale_);
    
int NOWidth = (int)(target.ObjectWidth * scale), NOHeight = (int)(target.ObjectHeight * scale);
    
int EndWidth, EndHeight;
    
//size definement
    ListObjectType *ListObjects;
    ListObjects 
= new ListObjectType;
    ListObjectType 
*objptr, *oldptr;
    objptr 
= ListObjects;
    
int ListCount = 0, Count = 0;
    
//object list
    TWeakClassifier *cptr = NULL, *ocptr = target.Classifiers;
    PtrWeakClassifier 
*scptr = NULL, *oscptr = target.ScaleClassifiers;
    
int Nc = target.NClassifiers;
    
int Ignore = DS.Ignore, MinW = DS.MinW;
    
//scaling && detecting
    do{
        
int x, y, swidth, sheight;
        cptr 
= ocptr; scptr = oscptr;
        
for (int i = 0; i < Nc; i++)
        
{
            x 
= (int)(cptr->Rectangles[0].x * scale);
            y 
= (int)(cptr->Rectangles[0].y * scale);
            swidth 
= (int)(cptr->Rectangles[0].width * scale);
            sheight 
= (int)(cptr->Rectangles[0].height * scale);
            scptr
->tl0 = IntegralImage + x + y * (Width + 1);
            scptr
->tr0 = scptr->tl0 + swidth;
            scptr
->bl0 = IntegralImage + x + (y + sheight) * (Width + 1);
            scptr
->br0 = scptr->bl0 + swidth;
            scptr
->size0 = sheight * swidth;
            x 
= (int)(cptr->Rectangles[1].x * scale);
            y 
= (int)(cptr->Rectangles[1].y * scale);
            swidth 
= (int)(cptr->Rectangles[1].width * scale);
            sheight 
= (int)(cptr->Rectangles[1].height * scale);
            scptr
->tl1 = IntegralImage + x + y * (Width + 1);
            scptr
->tr1 = scptr->tl1 + swidth;
            scptr
->bl1 = IntegralImage + x + (y + sheight) * (Width + 1);
            scptr
->br1 = scptr->bl1 + swidth;
            scptr
->size1 = sheight * swidth;
            scptr
->offset = 0;
            scptr
++; cptr++;
        }

        
int  oldy = 0, diffx = 0, diffy = 0;
        
double InvWindowArea = 1 / (double)(NOWidth * NOHeight);
        
if (scale < 1)
        
{
            EndWidth 
= (int)((Width - NOWidth) / DS.OffsetX);
            EndHeight 
= (int)((Height - NOHeight) / DS.OffsetY);
            newscalex 
= DS.OffsetX; newscaley = DS.OffsetY;
        }

        
else
        
{
            EndWidth 
= (int)((NewWidth - target.ObjectWidth) / DS.OffsetX);
            EndHeight 
= (int)((NewHeight - target.ObjectHeight) / DS.OffsetY);
            newscalex 
= scale * DS.OffsetX; newscaley = scale * DS.OffsetY;
        }

        
for (i = 0; i < EndHeight; i++)
        
{
            y 
= (int)(i * newscaley);
            diffy 
= (y - oldy - 1* (Width + 1); oldy = y;
            
if (diffy > 0)
            
{
                scptr 
= oscptr;
                
for (int k = 0; k < Nc; k++)
                
{
                    scptr
->tl0+=diffy; scptr->tr0+=diffy;
                    scptr
->bl0+=diffy; scptr->br0+=diffy;
                    scptr
->tl1+=diffy; scptr->tr1+=diffy;
                    scptr
->bl1+=diffy; scptr->br1+=diffy;
                    scptr
++;
                }

            }

            
for (int j = 0; j < EndWidth; j++)
            
{
                x 
= (int)(j * newscalex);
                
bool Identify = true;
                
int w = 0;
                scptr 
= oscptr;
                
for (int k = 0; k < Nc; k++)
                
{
                    diffx 
= x - scptr->offset; scptr->offset = x;
                    scptr
->tl0+=diffx; scptr->tr0+=diffx;
                    scptr
->bl0+=diffx; scptr->br0+=diffx;
                    scptr
->tl1+=diffx; scptr->tr1+=diffx;
                    scptr
->bl1+=diffx; scptr->br1+=diffx;
                    
int gray = (*(scptr->br0) - *(scptr->bl0) - *(scptr->tr0) + *(scptr->tl0)) / scptr->size0;
                    gray 
-= (*(scptr->br1) - *(scptr->bl1) - *(scptr->tr1) + *(scptr->tl1)) / scptr->size1;
                    
if ((gray < scptr->Threshold - Ignore) || (gray > scptr->Threshold + Ignore))
                    
{
                        Identify 
= false;
                        
break;
                    }

                    
else
                        w 
+= abs(scptr->Threshold - gray);
                    scptr
++;
                }

                
if (w > MinW) Identify = false;
                
if (Identify)
                
{
                    objptr
->next = new ListObjectType;
                    objptr 
= objptr->next;
                    objptr
->= x; objptr->= y;
                    objptr
->width = NOWidth; objptr->height = NOHeight;
                    objptr
->= w; objptr->use = true;
                    ListCount
++;
                }

            }

            x 
= Width + 1;
            scptr 
= oscptr;
            
for (int k = 0; k < Nc; k++)
            
{
                diffx 
= x - scptr->offset; scptr->offset = 0;
                scptr
->tl0+=diffx; scptr->tr0+=diffx;
                scptr
->bl0+=diffx; scptr->br0+=diffx;
                scptr
->tl1+=diffx; scptr->tr1+=diffx;
                scptr
->bl1+=diffx; scptr->br1+=diffx;
                scptr
++;
            }

        }

        scale 
*= DS.ScaleRatio;
        scale_ 
= 1 / scale;
        NewWidth 
= (int)(Width * scale_); NewHeight = (int)(Height * scale_);
        NOWidth 
= (int)(target.ObjectWidth * scale); NOHeight = (int)(target.ObjectHeight * scale);
        
if ((NOWidth > DS.EndSubWindow) || (NOHeight > DS.EndSubWindow) || (NewWidth < target.ObjectWidth) || (NewHeight < target.ObjectHeight))
            smallenough 
= true;
        
else
            smallenough 
= false;
    }
while (!smallenough);

    
//merging
    ListObjectType *objptr2;
    objptr 
= ListObjects->next;
    
for (int i = 0; i < ListCount; i++)
    
{
        
if (objptr->use)
        
{
            objptr2 
= objptr->next;
            
for (int j = i + 1; j < ListCount; j++)
            
{
                
if (objptr2->use)
                    
if (Overlapped(objptr, objptr2))
                    
{
                        
if (objptr2->< objptr->w)
                            objptr
->use = false;
                        
else
                            objptr2
->use = false;
                    }

                objptr2 
= objptr2->next;
            }

        }

        objptr 
= objptr->next;
    }

    objptr 
= ListObjects->next; Count = 0;
    
for (i = 0; i < ListCount; i++)
    
{
        
if (objptr->use)
            Count
++;
        objptr 
= objptr->next;
    }

    Objects 
= new CvRect [Count];
    CvRect 
*recptr;
    objptr 
= ListObjects->next;
    recptr 
= Objects;
    
for (i = 0; i < ListCount; i++)
    
{
        
if (objptr->use)
        
{
            recptr
->= objptr->x; recptr->= objptr->y;
            recptr
->width = objptr->width; recptr->height = objptr->height;
            recptr
++;
        }

        objptr 
= objptr->next;
    }

    oldptr 
= ListObjects; objptr = ListObjects->next;
    
for (i = 0; i < ListCount; i++)
    
{
        delete oldptr; oldptr 
= objptr;
        objptr 
= objptr->next;
    }

    delete oldptr;

    delete [] IntegralImage;

    
return Count;
}


bool LoadDefaultSetting(char *FileName, TDetectSettings &DS)
{
    FILE 
*dsf = fopen(FileName, "r");
    
if (NULL != dsf)
    
{
        fscanf(dsf, 
"%g"&DS.ScaleRatio);
        fscanf(dsf, 
"%g %g"&DS.OffsetX, &DS.OffsetY);
        fscanf(dsf, 
"%d %d"&DS.Ignore, &DS.MinW);
        fscanf(dsf, 
"%d %d"&DS.StartSubWindow, &DS.EndSubWindow);
        fclose(dsf);
        
return true;
    }

    
else
        
return false;
}
發佈了37 篇原創文章 · 獲贊 2 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章