2013-02-10 37 views
0

我在函数中传递IplImage *参数时遇到问题。这是一个学校项目,不幸的是我不应该编辑文件来调用我的过滤器函数。在主,图像带来了作为命令行参数,那么这一份拷贝并传递给正确的过滤器功能,因为这样:传递IplImage *功能,原始不更新

IplImage * floating = cvCreateImage (cvSize (img->width, img->height), IPL_DEPTH_32F, 3); 
cvConvertScale (img, floating, 1/255., 0); 

IplImage * filtered; 

switch (filter.ImageFormat) 
{ 
    case YUV24: 
     filtered = cvCreateImage (cvSize (floating->width, floating->height), IPL_DEPTH_32F, 3); 
     cvCvtColor (floating, filtered, CV_BGR2YCrCb); 
     break; 
    case BGR24: 
     filtered = cvCloneImage (floating); 
     break; 
    case Gray: 
     filtered = cvCreateImage (cvSize (floating->width, floating->height), IPL_DEPTH_32F, 1); 
     cvCvtColor (floating, filtered, CV_BGR2GRAY); 
     break; 
} 

cvNamedWindow ("original", CV_WINDOW_AUTOSIZE); 
cvShowImage ("original", img); 

filter.ImageFilter (filtered, p); 

if (filter.ImageFormat == YUV24) 
{ 
     cvCvtColor (filtered, filtered, CV_YCrCb2BGR); 
} 

cvNamedWindow (filterName.c_str(), CV_WINDOW_AUTOSIZE); 
cvShowImage (filterName.c_str(), filtered); 

这里是我的一个过滤器的代码:

void median (IplImage * image, int k){ 
    cout << "image address: " << &image << endl; 
    Mat matImage(image);  //convert IplImage to Mat for work 
    vector<Mat> bgr_channels; //vector to hold each channel 
    int i,j,m,n;    //row/column indeces 
    int kernelSize = (2*k+1)*(2*k+1); 
    vector<float> vals(kernelSize); //kernelSized vector to hold all values of image 
       //within kernel centered at a given pixel 
    int vecIndex = 0; //then sorted to get the median 
    int chanIndex = 0; //index used to for each channel 

    //add padding to account for border issues with convolution 
    copyMakeBorder(matImage, matImage, k, k, k, k, BORDER_REPLICATE); 
    //split channes to do work on individual channels 
    split(matImage, bgr_channels); 

    for(chanIndex=0; chanIndex < matImage.channels(); chanIndex++){ 
     //outer loop for scanning entire image 
     for(i=k; i<matImage.rows-k; i++)/*image row index*/{ 
      for(j=k; j<matImage.cols-k; j++)/*image column index*/{ 
       //inner loop for scanning image only in kernel boundaries 
       vecIndex = 0; //reset vecIndex at start of each kernel loop 
       for(m=i-k; m<(i+k+1); m++)/*kernel row index*/{ 
        for(n=j-k; n<(j+k+1); n++)/*kernel column index*/{      
         vals[vecIndex++] = bgr_channels[chanIndex].at<float>(m,n); 
        } 
       } 
       insertionSort(vals, 0, vals.size()-1); //insertion sort from CSCI362 text, see references 
       bgr_channels[chanIndex].at<float>(i,j) = vals[vals.size()/2]; //new value chosen from middle element                //of sorted vector 
      } 
     } 
    } 

    merge(bgr_channels, matImage);  //merge channels together 
    imshow("Median: Mat", matImage); //left this in becuase the original doesn't seem to get modified  
             //when converting the Mat back to an IplImage 
    image = cvCloneImage(&(IplImage)matImage); //convert backto IplImage for DesktopMain 
} 

问题是,显示在main中的过滤图像并不反映实际图像。它只显示原始图像。当我输出将Mat样式图像matImage放入我的过滤器函数中时,它将显示已过滤的图像。立即在我转换回IplImage并将IplImage *输入参数设置为等于转换后的过滤版本后立即生效。但这些更改不反映主要功能中显示的图像。

这使得很难创建一些我的其他过滤器,如高斯和索贝尔,因为这些过滤器本身在进行操作之前调用其他函数,并且我没有获取编辑的数据。在如何编辑传递的IplImage *变量时是否存在缺少的内容?

非常感谢您的帮助!

回答

2

取而代之的是:

image = cvCloneImage(&(IplImage)matImage); 

使用本:

cvCopy(&(IplImage)matImage,image); 
+0

是的,这真是棒极了。最初有一些问题,因为我已经填充了matImage的边界,但剥离了它并且工作得很好。 出于好奇,需要了解,上述两者有何区别。两者似乎都在IplImage *图像上运行。如果我在cvCloneImage调用后执行cvShowImage(“image”,image),我会看到过滤的版本。为什么不会像cvCopy那样影响主图像?非常感谢你的帮助! – jrpharis 2013-02-10 17:39:01

+1

@JoshPharis:您正在通过值传递参数,即将指针的*副本*传递给该函数。这意味着你可以改变*指针指向的内容*,并且该变异可以在函数之外看到,但是如果给参数赋予一个全新的值,那么你只是修改了传递给该函数的副本。C中的所有参数都是按值传递的,而在C++中,当您使用类似的东西时,您可以通过引用传递; void foo(SomeType & arg);' – 2013-02-11 00:52:15

3

您的函数从不编辑传递给它的图像。

这行大概是制作图像的副本。

Mat matImage(image);  //convert IplImage to Mat for work 

然后你的代码修改matImage副本。

并且在该函数结束时,该本地副本被销毁,并且image指向的IplImage从未被修改过。

编辑: Vaughn Cato的答案显示了具体如何解决这个问题。

0

走过去3个通道,你应该使用迭代器:

Mat out; 
*********open out******** 
Mat_<Vec3b>::iterator it = out.begin<Vec3b>(); 
MatConstIterator_<Vec3b> it_end = out.end<Vec3b>(); 

for(; it != it_end; ++it) 
{ 
    //your 3 channels 
    (*it)[0] = ...; 
    (*it)[1] = ....; 
    (*it)[2] = ......; 
}