CS50 Filter - Blur - c

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

Related

So, this function was supposed to use edge detection and apply sobel filter. But well It doesn't

I'm trying to figure out what I did wrong. My intent is in title :)
This is the code I tried, and it clearly isn't working. It just print's 1 solid colour, also edges are not included yet. What part is wrong I can't figure it out what part of this code is wrong. It's just a function and it's in C.
void edges(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE edit[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
edit[i][j] = image[i][j];
}
}
for (int q = 1; q < height - 1; q++)
{
for (int w = 1; w < width - 1; w++)
{
int redEdit[9];
int greenEdit[9];
int blueEdit[9];
for (int top = 0; top < 3; top++)
{
redEdit[top] += edit[q - 1][w - 1 + top].rgbtRed;
greenEdit[top] += edit[q - 1][w - 1 + top].rgbtGreen;
blueEdit[top] += edit[q - 1][w - 1 + top].rgbtBlue;
}
int midctr = 0;
for (int mid = 3; mid < 6; mid++)
{
redEdit[mid] += edit[q][w - 1 + midctr].rgbtRed;
greenEdit[mid] += edit[q][w - 1 + midctr].rgbtGreen;
blueEdit[mid] += edit[q][w - 1 + midctr].rgbtBlue;
midctr ++;
}
int topctr = 0;
for (int top = 6; top < 9; top++)
{
redEdit[top] += edit[q + 1][w - 1 + topctr].rgbtRed;
greenEdit[top] += edit[q + 1][w - 1 + topctr].rgbtGreen;
blueEdit[top] += edit[q + 1][w - 1 + topctr].rgbtBlue;
topctr ++;
}
int matrixgx[] = {-1, 0, 1, -2, 0, 2, -1, 0, 1};
int matrixgy[] = {- 1, -2, -1, 0, 0, 0, 1, 2, 1};
int redEditgx[9];
int greenEditgx[9];
int blueEditgx[9];
int redEditgy[9];
int greenEditgy[9];
int blueEditgy[9];
for (int mtrx = 0; mtrx < 9; mtrx++)
{
redEditgx[mtrx] = redEdit[mtrx] * matrixgx[mtrx];
greenEditgx[mtrx] = greenEdit[mtrx] * matrixgx[mtrx];
blueEditgx[mtrx] = blueEdit[mtrx] * matrixgx[mtrx];
redEditgy[mtrx] = redEdit[mtrx] * matrixgy[mtrx];
greenEditgy[mtrx] = greenEdit[mtrx] * matrixgy[mtrx];
blueEditgy[mtrx] = blueEdit[mtrx] * matrixgy[mtrx];
}
// now sum up the changes of gx and gt
int redSumgx = 0;
int greenSumgx = 0;
int blueSumgx = 0;
int redSumgy = 0;
int greenSumgy = 0;
int blueSumgy = 0;
for (int sum = 0; sum < 9; sum++)
{
redSumgx += redEditgx[sum];
greenSumgx += greenEditgx[sum];
blueSumgx += blueEditgx[sum];
redSumgy += redEditgy[sum];
greenSumgy += greenEditgy[sum];
blueSumgy += blueEditgy[sum];
}
int finalRed = round(sqrt(pow(redSumgx, 2) + pow(redSumgy, 2)));
int finalGreen = round(sqrt(pow(greenSumgx, 2) + pow(greenSumgy, 2)));
int finalBlue = round(sqrt(pow(blueSumgx, 2) + pow(blueSumgy, 2)));
if (finalRed > 255)
{
finalRed = 255;
}
if (finalGreen > 255)
{
finalGreen = 255;
}
if (finalBlue > 255)
{
finalBlue = 255;
}
image[q][w].rgbtRed = finalRed;
image[q][w].rgbtGreen = finalGreen;
image[q][w].rgbtBlue = finalBlue;
}
}
return;
}
I know this code is cancer please don't judge
These arrays
int redEdit[9];
int greenEdit[9];
int blueEdit[9];
have not been initialised and hold arbitrary values. So when you execute statements such as
redEdit[top] += edit[q - 1][w - 1 + top].rgbtRed;
the sum is meaningless. You need
int redEdit[9] = { 0 };
int greenEdit[9] = { 0 };
int blueEdit[9] = { 0 };
Only static variables are implicitly initialised to 0. Local (auto) variables are not.

Blur filter in C results in black-ish image

I'm working on CS50 week 4 : blur filter picture. I have to implement a box blur algorithm that works by taking each pixel and, for each color value, giving it a new value by averaging the color values of neighboring pixels. But the output is always a black-ish picture and I can't figure out why.
Can someone give me a hint of where I am wrong? Thank you!
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++)
{
BYTE red_sum = 0;
BYTE green_sum = 0;
BYTE blue_sum = 0;
float pixel_count = 0.0;
// Row above
if (i > 0)
{
red_sum += copy[i-1][j].rgbtRed;
green_sum += copy[i-1][j].rgbtGreen;
blue_sum += copy[i-1][j].rgbtBlue;
pixel_count++;
if (j > 0)
{
red_sum += copy[i-1][j-1].rgbtRed;
green_sum += copy[i-1][j-1].rgbtGreen;
blue_sum += copy[i-1][j-1].rgbtBlue;
pixel_count++;
}
if (j < (width - 1))
{
red_sum += copy[i-1][j+1].rgbtRed;
green_sum += copy[i-1][j+1].rgbtGreen;
blue_sum += copy[i-1][j+1].rgbtBlue;
pixel_count++;
}
}
// Row underneath
if (i < (height - 1))
{
red_sum += copy[i+1][j].rgbtRed;
green_sum += copy[i+1][j].rgbtGreen;
blue_sum += copy[i+1][j].rgbtBlue;
pixel_count++;
if (j > 0)
{
red_sum += copy[i+1][j-1].rgbtRed;
green_sum += copy[i+1][j-1].rgbtGreen;
blue_sum += copy[i+1][j-1].rgbtBlue;
pixel_count++;
}
if (j < (width - 1))
{
red_sum += copy[i+1][j+1].rgbtRed;
green_sum += copy[i+1][j+1].rgbtGreen;
blue_sum += copy[i+1][j+1].rgbtBlue;
pixel_count++;
}
}
// Same row
red_sum += copy[i][j].rgbtRed;
green_sum += copy[i][j].rgbtGreen;
blue_sum += copy[i][j].rgbtBlue;
pixel_count++;
if (j > 0)
{
red_sum += copy[i][j-1].rgbtRed;
green_sum += copy[i][j-1].rgbtGreen;
blue_sum += copy[i][j-1].rgbtBlue;
pixel_count++;
}
if (j < (width - 1))
{
red_sum += copy[i][j+1].rgbtRed;
green_sum += copy[i][j+1].rgbtGreen;
blue_sum += copy[i][j+1].rgbtBlue;
pixel_count++;
}
// Find average
BYTE average_red = round(red_sum / pixel_count);
BYTE average_green = round(green_sum / pixel_count);
BYTE average_blue = round(blue_sum / pixel_count);
image[i][j].rgbtRed = average_red;
image[i][j].rgbtGreen = average_green;
image[i][j].rgbtBlue = average_blue;
}
}
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