├── ocv.h ├── data ├── 9.bmp ├── cascade.txt.range └── cascade.txt ├── Makefile ├── MyStruct.h ├── SimpleClassifier.cpp ├── MatrixRotate.cpp ├── CascadeClassifier.h ├── AdaBoostClassifier.h ├── RotateImage.cpp ├── MyStruct.cpp ├── IntImage.h ├── AdaBoostClassifier.cpp ├── SimpleClassifier.h ├── main.cpp ├── MyCamshift.cpp ├── CascadeClassifier.cpp └── IntImage.cpp /ocv.h: -------------------------------------------------------------------------------- 1 | 2 | #include "opencv/cv.h" 3 | #include "opencv/highgui.h" 4 | -------------------------------------------------------------------------------- /data/9.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/andrewrong/FaceDect/HEAD/data/9.bmp -------------------------------------------------------------------------------- /data/cascade.txt.range: -------------------------------------------------------------------------------- 1 | 17087.4 2 | 141337 3 | 661507 4 | 3.2258e+007 5 | 14.3214 6 | 89.1736 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | main:MyCamshift.cpp RotateImage.cpp AdaBoostClassifier.cpp CascadeClassifier.cpp IntImage.cpp MyStruct.cpp SimpleClassifier.cpp MatrixRotate.cpp main.cpp 2 | g++ `pkg-config opencv --libs --cflags opencv` MyCamshift.cpp RotateImage.cpp AdaBoostClassifier.cpp CascadeClassifier.cpp IntImage.cpp MatrixRotate.cpp MyStruct.cpp SimpleClassifier.cpp main.cpp -o main 3 | -------------------------------------------------------------------------------- /MyStruct.h: -------------------------------------------------------------------------------- 1 | #ifndef MYSTRUCT_H 2 | #define MYSTRUCT_H 3 | struct MRect 4 | { 5 | long left; 6 | long top; 7 | long right; 8 | long bottom; 9 | 10 | public: 11 | long Height() const 12 | { 13 | return bottom - top; 14 | } 15 | long Width() const 16 | { 17 | return right - left; 18 | } 19 | bool IntersectRect(MRect& source1,MRect& source2); 20 | void UnionRect(MRect& s1,MRect& s2); 21 | }; 22 | 23 | struct MSize 24 | { 25 | long cx; 26 | long cy; 27 | MSize(long x,long y) 28 | { 29 | cx = x; 30 | cy = y; 31 | } 32 | }; 33 | #endif 34 | -------------------------------------------------------------------------------- /SimpleClassifier.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | #include "IntImage.h" 7 | #include "SimpleClassifier.h" 8 | #include "AdaBoostClassifier.h" 9 | #include "CascadeClassifier.h" 10 | 11 | 12 | 13 | void SimpleClassifier::ReadFromFile(ifstream& f) 14 | { 15 | f>>thresh>>parity>>type; 16 | f>>x1>>x2>>x3>>x4>>y1>>y2>>y3>>y4; 17 | f.ignore(256,'\n'); 18 | ASSERT(parity == 0 || parity == 1); 19 | ASSERT(type>=0 && type<=4); 20 | } 21 | 22 | void SimpleClassifier::WriteToFile(ofstream& f) const 23 | { 24 | f< 6 | #include 7 | #include 8 | #include "opencv/cv.h" 9 | #include "opencv/highgui.h" 10 | 11 | using namespace std; 12 | 13 | void MatrixRotate(int x,int y,float degree,int& rotatedX,int& rotatedY) 14 | { 15 | float map[2]; 16 | map[0] = x; 17 | map[1] = y; 18 | 19 | CvMat mat = cvMat(2,1,CV_32F,map); 20 | 21 | double angle = (degree * CV_PI) / 180.0; 22 | double sina = sin(angle); 23 | double cosa = cos(angle); 24 | 25 | float mulMap[4]; 26 | CvMat mulMat = cvMat(2,2,CV_32F,mulMap); 27 | mulMap[0] = cosa; 28 | mulMap[1] = sina; 29 | mulMap[2] = -sina; 30 | mulMap[3] = cosa; 31 | 32 | float dst[2] = {0}; 33 | CvMat dstMat = cvMat(2,1,CV_32F,dst); 34 | 35 | cvGEMM(&mulMat,&mat,1,NULL,0,&dstMat,0); 36 | 37 | rotatedX = dst[0]; 38 | rotatedY = dst[1]; 39 | } 40 | -------------------------------------------------------------------------------- /CascadeClassifier.h: -------------------------------------------------------------------------------- 1 | #ifndef CAS_H 2 | #define CAS_H 3 | #include 4 | #include 5 | #include 6 | #include "IntImage.h" 7 | #include "AdaBoostClassifier.h" 8 | #include "SimpleClassifier.h" 9 | #include "MyStruct.h" 10 | #include "ocv.h" 11 | 12 | const int sx = 24; 13 | const int sy = 24; 14 | extern REAL mean_min,mean_max,sq_min,sq_max,var_min,var_max; 15 | 16 | struct CascadeClassifier 17 | { 18 | int count; 19 | AdaBoostClassifier* ac; 20 | 21 | CascadeClassifier(); 22 | ~CascadeClassifier(); 23 | void Clear(void); 24 | CascadeClassifier& operator=(const CascadeClassifier& source); 25 | 26 | void WriteToFile(std::ofstream& f) const; 27 | void ReadFromFile(std::ifstream& f); 28 | void LoadDefaultCascade(std::string& cascade_filename,std::string& cascade_filename_range); 29 | virtual void ApplyOriginalSize(IntImage& original,std::vector& results) ; 30 | void DrawResults(IntImage& image, const std::vector& results) const; 31 | }; 32 | 33 | void PostProcess(std::vector& result, const int combine_min); 34 | #endif 35 | -------------------------------------------------------------------------------- /AdaBoostClassifier.h: -------------------------------------------------------------------------------- 1 | #ifndef ADA_H 2 | #define ADA_H 3 | #include 4 | #include "IntImage.h" 5 | #include "SimpleClassifier.h" 6 | #include "MyStruct.h" 7 | #include "ocv.h" 8 | 9 | 10 | enum GOAL_METHODS {GOAL_METHOD_MIN_ERROR = 1, GOAL_METHOD_VALID_DR = 2, GOAL_METHOD_FIX_FP = 3}; 11 | 12 | struct AdaBoostClassifier 13 | { 14 | int count; 15 | SimpleClassifier* scs; 16 | REAL* alphas; 17 | REAL thresh; 18 | 19 | AdaBoostClassifier(); 20 | ~AdaBoostClassifier(); 21 | void Clear(void); 22 | AdaBoostClassifier& operator=(const AdaBoostClassifier& source); 23 | 24 | void WriteToFile(std::ofstream& f) const; 25 | void ReadFromFile(std::ifstream& f); 26 | void InitToGivenSize(const int size); 27 | 28 | inline REAL GetValue(const IntImage& im) const; 29 | inline int ApplyImagePatch(const IntImage& im) const; 30 | }; 31 | 32 | REAL AdaBoostClassifier::GetValue(const IntImage& im) const 33 | { 34 | int i; 35 | REAL value; 36 | 37 | value = 0.0; 38 | for(i=0;i=thresh)?1:0; 46 | } 47 | #endif 48 | -------------------------------------------------------------------------------- /RotateImage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "opencv/cv.h" 3 | #include "opencv/highgui.h" 4 | 5 | using namespace std; 6 | 7 | void RotateImage(IplImage* img,IplImage* imgRotate,float degree) 8 | { 9 | double angle = degree * CV_PI / 180.0; // 弧度 10 | double a = sin(angle), b = cos(angle); 11 | int width = img->width; 12 | int height = img->height; 13 | //int width_rotate= int(height * fabs(a) + width * fabs(b)); 14 | //int height_rotate=int(width * fabs(a) + height * fabs(b)); 15 | //旋转数组map 16 | // [ m0 m1 m2 ] ===> [ A11 A12 b1 ] 17 | // [ m3 m4 m5 ] ===> [ A21 A22 b2 ] 18 | float map[6]; 19 | CvMat map_matrix = cvMat(2, 3, CV_32F, map); 20 | // 旋转中心 21 | CvPoint2D32f center = cvPoint2D32f(width / 2, height / 2); 22 | cv2DRotationMatrix(center, degree, 1.0, &map_matrix); 23 | //map[2] += (width_rotate - width) / 2; 24 | //map[5] += (height_rotate - height) / 2; 25 | //对图像做仿射变换 26 | //CV_WARP_FILL_OUTLIERS - 填充所有输出图像的象素。 27 | //如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval. 28 | //CV_WARP_INVERSE_MAP - 指定 map_matrix 是输出图像到输入图像的反变换, 29 | cvWarpAffine( img,imgRotate, &map_matrix, CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, cvScalarAll(0)); 30 | } 31 | -------------------------------------------------------------------------------- /MyStruct.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "MyStruct.h" 3 | long max(long left,long right) 4 | { 5 | if(left > right) 6 | { 7 | return left; 8 | } 9 | else 10 | { 11 | return right; 12 | } 13 | } 14 | 15 | 16 | long min(long left,long right) 17 | { 18 | if(left < right) 19 | { 20 | return left; 21 | } 22 | else 23 | { 24 | return right; 25 | } 26 | } 27 | 28 | bool MRect::IntersectRect(MRect& source1,MRect& source2) 29 | { 30 | long maxX = max(source1.left,source2.left); 31 | long maxY = max(source1.top,source2.top); 32 | long minX = min(source1.right,source2.right); 33 | long minY = min(source1.bottom,source2.bottom); 34 | 35 | if(maxX < minX && maxY < minY) 36 | { 37 | this->top = maxY; 38 | this->left = maxX; 39 | this->bottom = minY; 40 | this->right = minX; 41 | 42 | return 1; 43 | } 44 | else 45 | { 46 | this->top = this->left = this->bottom = this->right = 0; 47 | return 0; 48 | } 49 | } 50 | 51 | void MRect::UnionRect(MRect& source1,MRect& source2) 52 | { 53 | long minX = min(source1.left,source2.left); 54 | long minY = min(source1.top,source2.top); 55 | long maxX = max(source1.right,source2.right); 56 | long maxY = max(source1.bottom,source2.bottom); 57 | 58 | this->top = minY; 59 | this->left = minX; 60 | this->bottom = maxY; 61 | this->right = maxX; 62 | } 63 | -------------------------------------------------------------------------------- /IntImage.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGE_H 2 | #define IMAGE_H 3 | #define USE_DOUBLE 4 | 5 | #ifdef USE_DOUBLE 6 | typedef double REAL; 7 | #else 8 | typedef float REAL; 9 | #endif 10 | #include 11 | #include 12 | #include "MyStruct.h" 13 | #include "ocv.h" 14 | 15 | 16 | #define ASSERT(p) assert(p) 17 | class IntImage 18 | { 19 | public: 20 | IntImage(); 21 | ~IntImage(); 22 | 23 | void Clear(void); 24 | void SetSize(const MSize size); 25 | IntImage& operator=(const IntImage& source); 26 | void CalcSquareAndIntegral(IntImage& square,IntImage& image) const; 27 | void CalculateVarianceAndIntegralImageInPlace(void); 28 | void Resize(IntImage &result, REAL ratio) const; 29 | void Copy(const IntImage& source); 30 | void Load(const std::string& filename); 31 | void IplImageToIntImage(IplImage* img); 32 | void Save(const std::string& filename) const; 33 | IplImage* IntImageToIplImage() const; 34 | 35 | public: 36 | int height; // height, or, number of rows of the image 37 | int width; // width, or, number of columns of the image 38 | REAL** data; // auxiliary pointers to accelerate the read/write of the image 39 | // no memory is really allocated, use memory in (buf) 40 | // data[i][j] is a pixel's gray value in (i)th row and (j)th column 41 | REAL* buf; // pointer to a block of continuous memory containing the image 42 | REAL variance; 43 | int label; 44 | }; 45 | 46 | void SwapIntImage(IntImage& i1,IntImage& i2); 47 | #endif 48 | -------------------------------------------------------------------------------- /AdaBoostClassifier.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | #include "AdaBoostClassifier.h" 9 | 10 | //#include "CascadeClassifier.h" 11 | 12 | 13 | AdaBoostClassifier::AdaBoostClassifier():count(0),thresh(0.0),alphas(NULL),scs(NULL) 14 | { 15 | } 16 | 17 | AdaBoostClassifier::~AdaBoostClassifier() 18 | { 19 | Clear(); 20 | } 21 | 22 | void AdaBoostClassifier::Clear() 23 | { 24 | delete[] scs; scs=NULL; 25 | delete[] alphas; alphas=NULL; 26 | count = 0; 27 | thresh = 0.0; 28 | } 29 | 30 | AdaBoostClassifier& AdaBoostClassifier::operator=(const AdaBoostClassifier& source) 31 | { 32 | InitToGivenSize(source.count); 33 | count = source.count; 34 | thresh = source.thresh; 35 | memcpy(alphas,source.alphas,sizeof(*alphas)*count); 36 | for(int i=0;i>count; ASSERT(count>0); 63 | f.ignore(256,'\n'); 64 | scs = new SimpleClassifier[count]; ASSERT(scs!=NULL); 65 | alphas = new REAL[count]; ASSERT(alphas!=NULL); 66 | 67 | f>>thresh; f.ignore(256,'\n'); 68 | for(int i=0;i>alphas[i]; f.ignore(256,'\n'); 69 | for(int i=0;i 5 | #include "MyStruct.h" 6 | #include "ocv.h" 7 | 8 | struct SimpleClassifier 9 | { 10 | REAL thresh; 11 | REAL error; 12 | int parity; 13 | int type; // which type of feature? 14 | int x1,x2,x3,x4,y1,y2,y3,y4; 15 | 16 | inline const REAL GetOneFeature(const IntImage& im) const; 17 | inline const REAL GetOneFeatureTranslation(REAL** const data,const int y) const; 18 | inline const int Apply(const REAL value) const; 19 | inline const int Apply(const IntImage& im) const; 20 | void WriteToFile(std::ofstream& f) const; 21 | void ReadFromFile(std::ifstream& f); 22 | }; 23 | 24 | const int SimpleClassifier::Apply(const IntImage& im) const 25 | { 26 | if(parity == 1) 27 | return (GetOneFeature(im)=thresh)?1:0; 30 | } 31 | 32 | const int SimpleClassifier::Apply(const REAL value) const 33 | { 34 | if(parity == 1) 35 | return (value=thresh)?1:0; 38 | } 39 | 40 | const REAL SimpleClassifier::GetOneFeature(const IntImage& im) const 41 | { 42 | REAL f1; 43 | REAL** data = im.data; 44 | 45 | switch(type) 46 | { 47 | case 0: 48 | f1 = data[x1][y3] - data[x1][y1] + data[x3][y3] - data[x3][y1] 49 | + 2*(data[x2][y1] - data[x2][y3]); 50 | break; 51 | case 1: 52 | f1 = data[x3][y1] + data[x3][y3] - data[x1][y1] - data[x1][y3] 53 | + 2*(data[x1][y2] - data[x3][y2]); 54 | break; 55 | case 2: 56 | f1 = data[x1][y1] -data[x1][y3] + data[x4][y3] - data[x4][y1] 57 | + 3*(data[x2][y3] - data[x2][y1] + data[x3][y1] - data[x3][y3]); 58 | break; 59 | case 3: 60 | f1 = data[x1][y1] - data[x1][y4] + data[x3][y4] - data[x3][y1] 61 | + 3*(data[x3][y2] - data[x3][y3] + data[x1][y3] - data[x1][y2] ); 62 | break; 63 | case 4: 64 | f1 = data[x1][y1] + data[x1][y3] + data[x3][y1] + data[x3][y3] 65 | - 2*(data[x2][y1] + data[x2][y3] + data[x1][y2] + data[x3][y2]) 66 | + 4*data[x2][y2]; 67 | break; 68 | } 69 | return f1/im.variance; 70 | } 71 | 72 | const REAL SimpleClassifier::GetOneFeatureTranslation(REAL** const data,const int y) const 73 | { 74 | REAL f1=0; 75 | 76 | switch(type) 77 | { 78 | case 0: 79 | f1 = data[x1][y+y3] - data[x1][y+y1] + data[x3][y+y3] - data[x3][y+y1] 80 | + 2*(data[x2][y+y1] - data[x2][y+y3]); 81 | break; 82 | case 1: 83 | f1 = data[x3][y+y1] + data[x3][y+y3] - data[x1][y+y1] - data[x1][y+y3] 84 | + 2*(data[x1][y+y2] - data[x3][y+y2]); 85 | break; 86 | case 2: 87 | f1 = data[x1][y+y1] - data[x1][y+y3] + data[x4][y+y3] - data[x4][y+y1] 88 | + 3*(data[x2][y+y3] - data[x2][y+y1] + data[x3][y+y1] - data[x3][y+y3]); 89 | break; 90 | case 3: 91 | f1 = data[x1][y+y1] - data[x1][y+y4] + data[x3][y+y4] - data[x3][y+y1] 92 | + 3*(data[x3][y+y2] - data[x3][y+y3] + data[x1][y+y3] - data[x1][y+y2]); 93 | break; 94 | case 4: 95 | f1 = data[x1][y+y1] + data[x1][y+y3] + data[x3][y+y1] + data[x3][y+y3] 96 | - 2*(data[x2][y+y1] + data[x2][y+y3] + data[x1][y+y2] + data[x3][y+y2]) 97 | + 4*data[x2][y+y2]; 98 | break; 99 | default: 100 | break; 101 | } 102 | return f1; 103 | } 104 | #endif 105 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "IntImage.h" 6 | #include "MyStruct.h" 7 | #include "CascadeClassifier.h" 8 | #include "ocv.h" 9 | 10 | using namespace std; 11 | 12 | float CamShift(IplImage* frame,const CvRect& rect,int resetCam); 13 | void RotateImage(IplImage* frame,IplImage* imgRotate,float degree); 14 | void MatrixRotate(int x,int y,float degree,int& rotatedX,int& rotatedY); 15 | 16 | int main() 17 | { 18 | CascadeClassifier face; 19 | 20 | string filename = "./data/cascade.txt"; 21 | string filenameRange = "./data/cascade.txt.range"; 22 | 23 | face.LoadDefaultCascade(filename,filenameRange); 24 | cvNamedWindow("face",CV_WINDOW_AUTOSIZE); 25 | 26 | IntImage img; 27 | 28 | CvCapture* capture = cvCreateCameraCapture(0); 29 | if(capture == NULL) 30 | { 31 | fprintf(stderr,"error capture is null!\n"); 32 | return -1; 33 | } 34 | 35 | IplImage* frame ; 36 | vector results; 37 | CvRect detectedRect; 38 | int detected = 0; 39 | CvPoint** points = new CvPoint*[1]; 40 | points[0] = new CvPoint[4]; 41 | 42 | while(1) 43 | { 44 | int resetCam = 0; 45 | frame = cvQueryFrame(capture); 46 | if(!frame) 47 | { 48 | break; 49 | } 50 | 51 | img.IplImageToIntImage(frame); 52 | face.ApplyOriginalSize(img,results); 53 | 54 | if(results.size() != 0) 55 | { 56 | detected = 1; 57 | for(int i = 0; i < results.size();i++) 58 | { 59 | cvRectangle(frame,cvPoint(results[i].left,results[i].top),cvPoint(results[i].right,results[i].bottom),cvScalar(0x00,0x00,0xff),3); 60 | } 61 | printf("rect's num is %d,(%ld,%ld),(%ld,%ld)\n",results.size(),results[0].left,results[0].top,results[0].right,results[0].bottom); 62 | detectedRect.x = results[0].left; 63 | detectedRect.width = results[0].right - results[0].left; 64 | detectedRect.y = results[0].top; 65 | detectedRect.height = results[0].bottom - results[0].top; 66 | 67 | resetCam = 1; 68 | } 69 | 70 | 71 | if(resetCam == 1) 72 | { 73 | cout<<"reset Rect"< 0) 110 | { 111 | int left = results[0].left; 112 | int right = results[0].right; 113 | int top = results[0].top; 114 | int bottom = results[0].bottom; 115 | 116 | cout<<"("< 5 | 6 | IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0; 7 | CvHistogram *hist = 0; 8 | int i,c; 9 | int vmin = 10, vmax = 256, smin = 30; 10 | float hranges_arr[] = {0,180}; 11 | float* hranges = hranges_arr; 12 | int hdims = 16; 13 | CvRect selection; 14 | CvRect track_window; 15 | CvBox2D track_box; 16 | CvConnectedComp track_comp; 17 | int track_object = 1; 18 | 19 | void CamShift(IplImage* frame,const MRect& rect,int resetCam) 20 | { 21 | selection.x = rect.left; 22 | selection.y = rect.top; 23 | selection.width = rect.right - rect.left; 24 | selection.height = rect.bottom - rect.top; 25 | 26 | if(!hsv) 27 | { 28 | /* allocate all the buffers */ 29 | //image = cvCreateImage( cvGetSize(frame), 8, 3 ); 30 | //image->origin = frame->origin; 31 | hsv = cvCreateImage( cvGetSize(frame), 8, 3 ); 32 | hue = cvCreateImage( cvGetSize(frame), 8, 1 ); 33 | mask = cvCreateImage( cvGetSize(frame), 8, 1 ); 34 | backproject = cvCreateImage( cvGetSize(frame), 8, 1 ); 35 | hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 ); 36 | } 37 | 38 | //cvCopy(frame,image,0); 39 | cvCvtColor(frame,hsv,CV_BGR2HSV); 40 | 41 | int _vmin = vmin, _vmax = vmax; 42 | 43 | cvInRangeS(hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0), 44 | cvScalar(180,256,MAX(_vmin,_vmax),0), mask ); 45 | cvSplit( hsv, hue, 0, 0, 0 ); 46 | 47 | 48 | if(resetCam) 49 | { 50 | float max_val = 0.f; 51 | cvSetImageROI(hue, selection); 52 | cvSetImageROI(mask, selection); 53 | cvCalcHist(&hue, hist, 0, mask); 54 | cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0); 55 | //cvConvertScale(hist->bins,hist->bins,max_val ? 255. / max_val : 0., 0 ); 56 | cvResetImageROI(hue); 57 | cvResetImageROI(mask); 58 | track_window = selection; 59 | } 60 | 61 | cvCalcBackProject(&hue, backproject, hist); 62 | cvAnd( backproject, mask, backproject, 0 ); 63 | cvCamShift( backproject, track_window, 64 | cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ), 65 | &track_comp, &track_box ); 66 | track_window = track_comp.rect; 67 | 68 | cvEllipseBox(frame, track_box, CV_RGB(255,0,0), 3, CV_AA, 0); 69 | //cvSaveImage("test.bmp",image); 70 | //printf("angle:%f\n",track_box.angle); 71 | //cvRectangle(image,cvPoint(track_window.x,track_window.y),cvPoint(track_window.x + track_window.width,track_window.y + track_window.height * 3.0 / 4),cvScalar(0x00,0x00,0xff),3); 72 | } 73 | #endif 74 | 75 | 76 | #include "ocv.h" 77 | #include "MyStruct.h" 78 | #include 79 | 80 | IplImage *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0; 81 | CvHistogram *hist = 0; 82 | 83 | int backproject_mode = 0; 84 | 85 | CvRect selection; 86 | CvRect track_window; 87 | CvBox2D track_box; 88 | CvConnectedComp track_comp; 89 | int hdims = 16; 90 | float hranges_arr[] = {0,180}; 91 | float* hranges = hranges_arr; 92 | int vmin = 10, vmax = 256, smin = 30; 93 | 94 | CvScalar hsv2rgb( float hux ) 95 | { 96 | int rgb[3], p, sector; 97 | static const int sector_data[][3]= 98 | {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}}; 99 | hux *= 0.033333333333333333333333333333333f; 100 | sector = cvFloor(hux); 101 | p = cvRound(255*(hux - sector)); 102 | p ^= sector & 1 ? 255 : 0; 103 | 104 | rgb[sector_data[sector][0]] = 255; 105 | rgb[sector_data[sector][1]] = 0; 106 | rgb[sector_data[sector][2]] = p; 107 | 108 | return cvScalar(rgb[2], rgb[1], rgb[0],0); 109 | } 110 | 111 | float CamShift(IplImage* frame,const CvRect& rect,int resetCam) 112 | { 113 | int i, bin_w, c; 114 | if(!hsv) 115 | { 116 | hsv = cvCreateImage( cvGetSize(frame), 8, 3 ); 117 | hue = cvCreateImage( cvGetSize(frame), 8, 1 ); 118 | mask = cvCreateImage( cvGetSize(frame), 8, 1 ); 119 | backproject = cvCreateImage( cvGetSize(frame), 8, 1 ); 120 | hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 ); 121 | histimg = cvCreateImage( cvSize(320,200), 8, 3 ); 122 | cvZero( histimg ); 123 | } 124 | 125 | cvCvtColor(frame, hsv, CV_BGR2HSV ); 126 | 127 | int _vmin = vmin, _vmax = vmax; 128 | 129 | cvInRangeS(hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),cvScalar(180,256,MAX(_vmin,_vmax),0), mask ); 130 | cvSplit(hsv, hue, 0, 0, 0 ); 131 | 132 | if(resetCam == 1) 133 | { 134 | float max_val = 0.f; 135 | cvSetImageROI(hue, rect); 136 | cvSetImageROI(mask, rect); 137 | cvCalcHist(&hue, hist, 0, mask ); 138 | cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 ); 139 | cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 ); 140 | cvResetImageROI( hue ); 141 | cvResetImageROI( mask ); 142 | track_window = rect; 143 | cvZero( histimg ); 144 | bin_w = histimg->width / hdims; 145 | for( i = 0; i < hdims; i++ ) 146 | { 147 | int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 ); 148 | CvScalar color = hsv2rgb(i*180.f/hdims); 149 | cvRectangle( histimg, cvPoint(i*bin_w,histimg->height), 150 | cvPoint((i+1)*bin_w,histimg->height - val), 151 | color, -1, 8, 0 ); 152 | } 153 | } 154 | 155 | cvCalcBackProject(&hue, backproject, hist); 156 | cvAnd(backproject, mask, backproject, 0 ); 157 | cvCamShift( backproject, track_window,cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),&track_comp, &track_box ); 158 | track_window = track_comp.rect; 159 | //printf("track_window:(%d,%d,%d,%d)\n",track_window.x,track_window.y,track_window.width,track_window.height); 160 | 161 | if(!frame->origin ) 162 | track_box.angle = -track_box.angle; 163 | cvEllipseBox(frame, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 ); 164 | 165 | //cvRectangle(image,cvPoint(track_window.x,track_window.y),cvPoint(track_window.x + track_window.width,track_window.y + track_window.height),cvScalar(0x00,0x00,0xff),3); 166 | 167 | cvNamedWindow( "Histogram", 1 ); 168 | cvShowImage( "Histogram", histimg ); 169 | 170 | return track_box.angle; 171 | } 172 | 173 | 174 | -------------------------------------------------------------------------------- /CascadeClassifier.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | #include "CascadeClassifier.h" 9 | 10 | REAL mean_min,mean_max,sq_min,sq_max,var_min,var_max; 11 | 12 | CascadeClassifier::CascadeClassifier():count(0),ac(NULL) 13 | { 14 | } 15 | 16 | CascadeClassifier::~CascadeClassifier() 17 | { 18 | Clear(); 19 | } 20 | 21 | void CascadeClassifier::Clear() 22 | { 23 | count = 0; 24 | delete[] ac; ac=NULL; 25 | } 26 | 27 | CascadeClassifier& CascadeClassifier::operator=(const CascadeClassifier& source) 28 | { 29 | Clear(); 30 | count = source.count; 31 | int max_nodes = 50; 32 | ac = new AdaBoostClassifier[max_nodes]; ASSERT(ac!=NULL); 33 | for(int i=0;i>count; f.ignore(256,'\n'); 41 | int max_nodes = 50; 42 | ac = new AdaBoostClassifier[max_nodes]; ASSERT(ac!=NULL); 43 | for(int i=0;i>mean_min>>mean_max>>sq_min>>sq_max>>var_min>>var_max; 59 | ReadFromFile(f); 60 | f.close(); 61 | frange.close(); 62 | } 63 | 64 | void CascadeClassifier::DrawResults(IntImage& image,const vector& results) const 65 | { 66 | int i; 67 | unsigned int k; 68 | int x1,x2,y1,y2; 69 | 70 | for(k=0;k=0)?results[k].top:0; 73 | y1 = (results[k].top=0)?results[k].bottom:0; 75 | y2 = (results[k].bottom=0)?results[k].left:0; 77 | x1 = (results[k].left=0)?results[k].right:0; 79 | x2 = (results[k].right& results) 94 | { 95 | IntImage procface; 96 | IntImage image,square; 97 | REAL sq,ex,value; 98 | int result; 99 | MRect rect; 100 | REAL ratio; 101 | 102 | procface.Copy(original); 103 | ratio = 1.0; 104 | results.clear(); 105 | REAL paddedsize = REAL(1)/REAL((sx+1)*(sy+1)); 106 | while((procface.height>sx+1) && (procface.width>sy+1)) 107 | { 108 | procface.CalcSquareAndIntegral(square,image); 109 | for(int i=0,size_x=image.height-sx;imean_max) continue; 114 | sq = square.data[i+sx][j+sy]+square.data[i][j]-square.data[i+sx][j]-square.data[i][j+sy]; 115 | if(sq=0); 121 | if(sq>0) sq = sqrt(sq); else sq = 1.0; 122 | if(sq=sq*s.thresh) 165 | value += ac[k].alphas[t]; 166 | else ; 167 | } 168 | if(value& result,const int combine_min) 201 | { 202 | vector res1; 203 | vector resmax; 204 | vector res2; 205 | bool yet; 206 | MRect rectInter; 207 | 208 | for(unsigned int i=0,size_i=result.size();i0.6*SizeOfRect(result_i) 219 | && SizeOfRect(rectInter)>0.6*SizeOfRect(resmax_j) 220 | ) 221 | { 222 | MRect& res1_j = res1[j]; 223 | resmax_j.UnionRect(resmax_j,result_i); 224 | res1_j.bottom += result_i.bottom; 225 | res1_j.top += result_i.top; 226 | res1_j.left += result_i.left; 227 | res1_j.right += result_i.right; 228 | res2[j]++; 229 | yet = true; 230 | break; 231 | } 232 | } 233 | } 234 | if(yet==false) 235 | { 236 | res1.push_back(result_i); 237 | resmax.push_back(result_i); 238 | res2.push_back(1); 239 | } 240 | } 241 | 242 | for(unsigned int i=0,size=res1.size();icombine_min) 255 | result.push_back(res1[i]); 256 | } 257 | -------------------------------------------------------------------------------- /IntImage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "IntImage.h" 4 | using namespace std; 5 | 6 | 7 | IntImage::IntImage():height(0),width(0),data(NULL),buf(NULL),variance(0.0),label(-1) 8 | { 9 | } 10 | 11 | IntImage::~IntImage() 12 | { 13 | Clear(); 14 | } 15 | 16 | void IntImage::Clear(void) 17 | { 18 | if(data == NULL) 19 | ASSERT(buf == NULL); 20 | else 21 | { 22 | ASSERT(buf != NULL); 23 | for(int i=0; i 0); 38 | ASSERT(source.width > 0); 39 | if(&source == this) return; 40 | SetSize(MSize(source.height,source.width)); 41 | memcpy(buf,source.buf,sizeof(REAL)*height*width); 42 | } 43 | 44 | void IntImage::Load(const string& filename) 45 | { 46 | IplImage* img; 47 | 48 | img = cvLoadImage(filename.c_str(),0); 49 | SetSize(MSize(img->height,img->width)); 50 | for(int i=0,ih=img->height,iw=img->width; i(img->imageData+img->widthStep*i); 54 | for(int j=0; jwidth,img->height),IPL_DEPTH_8U,1); 62 | switch(img->nChannels) 63 | { 64 | case 1: 65 | break; 66 | case 2: 67 | { 68 | cvCvtColor(img,changedImage,CV_BGR5652GRAY); 69 | break; 70 | } 71 | case 3: 72 | { 73 | cvCvtColor(img,changedImage,CV_BGR2GRAY); 74 | break; 75 | } 76 | case 4: 77 | { 78 | cvCvtColor(img,changedImage,CV_BGRA2GRAY); 79 | break; 80 | } 81 | } 82 | 83 | SetSize(MSize(img->height,img->width)); 84 | for(int i=0,ih=img->height,iw=img->width; i(changedImage->imageData+changedImage->widthStep*i); 88 | for(int j=0; jheight,iw=img->width; i(img->imageData+img->widthStep*i); 102 | for(int j=0; jheight,iw=img->width; i(img->imageData+img->widthStep*i); 116 | for(int j=0; j= 0); 127 | ASSERT(size.cy >= 0); 128 | Clear(); 129 | 130 | height = size.cx; 131 | width = size.cy; 132 | 133 | buf = new REAL[height*width]; 134 | ASSERT(buf != NULL); 135 | data = new REAL*[height]; 136 | ASSERT(data != NULL); 137 | for(int i=0; i=1, take care. 169 | if (x0 == width-1) x0--; 170 | if (y0 == height-1) y0--; 171 | 172 | x = x - x0; 173 | y = y - y0; 174 | 175 | fx0 = data[y0][x0] + x*(data[y0][x0+1]-data[y0][x0]); 176 | fx1 = data[y0+1][x0] + x*(data[y0+1][x0+1]-data[y0+1][x0]); 177 | 178 | result.data[i][j] = fx0 + y*(fx1-fx0); 179 | } 180 | } 181 | 182 | void IntImage::CalculateVarianceAndIntegralImageInPlace(void) 183 | // We pad a zero column and a zero row, so 24*24 image will be 25*25 in size 184 | { 185 | REAL partialsum; 186 | REAL ex,ex2; 187 | REAL size,var; 188 | 189 | ex = 0; 190 | ex2 = 0; 191 | for(int i=0,size=height*width; i= 0); 199 | if(var>0) 200 | variance = sqrt(var); 201 | else 202 | variance = 1.0; 203 | 204 | 205 | for(int i=1; i