问题描述
我很抱歉出现草率的代码或格式错误的问题,这是我的第一篇帖子!
此代码块的基本要点是对sobel运算符应用边缘检测。 我有一个for循环嵌套在一个for循环中,以迭代遍历各个像素,另一个嵌套的for循环中,迭代遍历较小的2D数组以应用sobel运算符,但是最后一行像素和一些右边缘arent正确解析。 非常感谢!
#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 *red);
// Detect edges
void edges(int height,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,&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 *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 *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;
}
}
}
}
解决方法
您的代码确实很复杂,并且由于每个像素的测试次数很多,因此效率很低。我强烈建议您使用以下结构重写该函数:
-
第一行的处理;
-
内部行的处理循环;
-
最后一行的处理;
以及每一行
-
第一个像素的处理;
内列上的 -
处理循环;
-
处理最后一个像素。
对于内核的应用,不要使用双循环,而要对公式进行硬编码(实际上有六个术语,而不是九个)。将处理分成9个实例,使您可以清晰地对边界上的代码进行专业化处理。
为避免RGB组件重复,可以使用辅助函数,并希望编译器可以内联它们。