参考http://blog.csdn.net/carson2005/article/details/6547250 数据和标签格式还是和上一篇Adaboost一样的
#include
#include
#include
#include "opencv2/imgproc/imgproc.hpp"
#include
#include
#include
#include "time.h"
using namespace std;
using namespace cv;
int main()
{
//开始计时
clock_t start, finish;
double duration;
start = clock();
// 样本
CvMLData cvmlprimer;
cvmlprimer.read_csv("featurewet.csv");
cv::Mat cvml = cv::Mat(cvmlprimer.get_values(), true);
CvMLData resprimer;
resprimer.read_csv("labelwet.csv");
cv::Mat res = cv::Mat(resprimer.get_values(), true);
////////////////////////////////////////
//打乱顺序结果在stonevec[]和kuangvec[]两个数组里 图像标号
const int uselesssample = 358, usefulsample = 192, allsample = usefulsample + uselesssample, featurecol = 1000;
//打乱顺序 前uselesssample个为废石 后usefulsample个为矿
int stonevec[uselesssample], kuangvec[usefulsample];
for (int i = 0; i < uselesssample; i++)
stonevec[i] = i;
for (int i = 0; i
random_shuffle(stonevec, stonevec + uselesssample);
random_shuffle(kuangvec, kuangvec + usefulsample);
/////////////////////////////////////////////////////////////////////saperate into trainset randomly
const float rate = 0.8;
int trainnum = int(uselesssample*rate) + int(usefulsample*rate), testnum = allsample - trainnum;
Mat traindata = Mat::zeros(trainnum, featurecol, cvml.type()), testdata = Mat::zeros(testnum, featurecol, cvml.type()), trainlabel = Mat::zeros(trainnum, 1, res.type()), testlabel = Mat::zeros(testnum, 1, res.type());
for (int i = 0; i
float* newrow = traindata.ptr
int currentrow = stonevec[i];
float* primerow = cvml.ptr
for (int j = 0; j < featurecol; j++)
newrow[j] = primerow[j];
float* newlabelrow = trainlabel.ptr
float* primerlabelrow = res.ptr
newlabelrow[0] = primerlabelrow[0];
}
for (int i = int(uselesssample*rate); i
float* newrow = traindata.ptr
int ii = i - int(uselesssample*rate);
int currentrow = kuangvec[ii];
float* primerow = cvml.ptr
for (int j = 0; j < featurecol; j++)
newrow[j] = primerow[j];
float* newlabelrow = trainlabel.ptr
float* primerlabelrow = res.ptr
newlabelrow[0] = primerlabelrow[0];
}
//saperate into testset
for (int i = 0; i
float* newrow = testdata.ptr
int iii = i + int(uselesssample*rate);
int currentrow = stonevec[iii];
float* primerow = cvml.ptr
for (int j = 0; j < featurecol; j++)
newrow[j] = primerow[j];
float* newlabelrow = testlabel.ptr
float* primerlabelrow = res.ptr
newlabelrow[0] = primerlabelrow[0];
}
for (int i = uselesssample - int(uselesssample*rate); i
int ii = int(usefulsample*rate) + i - (uselesssample - int(uselesssample*rate));
float* newrow = testdata.ptr
int currentrow = kuangvec[ii];
float* primerow = cvml.ptr
for (int j = 0; j < featurecol; j++)
newrow[j] = primerow[j];
float* newlabelrow = testlabel.ptr
float* primerlabelrow = res.ptr
newlabelrow[0] = primerlabelrow[0];
}
/////////////////////////////////////////////train
cout << "Ready for Training ... " << endl;
// 设置SVM参数
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
//params.kernel_type = CvSVM::RBF;
//params.kernel_type = CvSVM::SIGMOID;
params.kernel_type = CvSVM::LINEAR;
//params.C= 0.1;
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
// 对SVM进行训练
CvSVM SVM;
SVM.train(traindata, trainlabel, Mat(), Mat(), params);
cout << "training done!!!prepare for test..." << endl;
////////////////////////////test
const int numfortest = testdata.rows;
Mat currentsample;
currentsample.create(1, featurecol, testdata.type());
float* outputlabels = new float[numfortest]; //动态数组可以避免必须写明确维度的麻烦 记得delete
for (int i = 0; i < numfortest; i++)
{
float* currentrow = testdata.ptr
for (int j = 0; j < featurecol; j++)
currentsample.at
float currentoutputs = SVM.predict(currentsample);//必须一个一个样本的进行测试
outputlabels[i] = currentoutputs;
//cout << currentoutputs << endl;
}
cout << "test done!!!prepare for calculating the accurency..." << endl << endl;
/////////////////////////////////////////////////////////////////////////////////calculate whole error
int correct = 0;
float accurency;
for (int i = 0; i < testlabel.rows; ++i)
{
float* p = testlabel.ptr
cout << "true label= " << p[0] << " output label= " << outputlabels[i] << endl;
if (p[0] == outputlabels[i])
++correct;
}
cout << endl;
accurency = (float)correct / testlabel.rows;
cout << "whole accurency= " << accurency << endl;
/////////calculate the positive sample error and negative sample error
int alluseless = 0, uselesserror = 0, alluseful = 0, usefulerror = 0;
float stoneerror = 0, kuangerror = 0;
//stone error
for (int i = 0; i < testlabel.rows; ++i)
{
float* p = testlabel.ptr
if (p[0] == (float)1)
{
++alluseless;
if (p[0] != outputlabels[i])
++uselesserror;
}
}
cout << alluseless << " " << uselesserror << endl;
stoneerror = (float)uselesserror / alluseless;
cout << " stone error= " << stoneerror << endl;
//kuang error
for (int i = 0; i
float* p = testlabel.ptr
if (p[0] == (float)2)
{
++alluseful;
if (p[0] != outputlabels[i])
++usefulerror;
}
}
cout << alluseful << " " << usefulerror << endl;
kuangerror = (float)usefulerror / alluseful;
cout << " kuang error= " << kuangerror << endl;
////////////////////////////////////////////////////////////////////////
delete[] outputlabels;
//结束计时
finish = clock();
duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "训练过程结束,共耗时:" << duration << "秒" << endl;
return 0;
}
可以是可以 可是准确率太低了 调参是门技术
参考http://blog.csdn.net/computerme/article/details/38677599自动寻优参数:
RBF核函数 自动寻参数最优哎。。。。。。。。。调参是门技术
另一个SVM程序:
#include
#include
#include
#include
using namespace cv;
using namespace std;
#define cvQueryHistValue_1D( hist, idx0 ) ((float)cvGetReal1D( (hist)->bins, (idx0)))
Mat mypredone(IplImage* srcipl,vector bgrimgs)
{
//////////////////////////////////////////////////////////找轮廓
Mat img(srcipl, 0);
split(img, bgrimgs);
Mat bimg(img.size(), CV_8UC1, cv::Scalar(0));
bgrimgs[0].copyTo(bimg);
threshold(bimg, bimg, 12, 255, CV_THRESH_BINARY/*|CV_THRESH_OTSU*/);
Mat element(4, 4, CV_8U, cv::Scalar(1));
morphologyEx(bimg, bimg, cv::MORPH_OPEN, element);
for (int i = 0; i < 20; i++)
{
uchar* data = bimg.ptr(i);
for (int j = 0; j < bimg.size().width; j++)
data[j] = 0;
}
//for (int i = bimg.size().height - 19; i < bimg.size().height; i++)
//{
// uchar* data = bimg.ptr(i);
// for (int j = 0; j < bimg.size().width; j++)
// data[j] = 0;
//}
return bimg;
}
Mat my_contour(IplImage* dst, IplImage bimgipl)
{
cvZero(dst);
CvMemStorage *storage = cvCreateMemStorage();
CvSeq *contour = NULL, *hull = NULL;
vector allpoints;
CvContourScanner scanner = cvStartFindContours(&bimgipl, storage);
while ((contour = cvFindNextContour(scanner)) != NULL)
{
cvDrawContours(dst, contour, cv::Scalar(255), cv::Scalar(255), 0);
hull = cvConvexHull2(contour, 0, CV_CLOCKWISE, 0);
CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull, hull->total - 1);
allpoints.push_back(pt0);
for (int i = 0; i < hull->total; ++i)
{
CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull, i);
allpoints.push_back(pt1);
cvLine(dst, pt0, pt1, cv::Scalar(255));
pt0 = pt1;
}
}
//上面是第一次寻找 可能有多个凸包 下面存储每个凸包的凸点到容器中 方便我连线画图再寻找一次 也是最后的
Mat dstmat(dst, 0);
std::vector> myown_contours;
cv::findContours(dstmat, myown_contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
//cout << myown_contours.size() << endl;
if (myown_contours.size() > 1)
{
for (int i = 0; i < allpoints.size() - 1; i++)
{
CvPoint firstdot = allpoints[i];
CvPoint secdot = allpoints[i + 1];
cvLine(dst, firstdot, secdot, cv::Scalar(255), 2);
}
CvContourScanner scanner2 = cvStartFindContours(dst, storage);
while ((contour = cvFindNextContour(scanner2)) != NULL)
{
cvDrawContours(dst, contour, cv::Scalar(255), cv::Scalar(255), 0);
hull = cvConvexHull2(contour, 0, CV_CLOCKWISE, 0);
CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull, hull->total - 1);
for (int i = 0; i < hull->total; ++i)
{
CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull, i);
cvLine(dst, pt0, pt1, cv::Scalar(255));
pt0 = pt1;
}
}
}
Mat bimgdst(dst, 0);
std::vector> contours;
cv::findContours(bimgdst, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
Mat contoursimg(bimgdst.size(), CV_8UC1, cv::Scalar(0));
drawContours(contoursimg, contours, -1, Scalar(255), CV_FILLED);
return contoursimg;
}
void myfeatures(IplImage* srcipl,IplImage myresultipl,float features[])
{
cvCvtColor(srcipl, srcipl, CV_BGR2Lab);
IplImage* limg = cvCreateImage(cvGetSize(srcipl), srcipl->depth, 1);
IplImage* aimg = cvCreateImage(cvGetSize(srcipl), srcipl->depth, 1);
IplImage* bbimg = cvCreateImage(cvGetSize(srcipl), srcipl->depth, 1);
cvSplit(srcipl, limg, aimg, bbimg, 0);
//cvAnd(limg, &myresultipl, limg);
cvAnd(aimg, &myresultipl, aimg);
cvAnd(bbimg, &myresultipl, bbimg);
//cvShowImage("a", aimg);
//waitKey(0);
/////////////////////////////////////////////////////////////////A B的直方图
int histsize = 256;
float range[] = { 0, histsize };
float *ranges[] = { range };
CvHistogram* hista = cvCreateHist(1, &histsize, CV_HIST_ARRAY, ranges, 1);
cvCalcHist(&aimg, hista, 0, 0);
cvNormalizeHist(hista, 1.0);
CvHistogram* histb = cvCreateHist(1, &histsize, CV_HIST_ARRAY, ranges, 1);
cvCalcHist(&bbimg, histb, 0, 0);
cvNormalizeHist(histb, 1.0);
//////////////////////////////////////////////////////////my features
//float features[256*2];
for (int i = 0; i < histsize; i++)
features[i] = cvQueryHistValue_1D(hista, i);
for (int i = histsize; i < 2 * histsize; i++)
features[i] = cvQueryHistValue_1D(histb, i - histsize);
//////////////////////////////////////////////////////////////show hist img
/*
int scale= 2,height=256;
IplImage* hist_img= cvCreateImage(cvSize(histsize* scale, height), 8, 3);
cvZero(hist_img);
float max_value= 0;
cvGetMinMaxHistValue(histb, 0, &max_value, 0, 0);
for (int i = 0; i < histsize; i++)
{
float bin_val = cvQueryHistValue_1D(histb, i);
int intensity = cvRound(bin_val* height / max_value);
cvRectangle(hist_img, cvPoint(i* scale, height - 1),
cvPoint((i + 1)* scale - 1, height - intensity), cv::Scalar(255, 255, 255));
}
cvShowImage("aimg hist", hist_img);
waitKey(0);
*/
/////////////////////////////////////////////////////////////return features;
}
char filename[100];
void main()
{
TickMeter tm;
tm.start();
/* ////////////////////////////1 img test
IplImage* src_ipl = cvLoadImage("1.bmp");
vector bgrimgs;
Mat bimg = mypredone(src_ipl, bgrimgs);
///////////////////////////////////////////////////////////////
IplImage mybimgipl = bimg;
IplImage *mydst = cvCreateImage(cvGetSize(src_ipl), 8, 1);
Mat myresult(mydst, 0);
myresult = my_contour(mydst, mybimgipl);
IplImage my_resultipl = myresult;
/////////////////////////////////////////////////////////////////上面是找轮廓得到掩模
float myfeature[256 * 2];
myfeatures(src_ipl, my_resultipl, myfeature);
*/
Mat featuremat(1657,256*2, CV_32FC1, cv::Scalar(0));
//float* finalfeatures[1657];
for (int i = 1; i <= 1657; i++)
{
sprintf(filename, "正常图_压缩\\%d.bmp", i);
IplImage* src_ipl = cvLoadImage(filename);
vector bgrimgs;
Mat bimg = mypredone(src_ipl, bgrimgs);
///////////////////////////////////////////////////////////////找轮廓得到掩模
IplImage mybimgipl = bimg;
IplImage *mydst = cvCreateImage(cvGetSize(src_ipl), 8, 1);
Mat myresult(mydst, 0);
myresult = my_contour(mydst, mybimgipl);
IplImage my_resultipl = myresult;
//////////////////////////////////////////////////////////LAB图像与掩模与操作 得到掩模中的图像 特征
float myfeature[256 * 2];
myfeatures(src_ipl, my_resultipl, myfeature);
//////////////////////////////////////////////////////////////////
//finalfeatures[i - 1] = myfeature; //每个图片的特征向量的指针放在这个数组中
//////////////////////////////////////////////////////////特征保存为mat featuremat
float* datarow = featuremat.ptr(i - 1);
for (int j = 0; j < featuremat.cols; j++)
datarow[j] = float(myfeature[j]);
}
//////////////////////////////////////////////////////////////////label:res
CvMLData resprimer;
resprimer.read_csv("label.csv");
cv::Mat label = cv::Mat(resprimer.get_values(), true);
//////////////////////////////////////////////////////////saperate train and test data
float rate = 0.6;
Mat traindata = Mat::zeros(int(rate * 1657), 256 * 2, featuremat.type());
//Mat traindata(int(rate * 1657), 256 * 2, CV_32FC1, cv::Scalar(0));
Mat trainlabel = Mat::zeros(int(rate * 1657),1, label.type());
//Mat trainlabel(int(rate * 1657), 1, CV_32SC1, cv::Scalar(0));
//Mat testdata(1657 - int(rate * 1657), 256 * 2, CV_32FC1, cv::Scalar(0));
Mat testdata = Mat::zeros(1657 - int(rate * 1657), 256 * 2, featuremat.type());
//Mat testlabel(1657 - int(rate * 1657), 1, CV_32SC1, cv::Scalar(0));
Mat testlabel = Mat::zeros(1657 - int(rate * 1657), 1, label.type());
for (int i = 0; i < featuremat.rows; i++)
{
float* datarow = featuremat.ptr(i);
int* labelrow = label.ptr(i);
if (i < traindata.rows)
{
int* trainlabelrow = trainlabel.ptr(i);
trainlabelrow[0] = int(labelrow[0]);
float* traindatarow = traindata.ptr(i);
for (int j = 0; j < featuremat.cols; j++)
traindatarow[j] = datarow[j];
}
else
{
int newi = i - traindata.rows;
int* testlabelrow = testlabel.ptr(newi);
testlabelrow[0] = labelrow[0];
float* testdatarow = testdata.ptr(newi);
for (int j = 0; j < featuremat.cols; j++)
testdatarow[j] = datarow[j];
}
}
////////////////////////////////////////////////////////
cout << "Ready for Training ... " << endl;
CvSVMParams params;
params.svm_type = CvSVM::C_SVC;
CvSVM SVM;
//////////////////////////////////////////////
//params.kernel_type = CvSVM::SIGMOID;
//params.kernel_type = CvSVM::LINEAR;
//params.C= 0.1;
//params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
//SVM.train(traindata, trainlabel, Mat(), Mat(), params);
////////////////////////////////////////////
params.kernel_type = CvSVM::RBF;
params.C = 0.1; //给参数赋初始值
params.gamma = 0.01; //给参数赋初始值
params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);
//对不用的参数step设为0
CvParamGrid p = CvParamGrid(1, 1, 0.0);
CvParamGrid nuGrid = CvParamGrid(1, 1, 0.0);
CvParamGrid coeffGrid = CvParamGrid(1, 1, 0.0);
CvParamGrid degreeGrid = CvParamGrid(1, 1, 0.0);
CvMat traindata2 = traindata, trainlabel2 = trainlabel;
CvMat* traindata3 = cvCreateMat(traindata2.rows, traindata2.cols, traindata2.type);
cvCopy(&traindata2, traindata3);
CvMat* trainlabel3 = cvCreateMat(trainlabel2.rows, trainlabel2.cols, trainlabel2.type);
cvCopy(&trainlabel2, trainlabel3);
SVM.train_auto(traindata3, trainlabel3, NULL, NULL, params, 10, SVM.get_default_grid(CvSVM::C), SVM.get_default_grid(CvSVM::GAMMA), p, nuGrid, coeffGrid, degreeGrid);
CvSVMParams params_re = SVM.get_params();
//SVM.save("auto_training_arguments.xml");
float C = params_re.C;
float gamma = params_re.gamma;
printf("\nBest Parms: P=%f, gamma=%f \n", C, gamma);
///////////////////////////////////
cout << "training done!!!prepare for test..." << endl;
////////////////////////////test
const int numfortest = testdata.rows;
Mat currentsample;
currentsample.create(1, 256*2, testdata.type());
float* outputlabels = new float[numfortest]; //记得delete
for (int i = 0; i < numfortest; i++)
{
float* currentrow = testdata.ptr(i);
for (int j = 0; j < 256*2; j++)
currentsample.at(0, j) = currentrow[j];
float currentoutputs = SVM.predict(currentsample);//必须一个一个样本的进行测试
outputlabels[i] = currentoutputs;
//cout << currentoutputs << endl;
}
cout << "test done!!!prepare for calculating the accurency..." << endl << endl;
/////////////////////////////////////////////////////////////////////////////////calculate whole error
int correct = 0;
float accurency;
for (int i = 0; i < testlabel.rows; ++i)
{
float* p = testlabel.ptr(i);
//cout << "true label= " << p[0] << " output label= " << outputlabels[i] << endl;
if (p[0] == outputlabels[i])
++correct;
}
cout << endl;
accurency = (float)correct / testlabel.rows;
cout << "whole accurency= " << accurency << endl;
/////////calculate the positive sample error and negative sample error
int alluseless = 0, uselesserror = 0, alluseful = 0, usefulerror = 0;
float stoneerror = 0, kuangerror = 0;
//stone error
for (int i = 0; i < testlabel.rows; ++i)
{
float* p = testlabel.ptr(i);
if (p[0] == (float)0)
{
++alluseless;
if (p[0] != outputlabels[i])
++uselesserror;
}
}
cout << "alluseless=" << alluseless << " " << "uselesserror="<< uselesserror << endl;
stoneerror = (float)uselesserror / alluseless;
cout << " stone error= " << stoneerror << endl;
//kuang error
for (int i = 0; i (i);
if (p[0] == (float)1)
{
++alluseful;
if (p[0] != outputlabels[i])
++usefulerror;
}
}
cout << " alluseful=" << alluseful << " " << "usefulerror=" << usefulerror << endl;
kuangerror = (float)usefulerror / alluseful;
cout << " kuang error= " << kuangerror << endl;
////////////////////////////////////////////////////////////////////////
delete[] outputlabels;
tm.stop();
cout << "count=" << tm.getCounter() << ",process time=" << tm.getTimeMilli() << endl;
}
整体是: