gaussian blur?

Pixilang programming language
Post Reply
User avatar
AutumnCheney
Posts: 503
Joined: Sun Dec 29, 2019 8:16 am
Location: tahlequah, ok, usa
Contact:

gaussian blur?

Post by AutumnCheney »

hello, it's me, back with my pixilang shenanigans again!

i'm trying to implement a gaussian blur using pixilang's convolution filter; i'm using this site as a reference for the implementation: https://aryamansharda.medium.com/image- ... 36db6781b1

as of now, it almost works, except it doesn't look the way i'd expect it to

here's the way it looks now, with pixilang and radius=11:

Image

and here's how i think it should look, using the gimp and the same radius:

Image

here's my code, with some unnecessary stuff commented out:

Code: Select all

cover = load("cover.png")
cover_src = clone(cover)

cover_blur_rad = 11

// gaussian blur

sigma = max((cover_blur_rad / 2), 1)

kernel_width = (2 * cover_blur_rad) + 1

kernel = new(kernel_width, kernel_width, INT)
clean(kernel, 1)

//sum = 0

for (x = -cover_blur_rad ; x < cover_blur_rad ; x + 1) {
	for (y = -cover_blur_rad ; y < cover_blur_rad ; y + 1) {
	    exp_num = -(x * x + y * y)
	    exp_dem = 2 * sigma * sigma
	    expression = pow(M_E, exp_num / exp_dem)
	    ker_val = (expression / (2 * M_PI * sigma * sigma))

	    kernel[(x + cover_blur_rad), (y + cover_blur_rad)] = ker_val
	    //sum = sum + ker_val
	}
}

/* for (x = 0 ; x < kernel_width ; x + 1) {
	for (y = 0 ; y < kernel_width ; y + 1) {
		kernel[x, y] = kernel[x, y] / sum
	}
} */

conv_filter(cover, cover_src, kernel, kernel_width, 0, CONV_FILTER_COLOR)

while 1
{
    pixi( cover, 0, 0 )

    while get_event() { if EVT[ EVT_TYPE ] == EVT_QUIT { halt } }

    frame()
}

fn max($a, $b) {
	if ($a >= $b) {
		ret($a)
	} else {
		ret($b)
	}
}
here's a link to the test image i'm using:

https://ibb.co/QH88nXF

any pointers please? this is my first time working with image convolution

thank you!
my website: https://acheney.xyz

it features my music, sunvox content, and social media links!
ainegil
Posts: 168
Joined: Thu Sep 22, 2022 11:37 pm

Re: gaussian blur?

Post by ainegil »

I am not so familiar with pixilang yet, but with convolution.
So I am not sure what the code does pixilangwise

How I would test it without using any pixilang specific thing is to create a new container the size of xour image, loop through your image pixel by pixel, and for each pixel loop through the kernel, and write the weighted sum of pixels into the pixel in your new container.
That should work if your kernel is correct which I asume it is
User avatar
NightRadio
Site Admin
Posts: 3941
Joined: Fri Jan 23, 2004 12:28 am
Location: Ekaterinburg. Russia
Contact:

Re: gaussian blur?

Post by NightRadio »

1)
You need floating point kernel, not INT
But conv_filter() requires INT kernel for integer/color dest/src containers.
There are two ways to satisfy this requirement.
a) split your image to 3 FLOAT containers (with split_rgb()), apply conv_filter() to each, then merge them back to the PIXEL container;
b) use fixed point kernel - INT multiplied by some big number.
Let's try "b"

2)
Create FLOAT kernel, and convert it to INT before the conv_filter():
kernel = new(kernel_width, kernel_width, FLOAT)
//clean is not needed here

3)
uncomment the code for sum and normalization

4)
you need <= in the condition, because the kernel width is (2 * cover_blur_rad) + 1
for (x = -cover_blur_rad ; x <= cover_blur_rad ; x + 1) {
for (y = -cover_blur_rad ; y <= cover_blur_rad ; y + 1) {

5)
normalization:

Code: Select all

FIXED_POINT_MUL = 32768
for (x = 0 ; x < kernel_width ; x + 1) {
    for (y = 0 ; y < kernel_width ; y + 1) {
        kernel[x, y] = kernel[x, y] / sum * FIXED_POINT_MUL
    }
}
6)
filtering:

Code: Select all

convert_type( kernel, INT )
conv_filter( cover, cover_src, kernel, FIXED_POINT_MUL, 0, CONV_FILTER_COLOR )
User avatar
AutumnCheney
Posts: 503
Joined: Sun Dec 29, 2019 8:16 am
Location: tahlequah, ok, usa
Contact:

Re: gaussian blur?

Post by AutumnCheney »

NightRadio wrote: Tue Oct 04, 2022 7:12 pm 1)
You need floating point kernel, not INT
But conv_filter() requires INT kernel for integer/color dest/src containers.
There are two ways to satisfy this requirement.
a) split your image to 3 FLOAT containers (with split_rgb()), apply conv_filter() to each, then merge them back to the PIXEL container;
b) use fixed point kernel - INT multiplied by some big number.
Let's try "b"

2)
Create FLOAT kernel, and convert it to INT before the conv_filter():
kernel = new(kernel_width, kernel_width, FLOAT)
//clean is not needed here

3)
uncomment the code for sum and normalization

4)
you need <= in the condition, because the kernel width is (2 * cover_blur_rad) + 1
for (x = -cover_blur_rad ; x <= cover_blur_rad ; x + 1) {
for (y = -cover_blur_rad ; y <= cover_blur_rad ; y + 1) {

5)
normalization:

Code: Select all

FIXED_POINT_MUL = 32768
for (x = 0 ; x < kernel_width ; x + 1) {
    for (y = 0 ; y < kernel_width ; y + 1) {
        kernel[x, y] = kernel[x, y] / sum * FIXED_POINT_MUL
    }
}
6)
filtering:

Code: Select all

convert_type( kernel, INT )
conv_filter( cover, cover_src, kernel, FIXED_POINT_MUL, 0, CONV_FILTER_COLOR )
thank you nightradio! now i understand the relationship between an int picture file and a float kernel

here's my code now, if anyone wants it:

Code: Select all

cover = load("cover.png")
cover_src = clone(cover)

cover_blur_rad = 11

// gaussian blur

sigma = max((cover_blur_rad / 2), 1)

kernel_width = (2 * cover_blur_rad) + 1

kernel = new(kernel_width, kernel_width, FLOAT)
clean(kernel, 1)

sum = 0

for (x = -cover_blur_rad ; x <= cover_blur_rad ; x + 1) {
	for (y = -cover_blur_rad ; y <= cover_blur_rad ; y + 1) {
	    exp_num = -(x * x + y * y)
	    exp_dem = 2 * sigma * sigma
	    expression = pow(M_E, exp_num / exp_dem)
	    ker_val = (expression / (2 * M_PI * sigma * sigma))

	    kernel[(x + cover_blur_rad), (y + cover_blur_rad)] = ker_val
	    sum = sum + ker_val
	}
}

FIXED_POINT_MUL = 32768
for (x = 0 ; x < kernel_width ; x + 1) {
    for (y = 0 ; y < kernel_width ; y + 1) {
        kernel[x, y] = kernel[x, y] / sum * FIXED_POINT_MUL
    }
}

convert_type( kernel, INT )
conv_filter( cover, cover_src, kernel, FIXED_POINT_MUL, 0, CONV_FILTER_COLOR )

while 1
{
    pixi( cover, 0, 0 )

    while get_event() { if EVT[ EVT_TYPE ] == EVT_QUIT { halt } }

    frame()
}

fn max($a, $b) {
	if ($a >= $b) {
		ret($a)
	} else {
		ret($b)
	}
}
my website: https://acheney.xyz

it features my music, sunvox content, and social media links!
Post Reply