[futurebasic] Re: [FB] Future FFT posted

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : December 2001 : Group Archive : Group : All Groups

From: Robert Covington <artlythere@...>
Date: Fri, 21 Dec 2001 06:24:20 -0500
>Robert,
>
>Thank you so much for this FFT example. Now I have questions. Where in the
>program can we change parameters to do filtering such as getting rid of
>high frequency (noise) or low frequency (background) variations in pixel
>intensity ?
>Do we need to have a square image or only have width and height to be
>multiples of 2 ?
>
>Thanks again.
>
>Cheers
>
>Patrick


Patrick,

The input image width and height both must be a power of 2, and square. The
FFT menu Show Valid Samples item will show allowable dimensions.

If you have an image that is not one of these sizes in one dimension for
example but it is in the other, you can zero pad it to match in that
dimension or zero - pad the entire image up to match if both are off. That
is, create an image the next size up, and then fill it with black, and
place your new image in the center. Or add a border to the one dimension
that is lacking, keeping the image centered.

Use the FN AdjustDestRect below to handle that, using the new image size as
the constraints instead of Syswidth or the like.

You will also need to change the array DIM size, and the gRect, and the
image will now be contained in gDestRect.

As far as filtering goes, the below is all I know currently, and it is
partially a port from the C code included in the archive.

No warranties of performance or fitness to purpose, the parameters are a
complete guess as to value other than the Power one (filter 4). But at
least shows something is going on. These menu items will handle all
transforms in a single step.

For more information on this particular code and FFT as applied here, check
out Paul Bourke's site via the URL in the Read Me, then do a search on his
site using the term FFT, and the appropriate pages will show up.


Robert


Try out this addition to the FFT beast. 3 easy Steps.

1. Add these menu items under the Filter menu

Menu 4,2, _enable,"Low Pass"
Menu 4,3, _enable,"Band Pass"
Menu 4,4, _enable,"High Pass"
Menu 4,5, _enable,"Power"

2. Then add these pups in the menu for select menu 4 in  FN doMenu after
the Invert Item 1.

The params are a -guess- after some min/max tests I did earlier.

Format:  FilterResults(filter,lowcut,highcut,power)

Power of 2 will fuzz out the image completely.

case 2
gFilled = 0
if gWorld then FN TransformImage(_Forward)
If gWorld Then FN DrawFFTSomething
If gWorld Then FN FilterResults(1,-9,24,.25)
if gWorld then FN TransformImage(_Reverse)
If gWorld Then FN DrawFFTSomething
case 3
gFilled = 0
if gWorld then FN TransformImage(_Forward)
If gWorld Then FN DrawFFTSomething
If gWorld Then FN FilterResults(2,-9,24,.25)
if gWorld then FN TransformImage(_Reverse)
If gWorld Then FN DrawFFTSomething
case 4
gFilled = 0
if gWorld then FN TransformImage(_Forward)
If gWorld Then FN DrawFFTSomething
If gWorld Then FN FilterResults(3,-9,24,.25)
if gWorld then FN TransformImage(_Reverse)
If gWorld Then FN DrawFFTSomething
case 5
gFilled = 0
if gWorld then FN TransformImage(_Forward)
If gWorld Then FN DrawFFTSomething
If gWorld Then FN FilterResults(4,-9,24,.25)
if gWorld then FN TransformImage(_Reverse)
If gWorld Then FN DrawFFTSomething

3. Try these after loading an image. This does the forward, filters,
reverses all in one.

Here is the filter include...

Local
DIM as double r,r1,r2,r3,r4
Local FN FilterResults(filter,cutoff1 as double,cutoff2 as double,power as
double)
DIM i,j as int
DIM iWidth as Int
DIM iHeight as int

iWidth  = gRect.right%
iHeight = gRect.bottom%

/*
Perform the filtering
0 - no filter
1 - low pass rectangular
2 - band pass rectangular
3 - high pass rectangular
4 - 1 / f^p
*/

for  i=0 TO iwidth-1
for  j=0 TO iheight - 1
r1 = i*i + j*j
r2 = (i-iwidth)*(i-iwidth) + j*j
r3 = i*i + (j-iheight)*(j-iheight)
r4 = (i-iwidth)*(i-iwidth) + (j-iheight)*(j-iheight)

if r1 < r2 then r = r1
if r3 < r  then r = r3
if r4 < r  then r = r4

Select filter
case 0/* No filtering */
Exit FN
case 1 /* Low pass */
Long if (r > cutoff1*cutoff1)
c.real(i,j) = 0
c.imag(i,j) = 0
End If
case 2/* Band pass */
Long if (r < cutoff1*cutoff1 OR r > cutoff2*cutoff2)
c.real(i,j) = 0
c.imag(i,j) = 0
End If
case 3/* High pass */
 Long if (r < cutoff1*cutoff1)
c.real(i,j) = 0
c.imag(i,j) = 0
End If
case 4
Long if r > 0
c.real(i,j) = c.real(i,j) * (1/(r^power))
c.imag(i,j) = c.imag(i,j) * (1/(r^power))
End if
End Select

next j/* j */
next i/* i */

END FN

// End Filter additions.



//-------------------
//------------------ Additions/ changes  required to Zero pad an invalid
sized image-------------------
//-------------------

Begin Globals
DIM gDestRect as Rect
End GLobals


Local
Local FN AdjustDestRect(size)
DIM cenRect as Rect
DIM wWidth as Int
DIM wHeight as int
DIM scale as Fixed, scaleH as fixed, scaleV as fixed

// assign your window or screen width here.*
wWidth  = size
wHeight = size

cenRect;8 = @gRect

Call OffsetRect(cenRect,-cenRect.left,-cenRect.top)
scale = FN Long2Fix(1)
scaleH = FN FixRatio(wWidth,cenRect.right-cenRect.left)
scaleV = FN FixRatio(wHeight,cenRect.bottom-cenRect.top)

If scaleH < scale then scale = scaleH
If scaleV < scale then scale = scaleV

Long if scale <> FN Long2Fix(1)
cenRect.right= FN Fix2Long(FN FixMul(scale,FN Long2Fix(cenRect.right)))
cenRect.bottom= FN Fix2Long(FN FixMul(scale,FN Long2Fix(cenRect.bottom)))
End If

// to center a small image in a larger window (assign at * above)
Call OffSetRect(cenRect,(wWidth-cenRect.right)/2,(wHeight-cenRect.bottom)/2)

gDestRect;8 = @cenRect

End Fn


// Now, in FN ImportImage:

gRect;8     = [PictH]+_PicFrame

offsetRect(gRect,gRect.top%,gRect.left%)

DIM max
Long if gRect.right% <> gRect.bottom%
if gRect.right% > gRect.bottom% then max = gRect.right% else max =
gRect.bottom%
End if

/// You would compare Max to Valid Sample Sizes here and pick next size up
using var Size.
Size = FN YourFnHereToSelectBestSampleSizeUsingMax(max)
// Then:

FN AdjustDestRect(Size)

Followed by:

SetRect(gRect,0,0,Size,Size)

Now make all well, and change the current to this:

Color _zBlack
CALL GETGWORLD(gScreenGW,gCurrDevice)
CALL SETGWORLD(gDrawGW,0)
call PaintRect(gRect)
call Drawpicture (PictH,gDestRect)
CALL SETGWORLD(gUndoGW,0)
call PaintRect(gRect)
call Drawpicture (PictH,gDestRect)
CALL SETGWORLD(gDraw2GW,0)
call PaintRect(gRect)
call Drawpicture (PictH,gDestRect)
Call Killpicture(PictH)
call SETGWORLD(gScreenGW, gCurrDevice)


Then all should work fine. Unless you exceed your array dimensions. :)




Robert