0
votes

Fairly new to C++ and I've been working with the OpenCV library. I'm attempting to create a dimming function for an image viewer. This is the main body of void dim(int val).

I'm looping over every pixel, getting a reference to the RGB values of the pixel within a Vec3b then decreasing them by some change factor, calculated from val / 255 (where 0 <= val <= 255. But for some reason the pix[0] etc are all being set to 0, meaning that for any value of val the image turns black.

May be doing something slightly stupid with floating point here, or misunderstanding some aspect of OpenCV; but I can't see what it is.

for(int x = 0; x < rows; x++) {
    for(int y = 0; y < cols; y++) {
        Vec3b &pix = dst.at<Vec3b>(x,y);

        float change = val / 255.0f;
        pix[0] = (uchar)(pix[0] * change);
        pix[1] = (uchar)(pix[1] * change);
        pix[2] = (uchar)(pix[2] * change);
    }
}

Thanks in advance!

2
I test your code and it works fine! Don't set val too small, or the result dst will turns all black.WangYudong
You can just do dst *= val/255.0f. Also, it looks like you have your indices wrong. You should have x < cols and y < rows.Nicu Stiurca
Cheers for the heads up on that shorthand. I don't understand how the indices wrong though, the current configuration works fine and if I switch the variables over, it only dims a portion of the image.Dan Prince

2 Answers

1
votes

OpenCV has a doc about changing the contrast and brightness of an image. Generally speaking, it applys alpha * pixel_value + beta to every pixel. Since you only need to adjust the brightness of images, alpha can be set 1.0. Here is the modified dim() function.

// negative beta dims image
void dim(Mat& src, Mat& dst, int beta) {
    for(int y = 0; y < src.rows; y++) {
        for(int x = 0; x < src.cols; x++) {
            for(int channel = 0; channel < 3; channel++) {
                dst.at<Vec3b>(y, x)[channel] = saturate_cast<uchar>(src.at<Vec3b>(y, x)[channel] + beta);
            }
        }
    }
}

Read what saturate_cast does if interested.

To test the function above:

int main( int argc, char** argv )
{
    int beta;
    Mat src = imread(...);
    Mat dst = Mat::zeros(src.size(), src.type());
    namedWindow("src", CV_WINDOW_AUTOSIZE);
    imshow("src", src);
    dim(src, dst, -200);
    namedWindow("dst", CV_WINDOW_AUTOSIZE);
    imshow("dst", dst);

    waitKey(0);
    return 0;
}
0
votes

If you multiply/divide integer value by real value less than 1 you'll get 0 because your scaling coefficient will be truncated to integer. To correct your problem you should convert pix[] to float or double when scale it and convert result back to char.