Question

I am having trouble passing IplImage* parameters in functions. This is for a school project and unfortunately am not supposed to edit the files doing the calling to my filter functions. In the main, the image is brought in as a command line parameter, then a copy of this is made and passed to the correct filter function, as such:

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

And here is the code from one of my filters:

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
}

The problem is, that the filtered image shown in the main, does not reflect the actual image. It only shows the original image. When I output put the Mat style image matImage in my filter function, it shows the filtered image. Immediately after I convert back to IplImage and set the IplImage* input parameter equal to the the converted, filtered version. But the changes do not reflect the image displayed in the main function.

This is making it hard to create some of my other filters such as Gaussian and Sobel, because those filters themselves make calls to other functions before doing their manipulations, and I am not getting edited data back. Is there something I am missing in how to edit the passed IplImage* variable?

Thank you in advance for any help!

Was it helpful?

Solution 2

Instead of this:

image = cvCloneImage(&(IplImage)matImage); 

use this:

cvCopy(&(IplImage)matImage,image);

OTHER TIPS

Your function never edits the image that's passed to it.

This line is presumably making a copy of the image.

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

Then your code modifies that matImage copy.

And at the end of the function, that local copy is destroyed, and the IplImage pointed to by image was never modified.

Edit: Vaughn Cato's answer shows specifically how you can address this.

To go over the 3 channels you should use an iterator :

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] = ......;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top