gpt4 book ai didi

c++ - SVM + HOG,发现对象总是NULL

转载 作者:太空宇宙 更新时间:2023-11-03 22:55:20 25 4
gpt4 key购买 nike

我正在研究真菌孢子检测。我有大约 359 张正图像(真菌颗粒的裁剪图像)和 171 张负图像(灰尘颗粒的裁剪图像)。

pos/nag 图像的实际大小与粒子大小相同,约为 8x8,但对于 SVM 训练,我已将其调整为 30x30,然后使用调整后的图像来训练 SVM 分类器。我直接用没有任何特征的图像训练 SVM。

成功训练分类器后,我使用了 hog.setSVMDetector(myclassifier) 和 hog.detectMultiScale,但找到的对象为零。

现在我的问题是我的代码哪里做错了?请单击下面的链接以获取我用于 SVM 分类器的负/正图像、测试图像和所需的粒子图像。

https://drive.google.com/folderview?id=0B7yRjtOGywg7fnNJTXcxR2NYb3ItWTZ0UjYwUmt6YW96R0NHLWZQbVJucEk0bnJmcFJGS0E&usp=sharing

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 : %d\n",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);

最佳答案

我没能让你的分类器正常工作,但我找到了你当前问题的原因。

我提出了一个要点 here所以你可以检查一下。我使用自己的文件读取方法读取图像,因此您必须进行一两处更改才能使其适用。

找不到对象的原因是你的分类器 vector 是空的。 是由于从 yml 文件中错误地读取了节点。 “support_vectors”是“my_svm”的子节点。您试图将其作为顶级节点读取,并返回一个空 vector 。

在我修复的文件读取循环中还有一些其他错误(标记为 FIXED)- 至少,它们对我来说似乎是不正确的。

这仍然不能正确分类(还)。支持 vector 数组的格式存在一些问题,这会破坏 hog 描述符。

因此您需要为此付出更多努力,但希望这能让您朝着正确的方向前进。

我在输出窗口中添加了一个 slider 。当您让分类器开始工作时,您可以使用 slider 更改 scaleFactor,这应该会在结果中产生有趣的变化。

关于c++ - SVM + HOG,发现对象总是NULL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31706560/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com