Мне нужно сформировать HOGDescriptor::setSVMDetector()
вход.
Я вычисляю дескрипторы с openCV, затем использую libSVM, чтобы получить файл модели.
Для формирования ввода я знаю, что мне нужно получить значения векторов поддержки и поэлементно смешать их с альфа-каналом (затем добавить -rho в конце), но я не понимаю, где взять эти альфы.
У меня есть список SV, как:
1 1:-0.0434783 2:0.153846 3:0.194444 4:-0.353712 5:-0.45054
1 1:-0.2173916 2:-0.38461 3:0.222262 4:-0.676686 5:-0.78062
а где взять альфы?
Но почему вы хотите классифицировать это «от руки»? OpenCV имеет процедуру классификации называется predict
, который использует найденные SV ‘и альфы’
float response = SVM.predict(sampleMat);
Если вы действительно хотите сделать это самостоятельно, вам понадобятся не только SV и альфы, но и функция ядра, используемая для обучения и вычислений.
SUM alpha_i K( support_vector_i , data_point ) - rho
Я не уверен, возможно ли извлечь альфы «вручную», не расширяя класс SVM, как можно увидеть в источники — Альфы хранятся в CvSVMDecisionFunc
состав:
struct CvSVMDecisionFunc
{
double rho;
int sv_count;
double* alpha;
int* sv_index;
};
в то время как единственная ссылка на эту структуру находится в protected
раздел:
protected:
(...)
CvSVMDecisionFunc* decision_func;
Из исходного кода svm.cpp
мы можем найти, что это только публично доступно через save
рутина. Таким образом, «взломать» можно было бы сохранить модель и извлечь из нее альфы (она будет расположена в разделе «Функция принятия решения», написанном в удобочитаемом формате).
Самая простая техника извлечения, кажется, расширяет CvSVM
класс и включить метод, как
public:
CvSVMDecisionFunc* get_decision_function() { return decision_func; }
после выяснения, что OP на самом деле пытается использовать внешне обученную модель в opencv — самый простой способ — преобразовать модель libsvm, созданную другим методом (libsvm, linearsvm и т. д.), в формат, совместимый с opencv, и загрузить его, используя read
метод
void CvSVM::read( CvFileStorage* fs, CvFileNode* svm_node )
Хорошо, кажется, теперь все ясно.
Альфы — первый столбец в моем случае.
Поскольку в моей тестовой модели все они были равны -1 или 1 (не знаю почему), я подумал, что это были ярлыки.
В любом случае, вот мой парсер (но вам нужно оставить только SV в файле):
std::ifstream ifs("cars_model.model");
const int nsv = 90;
const int nfeatures = 144;
float rho = 12.5459;
char ts[4000] = ""; // !
std::vector<float> res(nfeatures,0);
std::vector<float> alphas;
Mat_<float> temp(nsv, nfeatures);
int c = 0;
std::cout << "Loading model file...\n";
for (int i=0; i<nsv; i++) {
float al = 0;
ifs >> al;
alphas.push_back(al);
for (int j=0; j<nfeatures; j++) {
float ind, s;
char junk;
ifs >> ind >> junk >> s;
temp.at<float>(c, j) = s;
//std::cout << f << ' ' << s << '\n';
}
c++;
}
ifs.close();
std::cout << "Computing primal form...\n";
for (int i=0; i<nsv; i++) {
float alpha = alphas[i];
for (int j=0; j<nfeatures; j++) {
res[j] += (temp.at<float>(i,j) * alpha);
}
}
//res.push_back(-rho);
std::ofstream ofs("primal.txt");
for (int i=0; i<res.size(); i++)
ofs << res[i] << ' ';
ofs.close();
И вы знаете, это работает. Вы можете установить rho в качестве порога детектора.