Wrong result for non square image - c

I am trying to implement dark (not exactly)emboss filter, my problem is when I use it on SQUARED Lena image 512x512 result is good.
But when I use it on image which has rectangular shape e.g. 1280x720 result is all messed up, why is it so? Format of images is RGB.
GOOD result with Lena 512x512 (original):
WRONG result with 1280x720 image (original not same size just for comparison):

For a 24bit image, if the width of the image is 682 then it needs padding. Because 682*3 is not a multiple of 4. Try changing the image width to 680 and try again.
To pad the image rows, use the following formula:
int pad = WIDTH % 4;
if(pad == 4) pad = 0;
WIDTH += pad;
Change the condition to fb_j < HEIGHT - 1 - FILTER_HEIGHT and fb_i < WIDTH - 1 - FILTER_WIDTH to avoid buffer overflow.
The bitmap is scanned from top to bottom. It works fine when I switched the dimension as follows (but I loaded the bitmap differently)
//Pixel frame_buffer[WIDTH][HEIGHT];
//Pixel temp_buffer[WIDTH][HEIGHT];
Pixel frame_buffer[HEIGHT][WIDTH];
Pixel temp_buffer[HEIGHT][WIDTH];
...
for(int fb_j = 1; fb_j < HEIGHT - 1 - FILTER_HEIGHT; fb_j++) {
for(int fb_i = 1; fb_i < WIDTH - 1 - FILTER_WIDTH; fb_i++) {
float r = 0, g = 0, b = 0;
for(int ker_i = 0; ker_i < FILTER_WIDTH; ker_i++) {
for(int ker_j = 0; ker_j < FILTER_HEIGHT; ker_j++) {
r += ((float)(frame_buffer[fb_j + ker_j][fb_i + ker_i].r / 255.0) * emboss_kernel[ker_j][ker_i]);
g += ((float)(frame_buffer[fb_j + ker_j][fb_i + ker_i].g / 255.0) * emboss_kernel[ker_j][ker_i]);
b += ((float)(frame_buffer[fb_j + ker_j][fb_i + ker_i].b / 255.0) * emboss_kernel[ker_j][ker_i]);
}
}
if(r > 1.0) r = 1.0;
else if(r < 0) r = 0;
if(g > 1.0) g = 1.0;
else if(g < 0) g = 0;
if(b > 1.0) b = 1.0;
else if(b < 0) b = 0;
// Output buffer which will be rendered after convolution
temp_buffer[fb_j][fb_i].r = (GLubyte)(r*255.0);
temp_buffer[fb_j][fb_i].g = (GLubyte)(g*255.0);
temp_buffer[fb_j][fb_i].b = (GLubyte)(b*255.0);
}
}
Also try running a direct copy for testing. Example:
temp_buffer[fb_j][fb_i].r = frame_buffer[fb_j][fb_i].r;
temp_buffer[fb_j][fb_i].g = frame_buffer[fb_j][fb_i].g;
temp_buffer[fb_j][fb_i].b = frame_buffer[fb_j][fb_i].b;

Related

OCR : why are my results worse when i apply a median filter?

I am currently developing an OCR for a sudoku and i am trying to first get a clean black and white image. I first apply a grayscale then a median filter then an otsu algorithm.
My problem is that my results are better when i dont apply my median filter.
Does anyone know why ?
starting image
with my median filter
without my median filter
here is the code for my median filter :
void median_filter(SDL_Surface *image) {
int width = image->w;
int height = image->h;
for (int y = 1; y < height - 1; y++) {
for (int x = 1; x < width - 1; x++) {
Uint8 gray_values[9];
int index = 0;
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
int pixel_offset = (y+dy) * image->pitch + (x+dx) * 4;
Uint8 r = *(Uint8 *)((Uint8 *)image->pixels + pixel_offset);
Uint8 g = *(Uint8 *)((Uint8 *)image->pixels + pixel_offset + 1);
Uint8 b = *(Uint8 *)((Uint8 *)image->pixels + pixel_offset + 2);
gray_values[index++] = (0.3 * r) + (0.59 * g) + (0.11 * b);
}
}
qsort(gray_values, 9, sizeof(Uint8), cmpfunc);
Uint8 gray = gray_values[4];
int pixel_offset = y * image->pitch + x * 4;
*(Uint8 *)((Uint8 *)image->pixels + pixel_offset) = gray;
*(Uint8 *)((Uint8 *)image->pixels + pixel_offset + 1) = gray;
*(Uint8 *)((Uint8 *)image->pixels + pixel_offset + 2) = gray;
}
}
}
You are filtering with some neighbour values that were already filtered – the three pixels above and one on the left.
You need to create median values in a new image. This must also include the unfiltered pixels around the edges.
If you are applying multiple filters, then use one buffer as the source, and another as the destination, then swap the direction for the next filter application (by passsing two buffers to the filter functions).

Blur filter in C results in only a slightly changed image

i am trying to make a blur filter in c that takes the neighboring pixels of the main pixel, takes the avarage of the rgb values and stores it in the temp array, them changes the image using the temp array values, it seems correct but it is not working as intended, giving an output of a very slightly blured image. I realy dont see my mistake and would be very thankful if someone helped, sorry if i made something horrible, started learning c last week.
i checked this post
Blurring an Image in c pixel by pixel - special cases
but i did not see were i went wrong.
im working with this data struct
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// ints to use later
int j;
int p;
RGBTRIPLE temp[height][width];
for(int n = 0; n < height; n++) // loop to check every pixel
{
for(int k = 0; k < width; k++)
{
int widx = 3;
int hghtx = 3;
// conditionals for border cases
int y = 0;
if(n == 0)
{
p = 0;
hghtx = 2;
}
if(n == height - 1)
{
p = -1;
hghtx = 2;
}
if(k == 0)
{
j = 0;
widx = 2;
}
if(k == width - 1)
{
j = -1;
widx = 2;
}
for(int u = 0; u < hghtx; u++) // matrix of pixels around the main pixel using the conditionals gathered before
for(int i = 0; i < widx; i++)
if(y == 1) // takes the average of color and stores it in the RGB temp
{
temp[n][k].rgbtGreen = temp[n][k].rgbtGreen + image[n + p + u][k + j + i].rgbtGreen / (hghtx * widx);
temp[n][k].rgbtRed = temp[n][k].rgbtRed + image[n + p + u][k + j + i].rgbtRed / (hghtx * widx);
temp[n][k].rgbtBlue = temp[n][k].rgbtBlue + image[n + p + u][k + j + i].rgbtBlue / (hghtx * widx);
}
else // get first value of temp
{
temp[n][k].rgbtGreen = (image[n + p + u][k + j + i].rgbtGreen) / (hghtx * widx);
temp[n][k].rgbtRed = (image[n + p + u][k + j + i].rgbtRed) / (hghtx * widx);
temp[n][k].rgbtBlue = (image[n + p + u][k + j + i].rgbtBlue) / (hghtx * widx);
y++;
}
}
}
// changes the original image to the blured one
for(int n = 0; n < height; n++)
for(int k = 0; k < width; k++)
image[n][k] = temp[n][k];
}
I think it's a combination of things.
If the code worked the way you expect, you would be still doing a blur of just 3x3 pixels and that can be hardly noticeable, especially on large images (I'm pretty sure it will be unnoticeable on an image 4000x3000 pixels)
There are some problems with the code.
As #Fe2O3 says, at the end of the first line, widx will change to 2 and stay 2 for the rest of the image.
you are reading from temp[][] without initializing it. I think that if you compile that in release mode (not debug), temp[][] will contain random data and not all zeros as you probably expect. (as #WeatherWane pointed out)
The way you calculate the average of the pixels is weird. If you use a matrix 3x3 pixels, each pixel value shoud be divided by 9 in the final sum. But you divide the first pixel nine times by 2 (in effect doing /256), the second one eight times by 2 (so its pixel/128) etc. until the last one is divided by 2. So basically, it's mostly the value of the bottom right pixel.
also, since your RGB values are just bytes, you may want to divide them first and only then add them, because otherwise, you'll get overflows with wild results.
Try using a debugger to see the values you are actually calculating. It can be quite an eye opener :)

How to left pad a 2 dimensional byte array with leading zeros in C#

I have a 2 dimensional byte array of a bitmap pixel data that I need to send to a thermal printer using ESC/POS via comport. I can do this successfully. However, I need to shift the printed image to the right. Center justify, Right justify, HT, and all other ESC/POS commands have no effect due to the command used to print the bitmap (DC2 * r n [d1.....dn]).
I wish to left pad the array of bytes containing the bitmap in order to shift the printed image to the right. Below are my code lines to print bitmap
private void Print_Bipmap()
{
int x;
int y;
int i;
int RowBytes;
byte n;
Color Pixels;
byte[,] ImageArray = new byte[bitmap.Width, bitmap.Height];
// Calculate output size
RowBytes = (bitmap.Width + 7) / 8;
// Generate body of array
for (y = 0; y < bitmap.Height; y++)
{ // Each row...
for (x = 0; x < (bitmap.Width / 8); x++)
{ // Each 8-pixel block within row...
ImageArray[x, y] = 0;
for (n = 0; n < 8; n++)
{ // Each pixel within block...
Pixels = bitmap.GetPixel(x * 8 + n, y);
if (Pixels.GetBrightness() < 0.5)
{
ImageArray[x, y] += (byte)(1 << (7 - n));
}
}
}
}
comport_writeByte(18); //DC2
comport_writeByte(42); //*
comport_writeByte((byte)bitmap.Height); //r
comport_writeByte((byte)RowBytes); //n
for (y = 0; y < bitmap.Height; y++)
{
for (x = 0; x < RowBytes; x++)
{
comport_writeByte(ImageArray[x, y]); //[d1 ..... dn]
}
}
}
How do I left pad the 2 dimensional array (ImageArray[x, y])?
Many thanks in advance.

Ray Tracing calculation in C

I'm new to ray tracing and trying to program one in C. But My program keep on showing a dot (around 1-3 pixel) of the sphere in the wrong places and now I'm confused. This feels like a very stupid question, but I'm confused about exactly how big is 1 radius of a sphere? What I mean by that is if the radius is 1, the circle is 2 pixels?
I know all the calculations and I triple checked if I had any errors in my codes. but just incase, here is part of my codes:
Directions:
//size: 1024x768, view point (512 384 1), screen (0 0 0) to (1024 768 0)
ray[0] = x - start_x;
ray[1] = y - start_y;
ray[2] = 0 - start_z;
//normalize
double length;
length = (sqrt((ray[0]*ray[0]) + (ray[1]*ray[1]) + (ray[2]*ray[2])));
ray[0] = ray[0]/length;
ray[1] = ray[1]/length;
ray[2] = ray[2]/length;
Intersection:
temp = top; //my struct with sphere data, _x, _y, _z, _r, _red, _green, _blue
//x and y is the current pixel value
while (temp != NULL) {
x_diff = start_x - temp->_x + 0.0;
y_diff = start_y - temp->_y + 0.0;
z_diff = start_z - temp->_z + 0.0;
//a = 1 because my direction is a normalized
b = 2.0 * ((rayVector[0] * x_diff) + (rayVector[1] * y_diff) + (rayVector[2] * z_diff));
c = (x_diff * x_diff * 1.0) + (y_diff * y_diff) + (z_diff * z_diff) - (temp->_r * temp->_r);
check = (b * b) - (4.0 * c);
if (check < 0) { //0
pixels[width][height][0] = 0.0;
pixels[width][height][1] = 0.0;
pixels[width][height][2] = 0.0;
}
else if (check == 0) { //1
r1 = (b * -1.0) /2.0;
if (r1 < nearest_z) {
nearest_z = r1;
pixels[width][height][0] = temp->_red;
pixels[width][height][1] = temp->_green;
pixels[width][height][2] = temp->_blue;
}
}
else { //2
r1 = ((b * -1.0) + sqrt(check))/2.0;
r2 = ((b * -1.0) - sqrt(check))/2.0;
if ((r1 < r2) && (r1 < nearest_z)) {
nearest_z = r1;
pixels[width][height][0] = 255.0;
pixels[width][height][1] = 0;
pixels[width][height][2] = 0;
}
else if ((r2 < r1) && (r2 < nearest_z)) {
nearest_z = r2;
pixels[width][height][0] = temp->_red;
pixels[width][height][1] = temp->_green;
pixels[width][height][2] = temp->_blue;
}
}
temp = temp->next;
}
I haven't done any lightings yet since the flat colouring it doesn't work. I'm new to openGL so expect me to miss some common functions in the codes. Thanks in advance.
Edit:
I only have one sphere currently, but my output looks like: img1
I was expecting a bigger circle? Also, I had a printf for each intersection (if there is) and when I manually plot in a paper, it is a 4x5 pixel square. But there are 4 dots in the output.
Edit 2: I change the size of the sphere to: x = 512 y = 384 z = -21 r = 30, it gave me this:
img2
Again, I only have one sphere and there are 4 in the image. Also, there are holds between the lines?
If I change the z value to -20, now my output is all white (colour of sphere).
I use glDrawPixels(1024,768,GL_RGB,GL_FLOAT,pixels); to draw
I had a RBG output file, everything seems to be in the right place. but when I draw on the program, it is off.

Having trouble with Box Blur Edges

I am a newbie hobbyist trying to program a box blur and I am having trouble with respect to edges. I am hoping that someone can spot the error.
The edges are black and I am assuming that it's because the borders are not being reflected properly. I am sure this has been discussed with a fix size kernel however I am using a variable sized kernel.
I am using the code found on another post --
Optimized float Blur variations
However I just do not understand the reflected borders portion.
I do not really care if optimized or not nor do I care about other kernel shapes, box shape will be just fine.
The code is
{// code from https://stackoverflow.com/questions/7860575/optimized-float-blur-variations
//--------------------------------------
int image_width ;
int image_height ;
int scale = 0;
int weight = (radius * 2) + 1;
int kernel_X = 0;
int kernel_Y = 0;
//--------------------------------------
float sum = 0.0;
int kernel_width = radius;//set both to the same to make the kernel square
int kernel_height = radius;//set both to the same to make the kernel square
// HORIZONTAL
for(iy = 0; iy < image_height ;iy++)
{
sum = 0.0;
// Process entire window for first pixel (including wrap-around edge)
for (kernel_X = 0; kernel_X <= kernel_width; kernel_X++)
{
if (kernel_X >= 0 && kernel_X < image_width)
//sum += src[iy * image_width ];
sum += src[iy * image_width + kernel_X];
}
//>-------------- border code does not reflect edges HELP!!
// Wrap watch for left side of image & resulting black bar
for (kernel_X = (image_width - kernel_width); kernel_X < image_width; kernel_X++)
{
// if (kernel_X >= 0 && kernel_X < image_width)// HORIZONTAL width = horizontal = X
// sum += src[iy * kernel_width + image_width ];//<-------------------enter tester formula here
// sum += src[iy + ix * image_width + kernel_X];//<-------------------FAIL
// sum += src[iy * kernel_width + image_width ];//<-------------------streaky
}
// Store first window
tmp[iy * image_width] = (sum / weight );
for(ix = 1; ix < image_width; ix++)
{
// Subtract pixel leaving window
if (ix - kernel_width - 1 >= 0)
sum -= src[iy * image_width + ix - kernel_width - 1];
// Add pixel entering window
if (ix + kernel_width < image_width)
sum += src[iy * image_width + ix + kernel_width];
else
sum += src[iy * image_width + ix + kernel_width - image_width];
tmp[iy * image_width + ix] = (sum / weight);//just for testing
}
}
// VERTICAL
for(ix = 0; ix < image_width; ix++)
{
sum = 0.0;
// Process entire window for first pixel
for (kernel_Y = 0; kernel_Y <= kernel_height; kernel_Y++)
{
if (kernel_Y >= 0 && kernel_Y < image_height)
sum += tmp[kernel_Y * image_width + ix];
}
//>-------------- border code does not reflect edges HELP!!
// Wrap watch for top side of image & resulting black bar
for (kernel_Y = image_height-kernel_height; kernel_Y < kernel_height; kernel_Y++)
{
//if (kernel_Y >= 0 && kernel_Y < image_height)
// sum += tmp[(iy + kernel_height - image_height) * image_width + ix];
}
for(iy=1;iy< image_height ;iy++)
{
// Subtract pixel leaving window
if (iy-kernel_height-1 >= 0)
sum -= tmp[(iy - kernel_height-1) * image_width + ix];
// Add pixel entering window
if (iy + kernel_height < image_height)
sum += tmp[(iy + kernel_height) * image_width + ix];
else
sum += tmp[(iy + kernel_height - image_height) * image_width + ix];
dst[ (scale * image_width * image_height) + (iy * image_width + ix) ] = (sum / weight);
}
}
}
I appreciate any help on this.
Thanks
John
edit here are some links of image examples of the edges.
image with proper box blur
http://img687.imageshack.us/img687/931/standardboxblur.jpg
Image with improper edges using the above code (notice dark bar on Top and Left edges, bottom and right are not quite right either)
http://img202.imageshack.us/img202/5137/boxblurbadedges.jpg
It might be easiest if you put your sampling into a separate routine which, given an x and y coordinate, returns the pixel value. You can then do some checks and clamp the x and y values to be between 0 and width and 0 and height, respectively. Then you can safely pass in negative values or values greater than width or height. It also allows you to more easily try other schemes like reflection, clamping to a color, extrapolation, etc. Simply swap out the sampling function that clamps with one that does some other behavior.

Resources