-2

我对这段代码有疑问:

问题是当我看到原始图像时,它被“borrarFondo()”修改,但是这个函数是从“segmentarHoja”调用的,这里按值输入 img,但 img 修改了。

void borrarFondo(Mat& img){
   img = ~img;
   Mat background;
   medianBlur(img, background, 45);
   GaussianBlur(background, background, Size(203,203),101,101);
   img = img - background;
   img = ~img;
}

void segmentarHoja(Mat img, Mat& imsheet){
   Mat imgbw;
   borrarFondo(img); //borrarFondo is called from here where img is a copy
   cvtColor(img, imgbw, CV_BGR2GRAY);
   threshold(imgbw, imgbw, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
   Mat element = getStructuringElement(MORPH_ELLIPSE, Size(21,21));
   erode(imgbw, imgbw, element);
   vector<vector<Point> > contoursSheet; 
   findContours(imgbw, contoursSheet, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
   vector<Rect> boundSheet(contoursSheet.size());
   int largest_area=0;

   for( int i = 0; i< contoursSheet.size(); i++ )
   {
        double a= contourArea( contoursSheet[i],false);
        if(a>largest_area){
           largest_area=a; 
           boundSheet[i] = boundingRect(contoursSheet[i]);
           imsheet=img(boundSheet[i]).clone(); 
        }
    }
    borrarFondo(imsheet);
  }

int main()
{
    Mat imsheet;
    image= imread("c:/imagen.jpg");
    segmentarHoja(image, imsheet);

    imshow("imsheet",imsheet);
    imshow("imagen",image); //original image by amending borrarFondo 
    waitKey(0);
}

我不想更改原始图像

4

2 回答 2

2

opencvMat是一个计数引用(即 like std::shared_ptr,除了不同的语法),其中复制构造或赋值不复制。使用clone复制的方法。阅读文档,总是一个好主意。

于 2014-06-27T20:02:51.633 回答
1

如果你正在做这样的事情:

Mat a;
Mat b = a;

或像这样:

void func(Mat m) {...}

或者 :

vector<Mat> vm; 
vm.push_back(m);

所有这些都是拷贝。Mat 头将是一个副本,里面的指针也是。

因此,例如在第一个示例中, b 和 a 共享相同的大小和数据成员

这可以解释为什么按值传递 Mat 仍然会导致从“浅”副本中操纵像素。

为避免这种情况,您将不得不进行“深度”复制:

Mat c = a.clone(); // c has its own pixels now.

再一次,如果你不想让你的垫子被操纵,通过它作为const Mat &使用它时要非常小心,如下图所示。

#include <opencv2/opencv.hpp>

void foo( cv::Mat const& image )
{
    cv::Mat result = image;
    cv::ellipse(
        result,                     // img
        cv::Point( 300, 300 ),        // center
        cv::Size( 50, 50 ),         // axes (bounding box size)
        0.0,                        // angle
        0.0,                        // startAngle
        360.0,                      // endAngle
        cv::Scalar_<int>( 0, 0, 255 ),  // color
        6                           // thickness
        );
}

auto main() -> int
{
    auto window_name = "Display";
    cv::Mat lenna = cv::imread( "lenna.png" );
    foo( lenna );
    imshow( window_name, lenna );
    cv::waitKey( 0 );
}

关于可变性的谎言,Lenna 的鼻子也相应长了,这里用上面函数Mat const&放置的一个大胖圈标记:foo

在此处输入图像描述

于 2014-06-27T20:03:44.093 回答