Я пытаюсь создать программу на C ++, в которой много изображений в списке по сравнению с одним входным изображением. У меня все работает, и программа создает DMatch
Матчи.
Сейчас я пытаюсь определить, какое из списка изображений, которое сравнивается с исходным изображением, является наиболее подходящим. Сначала я попытался сделать это, просто сравнив количество совпадений между изображениями, но проблема заключается в том, что когда сгенерированное изображение имеет много ключевых точек; они также имеют тенденцию иметь много матчей, по крайней мере, в моей программе.
Так как же определить, какой из массивов изображений лучше всего подходит к исходному изображению? Я использую этот цикл для определения совпадений, но на самом деле он не работает:
vector< vector<DMatch> > filteredMatches;
vector<int> goodIds;
Ptr<DescriptorMatcher> matcher(new BFMatcher(NORM_HAMMING, false));
printf("bad matches: ");
for(size_t i = 0; i < images.size();i++){
vector<DMatch> matches, good_matches;
matcher->clear();
matcher->match(images[i], tex_des, matches);
if(matches.size() < 8){
printf("F%d,", (int)i + 1);
continue;
}
double min_dist = 100;
for(size_t j = 0; j < matches.size(); j++ ){
double dist = matches[j].distance;
if( dist < min_dist )
min_dist = dist;
}
if(min_dist > 50.0){
printf("D%d,", (int)i + 1);
continue;
}
double good_dist = min_dist * 3;
for(size_t j = 0; j < matches.size(); j++ ){
if(matches[j].distance < good_dist)
good_matches.push_back(matches[j]);
}
size_t size = good_matches.size();
if(size < 8){
printf("M%d,", (int)i + 1);
continue;
}
vector<Point2f> srcPoints(size);
vector<Point2f> dstPoints(size);
for(size_t j = 0; j < size; j++){
srcPoints[j] = destination[good_matches[j].trainIdx].pt;
dstPoints[j] = keyPoints[i][good_matches[j].queryIdx].pt;
}
vector<unsigned char> inliersMask(srcPoints.size());
Mat H = findHomography(srcPoints, dstPoints, CV_FM_RANSAC, 3.0, inliersMask);
vector<DMatch> inliers;
for(size_t j = 0; j < inliersMask.size(); j++){
if(inliersMask[j]){
inliers.push_back(good_matches[j]);
}
}
if(inliers.size() < 4){
printf("S%d,", (int)i + 1);
continue;
}
filteredMatches.push_back(inliers);
goodIds.push_back((int)i);
H.release();
}
printf(" good matches: ");
int best = -1;
int amount = 0;
for(size_t i = 0; i < filteredMatches.size(); i++){
int size = (int)filteredMatches.at(i).size();
if(size < 8) continue;
printf("%d,", goodIds[i] + 1);
if(amount < size){
amount = size;
best = i;
}
}
if(best >= 0) printf(" best match on image: %d, keypoints: %d, ", goodIds[best] + 1, amount);
Если кто-то может указать мне на функции или логику, которую я должен использовать, я был бы очень признателен!
Нет простого ответа. Для получения лучших результатов вы должны реализовать какое-то преобразование и выполнить кластеризацию на преобразованной карте, а не просто суммировать расстояния. Это сложно и даже опубликованию.
В противном случае вам придется использовать более практичные методы, такие как размерная фильтрация и фильтрация гистограмм. Вы можете взглянуть на OpenCV брошюровщик, изолируйте интересующий вас модуль и настройте исходный код в соответствии с вашими потребностями.
Вы должны выбрать только действительно стабильные соответствия. Я бы порекомендовал прочитать: Руководство по программированию приложений OpenCV 2 Computer Vision — Глава 9. Сопоставление изображений с использованием случайной выборки (http://opencv-cookbook.googlecode.com/svn/trunk/Chapter%2009/).
короткий поиск вашей проблемы предоставил мне следующую запись в разделах ответов opencv:
который, кажется, дает ответ на вопрос, который у вас, кажется, есть. Чтобы отфильтровать результаты, полученные в соответствии с предложением в ответе, я бы взглянул на алгоритм RANSAC, чтобы найти наилучшие результаты при выборе соответствия.
По крайней мере, это должно указать вам правильное направление.
Это зависит от того, какие изображения в списке. У вас не может быть одного решения для каждой проблемы со зрением в мире. Например, проект, над которым я работаю, должен распознавать материал на картинах стен. Вы не можете просто сравнить это с другой картиной стены с другим материалом и надеяться получить совпадение.
В моем случае мне нужно было создать дескрипторы. Дескрипторы являются алгоритмом, выводящим значение, которое можно сравнить с другим значением другого изображения. В openCV уже доступно множество дескрипторов, таких как LBP, SURF и т. Д. Проще говоря, вы больше не сравниваете изображение, вы сравниваете выходное значение дескриптора изображения 1 со значением дескриптора всех изображение в списке.
Вам нужно подобрать дескрипторы, которые ваши глаза / мозг используют, чтобы найти соответствие в реальной жизни. Например, если сопоставление основано на цвете, вы можете использовать CLD или DCD. Если сопоставление основано на текстуре, используйте LBP. Вы также можете делать то же, что и я в своем проекте, использовать множество дескрипторов и использовать машинное обучение с обученными алгоритмами данных, чтобы найти наилучшее соответствие.
Итак, подведем итог, нет серебряной пули, которая может решить все проблемы со зрением. Вы должны адаптировать свое решение к проблеме.
Надеюсь, поможет!