HOG+SVM坐车辆识别的遇到的wen'ti

i69699 2017-07-26 02:45:57
小弟菜鸟 刚学opencv正在做车辆识别 在做demo的时候遇到了问题
在setSVMDetector(detector);是的时候如果训练的Size()不是64*128就报断言错误 请哪位大神 帮忙解决一下 不胜感激
代码如下:

#include "cv.h"  
#include "cxcore.h"
#include <ml.h>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <opencv2/objdetect.hpp>
#include <opencv2/imgcodecs.hpp>//imread
#include <opencv2\imgproc\imgproc.hpp>//resize
#include <Windows.h>
#include <opencv2\highgui.hpp>//nameWindow
using namespace cv;
using namespace std;
using namespace ml;
void Train()
{
int ImgWidth = 128;
int ImgHeiht = 128;
int sized = ((ImgWidth - 16) / 8 + 1)*((ImgHeiht - 16) / 8 + 1) * 9 * 4;
vector<string> img_path;
vector<int> imageClass;
int nLine = 0;
string buf;
ifstream svm_data("E:\\opencvtran\\fcarp\\bcar.txt");
unsigned long n;
while (svm_data)
{
if (getline(svm_data, buf))
{
nLine++;
if (nLine % 2 == 0)
{
imageClass.push_back(atoi(buf.c_str()));
}
else
{
img_path.push_back(buf);
}
}
}
svm_data.close();//关闭文件
int numberOfSample = nLine / 2; //读入样本数量 ,因为是每隔一行才是图片路径,所以要除以2
//样本矩阵,nImgNum:横坐标是样本数量, WIDTH * HEIGHT:样本特征向量,即图像大小
Mat featureVectorOfSample(numberOfSample, sized, CV_32FC1);

Mat classOfSample(numberOfSample, 1, CV_32SC1);

Mat convertedImage;
Mat trainImage;
//所以上面定义了1764,如果要更改图片大小,可以先用debug查看一下descriptors是多少,然后设定好再运行

//开始搞HOG特征
for (vector<string>::size_type i = 0; i <= img_path.size() - 1; ++i)
{
Mat src = imread(img_path[i],-1);
if (src.empty())
{
cout << " can not load the image: " << img_path[i].c_str() << endl;
continue;
}

cout << " processing " << img_path[i].c_str() << endl;

// 归一化
resize(src, trainImage, Size(ImgWidth, ImgHeiht));
HOGDescriptor hog(cvSize(ImgWidth, ImgHeiht), cvSize(16, 16), cvSize(8, 8), cvSize(8, 8), 9);
double time1 = getTickCount();
vector<float> descriptors;//结果数组
hog.compute(trainImage, descriptors); //调用计算函数开始计算
double time2 = getTickCount();
double elapse_ms = (time2 - time1) * 1000 / getTickFrequency();
cout << "HOG dims: " << descriptors.size() << endl;
cout << "Compute time:" << elapse_ms << endl;

for (vector<float>::size_type j = 0; j <= descriptors.size() - 1; ++j)
{
featureVectorOfSample.at<float>(i, j) = descriptors[j];
//cout << "processing " << j << " " << descriptors.size() << endl;
}

classOfSample.at<int>(i, 0) = imageClass[i];
cout << " end processing " << img_path[i].c_str() << " " << imageClass[i] << endl;
}

Ptr<SVM> svm = SVM::create();
svm->setType(SVM::C_SVC);
svm->setKernel(SVM::LINEAR);
//svm->setC(C);
svm->setTermCriteria(TermCriteria(CV_TERMCRIT_ITER, 1000, FLT_EPSILON));
svm->train(featureVectorOfSample, ROW_SAMPLE, classOfSample);

svm->save(String("E:\\opencvtran\\")+"Classifier.xml");
Mat supportVector = svm->getSupportVectors();//
Mat alpha;//每个支持向量对应的参数α(拉格朗日乘子),默认alpha是float64的
Mat svIndex;//支持向量所在的索引
/*
SVM训练完成后得到的XML文件里面,有一个数组,叫做support vector,还有一个数组,叫做alpha,有一个浮点数,叫做rho;
将alpha矩阵同support vector相乘,注意,alpha*supportVector,将得到一个行向量,将该向量前面乘以-1。之后,再该行向量的最后添加一个元素rho。
如此,变得到了一个分类器,利用该分类器,直接替换opencv中行人检测默认的那个分类器(cv::HOGDescriptor::setSVMDetector()),
*/
float rho = svm->getDecisionFunction(0, alpha, svIndex);
//转换类型:这里一定要注意,需要转换为32的
Mat alpha2;
alpha.convertTo(alpha2, CV_32FC1);
//结果矩阵,两个矩阵相乘
Mat result(1, sized, CV_32FC1);
result = alpha2*supportVector;
//乘以-1,这里为什么会乘以-1?
//注意因为svm.predict使用的是alpha*sv*another-rho,如果为负的话则认为是正样本,在HOG的检测函数中,使用rho+alpha*sv*another(another为-1)
for (int i = 0; i < sized; ++i)
result.at<float>(0, i) *= -1;
//将分类器保存到文件,便于HOG识别
//这个才是真正的判别函数的参数(ω),HOG可以直接使用该参数进行识别
FILE *fp = fopen((String("E:\\opencvtran\\") + "HOG_SVM.txt").c_str(), "wb");
for (int i = 0; i<sized; i++)
{
fprintf(fp, "%f\r\n", result.at<float>(0, i));
}
fprintf(fp, "%f", rho);

fclose(fp);

}
void Detect()
{
Mat img;
FILE* f = 0;
char _filename[1024];
f = fopen((String("E:\\opencvtran\\test\\") + "TestData.txt").c_str(), "rt");
if (!f)
{
fprintf(stderr, "ERROR: the specified file could not be loaded\n");
return;
}
//加载训练好的判别函数的参数(注意,与svm->save保存的分类器不同)
vector<float> detector;
ifstream fileIn(String("E:\\opencvtran\\") + "HOG_SVM.txt", ios::in);
float val = 0.0f;
int i = 0;
while (!fileIn.eof())
{
cout << "processing " << i << endl;
fileIn >> val;
detector.push_back(val);
i++;
}
FILE *fp = fopen((String("E:\\opencvtran\\") + "HOG_SVM1.txt").c_str(), "wb");
for (int i = 0; i<detector.size(); i++)
{
fprintf(fp, "%f\r\n", detector[i]);
}

fclose(fp);
cout << "HOG detector: " << detector.size() << endl;
fileIn.close();
//设置HOG
HOGDescriptor hog;
hog.setSVMDetector(detector);// 使用自己训练的分类器
//hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
//可以直接使用05 CVPR已训练好的分类器,这样就不用Train()这个步骤了
namedWindow("detector", 1);

for (;;)
{
// 读取文件名
char* filename = _filename;
if (f)
{
if (!fgets(filename, (int)sizeof(_filename) - 2, f))
break;
//while(*filename && isspace(*filename))
// ++filename;
if (filename[0] == '#')
continue;

//去掉空格
int l = (int)strlen(filename);
while (l > 0 && isspace(filename[l - 1]))
--l;
filename[l] = '\0';
img = imread(filename);
}
printf("%s:\n", filename);
if (!img.data)
continue;
fflush(stdout);
vector<Rect> found, found_filtered;
double t = (double)getTickCount();
//多尺度检测
hog.detectMultiScale(img, found, 0, Size(8, 8), Size(32, 32), 1.05, 2);
t = (double)getTickCount() - t;
printf("detection time = %gms\n", t*1000. / cv::getTickFrequency());
size_t i, j;
//去掉空间中具有内外包含关系的区域,保留大的
for (i = 0; i < found.size(); i++)
{
Rect r = found[i];
for (j = 0; j < found.size(); j++)
if (j != i && (r & found[j]) == r)
break;
if (j == found.size())
found_filtered.push_back(r);
}
// 适当缩小矩形
for (i = 0; i < found_filtered.size(); i++)
{
Rect r = found_filtered[i];
// the HOG detector returns slightly larger rectangles than the real objects.
// so we slightly shrink the rectangles to get a nicer output.
r.x += cvRound(r.width*0.1);
r.width = cvRound(r.width*0.8);
r.y += cvRound(r.height*0.07);
r.height = cvRound(r.height*0.8);
rectangle(img, r.tl(), r.br(), cv::Scalar(0, 255, 0), 3);
}
imshow("detector", img);
int c = waitKey(0) & 255;
if (c == 'q' || c == 'Q' || !f)
break;

}
if (f)
fclose(f);
return;
}
void HOG_SVM2()
{
//如果使用05 CVPR提供的默认分类器,则不需要Train(),直接使用Detect检测图片
Train();
Detect();
}

int main()
{
//HOG+SVM识别方式1:直接输出类别
//HOG_SVM1();

//HOG+SVM识别方式2:输出图片中的存在目标的矩形
HOG_SVM2();
}
...全文
897 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
i69699 2017-07-28
  • 打赏
  • 举报
回复
都是64*64或者128*128
赵4老师 2017-07-27
  • 打赏
  • 举报
回复
或者你事先将不是64*128的图片都转为64*128的?
赵4老师 2017-07-27
  • 打赏
  • 举报
回复
崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack即“调用堆栈”里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处,看不懂时双击下一行,直到能看懂为止

5,530

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 模式及实现
社区管理员
  • 模式及实现社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧