2

I'm writing a Gaussian Blur filter with 3x3 matrix(kernel) and using QImage as external library. The kernel is calculated as it has to be. After kernel is initialized and calculated I bring the unsigned int Matrix into the program:

typedef std::vector<std::vector<unsigned int> > uintMatrix; // For copying pixels value

In the main.cpp it's initialized like:

uintMatrix tmpPxMat(image.width(); std::vector<unsigned int> (image.height(), 0));

I use it as a temporary storage for blurred pixels values.

Then, I use my algorithm to blur the image:

// Blur Pixels
for(int x = 0; x < image.width(); x++)
    for(int y = 0; y < image.height(); y++) {
        // To avoid edge cases don't process them, I'll fix it soon
        if(x == 0 || x == image.height()-1 || y == 0 || y == image.width()-1)
            continue;
        // 3x3 Matrix
        tmpPxMat[x][y] += kernel[0][0] * image.pixel(x-1, y-1) +
                          kernel[0][1] * image.pixel(x, y-1) +
                          kernel[0][2] * image.pixel(x+1, y-1);

        tmpPxMat[x][y] += kernel[1][0] * image.pixel(x-1, y) +
                          kernel[1][1] * image.pixel(x, y) +
                          kernel[1][2] * image.pixel(x+1, y);

        tmpPxMat[x][y] += kernel[2][0] * image.pixel(x-1, y+1) +
                          kernel[2][1] * image.pixel(x, y+1) +
                          kernel[2][2] * image.pixel(x+1, y+1);
    }

Then, I copy the result of tmpPxMat[][] to the origin image:

// Copy blurred values to the image
for(int x = 0; x < image.width(); x++)
        for(int y = 0; y < image.height(); y++)
            image.setPixel(x, y, tmpPxMat[x][y]);

And save it:

image.save("/home/john/Pictures/blurred", "PNG", 100);

But at the end I get not the result I was waiting for. Here what I get:

Before / After:

Origin/Blurred

Sorry for the long question description, but I compressed it as much as I could.

pushandpop
  • 455
  • 1
  • 10
  • 22
  • Are you sure there is no problem with casting? Gaussian kernel should be a float matrix, the result of your convolution being a float saved as an int. – Miki Jul 01 '15 at 14:21
  • How are the colors of the image represented in the texture? – jaggedSpire Jul 01 '15 at 14:22
  • 3
    Your output image is coloured, yet your processing doesn't seem to be processing three channels of colour data (RGB) so are you using greyscale processing on colour images? – Mark Setchell Jul 01 '15 at 14:49
  • @Miki, my kernel is float matrix, but temporary storage is not. I've changed it to float as needed, but at the end - I use **setPixel()** function, which accepts **uint**, I can avoid casting when calculate values, but can't when setting these values to the pixel. The casting should be very small, can it damage picture so hard? – pushandpop Jul 01 '15 at 14:53
  • It was just a guess.. probably wrong! @MarkSetchell question seems more appropriate – Miki Jul 01 '15 at 15:15
  • @Miki, I think he's 99% right. I'm trying now to convert it to RGB32 or load it properly or whatever. I'll leave feedback. – pushandpop Jul 01 '15 at 15:22
  • @MarkSetchell, I've just found this question on [SO](http://stackoverflow.com/questions/25216834/converting-2d-mask-to-1d-in-gaussian-blur?rq=1) and the OP was having the same effect on the resulting image. As one of the commentators said: "2d kernel must have total sum of 1, otherwise it won't work". I traced my ``sum`` variable and it equals ~4.xxxxx which is not right. I'm gonna try fix it right now. – pushandpop Jul 01 '15 at 15:51
  • @MarkSetchell, Oh, no. I was checking the total sum of kernel before normalizing it. I've just checked it after normalizing and it equals to ``1``. So, the problem is not in the kernel. I should go deeper and find mistake somewhere else. – pushandpop Jul 01 '15 at 15:58

1 Answers1

3

I assume uintMatrix is a two-dimensional array of 32-bit ints, and that you've packed the red, green, and blue channels into that.

If so, that's your problem. You need to blur each channel independently.

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
  • Yes, you're exactly right. It works like a charm. So, you're my hero today, I was struggling with implementation of this filter for a few days. Does the strength of the blur depend on a size of a kernel? If I increase it to 5x5, will it be more blured? – pushandpop Jul 01 '15 at 16:50
  • 1
    @pushandpop - yes it will. The larger the size the larger the blur. Experiment with different sizes and see for yourself! – rayryeng Jul 01 '15 at 17:16