テンプレート画像 (ロゴ) が 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 エラー: アサーションが失敗しました (type == src2.type() && src1.cols == src2.cols && (type == CV_32F || type == CV_8U))、batchDistance、ファイル /home/das/Downloads/opencv- 2.4.5/modules/core/src/stat.cpp、行 1797 は、'cv::Exception' what() のインスタンスをスローした後に呼び出されて終了します: /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 に適用される変換が何であるかを知っておく必要があると思います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);
}