-1

Please have a look at the following code

using namespace cv;
double alpha = 1.6;
int beta = 50;
int i = 0;
IplImage* input_img = cvLoadImage("c:\\Moori.jpg", CV_LOAD_IMAGE_GRAYSCALE);
IplImage* imageGray = cvCreateImage(cvSize(input_img->width, input_img->height), IPL_DEPTH_8U, 1);
    for( int y = 0; y < input_img->height; y++ )
    { 
        for( int x = 0; x < input_img->width; x++ )
        { 

            i = y * imageGray->width + x;
            imageGray->imageData[i] = (alpha * input_img->imageData[i]) + beta;
        }
    }
cvNamedWindow("Image IplImage", 1);
cvShowImage("Image IplImage", imageGray);
waitKey();
cvReleaseImage(&imageGray);
cvReleaseImage(&input_img);
cvDestroyWindow("Image IplImage");

when I run this code, it shows an image with many dark pixels. But, when i run the code, which is available at: http://docs.opencv.org/doc/tutorials/core/basic_linear_transform/basic_linear_transform.html it works fine. I want to do by IplImage. Please help

sgarizvi
  • 16,623
  • 9
  • 64
  • 98
IRFAN
  • 21
  • 4

3 Answers3

1

saturate_cast is for c++. http://docs.opencv.org/modules/core/doc/intro.html

Finally, I have solved this problem.

IplImage* img;
cvNamedWindow("Display");
while(true)
{
    img = cvLoadImage("Moori.jpg");
    CvScalar brVal = cvScalarAll(abs(10.0));
    cvAddS(img, brVal, img, NULL);
    IplImage *pTempImg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, img->nChannels);
    cvSet( pTempImg, cvScalarAll(1), NULL );
    double scale = 1.5;
    cvMul(img, pTempImg, img, scale);
    cvReleaseImage(&pTempImg);
    cvShowImage("Display", img);
    cvReleaseImage(&img);
    int c=cvWaitKey(10);              
    if(c==27) break;
}
cvDestroyWindow("Display");
IRFAN
  • 21
  • 4
0

If you are using C++ I am not sure why anybody would want to use IplImage. But your problem is this line

 imageGray->imageData[i] = (alpha * input_img->imageData[i]) + beta;

It can overflow. Also imageData is a char*, and a char may be signed or unsigned, you need to make it unsigned. You need use saturate_cast to prevent overflow, and a cast to get rid of the signed char:

imageGray->imageData[i] = saturate_cast<uchar>((alpha * static_cast<uchar>(input_img->imageData[i])) + beta);

You can use this little program to see what is going on:

#include <opencv2/core/core.hpp>
#include <iostream>     // std::cout
#include <vector>       // std::vector
int main(int argc, char** argv)
{
    double alpha = 1.6;
    int beta = 50;

    std::vector<uchar> z;
    for(int i = 0; i <= 255; ++i)
        z.push_back(i);

    char* zp = reinterpret_cast<char *>(&z[0]);

    for(int i = 0; i <= 255; ++i)
        std::cout << i << " -> " << int(cv::saturate_cast<uchar>(alpha * static_cast<uchar>(zp[i]) + beta))  << std::endl;
}
Bull
  • 11,771
  • 9
  • 42
  • 53
  • I already tried to use saturate_cast, but it gives very little effect. It makes dark pixels (error) more dark. The problem is that some pixel values become NULL. – IRFAN Dec 16 '13 at 06:47
  • OK, I forgot that imageData is a char* (which can be signed (platform dependent)) and this will mess things up. I have edited my answer to fix this. – Bull Dec 16 '13 at 07:19
  • I added static_cast(input_img->imageData[i]), but result is same. I also tried same code on different images, but result was same. Please see the image from the following link: http://sl.avouch.org/files/changed_image.jpg – IRFAN Dec 16 '13 at 08:37
  • Did you include the saturate_cast as well (it is essential)? This works fine for me in VS2012. Could you add your modified code to the end of your question? Also, what platform are you on? – Bull Dec 16 '13 at 12:56
0

You dont have to cast the image values to uchar. You have to reinterpret the values as uchar. It Means you have to assume that the data bits actually represent an unsigned char, regardless of the type of pointer. It can be done as follows:

uchar* ptr = reinterpret_cast<uchar*>(imageGray->imageData);
ptr[i] = saturate_cast<uchar>(alpha * ptr[i] + beta);
sgarizvi
  • 16,623
  • 9
  • 64
  • 98
  • Am I correct? uchar* Imgptr = reinterpret_cast(input_img->imageData); imageGray->imageData[i] = saturate_cast(alpha * Imgptr[i]) + beta; Result is same like previous. I am using VS2010. – IRFAN Dec 17 '13 at 00:10
  • @IRFAN... No, you have to access data using `Imgptr` like this: `Imgptr[i] = saturate_cast(alpha * Imgptr[i] + beta);` – sgarizvi Dec 17 '13 at 04:33
  • like this...?: uchar* Imgptr = reinterpret_cast(imageGray->imageData); Imgptr[i] = saturate_cast(alpha * input_img->imageData[i]) + beta; imageGray->imageData = (char*)Imgptr; – IRFAN Dec 17 '13 at 07:36
  • @IRFAN... not like this. `Imgptr` and `imageGray->imageData` are pointing to same memory location. Just dont use `imageGray->imageData` in any calculations. The last statement is not required and it doesn't do anything. Also, place `beta` inside the bracket as I have mentioned in my previous comment. – sgarizvi Dec 17 '13 at 07:41
  • Result is same.... uchar* Imgptr = reinterpret_cast(imageGray->imageData); Imgptr[i] = cv::saturate_cast(alpha * input_img->imageData[i] + beta); – IRFAN Dec 17 '13 at 07:45
  • @IRFAN... *i am banging my head*... why are you still using `imageData` directly again and again? Use Imgptr in **all** the calculations. – sgarizvi Dec 17 '13 at 08:42
  • @sgar... if i use only Imgptr, I get nothing. no image.. Imgptr[i] = saturate_cast(alpha * Imgptr[i] + beta); because i am reading image by IplImage* input_img.... – IRFAN Dec 19 '13 at 23:15