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?
Related
Got a problem with code in C, the purpose is to blur given image working as a filter. The code reads height and width from RGBTRIPLE bmp.h file, makes a copy of each pixel in advance to compute the average in the middle pixel (when its 3x3 pixels chunk) or the boundary pixel's average (when its 2x3 chunk). I nested for-loops, 2 outer ones to copy each pixel from 'image', defined there 4 integers (3 doubles, 1 int.) to count each pixel's red, green and blue. The last int. is named counter to be my denominator in division.
The problem occurs not in syntax, but on the image. 4 down rows of pixels are like rainbow, each is different, not blurred. And the image is darkened.
When I don't use the pixels' copy it seems to work fine.
// 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++)
{
// make a copy of rgbtriple image
copy[i][j].rgbtRed = image[i][j].rgbtRed;
copy[i][j].rgbtGreen = image[i][j].rgbtGreen;
copy[i][j].rgbtBlue = image[i][j].rgbtBlue;
// i need to ensure that image's pixels wont be out of bounds of rows/columns
// it's inappropriate to have static division by 9 because sometimes there will be less pixels to divide by
double sumRed = 0;
double sumGreen = 0;
double sumBlue = 0;
int count = 0;
for (int ii = i - 1; ii <= i + 1; ii++)
{
for (int jj = j - 1; jj <= j + 1; jj++)
{
if (ii >= 0 && ii < height && jj >= 0 && jj < width)
{
sumRed += copy[ii][jj].rgbtRed;
sumGreen += copy[ii][jj].rgbtGreen;
sumBlue += copy[ii][jj].rgbtBlue;
count++;
}
}
}
if (count != 0 && count <= 9)
{
image[i][j].rgbtRed = round(sumRed / count);
image[i][j].rgbtGreen = round(sumGreen / count);
image[i][j].rgbtBlue = round(sumBlue / count);
}
}
}
return;
}
Thanks in advance!
You compute the new value of the image pixels from the data in the copy matrix, but you did not copy the whole image before hand, only pixel values up to the current pixel. Hence the results are incorrect.
You should copy the whole image in a separate loop or using memcpy.
Here is a modified version:
#include <string.h>
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width]) {
RGBTRIPLE copy[height][width];
// make a copy of rgbtriple image
#if 1 // using memcpy
memcpy(copy, image, sizeof(copy));
#else
// if you cannot use memcpy
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
copy[i][j] = image[i][j];
}
}
#endif
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
// Mix the color values with the adjacent pixels
// making sure the pixels are inside the image.
// It is inappropriate to always divide by 9
// because depending on the pixel position and image size
// count can be 1, 2, 3, 4, 6 or 9
double sumRed = 0;
double sumGreen = 0;
double sumBlue = 0;
int count = 0;
for (int ii = i - 1; ii <= i + 1; ii++) {
for (int jj = j - 1; jj <= j + 1; jj++) {
if (ii >= 0 && ii < height && jj >= 0 && jj < width) {
sumRed += copy[ii][jj].rgbtRed;
sumGreen += copy[ii][jj].rgbtGreen;
sumBlue += copy[ii][jj].rgbtBlue;
count++;
}
}
}
// no need to test count: there is at least one pixel
image[i][j].rgbtRed = round(sumRed / count);
image[i][j].rgbtGreen = round(sumGreen / count);
image[i][j].rgbtBlue = round(sumBlue / count);
}
}
}
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.
This is an exercise from CS50 pset4 (more comfortable). This is part of a larger piece of code and it is the blur function. I am having trouble fixing my code.
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE temp_img[height][width];
// copy original image array
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
temp_img[i][j] = image[i][j];
}
}
// iterate throughout the image
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int sumBlue = 0;
int sumGreen = 0;
int sumRed = 0;
float count_pix = 0;
// obtain value of original colour values around target pixel- red green blue
for (int r = -1; r <= 1; r++)
{
for (int c = -1; c <= 1; c++)
{
// logic to determine if pixel is existent
if ((0 <= i + r && i + r < height) && (0 <= j + c && j + c < width))
{
// add all RGB values accordingly, with counter
sumBlue += temp_img[i + r][j + r].rgbtBlue;
sumGreen += temp_img[i + r][j + r].rgbtGreen;
sumRed += temp_img[i + r][j + r].rgbtRed;
count_pix ++; //count number of iterations to average out later
}
}
}
// average out and add replace values into original image for output
image[i][j].rgbtBlue = round(sumBlue / count_pix);
image[i][j].rgbtGreen = round(sumGreen / count_pix);
image[i][j].rgbtRed = round(sumRed / count_pix);
}
}
return;
}
Below is the list of expected output and output from this code
:( blur correctly filters middle pixel
expected "127 140 149\n", not "123 137 145\n
:( blur correctly filters pixel on edge
expected "80 95 105\n", not "85 100 110\n
:( blur correctly filters pixel in corner
expected "70 85 95\n", not "65 80 90\n
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;
}
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;
}