Как обрезать CvMat в OpenCV? - PullRequest
       64

Как обрезать CvMat в OpenCV?

48 голосов
/ 25 ноября 2011

У меня есть изображение, преобразованное в матрицу CvMat, скажем CVMat source. Как только я получу область интереса от source, я хочу, чтобы остальная часть алгоритма была применена только к этой области интереса. Для этого я думаю, что мне придется каким-то образом обрезать матрицу source, которую я не могу сделать. Есть ли метод или функция, которая может обрезать матрицу CvMat и возвращать другую обрезанную матрицу CvMat? спасибо.

Ответы [ 6 ]

109 голосов
/ 25 ноября 2011

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);

Документация для извлечения подизображения

35 голосов
/ 03 апреля 2014

Я знаю, что этот вопрос уже решен .. но есть очень простой способ обрезки. Вы можете просто сделать это в одну строку -

Mat cropedImage = fullImage(Rect(X,Y,Width,Height));
17 голосов
/ 03 апреля 2014

Чтобы получить лучшие результаты и устойчивость к разным типам матриц, вы можете сделать это в дополнение к первому ответу, который копирует данные:

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);
3 голосов
/ 16 февраля 2016

Чтобы создать копию нужной нам обрезки, мы можем сделать следующее:

// 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();
1 голос
/ 28 января 2014

Я понимаю, что на этот вопрос ответили, но, возможно, это может быть кому-то полезно ...

Если вы хотите скопировать данные в отдельный 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<uchar>(i);
        uchar* outP = outImage.ptr<uchar>(i-roi.y);
        for (int j = roi.x; j < (roi.x+roi.width); j++){
            outP[j-roi.x] = inP[j];
        }
    }
}

Важно отметить, что это будет правильно работать только на одноканальных изображениях .

0 голосов
/ 25 июня 2016

Вы можете легко обрезать мат, используя функции opencv.

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: "<<cor1<<endl;

        }
        if(event==EVENT_LBUTTONUP)
        {
            if(abs(x-cor1.x)>20&&abs(y-cor1.y)>20) //checking whether the region is too small
            {
                leftup=true;
                cor2.x=x;
                cor2.y=y;
                cout<<"Corner 2: "<<cor2<<endl;
            }
            else
            {
                cout<<"Select a region more than 20 pixels"<<endl;
            }
        }

        if(leftDown==true&&leftup==false) //when the left button is down
        {
            Point pt;
            pt.x=x;
            pt.y=y;
            Mat temp_img=img.clone();
            rectangle(temp_img,cor1,pt,Scalar(0,0,255)); //drawing a rectangle continuously
            imshow("Original",temp_img);

        }
        if(leftDown==true&&leftup==true) //when the selection is done
        {

            box.width=abs(cor1.x-cor2.x);
            box.height=abs(cor1.y-cor2.y);
            box.x=min(cor1.x,cor2.x);
            box.y=min(cor1.y,cor2.y);
            Mat crop(img,box);   //Selecting a ROI(region of interest) from the original pic
            namedWindow("Cropped Image");
            imshow("Cropped Image",crop); //showing the cropped image
            leftDown=false;
            leftup=false;

        }
    }

Для получения подробной информации вы можете посетить ссылку ОбрезкаИзображение с помощью мышки

...