Search code examples
c++imageedge-detection

Prewitt filter, edge detection


I have this code that implements Prewitt edge detection. What I need to do is to implement it with only one buffer, meaning, I will not create copy of the image but edit original image. So if i want to change pixel with value 78, I cant put the new value e.g. 100 until all surrounding pixels have read value 78. Color values of the pixels. I have tried all day to figure it out but couldn't, if someone would write me some kind of pseudocode I would be very grateful

void filter_serial_prewitt(int *inBuffer, int *outBuffer, int width, int height){
   for (int i = 1; i < width - 1; i ++) {
     for (int j = 1; j < height - 1; j ++) {
        int Fx = 0;
        int Fy = 0;
        int F = 0;
        for (int m = -1; m <= 1; m++) {
            for (int n = -1; n <= 1; n++) {
                Fx += inBuffer[(j + n) * width + (i + m)] * n;
                Fy += inBuffer[(j + n) * width + (i + m)] * m;
            }
        }
            F = abs(Fx) + abs(Fy);

            if (F < THRESHOLD){
                outBuffer[j * width + i] = 255;
            } else{
                outBuffer[j * width + i] = 0;
            }
       }
   }
}

Solution

  • One thing to know about a Prewitt operator is that it is separable. See the Wikipedia article for details.

    To calculate a single output row, you need to do the following (pseudocode):

    int* buffer = malloc (sizeof(int) * width);
    for (int i = 0; i < width; i++)
    {
        // Do the vertical pass of the convolution of the first 3 rows into
        // the buffer.
        buffer [ i ] = vertical_convolve(inBuffer [ i ], vertical_kernel);
    }
    
    // Next, do the horizontal convolution of the first row. We need to 
    // keep the previous value in a temp buffer while we work
    int temp0 = horizontal_convolve(buffer [ 0 ], horizontal_kernel);
    for (int i = 1; i < width; i++)
    {
        int temp1 = horizontal_convolve(buffer[ i ], horizontal_kernel);
        inBuffer [ i - 1 ] = temp0;
        temp0 = temp1;
    }
    

    That requires a buffer that is 1 pixel tall and the width of the image.

    To work on the whole image, you need to keep 2 of the above buffers around and after you calculate a pixel on the third line, you can replace the first pixel of the first line of the image with the first pixel of the first buffer. Then you can put the newly calculated value into the buffer.

    So in this scenario, you won't keep around an entire second image, but will need to keep around 2 1-pixel tall buffers that are as wide as the image.