CS50x Blur Function - c

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

Related

My code cant blur a whole image but it can blur a single pixel in any part of the image

I've been doing the cs50x course but I'm stuck in the problem set 4, more precisely in the blur function, where I got to create a function that blurs a .bmp image. To blur it I need to do the average of each pixel that surrounds the pixel I'm blurring (him included).
My code works fine in the edge, corner, and middle pixels, but it doesn't work right for a whole 3x3 or 4x4 picture I've been trying everything but nothing seems to fix it.
This is what I got when I run check50: https://submit.cs50.io/check50/011dfd20a431c4e972f8789c677ed60438c5b133
void blur(int height, int width, RGBTRIPLE image[height][width])
{
//temporary variable to store the colour values
RGBTRIPLE copy[height][width];
//loop through each pixel and get the average value for each colour
for (int i=0;i<height;i++)
{
for (int j=0;j<width;j++)
{
float sumRed = 0, sumBlue = 0, sumGreen = 0;
int averageRed = 0, averageBlue = 0, averageGreen = 0, pixels=0, begginingheight =
i-1, endheight = i+1, begginingwidth = j-1, endwidth = j+1;
//height to take the average of the blur in each pixel
if (begginingheight < 0)
{
begginingheight = 0;
endheight = 1;
}
else if(begginingheight == height-1)
{
begginingheight = height-2;
endheight = height-1;
}
else
{
begginingheight = i-1;
endheight = i+1;
}
//width to take the average of the blur in each pixel
if(begginingwidth < 0)
{
begginingwidth = 0;
endwidth = 1;
}
else if(begginingwidth == width-1)
{
begginingwidth = width-2;
endwidth =width-1;
}
else
{
begginingwidth = j-1;
endwidth = j+1;
}
//get the sum of the box that he forms
for (int k = begginingheight; k <= endheight; k++)
{
for (int z = begginingwidth; z <= endwidth; z++)
{
sumRed += image[k][z].rgbtRed;
sumBlue += image[k][z].rgbtBlue;
sumGreen += image[k][z].rgbtGreen;
pixels+=1;
}
}
//calculate their average
averageRed = round(sumRed/pixels);
averageBlue = round(sumBlue/pixels);
averageGreen = round(sumGreen/pixels);
//use the copy to store the colour value
copy[i][j].rgbtRed = averageRed;
copy[i][j].rgbtBlue = averageBlue;
copy[i][j].rgbtGreen = averageGreen;
}
}
for (int i=0;i<height;i++)
{
for(int j=0;j<width;j++)
{
//copy the 2d copy into the true image
image[i][j].rgbtRed = copy[i][j].rgbtRed;
image[i][j].rgbtBlue = copy[i][j].rgbtBlue;
image[i][j].rgbtGreen = copy[i][j].rgbtGreen;
}
}
return;
}

CS50(2021) Filter - Blur

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

CS50 "BLUR" PSET 4

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

pset4 filter edges function fails check50 completely

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

Having Trouble With CS50 Pset4 Filter, Blur Effect

#include "helpers.h"
#include <math.h>
// Convert image to grayscale
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
int total = 0;
float avg = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
total = image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue;
avg = total / 3.00;
image[i][j].rgbtRed = round(avg);
image[i][j].rgbtGreen = round(avg);
image[i][j].rgbtBlue = round(avg);
}
}
return;
}
// Convert image to sepia
void sepia(int height, int width, RGBTRIPLE image[height][width])
{
float sepia_red = 0;
float sepia_green = 0;
float sepia_blue = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
sepia_red = (.393 * image[i][j].rgbtRed + .769 * image[i][j].rgbtGreen + .189 * image[i][j].rgbtBlue);
sepia_green = (.349*image[i][j].rgbtRed) + (.686*image[i][j].rgbtGreen) + (.168*image[i][j].rgbtBlue);
sepia_blue = (.272*image[i][j].rgbtRed) + (.534*image[i][j].rgbtGreen) + (.131*image[i][j].rgbtBlue);
if (sepia_red > 255)
{
sepia_red = 255;
}
if (sepia_green > 255)
{
sepia_green = 255;
}
if (sepia_blue > 255)
{
sepia_blue = 255;
}
image[i][j].rgbtRed = round(sepia_red);
image[i][j].rgbtGreen = round(sepia_green);
image[i][j].rgbtBlue = round(sepia_blue);
}
}
return;
}
// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
int temp[3];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width/2; j ++)
{
temp[0] = image[i][j].rgbtRed;
temp[1] = image[i][j].rgbtGreen;
temp[2] = image[i][j].rgbtBlue;
image[i][j].rgbtRed = image[i][width - j - 1].rgbtRed;
image[i][j].rgbtGreen = image[i][width - j - 1].rgbtGreen;
image[i][j].rgbtBlue = image[i][width - j - 1].rgbtBlue;
image[i][width - j - 1].rgbtRed = temp[0];
image[i][width - j - 1].rgbtGreen = temp[1];
image[i][width - j - 1].rgbtBlue = temp[2];
}
}
return;
}
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
int total = 0;
float count = 0;
int elements = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
for (int x = i - 1; x <= i + 1; x++)
{
if (x >= 0 && x <= height - 1)
{
elements++;
}
}
for (int y = j - 1; y <= j + 1; y++)
{
if (y >= 0 && y < width - 1)
{
elements++;
}
}
total = image[i][j].rgbtRed + image[i][j].rgbtGreen + image[i][j].rgbtBlue;
count = total / elements;
image[i][j].rgbtRed = round(count);
image[i][j].rgbtGreen = round(count);
image[i][j].rgbtBlue = round(count);
}
}
return;
}
After a few reddit posts, I have been told I need to
create a temporary variable and then once that has been created go about changing the original pixels to the value fo the temporary variable
create an incrementing variable such as (int pixels_used) to divide by
I do not know how to go about this, dividing by the incrementing variable troubles me because I would think I have to create red_count, blue_count, green_count and pixels_used.
I tried writing this form of code out here https://pastebin.com/UX1miGtd as it is similar to the example Brian gave us in this picture https://i.stack.imgur.com/K7rVL.png. We add up the total amount of red, green and blue – and then assign the selected pixel to those numbers. Obviously based off the amount of variables I had to use it does not look good and I assume is wrong, but I don't have any other ideas.
If anyone can help I would greatly appreciate!

Resources