0

I am trying to find number of bytes cvCreateImage( size, d, nChan); function call allocates to the pointer returned. (Say size : Width=1200,Hieght=600 ,d=32 ,nChan=3)

Does opencv allocate an aligned memory location or just a random memory location?

Does the memory released using the function cvReleaseImage immediately available to the running application ? (Say a program wherein image is created and released in a loop, looping for about 30000 times , would it cause out of memory error or any fragmentation error)

10
  • You have tagged your post with C++, but your question is a bout the OLD (deprecated) C API. DId you see the "old" in the documentation url docs.opencv.org/modules/core/doc/old_basic_structures.html ? Commented Aug 26, 2014 at 0:53
  • 1
    please give up with that idea entirely, as IplImages are deprecated and no more relevant. Commented Aug 26, 2014 at 20:07
  • 1
    @mooonimoon, the proper reaction, would be, to rewrite that piece of code. please don't be a moron, and try to fix it instead. Commented Aug 26, 2014 at 20:11
  • 1
    can we just agree on: "if you see code, that is either using IplImages or vc6" -- RUN, THAT IS JUST MOLD ! Commented Aug 26, 2014 at 20:19
  • 1
    @berak I don't necessarily agree with the RUN comment. I have added to my answer a translation of the ssim code using the C++ API, retaining the old code in comments - it was trivial to do. IplIMages are horrible to use, I can't understand why so many people insist on sticking with them. Commented Aug 27, 2014 at 0:47

1 Answer 1

5

You can look up the answer to your question in the OpenCV source.

cvCreateImage() allocates a header of sizeof(IplImage) (currently 112 bytes). The data is a bit more complicated; if you want an exact answer grep for image->imageSize in alloc.cpp, but it is approximately size.height * size.width * d * nChan / 8 (8,640,000 for you example).

Memory is allocated, ultimately, by fastMalloc() in alloc.cpp and aligned to a 16 byte boundary - but the pointer you are returned is the sizeof a pointer above that boundary.

cvReleaseImage decrements a reference count, and only frees data if the reference count reaches zero. If your program is simply creating and releasing an image in a loop you should't have a problem, except for performance. It is poor design to deallocate the image memory when you need it again on the next iteration.

Exact allocation/deallocation behavior will depend on whether your OpenCV was built with CV_USE_SYSTEM_MALLOC.

If you use a cv::Mat instead of an IplImage, OpenCV takes care of all of the memory management issues automaticly. I strongly recommend that you rewrite your code to use the C++ API (i.e. with Mat's)

For example here is a translation of the code you linked to in the comments above:

// Based on http://mehdi.rabah.free.fr/SSIM/SSIM.cpp
// Converted to OpenCV C++ API by B...

/*
 * The equivalent of Zhou Wang's SSIM matlab code using OpenCV.
 * from http://www.cns.nyu.edu/~zwang/files/research/ssim/index.html
 * The measure is described in :
 * "Image quality assessment: From error measurement to structural similarity"
 * C++ code by Rabah Mehdi. http://mehdi.rabah.free.fr/SSIM
 *
 * This implementation is under the public domain.
 * @see http://creativecommons.org/licenses/publicdomain/
 * The original work may be under copyrights. 
 */

//#include <cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

//#include <highgui.h>
#include "opencv2/highgui/highgui.hpp"

//#include <iostream.h>
#include <iostream>
using namespace std;


/*
 * Parameters : complete path to the two image to be compared
 * The file format must be supported by your OpenCV build
 */
int main(int argc, char** argv)
{
    if(argc!=3)
        return -1;

    // default settings
    double C1 = 6.5025, C2 = 58.5225;

    /*
    IplImage
        *img1=NULL, *img2=NULL, *img1_img2=NULL,
        *img1_temp=NULL, *img2_temp=NULL,
        *img1_sq=NULL, *img2_sq=NULL,
        *mu1=NULL, *mu2=NULL,
        *mu1_sq=NULL, *mu2_sq=NULL, *mu1_mu2=NULL,
        *sigma1_sq=NULL, *sigma2_sq=NULL, *sigma12=NULL,
        *ssim_map=NULL, *temp1=NULL, *temp2=NULL, *temp3=NULL;
    */

    /***************************** INITS **********************************/
    //img1_temp = cvLoadImage(argv[1]);
    cv::Mat img1 = cv::imread(argv[1]);
    //img2_temp = cvLoadImage(argv[2]);
    cv::Mat img2 = cv::imread(argv[2]);


    //if(img1_temp==NULL || img2_temp==NULL)
    if(img1.empty() || img2.empty())
        return -1;

    //int x=img1_temp->width, y=img1_temp->height;
    //int nChan=img1_temp->nChannels, d=IPL_DEPTH_32F;
    //CvSize size = cvSize(x, y);

    //img1 = cvCreateImage( size, d, nChan);
    //img2 = cvCreateImage( size, d, nChan);

    //cvConvert(img1_temp, img1);
    img1.convertTo(img1, CV_32F);
    //cvConvert(img2_temp, img2);
    img2.convertTo(img2, CV_32F);
    //cvReleaseImage(&img1_temp);
    //cvReleaseImage(&img2_temp);


    //img1_sq = cvCreateImage( size, d, nChan);
    cv::Mat img1_sq;
    //img2_sq = cvCreateImage( size, d, nChan);
    cv::Mat img2_sq;
    //img1_img2 = cvCreateImage( size, d, nChan);
    cv::Mat img1_img2;

    //cvPow( img1, img1_sq, 2 );
    cv::pow(img1, 2, img1_sq);
    //cvPow( img2, img2_sq, 2 );
    cv::pow(img1, 2, img1_sq);
    //cvMul( img1, img2, img1_img2, 1 );
    cv::multiply(img1, img2, img1_img2);

    //mu1 = cvCreateImage( size, d, nChan);
    cv::Mat mu1;
    //mu2 = cvCreateImage( size, d, nChan);
    cv::Mat mu2;

    //mu1_sq = cvCreateImage( size, d, nChan);
    cv::Mat mu1_sq;
    //mu2_sq = cvCreateImage( size, d, nChan);
    cv::Mat mu2_sq;
    //mu1_mu2 = cvCreateImage( size, d, nChan);
    cv::Mat mu1_mu2;


    //sigma1_sq = cvCreateImage( size, d, nChan);
    cv::Mat sigma1_sq;
    //sigma2_sq = cvCreateImage( size, d, nChan);
    cv::Mat sigma2_sq;
    //sigma12 = cvCreateImage( size, d, nChan);
    cv::Mat sigma12;

    //temp1 = cvCreateImage( size, d, nChan);
    //temp2 = cvCreateImage( size, d, nChan);
    //temp3 = cvCreateImage( size, d, nChan);

    //ssim_map = cvCreateImage( size, d, nChan);
    cv::Mat ssim_map;
    /*************************** END INITS **********************************/


    //////////////////////////////////////////////////////////////////////////
    // PRELIMINARY COMPUTING
    //cvSmooth( img1, mu1, CV_GAUSSIAN, 11, 11, 1.5 );
    cv::GaussianBlur(img1, mu1, cv::Size(11, 11), 1.5);
    //cvSmooth( img2, mu2, CV_GAUSSIAN, 11, 11, 1.5 );
    cv::GaussianBlur(img2, mu2, cv::Size(11, 11), 1.5);

    //cvPow( mu1, mu1_sq, 2 );
    cv::pow(mu1, 2, mu1_sq);
    //cvPow( mu2, mu2_sq, 2 );
    cv::pow(mu2, 2, mu2_sq);
    //cvMul( mu1, mu2, mu1_mu2, 1 );
    cv::multiply(mu1, mu2, mu1_mu2);

    //cvSmooth( img1_sq, sigma1_sq, CV_GAUSSIAN, 11, 11, 1.5 );
    cv::GaussianBlur(img1_sq, sigma1_sq, cv::Size(11, 11), 1.5);
    //cvAddWeighted( sigma1_sq, 1, mu1_sq, -1, 0, sigma1_sq );
    cv::addWeighted(sigma1_sq, 1.0, mu1_sq, -1.0, 0.0, sigma1_sq);

    //cvSmooth( img2_sq, sigma2_sq, CV_GAUSSIAN, 11, 11, 1.5 );
    cv::GaussianBlur(img2_sq, sigma2_sq, cv::Size(11, 11), 1.5);
    //cvAddWeighted( sigma2_sq, 1, mu2_sq, -1, 0, sigma2_sq );
    cv::addWeighted(sigma2_sq, 1.0, mu2_sq, -1.0, 0.0, sigma2_sq);

    //cvSmooth( img1_img2, sigma12, CV_GAUSSIAN, 11, 11, 1.5 );
    cv::GaussianBlur(img1_img2, sigma12, cv::Size(11, 11), 1.5);
    //cvAddWeighted( sigma12, 1, mu1_mu2, -1, 0, sigma12 );
    cv::addWeighted(sigma12, 1.0, mu1_mu2, -1.0, 0.0, sigma12);


    //////////////////////////////////////////////////////////////////////////
    // FORMULA

    // (2*mu1_mu2 + C1)
    //cvScale( mu1_mu2, temp1, 2 );
    //cvAddS( temp1, cvScalarAll(C1), temp1 );
    cv::Mat temp3 = 2 * mu1_mu2 + C1;

    // (2*sigma12 + C2)
    //cvScale( sigma12, temp2, 2 );
    //cvAddS( temp2, cvScalarAll(C2), temp2 );

    // ((2*mu1_mu2 + C1).*(2*sigma12 + C2))
    //cvMul( temp1, temp2, temp3, 1 );
    temp3 = temp3.mul(2 * sigma12 + C2);

    // (mu1_sq + mu2_sq + C1)
    //cvAdd( mu1_sq, mu2_sq, temp1 );
    //cvAddS( temp1, cvScalarAll(C1), temp1 );
    cv::Mat temp1 = mu1_sq + mu2_sq + C1;

    // (sigma1_sq + sigma2_sq + C2)
    //cvAdd( sigma1_sq, sigma2_sq, temp2 );
    //cvAddS( temp2, cvScalarAll(C2), temp2 );

    // ((mu1_sq + mu2_sq + C1).*(sigma1_sq + sigma2_sq + C2))
    //cvMul( temp1, temp2, temp1, 1 );
    temp1 = temp1.mul(sigma1_sq + sigma2_sq + C2);

    // ((2*mu1_mu2 + C1).*(2*sigma12 + C2))./((mu1_sq + mu2_sq + C1).*(sigma1_sq + sigma2_sq + C2))
    //cvDiv( temp3, temp1, ssim_map, 1 );
    cv::divide(temp3, temp1, ssim_map);


    //CvScalar index_scalar = cvAvg( ssim_map );
    cv::Scalar index_scalar = cv::mean(ssim_map);

    // through observation, there is approximately 
    // 1% error max with the original matlab program

    cout << "(R, G & B SSIM index)" << endl ;
    cout << index_scalar.val[2] * 100 << "%" << endl ;
    cout << index_scalar.val[1] * 100 << "%" << endl ;
    cout << index_scalar.val[0] * 100 << "%" << endl ;

    /*
    // if you use this code within a program
    // don't forget to release the IplImages
    */
    return 0;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the detailed explanation it clarified many doubts i had.
nice translation table !
Thanks a ton for modifying the algorithm. Just curious how much memory would cv::Mat img1 = cv::imread(); would take (Say a image of Width=1200,Hieght=600 ,d=32 ,nChan=3 is passed as argument). Is there any other advantage of using cv::Mat in place of IplImage other than memory management?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.