1
votes

I try to implement Laplacian filter. I think I implemented it right, but it returns VERY DARK image. Here is my code.

values is an array with pixel values. Each pixel is represented as three values(rgb). (values[0] = first pixel RED, values[1] = first pixel GREEN, values[2] = first pixel BLUE, values[3] = second pixel RED e.t.c.) It can't be error with array indeces/wrong channels/wrong pointers/e.t.c. because I copied this part from Gaussian filter that works fine.

I use integer array for storing average values of eaxh pixel, then scale them to 0...255 and copy to unsigned char array. Here I also added min/max, sum and I think, maybe, something wrong with scaling values to 0...255 or overflows somewhere... Please help me to find an error. Or maybe I do something wrong?

void Laplacian::filter3x3(unsigned char* values, int rows, int cols){

unsigned char mask [3][3]= {{1, 1, 1},{1,-8, 1},{1, 1, 1}};  

int* intValues = new int[rows*cols];


// For each channel(RGB).
for(int c=0; c <= BLUE; ++c){
    int min = 8*255;
    int max = -8*255;
    for(int i=1; i<rows-1; i+=1){
        for(int j=c+3; j<cols-3; j+=3){
            double sum = 0;
            for(int x=-1; x<=1; ++x)
                for(int y=-1; y<=1; ++y){
                    sum += values[(i+x)*cols + j+y*3] * mask[x+1][y+1];
                }
            if(sum < min)
                min = sum;
            if(sum > max)
                max = sum;
            intValues[i*cols + j] = sum;
        }
    }
    int delta = max - min;
    std::cout<<"Delta: "<<delta<<"\tMin:  "<<min<<"\tMax:"<<max<<"\n";
    for(int i=1; i<rows-1; i+=1)
        for(int j=c+3; j<cols-3; j+=3){
            values[i*cols + j] =(unsigned char)((intValues[i*cols + j] - min)/delta*255);
        }
}

}

Here is picture samples: Input and Output.

enter image description hereenter image description here

And console screenshot with min/max/delta values(red, then green, then blue). Looks like they work fine. enter image description here

Is there another way to normalize the values?

1

1 Answers

4
votes
    unsigned char mask [3][3]= {{1, 1, 1},{1,-8, 1},{1, 1, 1}};

Looks suspicious that you have a -8 in an unsigned.

    values[i*cols + j] =(unsigned char)((intValues[i*cols + j] - min)/delta*255);

Dividing by delta first means you're going to produce a fraction < 1.0, which will be rounded down to 0 as integer math, and then the multiply by 255 will do nothing.

If you do * 255 / delta you will avoid the problem as long as the intermediate value doesn't overflow (which seems reasonable).