我在Java中使用Opencv 3,我试图在其他图像上找到小图像(如25x25像素)。但FeatureDetector检测(0,0)大小在小图像上匹配。
Mat smallImage = ...
FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
Mat descriptorsSmall = new Mat();
MatOfKeyPoint keyPointsSmall = new MatOfKeyPoint();
detector.detect(smallImage, keyPointsSmall);
descriptor.compute(smallImage, keyPointsSmall, descriptorsSmall);
这里我将keyPointsSmall和descriptorsSmall大小设为零,并确保检测不起作用。
但是,如果我在150x150像素的较大图像上尝试此功能,那就可以了。 有什么建议?谢谢。
让它说我们有P字母的模板,所以我们需要在源图像上检测到这个P.
好吧,将图像缩放到更高的分辨率对我来说不起作用。这将耗费时间和资源。 理想情况下,它应该是旋转尺度不变的。但是没有旋转和缩放的简单解决方案也可以。
除了OpenCv之外的其他解决方案对我来说是不可接受的。 (例如使用Tesseract)
答案 0 :(得分:1)
您似乎尝试阅读PersonalID属性。基本上,人们做的是准备图像,对其进行矢量化(因此其比例和旋转不变)并进行比较/匹配。这可以在OpenCV中完成。
准备工作:通常会降低颜色和亮度。如果您的字母突出,您可以使用阈值(亮度/颜色/ perColorChannel)并删除这些颜色。对于你,你可以减少几乎不是黑色的一切,只是变成白色。您可能希望尝试额外的锐化甚至边缘检测。
矢量化非常简单,可以进一步改进,因为你知道你只对某些符号感兴趣,你应该找到可以用来改善矢量化结果的其他品质(抑制噪音,更好的选择和修正某些边缘/角度等)。
匹配应该非常简单。由于您知道目标字体和潜在符号,因此匹配应产生大量正面结果,并且具有非常小的误差范围。此外,大多数错误都应该易于识别,以便可能存在少量错误,您可以将错误发送给某人进行验证。
潜在的改进:
使用分形方法进行缩放通常可以很好地保留字母和数字的属性,并且可以提高结果的质量。
检测ID的不同部分将帮助您识别检测的目标区域。这使您可以进一步改善结果。通常人们只关注他们想要识别的内容并忘记其他不需要的信息。但是这些信息可以让您了解可能在检测中可能出现的错误。因此,如果您无法正确识别名称,那么您可能也会在ID上失败。因此,如果图片的质量足以确定您真正关心的信息,那么尝试获取ID的所有信息是一个很好的指标。
如果您确切知道目标区域是什么样的,则可以将目标区域缩放到固定大小并使用每像素匹配。由于您确切知道您所关注的字体,因此这种检测可以具有令人惊讶的高检测率。使用每像素匹配和矢量化将为您提供卓越的检测率。与矢量化相比,每像素匹配也非常快。
由于您知道预期符号的位置和大小,因此您可以根据属性(符号的实际大小,某些区域中的黑色分布等)创建决策树。这将把问题从35个中的一个减少到四个中的一个甚至更少。
答案 1 :(得分:1)
文本识别的关键点检测不是最佳解决方案,因为您将获得许多看起来相似的功能,如果模板非常小,滑动窗口将无法产生足够的检测到的功能。
幸运的是,OpenCV 3在contrib存储库中包含一个文本检测/识别模块:link,其中一个示例取自here,还有许多其他人找到here:
/*
* cropped_word_recognition.cpp
*
* A demo program of text recognition in a given cropped word.
* Shows the use of the OCRBeamSearchDecoder class API using the provided default classifier.
*
* Created on: Jul 9, 2015
* Author: Lluis Gomez i Bigorda <lgomez AT cvc.uab.es>
*/
#include "opencv2/text.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::text;
int main(int argc, char* argv[])
{
cout << endl << argv[0] << endl << endl;
cout << "A demo program of Scene Text Character Recognition: " << endl;
cout << "Shows the use of the OCRBeamSearchDecoder::ClassifierCallback class using the Single Layer CNN character classifier described in:" << endl;
cout << "Coates, Adam, et al. \"Text detection and character recognition in scene images with unsupervised feature learning.\" ICDAR 2011." << endl << endl;
Mat image;
if(argc>1)
image = imread(argv[1]);
else
{
cout << " Usage: " << argv[0] << " <input_image>" << endl;
cout << " the input image must contain a single character (e.g. scenetext_char01.jpg)." << endl << endl;
return(0);
}
string vocabulary = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // must have the same order as the clasifier output classes
Ptr<OCRHMMDecoder::ClassifierCallback> ocr = loadOCRHMMClassifierCNN("OCRBeamSearch_CNN_model_data.xml.gz");
double t_r = (double)getTickCount();
vector<int> out_classes;
vector<double> out_confidences;
ocr->eval(image, out_classes, out_confidences);
cout << "OCR output = \"" << vocabulary[out_classes[0]] << "\" with confidence "
<< out_confidences[0] << ". Evaluated in "
<< ((double)getTickCount() - t_r)*1000/getTickFrequency() << " ms." << endl << endl;
return 0;
}
答案 2 :(得分:1)
你可以对图像进行重新采样,它的缩放速度比其开启时快得多,并且只是将每个像素映射到一组像素,直到分辨率达到要求为止, 在opencv中你可以使用resize函数和INTER_AREA标志来做到这一点: http://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html
另一个解决方案是将图像复制到更大的空白图像并在较大的图像上运行检测。