边缘检测不起作用!二维像素数组中的最后一个下标未正确显示

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

对于草率的代码或格式不正确的问题,我深表歉意,这是我的第一个 post!

此代码块的基本要点是使用 sobel 算子应用边缘检测。 我有一个 for 循环嵌套在一个 for 循环中以迭代单个像素,另一个嵌套的 for 循环迭代一个较小的 2D 数组以应用 sobel 运算符,但最后一行像素和一些右边缘无法正确解析。 非常感谢!

#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;
            }
        }
    }
}

您的代码确实很复杂,并且由于每个像素的测试数量,效率很低。我强烈建议您使用以下结构重写该函数:

  • 处理第一行;

  • 处理内部行的循环;

  • 处理最后一行;

并且对于每一行

  • 处理第一个像素;

  • 处理内列循环;

  • 处理最后一个像素。

对于内核的应用,不要使用双循环而是hard-code公式(实际上有六项,而不是九项)。将处理拆分为九个实例可以让您干净地专门化边界上的代码。

为了避免 RGB 组件的重复,您可以使用辅助函数,希望它们能被编译器内联。