我正在尝试检测 pdf 文档中是否存在模板图像(徽标)。该文档可以是封装在 pdf 中的扫描件,也可以是“纯”pdf 文档,但这完全是随机的。
首先,我使用 ImageMagick 的转换工具将 pdf 文档转换为 png 图像,然后将输出图像切成两半,因为它们太大了,然后我尝试将数据库中的徽标与存在的任何形状进行匹配半切图像。
为此,我使用了一个带有 Orb Descriptor 的 Orb Feature Detector 和一个 RobustMatcher(一种改进的 BruteForce 匹配器,源代码可在此处获得)。这是我改编的一段代码:
// Read input images
Mat image1 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
Mat image2 = imread(argv[2], CV_LOAD_IMAGE_GRAYSCALE);
if (!image1.data || !image2.data) {
std::cout << " --(!) Error reading images " << std::endl;
exit(1);
}
// Setting up values for ORB Detector
int nfeatures = 800;
//float scaleFactor = 1.10;
int nlevels = 8;
int edgeThreshold = 12;
int firstLevel = 0;
int WTA_K = 2;
int scoreType = 0;
int patchSize = 31;
// Prepare the matcher
RobustMatcher rmatcher;
rmatcher.setConfidenceLevel(0.98);
rmatcher.setMinDistanceToEpipolar(1.0);
rmatcher.setRatio(0.80f);
cv::Ptr<cv::FeatureDetector> pfd = new cv::OrbFeatureDetector(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize);
rmatcher.setFeatureDetector(pfd);
cv::Ptr<cv::DescriptorExtractor> pde = new cv::OrbDescriptorExtractor();
rmatcher.setDescriptorExtractor(pde);
// Match the two images
std::vector<cv::DMatch> matches;
std::vector<cv::KeyPoint> keypoints1, keypoints2;
cv::Mat fundemental = rmatcher.match(image1, image2, matches, keypoints1, keypoints2);
// If nothing could be matched, stop here
if(matches.size() < 4){
exit(2);
}
该代码适用于我仔细选择的一些示例,具有高度可识别的徽标和干净的图像,具有一定的比例......等等。但是当我尝试将该过程应用于随机 pdf 文件时,我开始收到此错误来自 OpenCV:
OpenCV 错误:batchDistance,文件 /home/das/Downloads/opencv- 中的断言失败 (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U)) 2.4.5/modules/core/src/stat.cpp,第 1797 行终止在抛出“cv::Exception”实例后调用什么():/home/das/Downloads/opencv-2.4.5/modules/core/ src/stat.cpp:1797: 错误: (-215) type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U) in function batchDistance
中止(核心转储)
我检查了这个错误,发现 src1.cols != src2.cols,一个快速的解决方法是在尝试匹配图像之前测试条件。问题是我这样做会错过很多图像,只有在我处理视频流时才可以这样做……但我不是,下一张图像与前一张没有任何共同之处,并且我无法确定我的徽标是否出现在文档中。
这是 stat.cpp 中的代码,第 1789 到 1826 行:(断言在第 1797 行的开头)
void cv::batchDistance( InputArray _src1, InputArray _src2,
OutputArray _dist, int dtype, OutputArray _nidx,
int normType, int K, InputArray _mask,
int update, bool crosscheck )
{
Mat src1 = _src1.getMat(), src2 = _src2.getMat(), mask = _mask.getMat();
int type = src1.type();
CV_Assert( type == src2.type() && src1.cols == src2.cols &&
(type == CV_32F || type == CV_8U));
CV_Assert( _nidx.needed() == (K > 0) );
if( dtype == -1 )
{
dtype = normType == NORM_HAMMING || normType == NORM_HAMMING2 ? CV_32S : CV_32F;
}
CV_Assert( (type == CV_8U && dtype == CV_32S) || dtype == CV_32F);
K = std::min(K, src2.rows);
_dist.create(src1.rows, (K > 0 ? K : src2.rows), dtype);
Mat dist = _dist.getMat(), nidx;
if( _nidx.needed() )
{
_nidx.create(dist.size(), CV_32S);
nidx = _nidx.getMat();
}
if( update == 0 && K > 0 )
{
dist = Scalar::all(dtype == CV_32S ? (double)INT_MAX : (double)FLT_MAX);
nidx = Scalar::all(-1);
}
if( crosscheck )
{
CV_Assert( K == 1 && update == 0 && mask.empty() );
Mat tdist, tidx;
batchDistance(src2, src1, tdist, dtype, tidx, normType, K, mask, 0, false);
所以我想知道这个断言是什么意思?stat.cpp 中的 src1 和 src2 文件到底是什么?为什么它们需要具有相同数量的列?
我尝试更换为 Surf 检测器和提取器,但仍然出现错误。
如果有人有想法,请不要犹豫,我欢迎任何建议或通知!
提前致谢。
编辑
我现在有一个更准确的问题:我如何确保这一点src1.cols == src2.cols
?为了回答这个问题,我想我应该知道在调用 batchDistance(...) 之前应用于我的 cv::Mat image1 和 image2 的转换是什么,以便在 image1 和 image2 上找到一个可以确保的条件src1.cols == src2.cols
,所以我的代码看起来像这样:
// Match the two images
std::vector<cv::DMatch> matches;
std::vector<cv::KeyPoint> keypoints1, keypoints2;
if( CONDITION_ON_IMAGE1&IMAGE2_TO_ENSURE_SRC1.COLS==SRC2.COLS ){
cv::Mat fundemental = rmatcher.match(image1, image2, matches, keypoints1, keypoints2);
}