Я застрял на CS50 Filter - Edges уже несколько дней, с трудом определяя, что не так с моим кодом. Этот код возвращает почти все белые изображения (что указывает на то, что окончательные значения слишком велики для каждого из пикселей). Любая помощь будет принята с благодарностью!
Я также проверил код моего друга и не вижу очевидных логических недостатков в коде, изображение в основном белое, и на изображении определенно не обнаружено краев.
void edges(int height, int width, RGBTRIPLE image[height][width])
{
//Create Gx and Gy Matrixes
int Gx[3][3] = {{-1,0,1},{-2,0,2},{-1,0,1}};
int Gy[3][3] = {{-1,-2,-1},{0,0,0},{1,2,1}};
//create copy of image
RGBTRIPLE copy[height][width];
for(int row=0; row<height;row++)
{
for(int col=0; col<width; col++)
{
copy[row][col].rgbtBlue=image[row][col].rgbtBlue;
copy[row][col].rgbtRed=image[row][col].rgbtRed;
copy[row][col].rgbtGreen=image[row][col].rgbtGreen;
}
}
//create loop for edge detection
int red; int blue; int green;
double Gxsum[3]; double Gysum[3]; double finalval[3];
int icount; int jcount;
for(int row=0; row<height; row++)//inside image loop
{
for(int col=0; col<width; col++)
{
Gxsum[0]=0.0; Gxsum[1]=0.0; Gxsum[2]=0.0;
Gysum[0]=0.0; Gysum[1]=0.0; Gysum[2]=0.0;
icount=0; jcount=0;
for(int i=row-1; i<=row+1; i++)//inside 3x3 loop
{
for(int j=col-1; j<=col+1; j++)
{
if (i<0||j<0||i>=height||j>=width)
{
red=0.0;blue=0.0;green=0.0;
}
else
{
red=copy[i][j].rgbtRed;
blue=copy[i][j].rgbtBlue;
green=copy[i][j].rgbtGreen;
Gxsum[0]+=Gx[icount][jcount]*red;
Gxsum[1]+=Gx[icount][jcount]*blue;
Gxsum[2]+=Gx[icount][jcount]*green;
Gysum[0]+=Gy[icount][jcount]*red;
Gysum[1]+=Gy[icount][jcount]*blue;
Gysum[2]+=Gy[icount][jcount]*green;
}
jcount++;
}
icount++;
}
finalval[0]=round(sqrt(Gxsum[0]*Gxsum[0] + Gysum[0]*Gysum[0]));//red
finalval[1]=round(sqrt(Gxsum[1]*Gxsum[1] + Gysum[1]*Gysum[1]));//blue
finalval[2]=round(sqrt(Gxsum[2]*Gxsum[2] + Gysum[2]*Gysum[2]));//green
for(int k=0; k<3; k++)
{
if (finalval[k]>255)
{
finalval[k]=255;
}
}
//now assign image pixel to newvals;
image[row][col].rgbtRed=(int)finalval[0];
image[row][col].rgbtBlue=(int)finalval[1];
image[row][col].rgbtGreen=(int)finalval[2];
}
}
return;
}
Я думаю, что ваш код содержит ошибку компиляции и ошибку времени выполнения. Когда вы выполняете, вы просто запускаете версию материала курса. Следовательно, в результате получается белое изображение.
Во-первых, вам нужно #include <math.h>
использовать sqrt()
, round()
. Во-вторых, есть логическая ошибка, когда вы забыли сбросить jcount
на 0 после завершения каждой строки. Когда jcount
становится равным 3, он выходит за пределы индекса массива.
Ниже моя исправленная, упрощенная версия
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
//Create Gx and Gy Matrixes
int gx[3][3] = { {-1,0,1},{-2,0,2},{-1,0,1} };
int gy[3][3] = { {-1,-2,-1},{0,0,0},{1,2,1} };
// max of each channel
const int channelCap = 255;
//create copy of image
RGBTRIPLE copy[height][width];
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
copy[row][col].rgbtBlue = image[row][col].rgbtBlue;
copy[row][col].rgbtRed = image[row][col].rgbtRed;
copy[row][col].rgbtGreen = image[row][col].rgbtGreen;
}
}
//create loop for edge detection
int red; int blue; int green;
double finalRed, finalGreen, finalBlue;
double gxRed, gxGreen, gxBlue;
double gyRed, gyGreen, gyBlue;
for (int row = 0; row < height; row++)//inside image loop
{
for (int col = 0; col < width; col++)
{
gxRed = 0.0; gxGreen = 0.0; gxBlue = 0.0;
gyRed = 0.0; gyGreen = 0.0; gyBlue = 0.0;
int icount = 0, jcount = 0;
for (int i = row - 1; i <= row + 1; i++)//inside 3x3 loop
{
for (int j = col - 1; j <= col + 1; j++)
{
if (i >= 0 && j >= 0 && i < height && j < width)
{
// within boundary
red = copy[i][j].rgbtRed;
blue = copy[i][j].rgbtBlue;
green = copy[i][j].rgbtGreen;
gxRed += gx[icount][jcount] * red;
gxBlue += gx[icount][jcount] * blue;
gxGreen += gx[icount][jcount] * green;
gyRed += gy[icount][jcount] * red;
gyBlue += gy[icount][jcount] * blue;
gyGreen += gy[icount][jcount] * green;
}
jcount++;
}
icount++;
jcount = 0;
}
finalRed = fmin(round(sqrt(gxRed * gxRed + gyRed * gyRed)), channelCap);//red
finalBlue = fmin(round(sqrt(gxBlue * gxBlue + gyBlue * gyBlue)), channelCap);//blue
finalGreen = fmin(round(sqrt(gxGreen * gxGreen + gyGreen * gyGreen)), channelCap);//green
//now assign image pixel to newvals;
image[row][col].rgbtRed = (int)finalRed;
image[row][col].rgbtBlue = (int)finalBlue;
image[row][col].rgbtGreen = (int)finalGreen;
}
}
return;
}
$ ./filter -e ./images/yard.bmp outfile.bmp
Результат:
СПАСИБО БОЛЬШОЕ, @Mr. Бриковски, твой комментарий о моей логической ошибке попал в самую точку!! --> проблема не инициализируется jcount после завершения строки. мой код работает сейчас! Спасибо Спасибо спасибо
Пробовали ли вы отлаживать этот код с помощью
debug50
, как показано в лекции второй недели?