OpenCVにおけるパターンマッチングについて
受付中
回答 2
投稿
- 評価
- クリップ 0
- VIEW 6,039
前提・実現したいこと
現在、OpenCVとC++でDICひずみ計測システム(デジタル画像相関)を作っています。プログラミング初心者です。よろしくお願い致します。
まず、このシステムの原理ですが、変形する対象を画像からその変形量を求めるというものです。
CCDカメラから取り込まれた動画像におきまして、対象の負荷変形前後の画素の小集合(例えば30×30pixel)で比較、パターンマッチングしその小集合がどこに変位したかを画像全体でループ処理することで試験片の変形を計測するというものです。
今、行っているのは全画素に対して順番にアクセスし、アクセスした画素の周りで画素の集合(30×30pixelのサブセット)をテンプレートとしそれを画像全体にマッチング。マッチングが終わるとすぐとなりの画素にアクセスしサブセットを作ってテンプレートマッチング・・・を繰り返す部分です。
発生している問題・エラーメッセージ
実行しますと、途中まではうまく作動しているようですがある段階から(0,0) score=1 がずっと出力されてしまいます。
該当のソースコード
c++
include <iostream>
include <vector>
int main(int argc, char *argv[])
{
cv::Mat src_img = cv::imread("./lenna.png",CV_LOAD_IMAGE_GRAYSCALE);
if (!src_img.data) return -1;
cv::Mat result_img;
for( int y = 0 ; y < src_img.rows ; ++y ){
for( int x = 0 ; x < src_img.cols ; ++x ){
//unsigned char *p = &src_img.at<unsigned char>(y, 0);
cv::Size patch_sie(30, 30); //サブセットのサイズ
cv::Point2f points( x, y);
cv::Mat dst_img;
cv::getRectSubPix(src_img, patch_sie, points, dst_img); // 矩形領域ピクセル値をサブピクセル精度で取得
cv::Mat result_img;
cv::matchTemplate(src_img, dst_img, result_img, CV_TM_CCOEFF_NORMED); // テンプレートマッチング
cv::Rect roi_rect(0, 0, dst_img.cols, dst_img.rows); // 最大のスコアの場所を探す
cv::Point max_pt;
double maxVal;
cv::minMaxLoc(result_img, NULL, &maxVal, NULL, &max_pt);
roi_rect.x = max_pt.x;
roi_rect.y = max_pt.y;
std::cout << "(" << max_pt.x << ", " << max_pt.y << "), score=" << maxVal << std::endl;
// 探索結果の場所に矩形を描画
cv::rectangle(src_img, roi_rect, cv::Scalar(0, 0, 255), 3);
++x;
}
}
cv::namedWindow("search image", CV_WINDOW_AUTOSIZE | CV_WINDOW_FREERATIO);
cv::namedWindow("result image", CV_WINDOW_AUTOSIZE | CV_WINDOW_FREERATIO);
cv::imshow("search image", src_img);
cv::imshow("result image", result_img);
cv::waitKey(0);
}
試したこと
各画素にはポインタでアクセスしますが、画像の端まで行った時にサブセットが画像からはみ出すことになるので不具合が起きているのかなとは思っていますが、何が原因かわかりません。そもそも、この方法でのアプローチが合っているのでしょうか。
長文乱文たいへん失礼いたしました。
よろしくお願いいたします。
補足情報(言語/FW/ツール等のバージョンなど)
c++ VS2015 OpenCV3.1
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
0
内側のloopなんですが:
for( int x = 0 ; x < src_img.cols ; ++x ){
...
++x;
}
となってます。xは+2されちゃいますが、これでいいんですか?
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
こんにちは。
変形前画像はたぶんsrc_imgと思いますが、変形後画像はどれでしょうか?
実行しますと、途中まではうまく作動しているようですがある段階から(0,0) score=1 がずっと出力されてしまいます。
src_imgに矩形を書き込んでますので、それが影響する筈です。
ところで、result_imgが2つ定義されてます。1つ目は使ってないようですので影響はないとは思いますが。
各画素にはポインタでアクセスしますが、画像の端まで行った時にサブセットが画像からはみ出すことになる
はみ出した時、何が起こるか判らない状態であれば、まずははみ出さないようにすることをお薦めします。
画像処理の動作は非常に理解しづらい動作をすることが多いので、混乱する要素はなるべく減らしておいた方が開発期間を短縮できます。低レベル画像処理は急がば回れです。
matchTemplate()関数が返却するresult_imgのサイズを確認しましょう。src_imgより小さいですよ。
ということは、src_imgと座標系が異なります。そのまま使うとうまく行きません。
そもそも、この方法でのアプローチが合っているのでしょうか。
考え方は間違っていないと思います。オプティカル・フローとも呼ばれる考え方の1つです。
しかし、特徴がないサブセットをサーチしてもうまく見つかるとは限りません。というか、普通は特長のない領域についてテンプレートマッチしてもでたらめな場所にマッチします。
ですので、特徴的な場所を抽出してそれがどこへ移動したのか何らかの方法でマッチングするのが一般的です。下記などが参考になると思います。
特徴点の検出と追跡
SIFT SURFを用いた特徴点マッチング
iOS / OpenCV 3.0 で画像の特徴点を検出する(AKAZE, SIFT, SURF, ORB)
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.36%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2016/06/28 15:20
なるほど、文末の ++x; は要らないですね。
意図とずれていました。
また、仮になのですが画素へのアクセスをひとつずつではなく、飛び飛びにすることは可能でしょうか。飛び飛びとは、画素へのアクセス→すぐ一つ隣の画素ではなくサブセット分(30pixel飛ばして)アクセスしていき画像全体を網羅するにはどのようにすればよいでしょうか・・・。
ご教授頂けますと幸いです。
よろしくお願い致します。
2016/06/28 17:19