cimage-processingcs50sobel

edge detection not working! last subscript in 2D array of pixels isnt coming out properly


my apologies for sloppy code or an incorrectly formatted question, its my first post!

the basic gist of this block of code is to apply edge detection with the sobel operator. i have a for loop nested in a for loop to iterate through the individual pixels and another nested for loop to iterate through a smaller 2D array to apply the sobel operator, but the last line of pixels and some of the right edge arent resolving correctly. many thanks!

#include <math.h>
#include "helpers.h"

//prototype functions
void calcVert (int h, int w, int height, int width, RGBTRIPLE temp[height][width], int *blue, int *green, int *red);
void calcHori (int h, int w, int height, int width, RGBTRIPLE temp[height][width], int *blue, int *green, int *red);

// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int sobelBlueV;
    int sobelGreenV;
    int sobelRedV;
    int sobelBlueH;
    int sobelGreenH;
    int sobelRedH;
    RGBTRIPLE temp[height][width];
    for (int h = 0; h < height; h++)
    {
        for (int w = 0; w < width; w++)
        {
            temp[h][w].rgbtBlue = image[h][w].rgbtBlue;
            temp[h][w].rgbtGreen = image[h][w].rgbtGreen;
            temp[h][w].rgbtRed = image[h][w].rgbtRed;
        }
    }
    for (int h = 0; h < height; h++)
    {
        for (int w = 0; w < width; w++)
        {
            /*
            [-1] [0] [+1]    [+1] [+2] [+1]
            [-2] [0] [+2]    [0 ] [0 ] [0 ]
            [-1] [0] [+1]    [-1] [-2] [-1]
            
            */
            calcVert(h, w, height, width, temp, &sobelBlueV, &sobelGreenV, &sobelRedV);
            calcHori(h, w, height, width, temp, &sobelBlueH, &sobelGreenH, &sobelRedH);
            // ^2 and sqrt
            int bluePoint = round(sqrt(pow(sobelBlueV, 2) + pow(sobelBlueH, 2)));
            if (bluePoint > 255) bluePoint = 255;
            int GreenPoint = round(sqrt(pow(sobelGreenV, 2) + pow(sobelGreenH, 2)));
            if (GreenPoint > 255) GreenPoint = 255;
            int RedPoint = round(sqrt(pow(sobelRedV, 2) + pow(sobelRedH, 2)));
            if (RedPoint > 255) RedPoint = 255;
            image[h][w].rgbtBlue = bluePoint;
            image[h][w].rgbtGreen = GreenPoint;
            image[h][w].rgbtRed = RedPoint;
            
            
        }
    }
}
void calcVert (int h, int w, int height, int width, RGBTRIPLE temp[height][width], int *blue, int *green, int *red)
{
            //row 1: [-1] [0] [+1]
            //row 2: [-2] [0] [+2]
            //row 3: [-1] [0] [+1] vertical kernel
    int cellCalc = 0;
    int totalRed = 0;
    int totalBlue = 0;
    int totalGreen = 0;
    //row 1
    for (int relativeH = -1; relativeH <= 1; relativeH++)
    {
        for (int relativeW = -1; relativeW <= 1; relativeW++)
        {
            //overreach cases
            if (h + relativeH < 0 && w + relativeW < 0)//top left corner
            {
                //set cell values
                if (relativeH == 0 && relativeW == -1) cellCalc = 0;
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 0;
                if (relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 1 && relativeW == 1) cellCalc = 1;
                if (relativeH == 0 && relativeW ==1) cellCalc = 2;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (h + relativeH < 0 && w + relativeW >= width)//top right corner
            {
                //set cell values
                if (relativeH == 0 && relativeW == -1) cellCalc = -2;
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = -1;
                if (relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 0 && relativeW ==1) cellCalc = 0;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (h + relativeH < 0)//top edge
            {
                //set cell values
                if (relativeH == 0 && relativeW == -1) cellCalc = -2;
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = -1;
                if (relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 1 && relativeW == 1) cellCalc = 1;
                if (relativeH == 0 && relativeW ==1) cellCalc = 2;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (w + relativeW < 0 && h + relativeH >= height)//bottom left corner
            {
                //set cell values
                if (relativeH == 0 && relativeW == -1) cellCalc = 0;
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 0;
                if (relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 1;
                if (relativeH == 1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 0 && relativeW ==1) cellCalc = 2;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (w + relativeW < 0)//left edge
            {
                //set cell values
                if (relativeH == 0 && relativeW == -1) cellCalc = 0;
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 0;
                if (relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 1;
                if (relativeH == 1 && relativeW == 1) cellCalc = 1;
                if (relativeH == 0 && relativeW ==1) cellCalc = 2;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (h + relativeH >= height && w + relativeW >= width)//bottom right corner
            {
                //set cell values
                if (relativeH == 0 && relativeW == -1) cellCalc = -2;
                if (relativeH == -1 && relativeW == -1) cellCalc = -1;
                if (relativeH == 1 && relativeW == -1) cellCalc = 0;
                if (relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 0 && relativeW ==1) cellCalc = 0;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (w + relativeW >= width)//right edge
            {
                //set cell values
                if (relativeH == 0 && relativeW == -1) cellCalc = -2;
                if (relativeH == -1 && relativeW == -1) cellCalc = -1;
                if (relativeH == 1 && relativeW == -1) cellCalc = -1;
                if (relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 0 && relativeW ==1) cellCalc = 0;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else //valid cases
            {
                //set cell values
                if (relativeH == 0 && relativeW == -1) cellCalc = -2;
                if (relativeH == -1 && relativeW == -1) cellCalc = -1;
                if (relativeH == 1 && relativeW == -1) cellCalc = -1;
                if (relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 1;
                if (relativeH == 1 && relativeW == 1) cellCalc = 1;
                if (relativeH == 0 && relativeW ==1) cellCalc = 2;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
        }
    }
}

void calcHori (int h, int w, int height, int width, RGBTRIPLE temp[height][width], int *blue, int *green, int *red)
{
            //row 1: [+1] [+2] [+1]
            //row 2: [ 0] [ 0] [ 0]
            //row 3: [-1] [-2] [-1]
    int cellCalc = 0;
    int totalRed = 0;
    int totalBlue = 0;
    int totalGreen = 0;
    //row 1
    for (int relativeH = -1; relativeH <= 1; relativeH++)
    {
        for (int relativeW = -1; relativeW <= 1; relativeW++)
        {
            //overreach cases
            if (h + relativeH < 0 && w + relativeW < 0)//top left corner
            {
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == -1 && relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 0;
                if (relativeH == 1 && relativeW == 0) cellCalc = 2;
                if (relativeH == 1 && relativeW == 1) cellCalc = 1;
            }
            else if (h + relativeH < 0 && w + relativeW >= width)//top right corner
            {
                //set cell values
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == -1 && relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 1;
                if (relativeH == 1 && relativeW == 0) cellCalc = 2;
                if (relativeH == 1 && relativeW == 1) cellCalc = 0;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (h + relativeH < 0)//top edge
            {
                //set cell values
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == -1 && relativeW == 0) cellCalc = 0;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 1;
                if (relativeH == 1 && relativeW == 0) cellCalc = 2;
                if (relativeH == 1 && relativeW == 1) cellCalc = 1;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (w + relativeW < 0 && h + relativeH >= height)//bottom left corner
            {
                //set cell values
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == -1 && relativeW == 0) cellCalc = -2;
                if (relativeH == -1 && relativeW == 1) cellCalc = -1;
                if (relativeH == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 0;
                if (relativeH == 1 && relativeW == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == 1) cellCalc = 0;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (w + relativeW < 0)//left edge
            {
                //set cell values
                if (relativeH == -1 && relativeW == -1) cellCalc = 0;
                if (relativeH == -1 && relativeW == 0) cellCalc = -2;
                if (relativeH == -1 && relativeW == 1) cellCalc = -1;
                if (relativeH == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 0;
                if (relativeH == 1 && relativeW == 0) cellCalc = 2;
                if (relativeH == 1 && relativeW == 1) cellCalc = 1;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (h + relativeH >= height && w + relativeW >= width)//bottom right corner
            {
                //set cell values
                if (relativeH == -1 && relativeW == -1) cellCalc = -1;
                if (relativeH == -1 && relativeW == 0) cellCalc = -2;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 0;
                if (relativeH == 1 && relativeW == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == 1) cellCalc = 0;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else if (w + relativeW >= width)//right edge
            {
                //set cell values
                if (relativeH == -1 && relativeW == -1) cellCalc = -1;
                if (relativeH == -1 && relativeW == 0) cellCalc = -2;
                if (relativeH == -1 && relativeW == 1) cellCalc = 0;
                if (relativeH == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 1;
                if (relativeH == 1 && relativeW == 0) cellCalc = 2;
                if (relativeH == 1 && relativeW == 1) cellCalc = 0;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
            else //valid cases
            {
                //set cell values
                if (relativeH == -1 && relativeW == -1) cellCalc = -1;
                if (relativeH == -1 && relativeW == 0) cellCalc = -2;
                if (relativeH == -1 && relativeW == 1) cellCalc = -1;
                if (relativeH == 0) cellCalc = 0;
                if (relativeH == 1 && relativeW == -1) cellCalc = 1;
                if (relativeH == 1 && relativeW == 0) cellCalc = 2;
                if (relativeH == 1 && relativeW == 1) cellCalc = 1;
                
                totalBlue += ((temp[h + relativeH][w + relativeW].rgbtBlue) * cellCalc);
                totalGreen += ((temp[h + relativeH][w + relativeW].rgbtGreen) * cellCalc);
                totalRed += ((temp[h + relativeH][w + relativeW].rgbtRed) * cellCalc);
                
                *blue = totalBlue;
                *green = totalGreen;
                *red = totalRed;
            }
        }
    }
}

Solution

  • Your code is indeed complicated and due to the number of tests per pixel, pretty inefficient. I strongly advise you to rewrite the function with the following structure:

    and for every row

    For application of the kernels, do not use a double loop but hard-code the formula (there are actually six terms, not nine). Splitting the processing in nine instances allows you to cleanly specialize the code on the borders.

    To avoid the repetitions for the RGB components, you may use helper functions, with some hope that they will be inlined by the compiler.