My blur filter doesn't seem to working correctly, even though if I test it using sample pictures they are blurred - c

Currently I am doing a computer course in which I have to write a blur filter for .BMG images.
The filter loads the pictures correctly, and creates new ones based on my filter.
I have tested the blur filter using sample pictures, and it seems to work (to my eye).
However the course has an auto grader in which I can see that my results differ.
Here is a link to my results, scroll all the way down to see the results for the blurr function:
https://submit.cs50.io/check50/73d0a0da48b323a1a8e306fc0ef528cd2df269c3
Here is the code that I wrote to solve this problem:
// Blur image
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++)
{
TEMP[i][j].rgbtRed = image[i][j].rgbtRed;
TEMP[i][j].rgbtGreen = image[i][j].rgbtGreen;
TEMP[i][j].rgbtBlue = image[i][j].rgbtBlue;
}
}
// this forloop will read in the height
for(int i = 0; i < height; i++)
{
// this forloop will read in the with
for(int j = 0; j < width; j++)
{
float count = 0;
float red = 0;
float green = 0;
float blue= 0;
// this forloop will loop three times, for the average filter
for(int q = -1; q < 2; q++)
{
// this forloop will loop three times, making the total 9 for each pixel
for(int w = -1; w < 2; w++)
{
// this if statement makes sure that the I stay within the pixel I J array
if(w >= 0 && w < width && q >= 0 && q < height)
{
red += TEMP[i+q][j+w].rgbtRed;
green += TEMP[i+q][j+w].rgbtGreen;
blue += TEMP[i+q][j+w].rgbtBlue;
count ++;
}
else
{
continue;
}
}
}
// this should set the [i][j] value of each colour to the average of the values
image[i][j].rgbtRed = round(red/count);
image[i][j].rgbtGreen = round(green/count);
image[i][j].rgbtBlue = round(blue/count);
}
}
}
Hopefully someone can help me with my mistake.

Related

CS50 PS4 filter-less blur

I'm having issues getting my code to return correct values and I can't stare at it anymore or my eyeballs will fall out.
Specifically, the test I've failed are
-blur correctly filters middle pixel
-blur correctly filters pixel on edge
-blur correctly filters 3x3 image
-blur correctly filters 4x4 image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++) // Go through rows
{
for (int j = 0; j < width; j++) // Go through columns
{
// Reset counters
float totalblue = 0.0; // Total of values
float totalgreen = 0.0; // Total of values
float totalred = 0.0; // Total of values
int counter = 0;
for (int k = -1; k < 2; k++) // To make 3x3 square
{
for (int l = -1; l < 2; l++) // To make 3x3 square
{
if (i + k >= 0 && i + k < height && j + l >= 0 && j + j < width) // Determine if pixel exists
{
// Update totals
totalblue += image[i+k][j+l].rgbtBlue;
totalgreen += image[i+k][j+l].rgbtGreen;
totalred += image[i+k][j+l].rgbtRed;
counter++;
}
}
}
// Set new values
image[i][j].rgbtBlue = round(totalblue / counter);
image[i][j].rgbtGreen = round(totalgreen / counter);
image[i][j].rgbtRed = round(totalred / counter);
}
}
return;
}
I've tried playing with the data type (but that doesn't seem to be the issue) and reworking the parameters for determining whether a pixel exists. It seems like that test is what's giving me the problem? Or an issue with my counting?

pset4 blur Segmentation fault

I'm stuck on my code for too much time now and needing some help. I'm working on CS50 pset4 blur filter and I keep getting either a "Segmentation fault" or "Floating point exception" depending if try to change my " neighbour variables" on float instead of int. Can someone have any idea what I'm doing wrong with that ?
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// Copy image to "copy"
RGBTRIPLE copy[height][width];
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
copy[i][j] = image[i][j];
}
}
// Loop through all the neighbour's pixel and calculate the average RGB in each
int RedNeighbour = 0; int BlueNeighbour = 0; int GreenNeighbour = 0; int neighbourSum = 0;
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
for(int k = i - 1; k < i + 1; k++)
{
for(int l = j - 1 ; l < j + 1; l++)
{
if(k >= 0 && k < height && l >= 0 && l < width)
{
RedNeighbour += copy[l][k].rgbtRed;
BlueNeighbour += copy[l][k].rgbtBlue;
GreenNeighbour += copy[l][k].rgbtGreen;
neighbourSum++;
}
else
{
continue;
}
}
}
// Divide each color by the sum of the neighbouring pixels and copy the pixe into original image
image[i][j].rgbtRed = round(fmin(255, RedNeighbour/neighbourSum));
image[i][j].rgbtBlue = round(fmin(255, BlueNeighbour/neighbourSum));
image[i][j].rgbtGreen = round(fmin(255, GreenNeighbour/neighbourSum));
}
}
return;
}
Thanks !
I'd recommend just using a debugger (gdb, or your IDE's if you're using one) for that kind of thing.
That said, I'm noticing that on the following lines, you are potentially accessing out of bound indices in your copy array:
RedNeighbour += copy[l][k].rgbtRed;
BlueNeighbour += copy[l][k].rgbtBlue;
GreenNeighbour += copy[l][k].rgbtGreen;
In your code, l is constrained by your width, while k is constrained by your height. However, the definition of the copy array is RGBTRIPLE copy[height][width];, which means that you should probably be accessing your copy array with copy[k][l] rather than copy[l][k].

CS50 Pset4 Filter (less comfortable) blur function Algorithmic Issue

info about this task
when I try to implement blur function, It works fine to me on a picture, but check50 (cs50 test program) gives warning for my outputs.
Here is my code
void blur(int height, int width, RGBTRIPLE image[height][width])
{
float average_red = 0;
float average_green = 0;
float average_blue = 0;
float count = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
// reset values
average_red = 0;
average_blue = 0;
average_green = 0;
count = 0;
// look for around a pixel 3x3 box
// column
for (int k = i - 1; k < i + 2; k++)
{
// row
for (int l = j - 1; l < j + 2; l++)
{
// if pixel on the top
if (k == -1)
{
// it skips a column because it is out of the border
break;
}
// if pixel is on the left side
if (l == -1)
{
// skips a row otherwise it is out of the border
continue;
}
// if pixel passes the bottom
if (k >= height)
{
break;
}
// if pixels passes the right side
if (l >= width)
{
continue;
}
// everything else
else
{
average_red += image[k][l].rgbtRed;
average_green += image[k][l].rgbtGreen;
average_blue += image[k][l].rgbtBlue;
count++;
}
}
}
average_red /= count;
average_green /= count;
average_blue /= count;
image[i][j].rgbtRed = round(average_red);
image[i][j].rgbtGreen = round(average_green);
image[i][j].rgbtBlue = round(average_blue);
}
}
return;
}
expected output vs my output is here (blur functions output very down bellow)
It is working fine on the corner but other pixel values are very close to correct output, but not the same.
Any help appreciated
The code needs to take several factors into consideration. Suggest:
if the resulting row number is <0 or >(height-1) then don't calc that pixel
if the resulting column number is <0 or >(width-1) then don't calc that pixel
Therefore, for each of the surrounding 8 pixels, apply the two above criteria.
I solved my own problem, thanks for helps anyway
problem in was my sum calculation. it keeps result in image[i][j] and than again uses this value again.
I copy image values to a new value and use on this. Here is my code
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// copy original value to a new value to keep changing values
RGBTRIPLE copy[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
copy[i][j] = image[i][j];
}
}
float average_red = 0.0f;
float average_green = 0.0f;
float average_blue = 0.0f;
float count = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
// reset values
average_red = 0.0f;
average_blue = 0.0f;
average_green = 0.0f;
count = 0;
// look for around a pixel 3x3 box
// column
for (int k = i - 1; k < i + 2; k++)
{
// row
for (int l = j - 1; l < j + 2; l++)
{
// if pixel on the top
if (k == -1)
{
// it skips a column because it is out of the border
break;
}
// if pixel is on the left side
else if (l == -1)
{
// skips a row otherwise it is out of the border
continue;
}
// if pixel passes the bottom
else if (k >= height)
{
break;
}
// if pixels passes the right side
else if (l >= width)
{
continue;
}
// everything else
else
{
average_red += copy[k][l].rgbtRed;
average_green += copy[k][l].rgbtGreen;
average_blue += copy[k][l].rgbtBlue;
count++;
}
}
}
average_red /= count;
average_green /= count;
average_blue /= count;
image[i][j].rgbtRed = round(average_red);
image[i][j].rgbtGreen = round(average_green);
image[i][j].rgbtBlue = round(average_blue);
}
}
return;
}

Blur function for cs50 PSET4, where are the errors?

I have been stuck with this function for days now. I looked at other people questions, I watched youtube tutorials videos, but I can't get it right.
The task is part of Harvard's CS50 course (https://cs50.harvard.edu/x/2020/psets/4/filter/less/).
Any kind of help would be much appreciated! I really don't want to go on with the course without understanding what the problem is.
//check if pixels are valid
bool valid_pixel(int r, int c, int height, int width)
{
return r >= 0 && c >= 0 && r < height && c < width;
}
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
//create a copy of the original image
RGBTRIPLE temp[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
temp[i][j] = image[i][j];
}
}
int red, green, blue, count;
red = green = blue = count = 0;
//iterate through rows
for (int i = 0; i < height; i++)
{
//iterate through columns
for (int j = 0; j < width; j++)
{
//move one pixel up to one pixel down in the rows
for (int r = i - 1; r <= i + 1; r++)
{
//move one pixel left to one pixel right in the columns
for (int c = j - 1; c <= j + 1; c++)
{
//check if they are unvalid pixels
if (valid_pixel(r, c, height, width))
{
//count every valid pixel
count ++;
//"store" every pixel color
red += image[r][c].rgbtRed;
green += image[r][c].rgbtGreen;
blue += image[r][c].rgbtBlue;
}
}
}
//calculate average values
temp[i][j].rgbtRed = round((float)red / count);
temp[i][j].rgbtGreen = round((float)green / count);
temp[i][j].rgbtBlue = round((float)blue / count);
}
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
image[i][j] = temp[i][j];
}
}
return;
The primary problem is that you forget to reset red, blue and green variables (that you sum up) after each outer loop iteration. You should put this line inside the main loop-
red = green = blue = count = 0;
Also, you're copying the image into another temporary image and copying that temporary image into the original image again in the end. This is very in-efficient. You should not copy the pixels from the original image into the blurred image at first. You can put the modified values directly into this temporary image. And in the end, use memmove to efficiently move entire rows to the original image at once. (Remember to #include <string.h>)
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE blurred_img[height][width];
//iterate through rows
for (int i = 0; i < height; i++)
{
//iterate through columns
for (int j = 0, red, green, blue, count; j < width; j++)
{
// Reset the variables
red = blue = green = count = 0;
//move one pixel up to one pixel down in the rows
for (int r = i - 1; r <= i + 1; r++)
{
//move one pixel left to one pixel right in the columns
for (int c = j - 1; c <= j + 1; c++)
{
//check if they are unvalid pixels
if (valid_pixel(r, c, height, width))
{
//count every valid pixel
count++;
//"store" every pixel color
red += image[r][c].rgbtRed;
green += image[r][c].rgbtGreen;
blue += image[r][c].rgbtBlue;
}
}
}
//calculate average values
blurred_img[i][j].rgbtRed = round((float)red / count);
blurred_img[i][j].rgbtGreen = round((float)green / count);
blurred_img[i][j].rgbtBlue = round((float)blue / count);
}
}
for (int i = 0; i < height; i++)
{
// Copy the new image over to the original, row by row
memmove(image[i], blurred_img[i], sizeof(RGBTRIPLE) * width);
}
return;
}
This is assuming valid_pixel is correct. To determine whether the pixel position is valid you can just do-
if (k > 0 && k < height && l > -1 && l < width))
Notice however, when r (the row) is invalid, the innermost loop (column loop) is still iterated until c == width even though the entirety of this loop is useless, because r is invalid and it'll stay that way until the innermost loop completes and r increments.
For efficiency, you should break whenever r is invalid-
if (r < 0 || r > height - 1)
{
break;
}
if (c > -1 && c < width)
{
//count every valid pixel
count++;
//"store" every pixel color
red += image[r][c].rgbtRed;
green += image[r][c].rgbtGreen;
blue += image[r][c].rgbtBlue;
}

Blur filter works, but check50 disagrees

I've been working on problem set four of the CS50 computer science course and ran into a problem in the blur filter that I'm not sure how to fix. This filter is meant to, for each pixel, take the average of all the color values in a 3x3 area within the current pixel, and change the middle pixel using the average of those pixels. My filter is blurring the picture, but is a little off of what check50 requires. Here's my code.
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE copy[height][width];
for (int i = 0;i < height;i++)
{
for (int j = 0;j < width;j++)
{
copy[i][j] = image[i][j];
}
}
for (int i = 0;i < height;i++)
{
for (int j = 0;j < width;j++)
{
int redAvrg = 0;
int blueAvrg = 0;
int greenAvrg = 0;
int count = 0;
for (int x = i - 1;x < i + 2;x++)
{
for (int y = j - 1;y < j + 2;y++)
{
if(x >= 0 && y >= 0 && x < height && y < width)
{
redAvrg += copy[x][y].rgbtRed;
blueAvrg += copy[x][y].rgbtBlue;
greenAvrg += copy[x][y].rgbtGreen;
count++;
}
}
}
image[i][j].rgbtRed = round(redAvrg / count);
image[i][j].rgbtBlue = round(blueAvrg / count);
image[i][j].rgbtGreen = round(greenAvrg / count);
}
}
return;
}

Resources