SVM + HOG,发现的对象总是NULL
SVM + HOG, found object is always NULL
我的工作是真菌孢子检测。我有大约359张正面图像(真菌颗粒的裁剪图像)和171张负面图像(灰尘颗粒的裁剪图像)。
pos/nag图像的实际大小与粒子大小相同,约为8x8,但对于SVM训练,我将其调整为30x30,然后使用调整大小的图像来训练SVM分类器。我直接用不带任何特征的图像训练SVM。
在成功训练分类器后,我使用了hog.setSVMDetector(myclassifier)和hog.detectMultiScale,但发现的对象为零。
现在我的问题是我在我的代码做错了什么?请点击下面的链接查看我用于SVM分类器的阴性/阳性图像,测试图像和所需粒子图像。
https://drive.google.com/folderview?id=0B7yRjtOGywg7fnNJTXcxR2NYb3ItWTZ0UjYwUmt6YW96R0NHLWZQbVJucEk0bnJmcFJGS0E& usp =分享
class LinearSVM: public CvSVM {
public:
void getSupportVector(std::vector<float>& support_vector) const;
};
void LinearSVM::getSupportVector(std::vector<float>& support_vector) const {
int sv_count = this->get_support_vector_count();
// mexPrintf("size : %dn",support_vector.size());
const CvSVMDecisionFunc* df = this->decision_func;
const double* alphas = df[0].alpha;
double rho = df[0].rho;
int var_count = this->get_var_count();
support_vector.resize(var_count, 0);
for (unsigned int r = 0; r < (unsigned)sv_count; r++) {
float myalpha = alphas[r];
const float* v = this->get_support_vector(r);
for (int j = 0; j < var_count; j++,v++) {
support_vector[j] += (-myalpha) * (*v);
}
}
support_vector.push_back(rho);
}
////////////////////////////// main.cpp ///////////////////////////
int num_files = 359*171;
int img_area = 30*30;
Mat training_mat(num_files,img_area,CV_32FC1);
vector<int> training_Labels;
Mat labels(num_files,1,CV_32FC1);
int imagenum=0;
for (int pimageNum = 0; pimageNum < 359; pimageNum++)
{
// reading Positive Images from directory and resize it to 30x30
int ii = 0; // Current column in training_mat
for (int i = 0; i<posImage.rows; i++) {
for (int j = 0; j < posImage.cols; j++) {
training_mat.at<float>(imagenum,ii++) = posImage.at<uchar>(i,j);
imagenum++;
}
}
training_Labels.push_back(1.0);
}
for (int nimageNum = 0; nimageNum < 171; nimageNum++)
{
// reading Nagative Images from directory and resize it to 30x30
int ii = 0; // Current column in training_mat
for (int i = 0; i<nagImage.rows; i++) {
for (int j = 0; j < nagImage.cols; j++) {
training_mat.at<float>(imagenum,ii++) = nagImage.at<uchar>(i,j);
imagenum++;
}
}
training_Labels.push_back(-1.0);
}
Mat(training_Labels).copyTo(labels);
labels.convertTo(labels, CV_32FC1);
CvSVMParams SVM_params;
SVM_params.svm_type = CvSVM::C_SVC;
SVM_params.kernel_type = CvSVM::LINEAR; //CvSVM::LINEAR;
SVM_params.degree = 0;
SVM_params.gamma = 3;
SVM_params.coef0 = 0;
SVM_params.C = 1;
SVM_params.nu = 0;
SVM_params.p = 0;
SVM_params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 10, 0.03);
//Train SVM
LinearSVM svmClassifier;
svmClassifier.train(training_mat, labels, Mat(), Mat(), SVM_params);
svmClassifier.save("D:\svmClassifier.yml");
HOGDescriptor hog;
hog.winSize = Size(8, 8);
std::vector<float> support_vector;
FileStorage fs;
fs.open("D:\svmClassifier.yml", FileStorage::READ);
fs["support_vectors"] >> support_vector;
hog.setSVMDetector(support_vector);
vector< Rect> found,found_filtered;
Size padding(Size(0, 0));
Size winStride(Size(8, 8));
cv::Mat test=cv::imread("testimage.bmp",CV_LOAD_IMAGE_GRAYSCALE);
// actual size of test image is 1024x768 which I resize to 400x 300
hog.detectMultiScale(test, found, 0.0, winStride, padding, 1.01, 0);
cout<<""found particles"<< found.size() ; // it is always zero
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];
r.x += cvRound(r.width*0.1);
r.width = cvRound(r.width*0.8);
r.y += cvRound(r.height*0.06);
r.height = cvRound(r.height*0.9);
rectangle(test, r.tl(), r.br(), cv::Scalar(0,255,0), 2);
}
imshow("detected particles", test);
waitKey(0);
我还没有设法让你的分类器工作,但我已经找到了你当前问题的原因。
我在这里放了一个要点,你可以看看。我已经使用了我自己的文件读取方法来读取图像,所以你必须做一两个更改,以便它为你工作。
没有找到对象的原因是你的分类器向量是空的。该是由于错误地读取了yml文件中的节点。'support_vectors'是'my_svm'的子节点。你试图读取它作为一个顶级节点,并得到一个空向量。
在我已经修复的文件读取循环中还有其他一些错误(标记为FIXED
) -至少,它们对我来说似乎是不正确的。
这仍然不能正确分类。支持向量数组的格式有一些问题,它破坏了hog描述符。
因此,您需要在这方面投入更多的工作,但希望这将使您朝着正确的方向前进。
我在输出窗口中添加了一个滑块。当您让分类器工作时,您可以使用滑块更改scaleFactor,这将在结果中产生有趣的变化。
- Box2D World.GetBodyList() 返回 NULL,但 World 显然正在更新对象
- 正在将对象指针数组初始化为NULL
- 从模板化函数返回Null对象
- 在构造函数处将类对象强制转换为接口始终返回 NULL
- 在访问类的树层次结构中的对象时避免使用 null 指针
- 返回对象或 NULL 值的方法
- 删除对象与将指针设置为 null
- 为什么即使我们将指针分配给 NULL,指针的指向对象的大小也不为零
- 类返回对象类型,但如何返回和检查 null
- 一旦对象设置为 null,用于声明对象的堆大小的变量就设置为 null?
- 无法使用指针查找正确的元素 - 从函数返回时,对象上的 poiting 为 null
- 将对象作为 null 返回内容
- 将对象的数组设置为c 中的null
- 当通过其中一个指针删除对象时,C++将所有指针设置为null
- 将 NULL 作为对象返回时未收到任何警告
- 如何将对象的实例分配给为null的指针
- 对象向量中的空对象与指针向量中的NULL/nullptr
- 为什么我的C++程序在使用 NULL 对象时静默退出
- C++:无法通过传递给查找器函数来重新分配 null 初始化的对象指针
- 在 C# 等C++中设置对象 = null 的替代方案是什么