EDIT: я получил достаточную репутацию благодаря этому сообщению, чтобы иметь возможность редактировать его с помощью дополнительных ссылок, что поможет мне лучше понять
Люди, играющие в привязку isaac, часто сталкиваются с важными предметами на маленьких пьедесталах.
Цель состоит в том, чтобы пользователь путался о том, что элемент может нажимать на кнопку, которая затем предложит ему "вставить" элемент (подумайте о боксе на рабочем столе Windows). Коробка дает нам интересующую область (фактический элемент плюс некоторая фоновая среда) для сравнения с тем, что будет всей сеткой элементов.
Теоретический пользовательский бокс
Теоретическая сетка элементов (там не так много, я просто разорвал это из привязки isaac wiki)
Расположение в сетке элементов, идентифицированных как элемент, который пользовательский бокс представлял бы определенную область на изображении, которая коррелирует с соответствующей ссылкой на привязку wiki wiki, дающей информацию об элементе.
В сетке элемент - 1-й столбец 3-й из нижней строки. Я использую эти два изображения во всех вещах, которые я пробовал ниже.
Моя цель - создать программу, которая может взять ручную обрезку предмета из игры "Связывание Исаака", идентифицировать обрезанный предмет, находя сравнение изображения с изображением таблицы предметов в игре, затем отобразите соответствующую страницу вики.
Это будет мой первый "реальный проект" в том смысле, что он требует огромного количества обучения в библиотеке, чтобы получить то, что я хочу сделать. Это было немного подавляющим.
Я испортил несколько вариантов, просто из-за googling. (вы можете быстро найти учебники, которые я использовал при поиске имени метода и opencv. Моя учетная запись сильно ограничена проводкой ссылок по какой-либо причине)
используя bruteforcematcher:
http://docs.opencv.org/doc/tutorials/features2d/feature_description/feature_description.html
#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include <opencv2/legacy/legacy.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
void readme();
/** @function main */
int main( int argc, char** argv )
{
if( argc != 3 )
{ return -1; }
Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
if( !img_1.data || !img_2.data )
{ return -1; }
//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 400;
SurfFeatureDetector detector( minHessian );
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector.detect( img_1, keypoints_1 );
detector.detect( img_2, keypoints_2 );
//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat descriptors_1, descriptors_2;
extractor.compute( img_1, keypoints_1, descriptors_1 );
extractor.compute( img_2, keypoints_2, descriptors_2 );
//-- Step 3: Matching descriptor vectors with a brute force matcher
BruteForceMatcher< L2<float> > matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );
//-- Draw matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2, matches, img_matches );
//-- Show detected matches
imshow("Matches", img_matches );
waitKey(0);
return 0;
}
/** @function readme */
void readme()
{ std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl; }
приводит к не очень полезному виду. Более чистые, но одинаково ненадежные результаты с использованием flann.
http://docs.opencv.org/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.html
#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include <opencv2/legacy/legacy.hpp>
#include <opencv2/nonfree/features2d.hpp>
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
void readme();
/** @function main */
int main( int argc, char** argv )
{
if( argc != 3 )
{ readme(); return -1; }
Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );
if( !img_1.data || !img_2.data )
{ std::cout<< " --(!) Error reading images " << std::endl; return -1; }
//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 400;
SurfFeatureDetector detector( minHessian );
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector.detect( img_1, keypoints_1 );
detector.detect( img_2, keypoints_2 );
//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat descriptors_1, descriptors_2;
extractor.compute( img_1, keypoints_1, descriptors_1 );
extractor.compute( img_2, keypoints_2, descriptors_2 );
//-- Step 3: Matching descriptor vectors using FLANN matcher
FlannBasedMatcher matcher;
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_1.rows; i++ )
{ double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
printf("-- Max dist : %f \n", max_dist );
printf("-- Min dist : %f \n", min_dist );
//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist )
//-- PS.- radiusMatch can also be used here.
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptors_1.rows; i++ )
{ if( matches[i].distance < 2*min_dist )
{ good_matches.push_back( matches[i]); }
}
//-- Draw only "good" matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//-- Show detected matches
imshow( "Good Matches", img_matches );
for( int i = 0; i < good_matches.size(); i++ )
{ printf( "-- Good Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); }
waitKey(0);
return 0;
}
/** @function readme */
void readme()
{ std::cout << " Usage: ./SURF_FlannMatcher <img1> <img2>" << std::endl; }
templatematching был моим лучшим методом. из 6 методов он колеблется от получения только 0-4 правильных идентификаций, хотя.
http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
/// Global Variables
Mat img; Mat templ; Mat result;
char* image_window = "Source Image";
char* result_window = "Result window";
int match_method;
int max_Trackbar = 5;
/// Function Headers
void MatchingMethod( int, void* );
/** @function main */
int main( int argc, char** argv )
{
/// Load image and template
img = imread( argv[1], 1 );
templ = imread( argv[2], 1 );
/// Create windows
namedWindow( image_window, CV_WINDOW_AUTOSIZE );
namedWindow( result_window, CV_WINDOW_AUTOSIZE );
/// Create Trackbar
char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );
MatchingMethod( 0, 0 );
waitKey(0);
return 0;
}
/**
* @function MatchingMethod
* @brief Trackbar callback
*/
void MatchingMethod( int, void* )
{
/// Source image to display
Mat img_display;
img.copyTo( img_display );
/// Create the result matrix
int result_cols = img.cols - templ.cols + 1;
int result_rows = img.rows - templ.rows + 1;
result.create( result_cols, result_rows, CV_32FC1 );
/// Do the Matching and Normalize
matchTemplate( img, templ, result, match_method );
normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
/// Localizing the best match with minMaxLoc
double minVal; double maxVal; Point minLoc; Point maxLoc;
Point matchLoc;
minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
{ matchLoc = minLoc; }
else
{ matchLoc = maxLoc; }
/// Show me what you got
rectangle( img_display, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
rectangle( result, matchLoc, Point( matchLoc.x + templ.cols , matchLoc.y + templ.rows ), Scalar::all(0), 2, 8, 0 );
imshow( image_window, img_display );
imshow( result_window, result );
return;
}
http://imgur.com/pIRBPQM,h0wkqer,1JG0QY0,haLJzRF,CmrlTeL,DZuW73V#3
из 6 потерпеть неудачу, пройти, не в состоянии, проходят, проходят, проходят
Однако это был лучший результат. Следующий пункт, который я пробовал, был
и привели к сбою, сбою, сбоям, сбоям, сбоям, сбоям
От элемента к элементу все эти методы имеют некоторые из них, которые хорошо работают, а некоторые, которые действительно ужасно
Итак, я спрошу: templatematching мой лучший выбор или есть метод, который я не рассматриваю, что будет моим святым Граалем?
Как я могу получить ПОЛЬЗОВАТЕЛЯ для создания обрезки вручную? Документация Opencv на этом очень плохой, и примеры, которые я нахожу в Интернете, - это очень старые cpp или прямые C.
Спасибо за любую помощь. До сих пор это предприятие было интересным. Мне пришлось снять все ссылки, которые лучше отображали бы, как все работает, но сайт говорит, что я публикую более 10 ссылок, даже если это не так.
еще несколько примеров предметов на протяжении всей игры:
камень - редкий предмет и один из немногих, который может быть "в любом месте" на экране. такие предметы, как камень, являются причиной того, что обрезка предмета пользователем является наилучшим способом изолирования предмета, в противном случае их позиции находятся только в нескольких конкретных местах.
Предмет после боя босса, множество вещей повсюду и прозрачность посередине. Я бы предположил, что это один из самых трудных для правильной работы.
Редкая комната. простой фон. нет прозрачности элемента.
<Т411 >
вот две таблицы, все элементы в игре:.. Я сделаю им одно изображение в конце концов, но пока они были непосредственно взяты из вики файла isaac.