首页 > OPENCV > (怀旧向)第四弹:Adaboost二维点集分类

(怀旧向)第四弹:Adaboost二维点集分类

2012年7月28日 发表评论 阅读评论

之前发了一个Adaboost的matlab代码以及算法的解释,然后想起来以前还写了一个Adaboost的二维点集分类程序,就是在二维平面上以某种规律呈现一些点集,一些是正样本,一些是负样本,然后让Aboboost去学习,然后最后看能达到什么程度。

下面是识别结果,画图用的是OPENCV,比如说像下面这个结果,24个弱分类器就可以在那么多个训练集中使得识别率为100%,这个100%是通过训练样本计算出来的,而理论的识别率是98%。

//注:init_sample分别是样本的不同分布
#include<iostream>
#include<math .h>
#include<stdio .h>
#include<time .h>
#include<stdlib .h>
#include"cv.h"
#include"highgui.h"
//#include"sample.h"
//#include"classifier.h"
using namespace std;
#define P_SAMPLE_NUM 100  //正样本个数
#define N_SAMPLE_NUM 300  //负样本个数
#define FEATURE_NUM 20
#define sample_num (P_SAMPLE_NUM + N_SAMPLE_NUM)
#define iter 50        //最多迭代次数
#define pi 3.14159265358979//三角函数为弧度制
#define X_MAX 300
#define Y_MAX 300

class classifier
{
public:
    double threshold;
    int feature;
    int parity;
    double error;
    int result[sample_num];
    //double alpha;
    double beta;
};

class sample
{
public:
    double x;
    double y;
    int lable;
    double eigen_value;
    double weigth;
    double result;
    int result_lebel;
};

IplImage* frame = NULL;

void init_sample(sample sample_ori[]);
void get_eigenvalue(sample sample[],int feature);
void sort_sample(sample sample_ori[],sample sample_sort[]);
void swap(sample&,sample&);
classifier weaklearner(sample sample_ori[],int feature);
classifier weaklearner2(sample sample_ori[],int feature);
int teststrong(sample sample_ori[],classifier h[],int t);
void draw(sample s[]);
void draw_distribute(classifier h[],int T,sample s[]);

int main()
{
sample sample[sample_num];
classifier h[iter];
frame = cvCreateImage(cvSize(300,300),IPL_DEPTH_8U,3);
cvNamedWindow("show",0);
cvNamedWindow("distribute",0);
init_sample(sample);
int best = 0;//记录几个弱分类器可以达到最优分类效果
int lowest_error = sample_num;
for(int i = 0;i < iter;i++)
    {
    double error = 0.5;
    classifier h_temp;
    for(int j = 0;j < FEATURE_NUM;j++)
        {
            ///////////////////////////////
            h_temp = weaklearner(sample,j);
            //h_temp = weaklearner2(sample,j);
            ////////////////////////////////
            if(h_temp.error < error && h_temp.error != 0)
            {
                error = h_temp.error;
                h[i] = h_temp;
                h[i].beta = error / (1 - error);
            }
        }
    double weigth_sum = 0;
    for(int k = 0;k < sample_num;k++)
    {
        if(h[i].result[k] == sample[k].lable)
            sample[k].weigth *= h[i].beta;
        weigth_sum += sample[k].weigth;
    }

    for(int k = 0;k < sample_num;k++)
    {
    sample[k].weigth /=  weigth_sum;

    }
    int boost = teststrong(sample,h,i + 1);
    cout<<i+1<<":number of sample wrong classifiered:"<<boost<<endl;
    if(!boost)
    {
    lowest_error = 0;
    best = i+1;
    break;
    }
    if(boost < lowest_error)
        {
         lowest_error = boost;
         best = i+1;
        }
    //if(  boost  == 0 || i == iter)
    //    {
    //    //cout<<"final result:"<<endl;
    //    //for(int d = 0;d < sample_num;d++)
    //    //cout<<sample[d].result<<endl;
    //
    //    cout<<"feacture:"<<endl;
    //    for(int k = 0;k<i;k++)
    //    cout<<h[k].feature<<endl;
    //    cout<<endl;

    //    cout<<"error:"<<endl;
    //    for(int k = 0;k<i;k++)
    //    cout<<h[k].error<<endl;
    //    cout<<endl;

    //    cout<<"thresh:"<<endl;
    //    for(int k = 0;k<i;k++)
    //    cout<<h[k].threshold<<endl;
    //    cout<<endl;

    //    cout<<"parity:"<<endl;
    //    for(int k = 0;k<i;k++)
    //    cout<<h[k].parity<<endl;
    //    cout<<endl;

    //    cout<<"beta:"<<endl;
    //    for(int k = 0;k<i;k++)
    //    cout<<h[k].beta<<endl;
    //    cout<<endl;
    //     break;
    //    }
    cvWaitKey(50);
    }
cout<<"前"<<best<<"个分类器可以达到最好效果!!"<<endl;
cout<<"误判个数为:"<<lowest_error<<endl;
draw_distribute(h,best,sample);
cvWaitKey(0);
cvDestroyWindow("show");
return 0;
}

//void init_sample(sample sample_ori[])
//{
//for(int i = 0;i < frame->height;i++)
//    for(int j = 0;j < frame->width;j++)
//CV_IMAGE_ELEM(frame,uchar,i,3 * j) = CV_IMAGE_ELEM(frame,uchar,i,3 * j + 1) = CV_IMAGE_ELEM(frame,uchar,i,3 * j + 2)  = 255;
//double point_x[sample_num] = {};
//double point_y[sample_num] = {};
//srand(time(0));
//int counter = 0;
//int random_x,random_y;
//while(counter < P_SAMPLE_NUM)
//    {
//    random_x = rand() % 100;
//    random_y = rand() % 100;
//    point_x[counter] = random_x + 100;
//    point_y[counter] = random_y + 100;
//    cvCircle(frame,cvPoint(int(point_x[counter]),int(point_y[counter])),3, cvScalar(0,255,0), 1);
//    counter++;
//    }
//while(counter < sample_num)
//    {
//    random_x = rand() % 300;
//    random_y = rand() % 300;
//    if(!(random_x > 100 && random_x < 200 &&random_y > 100 && random_y < 200))
//    point_x[counter] = random_x;
//    point_y[counter] = random_y;
//    cvCircle(frame,cvPoint(int(point_x[counter]),int(point_y[counter])),3, cvScalar(0,0,255), 1);
//    counter++;
//    }
//
//for(int i = 0;i < sample_num;i++)
//    {
//        sample_ori[i].x = point_x[i];
//        sample_ori[i].y = point_y[i];
//        sample_ori[i].lable = i < P_SAMPLE_NUM ? 1 : 0;
//        sample_ori[i].result_lebel = 1 - sample_ori[i].lable;
//        //sample_ori[i].weigth = 1 / double(sample_num);  //正负样本权重一样
//
//        sample_ori[i].weigth = sample_ori[i].lable==1 ? 0.5 / double(P_SAMPLE_NUM) : 0.5 / double(N_SAMPLE_NUM);//正负样本权重不一样
//    }
//cvShowImage("show",frame);
//cvWaitKey(2);
//}

void init_sample(sample sample_ori[])
{
for(int i = 0;i < frame->height;i++)
    for(int j = 0;j < frame->width;j++)
CV_IMAGE_ELEM(frame,uchar,i,3 * j) = CV_IMAGE_ELEM(frame,uchar,i,3 * j + 1) = CV_IMAGE_ELEM(frame,uchar,i,3 * j + 2)  = 255;

double point_x[sample_num] = {};
double point_y[sample_num] = {};
srand(time(0));
int counter = 0;
int random_x,random_y;
while(counter < P_SAMPLE_NUM)
    {
    random_x = rand() % 100 - 50;
    random_y = rand() % 100 - 50;
    if(random_x * random_x + random_y * random_y > 2500)
        continue;
    point_x[counter] = random_x + 150;
    point_y[counter] = random_y + 150;
    cvCircle(frame,cvPoint(int(point_x[counter]),int(point_y[counter])),3, cvScalar(0,255,0), 1);
    counter++;
    }
while(counter < sample_num)
    {
    random_x = rand() % 300 - 150;
    random_y = rand() % 300 - 150;
    if(random_x * random_x + random_y * random_y < 2500)
        continue;
    point_x[counter] = random_x + 150;
    point_y[counter] = random_y + 150;
    cvCircle(frame,cvPoint(int(point_x[counter]),int(point_y[counter])),3, cvScalar(0,0,255), 1);
    counter++;
    }

for(int i = 0;i < sample_num;i++)
    {
        sample_ori[i].x = point_x[i];
        sample_ori[i].y = point_y[i];
        sample_ori[i].lable = i < P_SAMPLE_NUM ? 1 : 0;
        sample_ori[i].result_lebel = 1 - sample_ori[i].lable;
        //sample_ori[i].weigth = 1 / double(sample_num);  //正负样本权重一样

        sample_ori[i].weigth = sample_ori[i].lable==1 ? 0.5 / double(P_SAMPLE_NUM) : 0.5 / double(N_SAMPLE_NUM);//正负样本权重不一样
    }
cvShowImage("show",frame);
cvWaitKey(2);
}

void get_eigenvalue(sample sample[],int feature)
{
for(int i = 0;i < sample_num;i++)
sample[i].eigen_value = cos(pi * feature / FEATURE_NUM) * sample[i].x + sin(pi * feature / FEATURE_NUM) * sample[i].y;
}

void sort_sample(sample sample_ori[],sample sample_sort[])//升序排列
{
for(int i = 0;i < sample_num;i++)
        sample_sort[i] = sample_ori[i];

for(int pass = 1;pass < sample_num;pass++)
    {
    int work = 1;
    for(int i = 0;i < sample_num - pass;i++)
        if(sample_sort[i].eigen_value > sample_sort[i + 1].eigen_value)
        {
            swap(sample_sort[i],sample_sort[i+1]);
            work = 0;
        }
            if(work) break;
    }

}

void swap(sample &s1,sample &s2)
{
    sample s_temp;
    s_temp = s1;
    s1 = s2;
    s2 = s_temp;
}

classifier weaklearner(sample sample_ori[],int feature)
{
sample sample_sort[sample_num];
classifier h;
get_eigenvalue(sample_ori,feature);

double pos_weigth = 0,neg_weigth = 0;
for(int k = 0;k < sample_num;k++)
    {
        if(sample_ori[k].lable == 1)
            pos_weigth += sample_ori[k].weigth;
        else neg_weigth += sample_ori[k].weigth;
    }
sort_sample(sample_ori,sample_sort);

double loss_pos_weigth = 0,loss_neg_weigth = 0;
double besterror = 0.5;
int bestparity = 0;
double bestthresh = -1;

for(int k = 1;k < sample_num;k++)
    {
    if(sample_sort[k - 1].lable == 1)
        loss_pos_weigth += sample_sort[k - 1].weigth;
    else loss_neg_weigth += sample_sort[k - 1].weigth;

        if( (loss_pos_weigth + neg_weigth - loss_neg_weigth) < besterror)
            {
            besterror = loss_pos_weigth + neg_weigth - loss_neg_weigth;
            bestparity = -1;
            bestthresh = (sample_sort[k].eigen_value + sample_sort[k - 1].eigen_value) / 2;
            }
        else if(loss_neg_weigth + pos_weigth - loss_pos_weigth < besterror)
            {
            besterror = loss_neg_weigth + pos_weigth - loss_pos_weigth;
            bestparity = 1;
            bestthresh = (sample_sort[k].eigen_value + sample_sort[k - 1].eigen_value) / 2;
            }
    }
h.threshold = bestthresh;
h.error = besterror;
h.parity = bestparity;
h.feature = feature;

for(int i = 0;i < sample_num;i++)
    {
        if(h.parity * sample_ori[i].eigen_value < h.parity * h.threshold)
            h.result[i] = 1;
        else
            h.result[i] = 0;
    }  

return h;
}

classifier weaklearner2(sample sample_ori[],int feature)
{
    classifier h;
    return h;

//
//
//
//
//PN_cum1 = ( (max(P_cum)-P_cum) + N_cum);
//PN_cum2 = ( (max(N_cum)-N_cum) + P_cum);
//
//[min1,thresh_ind1]= min(PN_cum1);
//[min2,thresh_ind2]= min(PN_cum2);
//
//if (min1<min2)
//   thresh_ind=thresh_ind1;
//   PN_cum=PN_cum1;
//else
//   thresh_ind=thresh_ind2;
//   PN_cum=PN_cum2;
//end;
//
//
//
//lpn = length(PN_cum);
//thresh = ( V_sort(thresh_ind));
//%thresh = ( V_sort(thresh_ind)+V_sort(thresh_ind+1))/2;
//p = 2 *( (P_cum(thresh_ind)>N_cum(thresh_ind)) -0.5);

}

int teststrong(sample sample_ori[],classifier h[],int T)
{
int    error_counter = 0;
for(int i = 0;i < sample_num;i++)
    sample_ori[i].result = 0;
double egein[sample_num][FEATURE_NUM];
for(int i = 0;i < FEATURE_NUM;i++)
    {
    get_eigenvalue(sample_ori,i);
    for(int j = 0;j < sample_num;j++)
        {
            egein[j][i] = sample_ori[j].eigen_value;
        }
    }

for(int i = 0;i < sample_num;i++)
    {
        for(int j = 0;j < T;j++)
            {
            if(h[j].parity * egein[i][h[j].feature] < h[j].parity * h[j].threshold)
                sample_ori[i].result += 0.5 * log(1 / h[j].beta);
            else
                sample_ori[i].result -= 0.5 * log(1 / h[j].beta);
            }
        if(sample_ori[i].result > 0)
            sample_ori[i].result_lebel = 1;
        else
            sample_ori[i].result_lebel = 0;
        if(sample_ori[i].result_lebel != sample_ori[i].lable)
            error_counter++;
    }
draw(sample_ori);
draw_distribute(h,T,sample_ori);
//cvWaitKey(500);
return error_counter;
}

void draw(sample s[])
{
for(int i = 0;i < frame->height;i++)
    for(int j = 0;j < frame->width;j++)
CV_IMAGE_ELEM(frame,uchar,i,3 * j) = CV_IMAGE_ELEM(frame,uchar,i,3 * j + 1) = CV_IMAGE_ELEM(frame,uchar,i,3 * j + 2)  = 255;

for(int i = 0;i < sample_num;i++)
    {
        if(s[i].lable == 1)
            cvCircle(frame, cvPoint(int(s[i].x),int(s[i].y)), 3, cvScalar(0,255,0), 1);
        else
            cvCircle(frame, cvPoint(int(s[i].x),int(s[i].y)), 3, cvScalar(0,0,255), 1);
        if(s[i].lable != s[i].result_lebel)
        {
            cvLine(frame,cvPoint(int(s[i].x - 3),int(s[i].y - 3)),cvPoint(int(s[i].x + 3),int(s[i].y + 3)),cvScalar(0,0,0),1);
            cvLine(frame,cvPoint(int(s[i].x - 3),int(s[i].y + 3)),cvPoint(int(s[i].x + 3),int(s[i].y - 3)),cvScalar(0,0,0),1);
        }
    }
cvShowImage("show",frame);
cvWaitKey(2);
}

void draw_distribute(classifier h[],int T,sample s[])
{
double wrong_rate = 0;
for(int i = 0;i < frame->height;i++)
    for(int j = 0;j < frame->width;j++)
CV_IMAGE_ELEM(frame,uchar,i,3 * j) = CV_IMAGE_ELEM(frame,uchar,i,3 * j + 1) = CV_IMAGE_ELEM(frame,uchar,i,3 * j + 2) =0;

for(int i = 0;i < X_MAX;i++)
    for(int j = 0;j < Y_MAX;j++)
    {
        double result = 0;
    for(int k = 0;k < T;k++)
        {
            double egein = i * cos(h[k].feature * pi / FEATURE_NUM) + j * sin(h[k].feature * pi / FEATURE_NUM);
            if(h[k].parity * egein < h[k].parity *h[k].threshold)
                result += 0.5 * log(1 / h[k].beta);
            else
                result -= 0.5 * log(1 / h[k].beta);
        }
    if(result > 0)
        {
        CV_IMAGE_ELEM(frame,uchar,j,3 * i + 1) = 255;
        if((i - 150) * (i - 150) + (j - 150) * (j - 150) > 2500)
            wrong_rate++;
        }
    else
        {
        CV_IMAGE_ELEM(frame,uchar,j,3 * i + 2) = 255;
        if((i - 150) * (i - 150) + (j - 150) * (j - 150) < = 2500)
            wrong_rate++;
        }
    }
    for(int i = 0;i < sample_num;i++)
        {
        if(s[i].lable == 1)
            cvCircle(frame, cvPoint(int(s[i].x),int(s[i].y)), 3, cvScalar(255,255,0), 1);
        else
            cvCircle(frame, cvPoint(int(s[i].x),int(s[i].y)), 3, cvScalar(255,0,255), 1);
        }

cout<<"强分类器错误率为:"<<wrong_rate / (X_MAX *Y_MAX)<<endl<<endl;
cvShowImage("distribute",frame);
cvWaitKey(2);
}

【完】

本文内容遵从CC版权协议,转载请注明出自http://www.kylen314.com

分类: OPENCV 标签: , ,
  1. 2015年11月27日16:20 | #1

    你还会机器学习啊。

验证码:3 + 3 = ?

友情提示:留言可以使用大部分html标签和属性;

添加代码示例:[code lang="cpp"]your code...[/code]

添加公式请用Latex代码,前后分别添加两个$$