While this shouldn't happen the method seems to sometimes round up past
limits. For example, 1 * 2.0 could be 3 because the 2.0 might be like
2.0000000000001.
So, avoid using roundf. There are other methods this needs to be
switched out on. But, will do these ones for now.
Note that not all roundf values must be removed... just areas where
there's a clear limit on the max value returned from roundf.
It's not as good as mean shift filtering but can approximate it if you
heavily control the image image lighting conditions. That said, it's a
lot faster and less memory than mean shift filtering.
Runs faster than median filtering with a large kernel size. That said,
if sigma is set to low for the particular scene you can get corrupted
pixels if there's too much change in a particular kernel area. Tried a
few things to filter this out but was not successful. Not sure how to
fix... but, turning the sigma up hides the issue. It has something to do
with zeros in the luts used to speed the algorithm up causing
instability.
This brings all our basic operations code up to spec with other image
library offers.
Anyway, you can now pass a "color" value as the parameter to a basic op
method and it will apply that value to all pixels in the image.
Binary images are now handled. Cleaned up and optimized code. Some speed
gains after shifting to multiplies and not using int8_t.
Added a sharp and unsharp mask feature. Fixed up guassian. Added a
laplacian operation for edge detection.
Heavily upgraded the drawing features onboard the OpenMV Cam. We now
have all the basic drawing methods folks expect along with all the
parameters you need. Finally! You can make big text fonts.
* Added line thickness support
* Added shape fills
* Added text scaling
* Added draw arrow.
All of our argument parsing code has now been updated to handle
positional as well as keyword arguments in our python libraries.
Basically, python allows you to pass some number of positional arguments
to functions/methods followed by keyword arguments (you cannot have more
positional arguments after keyword arguments). Previously, our code
would only look for keyword arguments. Now, it works better and will
grab as many positional arguments as it can followed by processing
keyword arguments. Note: If the case of a positional argument value for
a parameter being passed followed by a keyword for that same parameter
the keyword value is taken (since it comes aftward).
Because arguments were passed in keyword form before this update has no
affect on current code. However, moving forward, argument positions are
now locked and cannot be moved around.
Add binary image support to the math operations and updated them to
support masks. Replace now also support mirroring operations. Finally,
adding missing basic math ops like add/sub/mul/div. The operations are
designed to work as image blending operations so they take care of
scaling their output accordingly.
Binary() can noew zero things so you can remove bright lights. All the
line ops (and/or/xor/etc) accept masks. Erode and dilate now accept
masks. And finally, you can now pass arguments versus keywords for folks
who don't read the documentation. Also, the binary image type is now
supported for these methods.
I'm putting in all this work because I saw the need for it when I was
doing shadow removal.
Note: Some effort needs to be put into optimizing the py_image.c code
soon. This is on the todo list before the next release.
Calling remove_shadows() on an image without a background source of
truth image now works. However, that said, the shadow remover isn't
suitable for anything other than removing shadow on an image of concrete
flow or somthing of the like. In general, it can only remove shadows
from a scene that has nothing else in it except for a hard edge shadow.
Improving this to work for anything is about a month of work. I've
researched enough about shadow removal to now know the optimal way to do
it. However, it requires many steps and a large amount of RAM. On the H7
I may revist this as being possible.
...
In order to get the shadow remover working well I had to add a few
features to the image library and fix some of the convolution code.
These fixes will likely be more useful than the shadow removal code.
Note the addition of the new get_threshold() method. This computes
otsu's threshold on a histogram allowing you to pick the optimal color
bounds.
Add in support for shadow removal from the current image using a shadow
free background image. Test results show the algorithm works similar to
max() while still keeping dark objects around. The preformance impact of
the algorithm is not too high. An in memory example can achieve 30 FPS.
Redid the phase correlation code again so it's one method call now. This
method call can either do logpolar phase correlation to get rotation/
scale or translation(x/y). Additionally, it will be able to also do both
at once. However, I don't have that quite working yet.
I've updated the example scripts to reflect the new code too.
Finally, I had to fix a bug in the rotation correction code.
...
Once I've got the full pipeline working I will post scripts for that. I
have all the code in there and it's been somewhat debugged... However, I
can't get a useful phase correlation lock out of the log polar fft mag.
I plan to look into noise filtering and spectral whitening solutions for
this.
Just doing one big commit/PR here since I noticed that breaking it up
causes issues.
Anyway, these fixes give us GOOD/WORKING/FAST optical flow now on the
OpenMV Cam M7. A number of changes were made to the optical flow
scripts. You have have absolute and differential estimation example
scripts. Additionally, you also have the ability to measure rotation and
scale changes too. Linear/Log Polar conversion was added for this. Users
may use the new code for generic image manipulation too. Finally, I
updated the power of 2 resolutions since you actually HAVE to use them
with optical flow for the phasecorrelation code to work correctly.
I have some more advanced scripts coming after this. But, This commit is
already getting kinda large so I'm stopping it here.
Image comparison using SSIM. It can be used to detect image
differences... but, the algorithm was designed to compare image quality
and look at compression artifacts. Anyway, it works kinda okay for
detecting frame differences.
Both algorithms were tested on the OpenMV Cam using images loaded from a
file and work correctly. However, shot noise from the sensor.snapshot()
makes the output value somewhat worthless except in a situation unless
you've controlled for it. Anyway, the illuminvar work best when the
image is constrained to a very particular view point looking at a flat
scene without shadow and then a shadow enters.
(Not adding demo's for these methods since the output looks like crap
unless you've put some work into constraining the scene... need to add
HDR code and other stuff to the sensor module to get better images).