3

我正在尝试检测 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);
    }
4

1 回答 1

3
  1. 为了消除错误,您可以将图像复制并粘贴到所需大小的空图像中,但这只是断言的一种快速而肮脏的解决方案。
  2. 为了使检测器和描述符正常工作,您可能必须了解它是如何工作的。也许那时您将能够获得可行的图像。看完这篇文章,看来ORB在缩放方面会出现问题(他们在结论部分提到了)。这意味着您将需要找到一种解决方法(如图像金字塔,或在多个比例下检查图像的另一种方法)或使用另一个提取器和描述符,它是比例和旋转不变的。
于 2013-07-04T07:41:57.103 回答