The heart of the 1D FFT works. I tested this on the PC. However, 2D FFTs
may have issues and the phase correlation algorithm does not generate
the expected results. That said, most of the work is done. Stuff just
needs to be deubgged.
The FFT lib is designed to handle up to 1024 point real FFTs and 512
complex FFTs. As for 2D FFTs, we can do up to 64x64 pixels. After which,
we don't have enough RAM to handle them because they use up about 128KB
each.
Things to do... the 2D FFT needs to be verified. So, we need to run an
image through it and then back again to verify that there are no
problems. Then we need to compare the 2D FFT output with another 2D FFT
algorithm on the PC...
Once the FFTs are known to be good we then need to make sure the phase
corelation algorithm outs the correct results. We need to test that with
multiple shifted images, etc.
Added the ability to turn AGC off. Kinda will need the ability to restore
AGC settings back to user specified ones in the future... but, this will
do for now.
Added the ability to turn AEC off. Objectively this function probably
won't be used. But, in low light situations it can help.
Added get_fb() to allow you to get the last image snapshot returned.
There was some old exposure function in the code that was getting
optimized out. So, I deleted the used methods that didn't have any code
in them and commented out the only method that did.
Finished going through imlib.c.
-> Histeq uses fb_alloc now and has hook for RGB histeq when reserve YUV
LUT is added (coming soon in next PR).
Cleanuped py_helper.c/h
-> No functional changes. Just added some header info.
Finished going through py_image.c
* 1 - Finished general code cleanup and updating everything to using new
library functions. In particular, I updated the remaining find_*
functions with the new roi clipping code when they accept rois.
* 2 - Made blob stuff return a list when nothing is found so you don't
have to do an if on the returned value anymore.
* 3 - img subscr is more powerful now allowing image reading and
writing. I updated this because I had to use it to find a previous bug
with socket.send() for the WINC driver.
* 4 - Renamed find_eyes to find_eye. Because it just finds one eye.
* 5 - Other than that just general code cleanup to make functions look
consistent.
And yes, changes have been test. Face tracking, eye tracking, keypoints,
etc. all work still.
Future things todo before release:
1 - Change all LAB stuff to YUV.
2 - Add in reverse YUV->RGB LUT and update functions like Mode() to use
this so they don't generate messed up outputs, also histeq() too.
3 - Add any remaining sensor control functions like agc control.
* Added the ability to control the quality on JPEG functions... However,
due to our JPEG implementation this doesn't seem to help. 90% JPEG
quality images and regular images should be about equal. But, you can
see heavy degredation with 90% still. E.g. text is unreabable. Not
exactly sure why this is happening but it can be fixed later.
* Changed the compress() function to compressed(). Also, it now
compresses using FB_Alloc to prevent realloc issues when compressing.
* Added new compress() function. This function compresses an image in
place and if that image is the frame bufffer then it will update the
frame buffer bpp value to reflect the image was compressed. Users can use
this function to basically finalize the frame buffer and then pass the FB
to functions that need to send image bytes. The benefit of using this
function is that it should allow higher quality JPEGs and let everything
run at a faster speed while connected to the IDE.
I made this function to speed up WiFi. However, I encountered a bug with
the winc.send() method. It appears to zero the bytes it sends. I didn't
debug further except to verify that the image data became zero after
calling send.
*Changed subimg to copy.
*Made blend work the same way as all our other double image argument
functions.
*Changed bilt to replace (the name of bilt is way to esoteric). Replace
gives you the basic assignment op.
* Removed scale/sacled. I removed this code because we don't want to
encourage people to scale things and allocate additional images in
memory. I decided to keep copy() for completeness sakes... but, I don't
see anyone using it. (By completeness sakes I mean that we now have the
assignment op, copy op, etc. for an image object).
* Removed rainbow. This feature is built into the FIR module now.
Moving on, compress needs to be renamed to compressed and a new compress
function will need to be added.
The compress() function will compress the image (or frame buffer, etc)
and not return a new object. The compressed() function will return a new
object and not compress the original image.
The compress function will make it easier for users to compress images
once they are done working on them before sending the image some where.
I don't see compressed() being used much then after adding the
compress() function. Since the compress() function won't use up heap
space this makes it very good.
Pixels, centroid, and orientation are calculated in the blob code now.
As for threshold, it is no longer needed (plus, it required storing a
secondary image in RAM which isn't really something we can handle).
Blob tracking has now been updated to work without requiring prior
segmentation of the image. You can still run it on a segmented image,
but, that is not needed anymore.
Use the copy color feature of the OpenMV IDE to get a color in the
image. Once you have that you can then pass the color to find_blobs which
will output a tuple of lists of blobs for each color. By default, all
blobs less than 1/1000th of the image are filtered out, however, you can
add a custom filter function which gets the image and the blob about to
be added to the list and you can decide to filter it or not.
For marker tracking, we now have a function called find markers which
basically merges all the blobs found by find blobs into one list of
blobs. Each new blob will have a color code value which will tell you
what colors are part of that blob. We support tracking up to 30 unique
colors this way.
Mean filter -> Fast and easy to use. This will likely be the only filter
that gets alot of action on the M4.
Median filter -> Works really well, but, slow. On grayscale at 160x120
you can get also 10 FPS with it for a 3x3 kernel. That said, it's still
slow. Also, the code only works for 3x3 and 5x5 kernels.
About the previous histogram filter... technically, that filter should be
better. However, it suffers from a startup cost. The operation of finding
the median point in the histogram costs too much to compute. This is
what causes it to be slow. On very large kernels it will be faster than
the sorting median alrogithm I put up... but, large kernels will be too
slow for anyone to use anyway. The paper Ibrahim linked to about it
showed it being used for like 7x7 kernels and up... so, I think the
researcher who thought of the idea was really thinking about the
algorithm for large kernels.
Mode filter -> Works great on grayscale. Not so much on color. I think it
needs to be run on the LAB color space instead of the RGB color space. I
say this because it causes pretty strong artifacts around edges. When we
get more flash we'll be able to have a reverse lookup table for LAB to
make the mode filter better. Until then...
So I'm just adding a function to do it cleanly and efficently. Call
skip_frames() after changing any camera settings to let it settle.
10 frames by default works fine. Tested it.