OpenCV编写Adaboost源程序
写在前面:
本文仅为记录编程经验和思路,所给程序并无识别作用(可能是由于特征太少)。
程序主要实现功能:
时间紧迫...这个程序效果很差,只能算个demo。但是还是实现了一下几个主要功能,代码全部为自己编写。
1. 完成了adaboost框架。
2. logistic二值分类作为弱分类器,使用梯度下降法计算(10w次迭代)得到。
3. 计算了几个简单的特征。(灰度均值,颜色均值,灰度方差)。实践表明这些特征不足以描述人脸特征(如果程序没问题的话)。
编程遇到的问题:
logistic回归也是有weighted形式的,类似的只要:在中加入w参数就行了。具体推到过程中,将权重参数w加入到似然函数指数中即可。
freopen("CON","r",stdin)表示回到控制台输入。
贴上自己的代码:(写的不规范,请见谅)。其中输入数据:pos.txt中记录正样本及target位置(可用ObjectMarker标出), neg.txt中记录负样本。
#include <opencv2\opencv.hpp> #include <cstring> #include <cstdio> #include <cmath> #include <ctime> using namespace cv; using std::memset; using std::pow; using std::fabs; using std::log; using std::exp; const int MAX_SAMPLES = 1000; const int MAX_DIMENSION = 200; //number of features; int dimension; int nsamples, npositive, nnegative; //features of image calculated by CALFEATURES function double features[MAX_SAMPLES][MAX_DIMENSION]; int isPositive[MAX_SAMPLES]; double y[MAX_SAMPLES]; //struct for weakclassifier const int MAX_CLASSIFIER = 200; struct weakClassifier { //theta[0] = b; double theta[MAX_DIMENSION]; //classifier vote weight; double alpha; double error; void clear() { for(int i = 0 ; i < MAX_DIMENSION; i++) theta[i] = 1; alpha = 0; error = 1; } double cal(double x[MAX_DIMENSION]) { double ans = 0 ; for(int i = 0 ; i < dimension; i++) ans += theta[i]*x[i]; return 1/(1 + exp(-ans)); } }weakclassifier[MAX_CLASSIFIER]; //parameter for adaboost int nweakclassifier = 100; double weight[MAX_SAMPLES]; int calbystrongclassifier(double x[MAX_DIMENSION]) { int ans = 0; for(int i = 0 ; i < nweakclassifier; i++) { double temp = weakclassifier[i].cal(x); if(temp > 0.5) ans += weakclassifier[i].alpha * 1; else ans += weakclassifier[i].alpha * -1; } if(ans > 0) return 1; else return -1; } //cal the feature of the image int calfeatures(IplImage *inputImage, double features[MAX_DIMENSION]) { int nfeatures = 0; int width = inputImage->width; int height = inputImage->height; double thisfeature; double ave; //create gray image IplImage* gray = cvCreateImage(cvGetSize(inputImage),inputImage->depth,1); cvCvtColor(inputImage, gray, CV_BGR2GRAY); //cal hist double hist[256]; memset(hist, 0, sizeof(hist)); for(int i = 0 ; i < gray->height; i++) { for(int j = 0 ; j < gray->width; j++) { //here it must be strongly converted to type-unsigned char int value = unsigned char(gray->imageData[i*gray->widthStep+j]); hist[value] += 1.0/gray->width/gray->height; } } //init features[0] = 1; features[nfeatures++] = 1; //cal 1st feature: average grey thisfeature = 0; for(int i = 0 ; i < 256; i++) thisfeature += i*hist[i]; features[nfeatures] = thisfeature; ave = thisfeature; nfeatures++; //cal 2st feature: average green thisfeature = 0; int sumgreen = 0; for(int i = 0 ; i < height; i++) { uchar* ptr = (uchar*)(inputImage->imageData + i * inputImage->widthStep); for(int j = 0 ; j < width; j++) { int value = ptr[3*j]; sumgreen += value; } } features[nfeatures] = sumgreen*1.0/width/height; ave = thisfeature; nfeatures++; //cal 3st feature: average red thisfeature = 0; int sumred = 0; for(int i = 0 ; i < height; i++) { uchar* ptr = (uchar*)(inputImage->imageData + i * inputImage->widthStep); for(int j = 0 ; j < width; j++) { int value = ptr[3*j+2]; sumred += value; } } features[nfeatures] = sumred*1.0/width/height; ave = thisfeature; nfeatures++; //cal 4st feature: average blue thisfeature = 0; int sumblue = 0; for(int i = 0 ; i < height; i++) { uchar* ptr = (uchar*)(inputImage->imageData + i * inputImage->widthStep); for(int j = 0 ; j < width; j++) { int value = ptr[3*j+1]; sumblue += value; } } features[nfeatures] = sumblue*1.0/width/height; ave = thisfeature; nfeatures++; //cal 5nd feature: grey variance thisfeature = 0; for(int i = 0 ; i < 256; i++) thisfeature += hist[i]*(i-features[0])*(i-features[0]); features[nfeatures] = sqrt(thisfeature*1.0); nfeatures++; cvReleaseImage(&gray); return nfeatures; } //train weak classifier using logisitic regression weakClassifier trainweakclassifier() { weakClassifier ans; ans.clear(); //cal parameter thetas for(int k = 0 ; k < 100000; k++) { int i = rand()%nsamples; int j = rand()%(dimension); ans.theta[j] = ans.theta[j] + weight[i]*0.01*(isPositive[i] - ans.cal(features[i]))*features[i][j]; } //cal error int rightnum = 0; for(int i = 0 ; i < nsamples; i++) { double tmp = ans.cal(features[i]); if(tmp > 0.5 && isPositive[i] || tmp < 0.5 && isPositive[i] == false) rightnum ++; } ans.error = (nsamples - rightnum)*1.0/nsamples; //cal alpha ans.alpha = 1.0/2*std::log((1-ans.error)/ans.error); return ans; } int main() { srand(int(time(0))); char filename[100]; IplImage *inputImage = NULL; nsamples = npositive = nnegative = 0; //read the positive samples to cal the features freopen("pos.txt","r",stdin); while(scanf("%s",filename)!=EOF) { int num_1,x1,y1,width1, height1; scanf("%d%d%d%d%d",&num_1,&x1, &y1, &width1, &height1); CvRect roi = cvRect(x1, y1, width1, height1); inputImage = cvLoadImage(filename); cvSetImageROI(inputImage, roi); IplImage* temp = cvCreateImage(cvSize(width1, height1), inputImage->depth, inputImage->nChannels); cvCopy(inputImage, temp); //cvShowImage("a",temp); //cvWaitKey(0); cvReleaseImage(&inputImage); inputImage = NULL; dimension = calfeatures(temp,features[nsamples]); cvReleaseImage(&temp); isPositive[nsamples] = 1; y[nsamples] = 1; nsamples++; npositive++; } //output the features; freopen("CON","w",stdout); for(int i = 0 ; i < nsamples; i++) { for(int j = 0 ; j < dimension; j++) printf("%lf ", features[i][j]); printf("\n "); } //read the negative samples to cal the features freopen("neg.txt","r",stdin); while(scanf("%s",filename)!=EOF) { inputImage = cvLoadImage(filename); dimension = calfeatures(inputImage, features[nsamples]); //cvShowImage("a",inputImage); //cvWaitKey(0); cvReleaseImage(&inputImage); isPositive[nsamples] = 0; y[nsamples] = -1; nsamples++; nnegative++; } //output the features; freopen("CON","w",stdout); for(int i = npositive ; i < nsamples; i++) { for(int j = 0 ; j < dimension; j++) printf("%lf ", features[i][j]); printf("\n"); } //adaboost framework for(int i = 0 ; i < nsamples; i++) { weight[i] = 1.0/nsamples; } for(int classifierindex = 0 ; classifierindex < nweakclassifier; classifierindex++) { weakclassifier[classifierindex] = trainweakclassifier(); double error = weakclassifier[classifierindex].error; double alpha = weakclassifier[classifierindex].alpha; if(error > 0.5 || alpha < 0) printf("Error: wrong classifier has been generated. %lf\n", error); printf("%d classifier: %lf\n",classifierindex, error); for(int i = 0 ; i < dimension; i++) printf("%lf ",weakclassifier[classifierindex].theta[i]); printf("\n"); double identitysum = 0; for(int sampleindex = 0 ; sampleindex < nsamples; sampleindex++) { if(weakclassifier[classifierindex].cal(features[sampleindex]) > 0.5) weight[sampleindex] *= exp(-alpha*y[sampleindex]*1); else weight[sampleindex] *= exp(-alpha*y[sampleindex]*-1); identitysum += weight[sampleindex]; } //reweight for(int sampleindex = 0 ; sampleindex < nsamples; sampleindex++) { weight[sampleindex] /= identitysum; } } double rightsum = 0; for(int i = 0 ; i < npositive; i++) { if(calbystrongclassifier(features[i]) == 1 && isPositive[i] == 1) rightsum += 1; if(calbystrongclassifier(features[i]) == -1 && isPositive[i] == 0) rightsum += 1; } printf("测试集的准确率为:%lf\n", rightsum/nsamples); //test freopen("CON","r",stdin); printf("please input the directory of test image\n"); scanf("%s",filename); cvReleaseImage(&inputImage); inputImage = cvLoadImage(filename); cvShowImage("a",inputImage); //cvWaitKey(0); int width = inputImage->width; int height = inputImage->height; int ansx = 0, ansy = 0, answ = 0, ansh = 0; //cvShowImage("a",temp); //cvWaitKey(0); for(int x1 = 0 ; x1 < width; x1 += 10) { for(int y1 = 0; y1 < height; y1 += 10) { for(int width1 = 100; x1 + width1 < width; width1 += 10) { for(int height1 = 123; y1 + height1 < height; height1 += 10) { IplImage* temp = cvCreateImage(cvSize(width1,height1),inputImage->depth, inputImage->nChannels); CvRect roi = cvRect(x1, y1, width1, height1); cvSetImageROI(inputImage, roi); cvCopy(inputImage,temp); cvResetImageROI(inputImage); double tempfeatures[MAX_DIMENSION]; //cvShowImage("a",temp); //cvWaitKey(0); calfeatures(temp,tempfeatures); if(calbystrongclassifier( tempfeatures ) == 1) { ansx = x1; ansy = y1; answ = width1; ansh = height1; cvShowImage("检测结果",temp); cvWaitKey(0); } cvReleaseImage(&temp); } } } } if(answ && ansh) { IplImage* ans = cvCreateImage(cvSize(answ,ansh),inputImage->depth, inputImage->nChannels); cvSetImageROI(inputImage,cvRect(ansx,ansy,answ,ansh)); cvCopy(inputImage, ans); cvShowImage("检测结果",ans); cvWaitKey(0); } else { printf("Can not detect.\n"); } }