when I run make filter it compiles but when I'm running it it does this... helpers.c:104:39: runtime error: -nan is outside the range of representable values of type 'int'
void blur(int height, int width, RGBTRIPLE image[height][width])
{
float red = 0, blue = 0, green = 0;
int average_red[height][width], average_blue[height][width], average_green[height][width];
float count = 0;
// LOOP HEIGHT
for (int i = 0; height > i; i++)
{
// LOOP WIDTH
for (int j = 0; width > j; j++)
{
// LOOP 3x3 PIXELS
for (int x = i - 1; i > x; x++)
{
for (int y = j - 1; j > y; y++)
{
// ONLY ACCEPT PIXELS WITHIN THE IMAGE
if ((x >= 0 && x < height) || (y >= 0 && y < width))
{
red += image[x][y].rgbtRed;
blue += image[x][y].rgbtBlue;
green += image[x][y].rgbtGreen;
count++;
}
}
}
// GET THE AVERAGE
average_red[i][j] = limit(round(red / count));
average_blue[i][j] = limit(round(blue / count));
average_green[i][j] = limit(round(green / count));
// RESET ALL VALUE
red = 0;
blue = 0;
green = 0;
count = 0;
}
}
// LOOP HEIGHT
for (int i = 0; height > i; i++)
{
// LOOP WIDTH
for (int j = 0; width > j; j++)
{
// RETURN THE VALUE BY COLOR TO RESPECTIVE PIXELS
image[i][j].rgbtRed = average_red[i][j];
image[i][j].rgbtBlue = average_blue[i][j];
image[i][j].rgbtGreen = average_green[i][j];
}
}
return;
}
for the inner loops I used
for (int col = i - 1; i + 2 > col; col++)
{
for (int row = j - 1; j + 2 > row; row++)
{
if (col >= 0 && col < height && row >= 0 && row < width)
{
red += image[col][row].rgbtRed;
blue += image[col][row].rgbtBlue;
green += image[col][row].rgbtGreen;
count++;
}
}
}
Related
I am currently working on the blur function in PSET4 for filter-more, and I am struggling to find the bug in my code. The blur function seems to correctly filter the middle pixel and I would assume other pixels that are not on the edges, but is incorrectly filtering those on the corners and edges. Any nudges in the right direction would be greatly appreciated.
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// Copy to store filtered image into
RGBTRIPLE temp[height][width];
int red_total = 0, blue_total = 0, green_total = 0;
int red_average = 0, blue_average = 0, green_average = 0;
// Goes through each pixel [i][j]
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
// Loops through surrounding 3x3 grid and records the average of all of them
for (int h = -1; h < 2; h++)
{
// Checks if the current row is within the image array
if (i + h >= 0 && i + h < height)
{
for (int k = -1; k < 2; k++)
{
// Checks if current column is within image array
if (j + k >= 0 && j + k < width)
{
red_total = red_total + image[i + h][j + k].rgbtRed;
blue_total = blue_total + image[i + h][j + k].rgbtBlue;
green_total = green_total + image[i + h][j + k].rgbtGreen;
}
else continue;
}
}
else continue;
}
// Averages and reassigns pixel value
red_average = round(red_total / 9.0);
blue_average = round(blue_total / 9.0);
green_average = round(green_total / 9.0);
temp[i][j].rgbtBlue = blue_average;
temp[i][j].rgbtRed = red_average;
temp[i][j].rgbtGreen = green_average;
// Resets counter variables
red_total = green_total = blue_total = 0;
red_average = blue_average = green_average = 0;
}
}
// Makes image (original) array equal to the filtered image
for (int x = 0; x < height; x++)
{
for(int y = 0; y < width; y++)
{
image[x][y] = temp[x][y];
}
}
return;
}
Good day,
I have written the code for CS50 blur filter and I understand there's a better way to code it (with less if statements), but before rewriting I would like to understand why it doesn't work at the moment. It produces a very dark image, it seems the RGB values are too low. I am stuck and would gladly welcome some help. Thank you.
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE temp[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int counter = 1;
temp[i][j].rgbtRed = image[i][j].rgbtRed;
temp[i][j].rgbtGreen = image[i][j].rgbtGreen;
temp[i][j].rgbtBlue = image[i][j].rgbtBlue;
if (i != height - 1)
{
temp[i][j].rgbtRed += image[i+1][j].rgbtRed;
temp[i][j].rgbtGreen += image[i+1][j].rgbtGreen;
temp[i][j].rgbtBlue += image[i+1][j].rgbtBlue;
counter++;
}
if (i != 0)
{
temp[i][j].rgbtRed += image[i-1][j].rgbtRed;
temp[i][j].rgbtGreen += image[i-1][j].rgbtGreen;
temp[i][j].rgbtBlue += image[i-1][j].rgbtBlue;
counter++;
}
if (j != width - 1)
{
temp[i][j].rgbtRed += image[i][j+1].rgbtRed;
temp[i][j].rgbtGreen += image[i][j+1].rgbtGreen;
temp[i][j].rgbtBlue += image[i][j+1].rgbtBlue;
counter++;
}
if (j != 0)
{
temp[i][j].rgbtRed += image[i][j-1].rgbtRed;
temp[i][j].rgbtGreen += image[i][j-1].rgbtGreen;
temp[i][j].rgbtBlue += image[i][j-1].rgbtBlue;
counter++;
}
if (i != 0 && j != 0)
{
temp[i][j].rgbtRed += image[i-1][j-1].rgbtRed;
temp[i][j].rgbtGreen += image[i-1][j-1].rgbtGreen;
temp[i][j].rgbtBlue += image[i-1][j-1].rgbtBlue;
counter++;
}
if (i != height - 1 && j != width - 1)
{
temp[i][j].rgbtRed += image[i+1][j+1].rgbtRed;
temp[i][j].rgbtGreen += image[i+1][j+1].rgbtGreen;
temp[i][j].rgbtBlue += image[i+1][j+1].rgbtBlue;
counter++;
}
if (i != height - 1 && j != 0)
{
temp[i][j].rgbtRed += image[i+1][j-1].rgbtRed;
temp[i][j].rgbtGreen += image[i+1][j-1].rgbtGreen;
temp[i][j].rgbtBlue += image[i+1][j-1].rgbtBlue;
counter++;
}
if (i != 0 && j != width - 1)
{
temp[i][j].rgbtRed += image[i-1][j+1].rgbtRed;
temp[i][j].rgbtGreen += image[i-1][j+1].rgbtGreen;
temp[i][j].rgbtBlue += image[i-1][j+1].rgbtBlue;
counter++;
}
image[i][j].rgbtRed = round(temp[i][j].rgbtRed / (counter * 1.0));
image[i][j].rgbtGreen = round(temp[i][j].rgbtGreen / (counter * 1.0));
image[i][j].rgbtBlue = round(temp[i][j].rgbtBlue / (counter * 1.0));
}
}
return;
}
why it doesn't work at the moment. It produces a very dark image
The sum formed via temp[i][j].rgbtRed += image[i+1][j].rgbtRed; and the like is overflowing temp[i][j].rgbtRed. #Weather Vane. The later division lowers the truncated sum toward black.
Use a wider type for the sum.
// RGBTRIPLE temp[height][width];
int r,g,b; // If temp[i][j].rgbtRed width less than int, else use long, etc.
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
...
// temp[i][j].rgbtRed += image[i+1][j].rgbtRed;
// temp[i][j].rgbtGreen += image[i+1][j].rgbtGreen;
// temp[i][j].rgbtBlue += image[i+1][j].rgbtBlue;
r += image[i+1][j].rgbtRed;
g += image[i+1][j].rgbtGreen;
b += image[i+1][j].rgbtBlue;
Untested candidate simplification:
void blur(int height, int width, RGBTRIPLE image[height][width]) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int r = 0;
int g = 0;
int b = 0;
int counter = 0;
for (int di = max(i - 1, 0); di < min(i + 2, height); di++) {
for (int dj = max(j - 1, 0); dj < min(j + 2, width); dj++) {
r += image[di][dj].rgbtRed;
g += image[di][dj].rgbtGreen;
b += image[di][dj].rgbtBlue;
counter++;
}
}
// simplified rounding
image[i][j].rgbtRed = (r + counter / 2) / counter;
image[i][j].rgbtGreen = (g + counter / 2) / counter;
image[i][j].rgbtBlue = (b + counter / 2) / counter;
}
}
}
I couldn't figure out why the blur doesn't work when I check with check50. The image becomes blurry, but the RGB values are wrong. I'm not sure what I did wrong. If anyone knows, please do tell.
This is the picture of my
results in check50.
This is my code:
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE copy[height][width];
// Copy image
for (int h = 0; h < height; h++)
{
for (int w = 0; w < width; w++)
{
copy[h][w] = image[h][w];
}
}
for (int h = 0; h < height; h++)
{
for (int w = 0; w < width; w++)
{
int row[] = { h - 1, h, h + 1 };
int col[] = { w - 1, w, w + 1 };
int R = 0;
int G = 0;
int B = 0;
int num = 0;
for (int x = 0; x < 3; x++)
{
// Check whether they are in frame
if (row[x] < 0 || row[x] >= height)
{
continue;
}
if (col[x] < 0 || col[x] >= width)
{
continue;
}
// Add up the value
R += copy[row[x]][col[x]].rgbtRed;
G += copy[row[x]][col[x]].rgbtGreen;
B += copy[row[x]][col[x]].rgbtBlue;
num++;
}
// Average
int blurRed = round(R / num);
int blurGreen = round(G / num);
int blurBlue = round(B / num);
// Update pixel
image[h][w].rgbtRed = blurRed;
image[h][w].rgbtGreen = blurGreen;
image[h][w].rgbtBlue = blurBlue;
}
}
return;
}
So I've finished my edges function and I can't wrap my head around why it fails. Any help would be greatly appreciated! The edges function is supposed to detect edges in a bitmap.
Here is my edges function:
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
// Copy of image so that we calculate based on the original values of RGB
RGBTRIPLE copy[height][width];
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; ++j)
{
copy[i][j] = image[i][j];
}
}
// Stores RGB values of each pixel in grid
RGBTRIPLE grid[3][3];
// Iterate over every pixel and alter its RGB values
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; ++j)
{
reset(grid);
// Includes current pixel in center of 3 x 3 grid
grid[1][1] = copy[i][j];
// Checks if left edge exists and if so, assigns to left edge in 3 x 3 grid
if (j != 0)
{
grid[1][0] = copy[i][j - 1];
}
// Checks if right edge exists
if (j + 1 != width)
{
grid[1][2] = copy[i][j + 1];
}
// Checks if top edge exists
if (i != 0)
{
grid[0][1] = copy[i - 1][j];
}
// Checks if bottom edge exists
if (i + 1 != height)
{
grid[2][1] = copy[i + 1][j];
}
// Checks if top left corner exists
if (i != 0 && j != 0)
{
grid[0][0] = copy[i - 1][j - 1];
}
// Checks if top right corner exists
if (i != 0 && j + 1 != width)
{
grid[0][2] = copy[i - 1][j + 1];
}
// Checks if bottom left corner exists
if (i + 1 != height && j != 0)
{
grid[2][0] = copy[i + 1][j - 1];
}
// Checks if bottom right corner exists
if (i + 1 != height && j + 1 != width)
{
grid[2][2] = copy[i + 1][j + 1];
}
// Store products of x version and y version
RGBTRIPLE XX[3][3], YY[3][3];
duplicate(grid, XX);
duplicate(grid, YY);
// Multiplies each pixel in grid by corresponding values for x version
multiply(&XX[0][0], -1);
multiply(&XX[2][0], -1);
multiply(&XX[1][0], -2);
multiply(&XX[1][2], 2);
multiply(&XX[0][2], 1);
multiply(&XX[2][0], 1);
multiply(&XX[0][1], 0);
multiply(&XX[1][1], 0);
multiply(&XX[2][1], 0);
// Multiplies each pixel in grid by corresponding values for y version
multiply(&YY[0][0], -1);
multiply(&YY[0][2], -1);
multiply(&YY[0][1], -2);
multiply(&YY[2][1], 2);
multiply(&YY[2][0], 1);
multiply(&YY[2][2], 1);
multiply(&YY[1][0], 0);
multiply(&YY[1][1], 0);
multiply(&YY[1][2], 0);
// Stores sum of the products for x and y version
RGBTRIPLE Gx, Gy;
Gx.rgbtRed = Gx.rgbtGreen = Gx.rgbtBlue = Gy.rgbtRed = Gy.rgbtGreen = Gy.rgbtBlue = 0;
sum(&Gx, XX);
sum(&Gy, YY);
set_pixel(Gx, Gy, &image[i][j]);
}
}
}
Here are the functions that support edges:
// Sets new RGB values for a pixel
void set_pixel(RGBTRIPLE Gx, RGBTRIPLE Gy, RGBTRIPLE *pixel)
{
int red, green, blue;
red = (int) round(sqrt((Gx.rgbtRed * Gx.rgbtRed) + (Gy.rgbtRed * Gy.rgbtRed)));
green = (int) round(sqrt((Gx.rgbtGreen * Gx.rgbtGreen) + (Gy.rgbtGreen * Gy.rgbtGreen)));
blue = (int) round(sqrt((Gx.rgbtBlue * Gx.rgbtBlue) + (Gy.rgbtBlue * Gy.rgbtBlue)));
if (red > 255)
{
red = 255;
}
if (green > 255)
{
green = 255;
}
if (blue > 255)
{
blue = 255;
}
pixel->rgbtRed = red;
pixel->rgbtGreen = green;
pixel->rgbtBlue = blue;
}
// Adds the products for each colour together
void sum(RGBTRIPLE *sum, RGBTRIPLE g[3][3])
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
sum->rgbtRed += g[i][j].rgbtRed;
sum->rgbtGreen += g[i][j].rgbtGreen;
sum->rgbtBlue += g[i][j].rgbtBlue;
}
}
}
// Copies 3 x 3 grid into XX or YY
void duplicate(RGBTRIPLE grid[3][3], RGBTRIPLE c[3][3])
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
c[i][j] = grid[i][j];
}
}
}
// Resets 3 x 3 grid all to 0
void reset(RGBTRIPLE grid[3][3])
{
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j)
{
grid[i][j].rgbtRed = grid[i][j].rgbtGreen = grid[i][j].rgbtBlue = 0;
}
}
}
// Multiplies the amount of each colour by a given factor
void multiply(RGBTRIPLE *x, int factor)
{
x->rgbtRed *= factor;
x->rgbtGreen *= factor;
x->rgbtBlue *= factor;
}
For more info, here's what check50 says:
https://submit.cs50.io/check50/081a89d81042ad121b7f63d2af8deaf8225cca71
This is the output and input image that my code generates: https://imgur.com/a/mT7YqCD
The following code is for the blur function, all the supporting code is untouched from pset4.
void blur(int height, int width, RGBTRIPLE image[height] [width])
{
RGBTRIPLE newImage[height][width];
for (int h = 0; h < height; h++)
{
for (int w = 0; w < width; w++)
{
BYTE redAvg = 0;
BYTE greenAvg = 0;
BYTE blueAvg = 0;
BYTE count = 0;
for (int y = -1; y <= 1; y++)
{
for (int x = -1; x <= 1; x++)
{
int h_1 = h + y;
int w_1 = w + x;
if (h_1 >= 0 && h_1 < height && w_1 >= 0 && w_1 < width)
{
count++;
redAvg += image[h_1][w_1].rgbtRed;
greenAvg += image[h_1][w_1].rgbtGreen;
blueAvg += image[h_1][w_1].rgbtBlue;
}
}
}
newImage[h][w].rgbtRed = redAvg/count;
newImage[h][w].rgbtGreen = greenAvg/count;
newImage[h][w].rgbtBlue = blueAvg/count;
}
}
for (int x = 0; x < height; x++)
{
for (int y = 0; y <width; y++)
{
image[x][y] = newImage[x][y];
}
}
return;
}