kerenl matrix problem =\

Started by
13 comments, last by ff8 17 years, 9 months ago
Hello everyone , i am tring to make some image's filtering effects on 1byte datatype 0-255 i tried many filers but i get weird effects most of time i get colored-nosie all over the image i tried mean filtering it worked just this filter only =\ can anyone check my code and tell me what is the problem ...

struct Pixel{
	unsigned char r,g,b;
};
float kernel[9]={-1,-1,-1,
			     -1,+9,-1,
			     -1,-1,-1};
unsigned char FtoC(float a,unsigned char b){
	return (unsigned char)((b*a>255)?255:(a*b));
}
void Filter(Pixel *image,int x,int y){
	for(int i=1;i<y;i++){
		for(int j=1;j<x;j++){
			image[MAP(j,i,x)].r=FtoC(kernel[0],image[MAP(j-1,i+1,x)].r)+FtoC(kernel[1],image[MAP(j,i+1,x)].r)+FtoC(kernel[2],image[MAP(j+1,i+1,x)].r)+
								FtoC(kernel[3],image[MAP(j-1,i,x)].r)	 +FtoC(kernel[4],image[MAP(j,i,x)].r)  +FtoC(kernel[5],image[MAP(j+1,i,x)].r)  +
								FtoC(kernel[6],image[MAP(j-1,i-1,x)].r)+FtoC(kernel[7],image[MAP(j,i-1,x)].r)+FtoC(kernel[8],image[MAP(j+1,i-1,x)].r);

			image[MAP(j,i,x)].g=FtoC(kernel[0],image[MAP(j-1,i+1,x)].g)+FtoC(kernel[1],image[MAP(j,i+1,x)].g)+FtoC(kernel[2],image[MAP(j+1,i+1,x)].g)+
								FtoC(kernel[3],image[MAP(j-1,i,x)].g)	 +FtoC(kernel[4],image[MAP(j,i,x)].g)  +FtoC(kernel[5],image[MAP(j+1,i,x)].g)  +
								FtoC(kernel[6],image[MAP(j-1,i-1,x)].g)+FtoC(kernel[7],image[MAP(j,i-1,x)].g)+FtoC(kernel[8],image[MAP(j+1,i-1,x)].g);

			image[MAP(j,i,x)].b=FtoC(kernel[0],image[MAP(j-1,i+1,x)].b)+FtoC(kernel[1],image[MAP(j,i+1,x)].b)+FtoC(kernel[2],image[MAP(j+1,i+1,x)].b)+
								FtoC(kernel[3],image[MAP(j-1,i,x)].b)	 +FtoC(kernel[4],image[MAP(j,i,x)].b)  +FtoC(kernel[5],image[MAP(j+1,i,x)].b)  +
								FtoC(kernel[6],image[MAP(j-1,i-1,x)].b)+FtoC(kernel[7],image[MAP(j,i-1,x)].b)+FtoC(kernel[8],image[MAP(j+1,i-1,x)].b);
		}
	}
}

thank you . cya,
Advertisement
You should FIRST compute the sum kernel[k]*pixel_value[k] and THEN map to char.
The 5th filter element has a value of +9. If you multiply - say - 50 by 9 and clip it,
you get completely wrong results. That's why you get colored noise. First compute the sum,
then clip to char.
Your kernel is a derivative-like filter. First, you need to kernel values to sum to 0. The kernel[4] value should be "8", not "9". Second, you should ensure that the absolute values of the kernel values sum to 1. So multiply all your kernel[] values by 1/16 = 0.0625.
thank you.
i have another question :
let's say i want make blurring effect what is the kernel matrix for it and what do i need to change ?
@Wasting Time :
what do u mean by "absolute values of the kernel"?

thanks again ^^.

Quote:Original post by ff8
let's say i want make blurring effect what is the kernel matrix for it and what do i need to change ?


There are infinitely many choices for a 3x3 blur-like kernel. Generally, you want some reasonable constraints:
1. symmetric:
kernel[0] = kernel[2] = kernel[6] = kernel[8]
kernel[1] = kernel[3] = kernel[5] = kernel[7]

2. nonnegativity: kernel >= 0 for all i

3. influence of pixels decreases with distance:
kernel[4] >= kernel[1] >= kernel[0]

4. energy preserving:
kernel[0] + kernel[1] + ... + kernel[8] = 1

You also have to decide how to handle boundary pixels (clamp? repeat? mirrored-repeat? wrap? ...)

Quote:
what do u mean by "absolute values of the kernel"?


I meant:
|kernel[0]| + |kernel[1]| + ... + |kernel[8]| = 1

thank you again ^^.
ok let's say i want to try symmetric kernel for blur filter what about the kernel elements' values is there any rule for them or just pick them randomly ?
Hello again ,
ok i tried this matrix :
float kernel[9]={0.0625,0.1,0.0625,			     0.1,0,0.1,			     0.0625,0.1,0.0625};

i got smooth effect not blured and the image was kinda dark
so i am not sure how can i select the kernel values is there anything to do w/ these values like rules for picking them ?
thanks again .
cya,
Quote:Original post by ff8
i got smooth effect not blured and the image was kinda dark


Are you paying attention to what I posted?

Your example violates two of the constraints I mentioned. First, you have kernel[4] = 0, which violates Constraint 3 (influence of pixels decreases with distance). When you compute a weighted average at a pixel, you invariably want to assign that pixel the *largest* weight. Second, the sum of your kernel values is 0.65, not 1, which violates Constraint 4 (energy preserving). The fact that the sum is less than 1 guarantees that the blurred image will be darker.

Try, for example, kernel[0..8] = (1/28)*{1,4,1,4,8,4,1,4,1}.
Assigning the elements based on the value of a gaussian function is used rather often, and produces nice results.

What exactly do you want to do anyway? As in, what's this for?
If at first you don't succeed, redefine success.
thank you again ^^ ,
i am really sorry about the missunderstanding =if i want to control the blur what do i need to do ? increase the kernel matrix or is there anothere way ?

This topic is closed to new replies.

Advertisement