OpenCVでCvMatを切り抜くには?

私は CVMat 行列 CVMat source で画像を変換しています。 source から関心領域を取得したら、残りのアルゴリズムをその関心領域にのみ適用します。そのためには、私が何とか source の行列を切り取らなければならないと思います。 CvMat 行列をトリミングし、別の切り捨てられた CvMat 行列を返すメソッドまたは関数がありますか?ありがとう。

43
プレ2.0 cスタイルまたはポスト2.0 c ++スタイルでそれをしたいですか?あなたの答えに応じてあなたの質問に再度タグを付けてください
追加された 著者 Boaz,

6 答え

OpenCVには、役に立つと思われる関心領域機能があります。 cv :: Mat を使用している場合は、次のようなものを使用できます。

// You mention that you start with a CVMat* imagesource
CVMat * imagesource;

// Transform it into the C++ cv::Mat format
cv::Mat image(imagesource); 

// Setup a rectangle to define your region of interest
cv::Rect myROI(10, 10, 100, 100);

// Crop the full image to that image contained by the rectangle myROI
// Note that this doesn't copy the data
cv::Mat croppedImage = image(myROI);

サブ画像を抽出するためのドキュメント

90
追加された
関心のある矩形領域の代わりに楕円領域が必要な場合はどうすればよいですか?
追加された 著者 Sohaib,
これはデータをコピーしないという意味ですか?
追加された 著者 Jameo,
つまり、コピーではなくそのイメージ領域への参照のみを作成します。つまり、croppedImageを変更すると、画像ソースも変更されます。この動作が望ましくない場合は、明示的にコピーを作成できます。
追加された 著者 Rui Marques,
元の行列が破壊されたらどうなるでしょうか?深いコピーは必要ありませんか?
追加された 著者 Vlad,
ちょっと私は疑問がある、私のイメージは、サイズ(3264 * 2448)のです。私は点をプロットすることができます。しかし、ポイントxまたはyはデバイス座標(例えば2400,1864など)ではありません。 cv ::デバイス座標をポイントする
追加された 著者 Mukesh,
@Sohaib次に、私たちが "マスク"と呼ぶものを使う必要があります。これは通常、処理関数の余分なパラメータとして利用できます。
追加された 著者 Samuel Audet,
ありがとう、それはうまくいきます。
追加された 著者 Dragan Ostojić,
cv :: Rectのパラメータが何であるかを明確にすることができますか?私がx、y、幅、高さを見つけたものから。あれは正しいですか?
追加された 著者 Björn Larsson,

私はこの問題が既に解決されていることを知っています。しかし、簡単に作物を作れる方法があります。あなたはただ1つの行でそれを行うことができます -

Mat cropedImage = fullImage(Rect(X,Y,Width,Height));
34
追加された
どこから fullImage()関数を取得できますか?編集:心配しないで、それは cv :: Mat 画像そのものです...
追加された 著者 mozzbozz,

異なるタイプの行列に対してより良い結果と堅牢性を得るには、データをコピーする最初の答えに加えてこれを行うことができます。

cv::Mat source = getYourSource();

// Setup a rectangle to define your region of interest
cv::Rect myROI(10, 10, 100, 100);

// Crop the full image to that image contained by the rectangle myROI
// Note that this doesn't copy the data
cv::Mat croppedRef(source, myROI);

cv::Mat cropped;
// Copy the data into new matrix
croppedRef.copyTo(cropped);
16
追加された

私たちが望む作物のコピーを作成するには、以下を行うことができます。

// Read img
cv::Mat img = cv::imread("imgFileName");
cv::Mat croppedImg;

// This line picks out the rectangle from the image
// and copies to a new Mat
img(cv::Rect(xMin,yMin,xMax-xMin,yMax-yMin)).copyTo(croppedImg);

// Display diff
cv::imshow( "Original Image",  img );
cv::imshow( "Cropped Image",  croppedImg);
cv::waitKey();
2
追加された
入力ミスが修正されました。私はそれが1行ですべてを行うという意味でそれが追加されると思います。この場合のクローンまたはcopyToについては、私はそれがちょうど好きなものだと思う。
追加された 著者 Reed Richards,
これにより、すでに提供されている回答には何も追加されません。また、セミコロンがありませんし、変数名も正しくありません。ところで、 Mat crop = img(Rect(...)).clone()でこれを行うことができます。
追加された 著者 Miki,

あなたはopencv関数を使ってMatを簡単に切り抜くことができます。

setMouseCallback("Original",mouse_call);

mouse_call は次のとおりです。

 void mouse_call(int event,int x,int y,int,void*)
    {
        if(event==EVENT_LBUTTONDOWN)
        {
            leftDown=true;
            cor1.x=x;
            cor1.y=y;
           cout <<"Corner 1: "<20&&abs(y-cor1.y)>20) //checking whether the region is too small
            {
                leftup=true;
                cor2.x=x;
                cor2.y=y;
                cout<<"Corner 2: "<

For details you can visit the link Cropping the Image using Mouse

2
追加された

私はこの質問が答えられたと理解していますが、おそらくこれは誰かにとって有益かもしれません...

データを別の cv :: Mat オブジェクトにコピーする場合は、次のような関数を使用できます。

void ExtractROI(Mat& inImage, Mat& outImage, Rect roi){
    /* Create the image */
    outImage = Mat(roi.height, roi.width, inImage.type(), Scalar(0));

    /* Populate the image */
    for (int i = roi.y; i < (roi.y+roi.height); i++){
        uchar* inP = inImage.ptr(i);
        uchar* outP = outImage.ptr(i-roi.y);
        for (int j = roi.x; j < (roi.x+roi.width); j++){
            outP[j-roi.x] = inP[j];
        }
    }
}

これは単一チャンネルの画像でのみ正しく機能することに注意することが重要です。

1
追加された