【问题标题】:How to crop a CvMat in OpenCV?如何在 OpenCV 中裁剪 CvMat?
【发布时间】:2011-11-25 09:47:09
【问题描述】:

我在CvMat 矩阵中转换了图像,例如CVMat source。一旦我从source 获得感兴趣区域,我希望算法的其余部分仅应用于该感兴趣区域。为此,我认为我将不得不以某种方式裁剪我无法这样做的source 矩阵。是否有可以裁剪CvMat 矩阵并返回另一个裁剪CvMat 矩阵的方法或函数?谢谢。

【问题讨论】:

  • 您希望它采用 pre 2.0 c 样式还是 post 2.0 c++ 样式?请根据您的回答重新标记您的问题

标签: opencv opencv-mat


【解决方案1】:

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

Documentation for extracting sub image

【讨论】:

  • 不复制数据是什么意思?
  • 这意味着它只创建对该图像区域的引用而不是副本。这意味着如果您更改croppedImage,它也会更改图像源。如果您不希望这种行为,您可以显式创建一个副本。
  • 如果我想要一个椭圆区域而不是感兴趣的矩形区域怎么办?
  • @Sohaib 然后我们需要使用我们所说的“掩码”,它通常作为处理函数的额外参数。
  • 如果我打电话给image.release()croppedImage 会发生什么?
【解决方案2】:

我知道这个问题已经解决了.. 但是有一种非常简单的裁剪方法。你可以在一行中完成-

Mat cropedImage = fullImage(Rect(X,Y,Width,Height));

【讨论】:

  • 从哪里获得fullImage() 函数?编辑:没关系,这是cv::Mat-image 本身...
  • 简单有效!!
  • 上面说这不是复制内容,只是一个参考。这是真的吗?
【解决方案3】:

要针对不同类型的矩阵获得更好的结果和稳健性,除了第一个答案之外,您还可以执行此操作,即复制数据:

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

【讨论】:

    【解决方案4】:

    要创建我们想要的裁剪副本,我们可以执行以下操作,

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

    【讨论】:

    • 这对已经提供的答案没有任何帮助。此外,您缺少分号并且变量名称不正确。顺便说一句,您可以使用 Mat crop = img(Rect(...)).clone()
    • 修正错别字。我确实认为它增加了它在一行中完成所有事情的意义。至于这种情况下的 clone 或 copyTo,我想这正是人们喜欢的。
    【解决方案5】:

    我知道这个问题已经得到解答,但也许这可能对某人有用...

    如果您希望将数据复制到单独的 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];
            }
        }
    }
    

    请务必注意,这只能在单通道图像上正常工作。

    【讨论】:

    【解决方案6】:

    您可以使用 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: "<<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;
    
            }
        }
    

    详情可以访问链接Cropping the Image using Mouse

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-05
      • 2020-09-07
      • 1970-01-01
      • 2013-03-13
      • 2019-12-28
      • 1970-01-01
      相关资源
      最近更新 更多