プロが教える店舗&オフィスのセキュリティ対策術

いつもお世話になっております.
OpenCVに関する質問です.
FastFeatureDetectorやGoodFeaturesToTrackDetector等の特徴点検出器を入力画像の特定の部分に対して行うために,入力画像に対してROIを設定したのですが上手くいかない場合があって困っています.

たとえば,
入力画像(640*480)に対して,
左上(0,0)右下(640,480)や左上(0,0)右下(320,240)を矩形領域を指定すれば上手くいくのですが,
左上(10,10)右下(640,480)や左上(320,240)右下(640,480)だと,結果がズレてしまいます.

下記のソースコードで
---------------------------------------------------------------
cv::Rect* roi = new cv::Rect(roi_x, roi_y, roi_w, roi_h);
cv::Mat* InuptImage = new cv::Mat(640, 480, CV_8UC1, data);//dataはbyte型
InuptImage = new cv::Mat(*InuptImage, *roi);
---------------------------------------------------------------
(roi_x, roi_y, roi_w, roi_y)が
(0, 0, 640, 480)や(0, 0, 320, 240)の場合は上手くいくのですが,
(10, 10, 630, 470)や(320, 240, 320, 240)の場合には,特徴点の位置がずれたり,全体的に縮小されたりします.

どこに問題があるのでしょうか?

OpenCVは2.3で,言語はC++です.
アドバイス宜しくお願い致します.

A 回答 (2件)

オフセットは必ず必要です。

ROIを指定する前の画像の全体のサイズと、本来の画像の左上から、ROIの左上の座標のオフセットは、locateROI メソッドで取得することができます。

実際には、オフセットを考慮して点群座標を変換するか、特徴点を描画したい場合などでは、元の画像ではなく ROI で切り取った画像に対して描画を行います。


参考まで。



// okwave01.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include <opencv2/opencv.hpp>

int main(int argc, char argv[])
{
const std::string FILE_PATH("lena.jpg");
//sample.bmpは640*480のRGBの画像

cv::Mat rgb_img = cv::imread(FILE_PATH);
// 画像読み込み

cv::Mat gray_img;
cv::cvtColor(rgb_img, gray_img, CV_BGR2GRAY);
// グレースケール画像に変換

const cv::Point ROI_TL(rgb_img.rows * 0.25, rgb_img.cols * 0.25);
const cv::Rect RECT(
rgb_img.rows * 0.25, rgb_img.cols * 0.25,
rgb_img.rows * 0.5, rgb_img.cols * 0.5);
// 中心 だけを切り取る ROI を作成。

cv::Mat rgbimage_roi = rgb_img(RECT);
cv::Mat grayimage_roi = gray_img(RECT);
// ROI による切り取り。


std::vector<cv::KeyPoint> corners;
// FAST 頂点座標の保存用変数

cv::FAST(grayimage_roi, corners, 10, true);

for (auto it = corners.begin(); it != corners.end(); ++it) {
cv::circle(grayimage_roi, it->pt, 1, cv::Scalar(255), 2);
// ROI を通してグレイスケール画像に書き込む

cv::circle(rgb_img, ROI_TL + cv::Point2i(it->pt), 1, cv::Scalar(0, 0xff, 0), 2);
// オフセットを考慮して直接RGB画像に書き込む
}

cv::imshow("RGB IMAGE", rgb_img);
cv::imshow("GRAY IMAGE", gray_img);
return cv::waitKey();
}
「OpenCV でのROIの指定方法につい」の回答画像2
    • good
    • 0
この回答へのお礼

回答ありがとうございます.
おかげさまで目標を達成することが出来ました.
原因はオフセットを考慮していないことでした.

また,OpenCVを初めて間もないので,ソースコードも非常に参考になりました.

適切なアドバイスをしていただき,有難うございました.

お礼日時:2012/01/20 17:57

1) ROI の指定方法が異なります.ROI付きの cv::Mat は,まず画像全体を参照する cv::Mat 型の変数を作った後に,その一部を参照する cv::Mat 型変数として作成します.以下のコードの3行目です.



2) OpenCV は,内部リソース管理がなされている,通常ポインタを通しては使いません.

以上を踏まえて,今回の例で行くと

cv::Rect roi(roi_x, roi_y, roi_w, roi_y);
cv::Mat inputimage(640, 480, CV_8UC1, 0);//dataはbyte型
cv::Mat inputimage_roi = inputimage(roi);

でいけるはずです.お試し下さい.

この回答への補足

補足します.
下記のコードを書きましたが上手くいきません.
もしかして,出力された座標値にオフセットが必要でしょうか?

std::string FilePath("sample.bmp");//sample.bmpは640*480のRGBの画像

const char *imagename = FilePath.c_str();

cv::Mat rgb_img = cv::imread(imagename);

cv::Mat gray_img;

cv::cvtColor(rgb_img, gray_img, CV_BGR2GRAY);

cv::Rect mask(320, 240,320, 240);

cv::Mat InuptImage_roi_cv= gray_img(mask);

std::vector<cv::KeyPoint> corners;

cv::FAST(InuptImage_roi_cv, corners, 50, true);

補足日時:2012/01/20 11:05
    • good
    • 0
この回答へのお礼

回答ありがとうございます.

試してみたのですが,上手くいきません.
cv::Rect roi(320, 240, 320, 240);
cv::Mat inputimage(640, 480, CV_8UC1, data);//dataはbyte*型
cv::Mat inputimage_roi = inputimage(roi);

であっていますでしょうか?

また,同じ画像の複数の領域に対して特徴点検出を実行したい場合,ROIを複数個所に設定できるでしょうか?
それとも,そんなことは普通はしませんか?

アドバイス宜しくお願い致します.

お礼日時:2012/01/20 10:51

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!