好贷网好贷款

SVM支持向量机(Support Vector Machine)-翻译版

发布时间:2016-12-4 12:01:15 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"SVM支持向量机(Support Vector Machine)-翻译版",主要涉及到SVM支持向量机(Support Vector Machine)-翻译版方面的内容,对于SVM支持向量机(Support Vector Machine)-翻译版感兴趣的同学可以参考一下。

第一个支持向量机(SupportVector Machine) CvSVM 利用SVM解决2维空间向量的3级分类问题 #include <cv.h> #include <highgui.h> #include <ml.h> #include <time.h> int main(int argc, char **argv) {  intsize= 400;                    //图像的长度和宽度  int s= 1000;  inti, j, sv_num;  IplImage*img;  CvSVMsvm= CvSVM ();  CvSVMParamsparam;  CvTermCriteriacriteria;  //停止迭代的标准  CvRNG rng= cvRNG(time(NULL));  CvPointpts[s];                 //定义1000个点  float data[s* 2];  intres[s];  CvMatdata_mat, res_mat;  CvScalarrcolor;  constfloat *support;  // (1)图像区域的确保和初始化   img= cvCreateImage(cvSize(size, size), IPL_DEPTH_8U, 3);   cvZero(img); // (1)图像区域的确保和初始化 确保画像区域,并清0(用黑色作初始化处理)。  // (2)学习数据的生成  for (i= 0; i< s; i++) {     pts[i].x= cvRandInt(&rng) % size;      //用随机整数赋值     pts[i].y= cvRandInt(&rng) % size;    if(pts[i].y> 50 * cos(pts[i].x* CV_PI/ 100) + 200) {       cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), CV_RGB(255, 0, 0));       cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), CV_RGB(255, 0, 0));       res[i] = 1;    }    else{      if(pts[i].x> 200) {         cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), CV_RGB(0, 255, 0));         cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), CV_RGB(0, 255, 0));         res[i]= 2;      }      else{         cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), CV_RGB(0, 0, 255));         cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), CV_RGB(0, 0, 255));         res[i]= 3;      }    }  } // (2)训练数据的生成 生成2维随机训练数据,并将其值放在CvPoint数据类型的数组pts[]中。  // (3)学习数据的显示   cvNamedWindow("SVM", CV_WINDOW_AUTOSIZE);   cvShowImage("SVM", img);   cvWaitKey(0); 将生成的数据绘制在起初确保的图像区域里,并显示出来。如图1-3,用红,绿,蓝各色标记的那样,直到等到某个键被按下。  // (4)学习参数的生成  for (i= 0; i< s; i++) {     data[i* 2] = float (pts[i].x) / size;     data[i* 2 + 1] = float (pts[i].y) / size;  }   cvInitMatHeader(&data_mat, s, 2, CV_32FC1, data);   cvInitMatHeader(&res_mat, s, 1, CV_32SC1, res);   criteria=cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);   param=CvSVMParams (CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, NULL, criteria); SVM种类:CvSVM::C_SVC Kernel的种类:CvSVM::RBF degree:10.0(此次不使用) gamma:8.0 coef0:1.0(此次不使用) C:10.0 nu:0.5(此次不使用) p:0.1(此次不使用) 然后对训练数据正规化处理,并放在CvMat型的数组里。  // (5)SVM学习   svm.train(&data_mat, &res_mat, NULL, NULL, param); 利用训练数据和确定的学习参数,进行SVM学习。  // (6)学习结果的绘图  for (i= 0; i< size; i++) {    for(j= 0; j< size; j++) {      CvMatm;      floatret= 0.0;      floata[] = { float (j) / size, float (i) / size};       cvInitMatHeader(&m, 1, 2, CV_32FC1, a);       ret=svm.predict(&m);      switch((int) ret) {      case1:         rcolor= CV_RGB(100, 0, 0);        break;      case 2:         rcolor= CV_RGB(0, 100, 0);        break;      case 3:         rcolor= CV_RGB(0, 0, 100);        break;      }       cvSet2D(img, i, j, rcolor);    }  } 为了显示学习结果,通过输入图像区域的所有像素(特征向量)并进行分类。然后对输入像素用所属等级的颜色绘图。    // (7)训练数据的再绘制  for (i= 0; i< s; i++) {    CvScalar rcolor;    switch (res[i]) {    case 1:       rcolor= CV_RGB(255, 0, 0);      break;    case 2:       rcolor= CV_RGB(0, 255, 0);      break;    case 3:       rcolor= CV_RGB(0, 0, 255);      break;    }     cvLine(img, cvPoint(pts[i].x- 2, pts[i].y- 2), cvPoint(pts[i].x+ 2, pts[i].y+ 2), rcolor);     cvLine(img, cvPoint(pts[i].x+ 2, pts[i].y- 2), cvPoint(pts[i].x- 2, pts[i].y+ 2), rcolor);  } 将训练数据在结果图像上重复的绘制出来。  // (8)支持向量的绘制   sv_num= svm.get_support_vector_count();  for (i= 0; i< sv_num; i++) {     support= svm.get_support_vector(i);     cvCircle(img, cvPoint((int) (support[0] * size), (int) (support[1] * size)), 5, CV_RGB(200, 200, 200));  } 用白色的圆圈对支持向量作标记。  // (9)图像的显示   cvNamedWindow("SVM", CV_WINDOW_AUTOSIZE);   cvShowImage("SVM", img);   cvWaitKey(0);   cvDestroyWindow("SVM");   cvReleaseImage(&img);  return 0; }显示实际处理结果的图像,直到某个键被按下为止。   第二个图像各像素值转化成特征向量的SVM学习 读取学习用的图像,并将像素值转化成特征向量进行SVM学习。 #include <cv.h> #include<highgui.h> #include<ml.h> #include<stdio.h> int main(int argc, char**argv) {  int i, j, ii, jj;  int width= 28, height= 30;      /*样本图像的尺寸大小*/  int image_dim= width* height;  int pimage_num= 500;         /*正样本数*/   int nimage_num= 1000;        /*负样本数*/   int all_image_num= pimage_num+ nimage_num;  IplImage *img_org;  IplImage *sample_img;  int res[all_image_num];  float data[all_image_num* image_dim];  CvMat data_mat, res_mat;  CvTermCriteria criteria;  CvSVM svm= CvSVM ();  CvSVMParams param;  char filename[64];  // (1) 读取正样本数据  for (i= 0; i< pimage_num; i++) {     sprintf(filename, "positive/%03d.png", i);     img_org=cvLoadImage(filename, CV_LOAD_IMAGE_GRAYSCALE);     sample_img= cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);     cvResize(img_org, sample_img);     cvSmooth(sample_img, sample_img, CV_GAUSSIAN, 3, 0, 0, 0);    for (ii= 0; ii< height; ii++) {      for (jj= 0; jj< width; jj++) {         data[i* image_dim+ (ii* width) + jj] =          float ((int) ((uchar) (sample_img->imageData[ii* sample_img->widthStep+ jj])) / 255.0);      }    }     res[i] = 1;  }     读取正样本的图像群,将各像素值转化成float数据类型。为了方便,预先在"positive/目录下准备了正样本图像,图像名用3位连续的数字名标识。首先,将读取的各图像转换成同一尺寸大小(28×30),为了减轻噪声的影响,对图像作了平滑化处理。然后,为了利用各像素亮度值(这里的图像作为等级图像被读取)的特征向量,将它变换成了数组。总之,对于一张图像的特征向量(图像宽度X图像长度),准备了和样本图像张数相同的数量。"1"表示利用此特征向量的判别数值。此外还使用500张脸部图像的正样本(基本上是正面脸部图像,没有侧面的)。     在OpenCV里实装了利用haar-like特征的物体检测算法,由于利用它检测脸部的精度和处理速度都很不错,虽然脸部图像检测没有太大意义,但从获取样本的难易程度和理解程度考虑,此次利用脸部图像进行学习。  // (2) 读取负样本数据   j= i;  for (i= j; i< j+ nimage_num; i++) {     sprintf(filename, "negative/%03d.jpg", i- j);     img_org= cvLoadImage(filename, CV_LOAD_IMAGE_GRAYSCALE);     sample_img= cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);     cvResize(img_org, sample_img);     cvSmooth(sample_img, sample_img, CV_GAUSSIAN, 3, 0, 0, 0);    for (ii= 0; ii< height; ii++) {      for (jj= 0; jj< width; jj++) {         data[i* image_dim+ (ii* width) + jj] =          float ((int) ((uchar) (sample_img->imageData[ii* sample_img->widthStep+ jj])) / 255.0);      }    }     res[i] = 0;  } 读取负样本的图像群,和正样本一样,将它们转化成数组,并用"0"表示利用该特征向量的判别数值。另外使用1000张任意图像的负样本(全部是脸部以外的图像)。  // (3)SVM学习数据和参数的初始化   cvInitMatHeader(&data_mat, all_image_num, image_dim, CV_32FC1, data);   cvInitMatHeader(&res_mat, all_image_num, 1, CV_32SC1, res);   criteria=cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);   param=CvSVMParams(CvSVM::C_SVC, CvSVM::RBF, 10.0, 0.09, 1.0, 10.0, 0.5, 1.0, NULL, criteria); 样本图像的像素值数组和判别值数组进行行列变换。为了样本学习对参数作了初始化处理。由于指定了非常适合的参数,也就有必要设定相应合适的参数。  // (4)SVM学习和数据保存   svm.train(&data_mat, &res_mat, NULL, NULL, param);   svm.save("svm_image.xml");   cvReleaseImage(&img_org);   cvReleaseImage(&sample_img);  return 0; }利用正负样本的像素值和被指定的参数,根据svm.train()方式进行SVM学习。样本数:正样本500,负样本1000,特征向量: 28×30=840维。学习的SVM参数用根据svm.save()方法的XML形式的文件保存。如此页开始部分讲述的那样,为了使用保存和下载功能,有必要对OpenCV源代码作修改。 第三个  根据图像各像素值转化成特征向量的SVM检测物体(脸部) 读取用于学习的SVM参数,从相关图像中检测物体。 #include <cv.h> #include<highgui.h> #include<ml.h> #include<stdio.h> int main(int argc, char**argv) {  int i, j;  int width= 28, height= 30;  /*样本图像的尺寸大小*/  int image_dim= width* height;  CvMat m;  float a[image_dim];  float ret= -1.0;  float scale;  IplImage *src,*src_color, *src_tmp;  int sx, sy, tw, th;  int stepx= 3, stepy= 3;  double steps= 1.2;  int iterate;  CvSVM svm= CvSVM ();  // (1)图像的读取  if (argc< 2 ||      (src= cvLoadImage(argv[1], CV_LOAD_IMAGE_GRAYSCALE))== 0 ||      (src_color= cvLoadImage(argv[1], CV_LOAD_IMAGE_COLOR))== 0) {    return -1;  }  // (2)SVM数据的读取   svm.load("svm_image.xml");  /* 对读取图像的每部分进行处理 */   cvInitMatHeader(&m, 1, image_dim, CV_32FC1, NULL);   tw=src->width;   th=src->height;  for (iterate= 0; iterate< 1; iterate++) { // (3)缩小图像,并对当前图像部分作行列变换     src_tmp= cvCreateImage(cvSize((int) (tw/ steps), (int) (th/ steps)), IPL_DEPTH_8U, 1);     cvResize(src, src_tmp);     tw=src_tmp->width;     th=src_tmp->height;    for (sy= 0; sy<= src_tmp->height- height; sy+= stepy) {      for (sx= 0; sx<= src_tmp->width- width; sx+= stepx) {        for (i= 0; i< height; i++) {          for (j= 0; j< width; j++) {             a[i* width+ j] =              float ((int) ((uchar) (src_tmp->imageData[(i+ sy) * src_tmp->widthStep+ (j+ sx)])) / 255.0);          }        }         cvSetData(&m, a, sizeof (float) * image_dim);  // (4)根据SVM的判定和结果绘图         ret= svm.predict(&m);        if ((int) ret== 1) {           scale= (float) src->width/ tw;           cvRectangle(src_color, cvPoint((int) (sx* scale), (int) (sy* scale)),                        cvPoint((int) ((sx+ width) * scale), (int) ((sy+ height) * scale)), CV_RGB(255, 0, 0), 2);        }      }    }     cvReleaseImage(&src_tmp);  }  // (5)显示检测出的结果图像   cvNamedWindow("svm_predict", CV_WINDOW_AUTOSIZE);   cvShowImage("svm_predict", src_color);   cvWaitKey(0);   cvDestroyWindow("svm_predict");   cvReleaseImage(&src);   cvReleaseImage(&src_color);   cvReleaseImage(&src_tmp);  return 0; } // (1)图像的读取     通过命令参数从指定文件中读取由SVM确定的判别对象的图像。处理时虽然是针对灰色等级的图像,但为了显示最终结果另外也准备了彩色图像。 // (2)SVM数据的读取 预先从svm.load()方式得到的文件(此处为"xvm_image.xml")中读取用于学习的SVM参数。如本页开始部分讲述的那样,为了利用保存和下载功能,有必要修改OpenCV的源代码。 // (3)缩小图像,并对当前图像部分作行列变换 为了处理被读取图像的每部分,每stepx=3, stepy=3像素,width×height=28×30尺寸大小的图像部分的像素值代入到了数组中。另外为了使SVM适用,我们通过函数cvSetData()对数组1×(28×30)行列的数据进行设定。 // (4)根据SVM的判定和结果绘图 通过svm.predict()方式对进行行列变换后的图像作所属等级的判定。在这里,由于利用了前面叙述的学习参数文件,对处理对象的部分图像作是否是被学习物体(脸部)的判定。被判定为脸部的部分图像,用红色矩形显示。因为没有对参数的最优化,特殊处理方面(处理领域的选定和特征像素的提取等)作处理,检测的精度不高。而且,在对整张图像作处理时,由于特征向量可能很大而耗用了处理时间。此外,iterate变量虽只作了一次循环,但如果想检测出图像中存在很大差异的脸部的话,应随时缩小原有图像以进行相同的处理。 // (5)显示检测出的结果图像 红色矩形表示被绘制图像的检测结果,直到某个键被按下为止。

上一篇:udev 和 mdev 总结
下一篇:1003. Erdős Number

相关文章

相关评论