我只使用OpenCV大约12个小时左右而且无法解决这个问题。最终目标是拍摄图像并将每个字符存储为6个单独的vector2数组(5个字符+气泡)中的条目
此外,我需要知道角色是否“放大”。
资源链接:https://imgur.com/a/lT5HA
正如你所知,在任何特定时刻都会有大量的事情发生,这使得这个任务变得有些困难。我知道这是可能的,但是 - Robotmon几乎100%准确地识别每个角色 - 唯一的缺点是“放大”的角色被识别3次(丢弃重复的距离因为它们而无法对大的角色起作用)足够大,可以多次注册。)
所有字符都标有单一颜色,同一颜色组中的字符不会出现在同一个匹配项中。
我确定我犯了很多错误 - 我没有在这个用例中找到有关OpenCV的有用信息。一个不错的数量是试验和错误+查看文件内部。
例如,我确信如果我要添加屏幕截图中出现的所有字符,搜索所有字符,然后比较“分数”,我就可以排除一些错误的标识(因为该字符将被准确地声明)。
重述我的问题: 如何识别图像中的每个字符,没有误报(包括“发送”到分数的小字符或逐渐消失的透明字符),所有字符都准确识别,并且单独标识放大的字符? (也许使用OpenCL?)
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core.hpp>
#include <opencv2/features2d.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/xfeatures2d.hpp>
#include <iostream>
#include <stdio.h>
#include <string>
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
int MatchFunction();
int main()
{
MatchFunction();
waitKey(0);
return 0;
}
int MatchFunction()
{
Mat Image_Scene = imread("Bubbles.jpg");
Mat image_Object = imread("block_peterpan_s.png");
// Check for invalid input
if (Image_Scene.empty() || image_Object.empty())
{
cout << "Could not open or find the image" << endl;
return 0;
}
// Initiate ORB detector
Ptr<ORB> detector = ORB::create();
//detector->setMaxFeatures(50);
detector->setScaleFactor(1.1);
detector->setNLevels(12);
//detector->setPatchSize(16);
std::vector<KeyPoint> keypoints_object, keypoints_scene;
Mat descriptors_object, descriptors_scene;
// find the keypoints and descriptors with ORB
detector->detect(image_Object, keypoints_object);
detector->detect(Image_Scene, keypoints_scene);
detector->compute(image_Object, keypoints_object, descriptors_object);
detector->compute(Image_Scene, keypoints_scene, descriptors_scene);
//-- Step 3: Matching descriptor vectors with a brute force matcher
//BFMatcher matcher(NORM_HAMMING, true); //BFMatcher matcher(NORM_L2);
//Ptr<BFMatcher> matcher = BFMatcher::create(); //Ptr<ORB> detector = ORB::create();
Ptr<BFMatcher> matcher = BFMatcher::create(NORM_HAMMING, true);
vector<DMatch> matches;
matcher->match(descriptors_object, descriptors_scene, matches);
//matcher.match(descriptors_object, descriptors_scene, matches);
vector<DMatch> good_matches;
//vector<Point2f> featurePoints1;
//vector<Point2f> featurePoints2;
//Sort the matches by adding them 1 by 1 to good_matches
//for (int i = 0; i<int(matches.size()); i++) { //Size is basically length
// good_matches.push_back(matches[i]);
//}
string k = to_string((matches.size()));
cout << k << endl;
//cout << " Usage: ./SURF_FlannMatcher <img1> <img2>" << std::endl;
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for (int i = 0; i < int(matches.size()); i++)
{
//cout << to_string(i) << endl;
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,
//-- or a small arbitary value ( 0.02 ) in the event that min_dist is very
//-- small)
//-- PS.- radiusMatch can also be used here.
//std::vector< DMatch > good_matches;
for (int i = 0; i < int(matches.size()); i++)
{
if (matches[i].distance <= max(4 * min_dist, 0.02))
{
good_matches.push_back(matches[i]);
}
}
Mat img_matches;
drawMatches(image_Object, keypoints_object, Image_Scene, keypoints_scene,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
imshow("Good Matches", img_matches);
}
答案 0 :(得分:0)
模板匹配将是最天真的方法,但您必须在每个对象的不同比例和旋转下强制使用相同的模板。如果您有关于游戏中此类比例/旋转的可能数量的信息,这将大大缩小迭代次数。
图像似乎没有噪音,失真或遮挡,因此在这种情况下,机器学习方法并不是必需的。如果您想要更高效的东西并熟悉科学语言和实现算法,请看一下使用径向和圆形过滤器来缩小组合数量的研究: http://pdfs.semanticscholar.org/c965/0f78bf9d18eba3850281841dc7ddd20e8d5e.pdf 如果需要,该算法或更具体地说,过滤器可以与OpenCL或任何其他库并行化。在现代机器上,这不应该是必要的,因为串行实现工作得非常快。
我前段时间成功实施了它并且运行良好且速度足以解决您的近实时性能问题。 RGB不是必需的。据我所知,它不是作为开源代码在任何地方实现的,但您也可以尝试查找缩放和旋转不变模板匹配,看看会出现什么。