-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[WIP] - Feature train orb #31
base: dev
Are you sure you want to change the base?
Conversation
- some methods needs a refactor
emscripten/webarkitJsfeat.cpp
Outdated
|
||
// orb.describe(lev_img.get(), lev_corners[0], corners_num, lev_descr.get()); | ||
// This probablly will work in a near future | ||
// orb.describe(lev_img.get(), lev_corners[0], corners_num, &pattern_descriptors[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
orb.describe can not be yet used here because it accept in the first parameter a uintptr_t
and in the second parameter an emscripten::val can not be managed here. I should create a new method in the Orb class:
orb.describe_internal(Matrix_t* mat, Keypoints* kp, int num corners, Matix_t* descr)
@@ -149,13 +149,17 @@ void train_orb_pattern_internal(const char* filename) { | |||
ext); | |||
free(ext); | |||
} | |||
webarkitLOGi("Image done!"); | |||
|
|||
JSLOGi("Starting detection routine..."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two printings works, they print tese messages:
Image done!
Starting detection routine...
but at the end of the code they fails to print in the console, i would understand why this happens.... see the comment above.
emscripten/webarkitJsfeat.cpp
Outdated
// This probablly will work in a near future | ||
// orb.describe(lev_img.get(), lev_corners[0], corners_num, &pattern_descriptors[0]); | ||
|
||
// console.log("train " + lev_img.cols + "x" + lev_img.rows + " points: " + corners_num); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...continuning from below, These two printings instead do nothing. I will open an issue as reminder.
auto count = kpc.count; | ||
// sort by score and reduce the count if needed | ||
if (count > max_allowed) { | ||
// qsort_internal<KeyPoint_t, bool>(corners.kpoints, 0, count - 1, [](KeyPoint_t i, KeyPoint_t j){return (i.score < j.score);}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure of this, maybe it's better to use another small different approach. I'm looking to the OpenCV code in the Orb implementation and there is another possibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
retainBest is taken from OpenCV, but i need to figure out if this is correct.
Speaking about sorting the keypoints, OpenCV use nor // Remove keypoints very close to the border
KeyPointsFilter::runByImageBorder(keypoints, img.size(), edgeThreshold);
// Keep more points than necessary as FAST does not give amazing corners
KeyPointsFilter::retainBest(keypoints, scoreType == ORB_Impl::HARRIS_SCORE ? 2 * featuresNum : featuresNum); this is the retainBest method: // takes keypoints and culls them by the response
void KeyPointsFilter::retainBest(std::vector<KeyPoint>& keypoints, int n_points)
{
//this is only necessary if the keypoints size is greater than the number of desired points.
if( n_points >= 0 && keypoints.size() > (size_t)n_points )
{
if (n_points==0)
{
keypoints.clear();
return;
}
//first use nth element to partition the keypoints into the best and worst.
std::nth_element(keypoints.begin(), keypoints.begin() + n_points - 1, keypoints.end(), KeypointResponseGreater());
//this is the boundary response, and in the case of FAST may be ambiguous
float ambiguous_response = keypoints[n_points - 1].response;
//use std::partition to grab all of the keypoints with the boundary response.
std::vector<KeyPoint>::const_iterator new_end =
std::partition(keypoints.begin() + n_points, keypoints.end(),
KeypointResponseGreaterThanOrEqualToThreshold(ambiguous_response));
//resize the keypoints, given this new end point. nth_element and partition reordered the points inplace
keypoints.resize(new_end - keypoints.begin());
}
}
https://github.com/opencv/opencv/blob/64aad34cb4abfb6a2603f3f4ecae7f4f0ba1414d/modules/features2d/src/keypoint.cpp#L68-L90 |
while testing with docker and emsdk:3.1.25 i got this error and of course fails to build:
Need to open a issue on webarkitlib in the meanwhile i will continue to use emsdk 3.1.20 |
emscripten/webarkitJsfeat.cpp
Outdated
|
||
|
||
JSLOGi("Resampling image..."); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resampling is not needed in our case, because we provide our image with the right size. The code was taken by the jsfeat sample_orb example and in that case we simply resampled the image taken by the canvas(webcam) to a smaller size. Anyway the resample function has some issues, infact the log console "Image resampled, starting pyrmaid now..." can not be printed with this function enabled. (just comment out and recompile to test)
emscripten/webarkitJsfeat.cpp
Outdated
// prepare preview | ||
std::unique_ptr<Matrix_t> pattern_preview = std::make_unique<Matrix_t>(jpegImage->xsize >> 1, jpegImage->ysize >> 1, ComboTypes::U8C1_t); | ||
imgproc.pyrdown_internal(lev0_img.get(), pattern_preview.get()); | ||
|
||
Array<KeyPoints> lev_corners; | ||
Array<KeyPoints*> lev_corners(4); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think we should provide a array of pointers and pre init them.
emscripten/webarkitJsfeat.cpp
Outdated
@@ -186,22 +190,30 @@ void train_orb_pattern_internal(const char* filename) { | |||
// preallocate corners array | |||
i = (new_width * new_height) >> lev; | |||
while (--i >= 0) { | |||
lev_corners[lev].set_size(i); | |||
lev_corners[lev]->set_size(i); | |||
lev_corners[lev]->allocate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need to set the size and allocate the entire set.
emscripten/webarkitJsfeat.cpp
Outdated
} | ||
std::cout << "Num. of level: " << lev << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this print 4 levels in the console:
Num. of level: 0
and so on...
emscripten/webarkitJsfeat.cpp
Outdated
pattern_descriptors.push_back(std::unique_ptr<Matrix_t>(new Matrix_t(32, max_per_level, ComboTypes::U8C1_t))); | ||
} | ||
|
||
imgproc.gaussian_blur_internal(lev0_img.get(), lev_img.get(), 5, 0.2); // this is more robust | ||
//std::cout << "Size of first lev_corners: " << lev_corners[0]->kpoints.size() << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not printed...
//std::cout << "Size of first lev_corners: " << lev_corners[0]->kpoints.size() << std::endl; | ||
|
||
imgproc.gaussian_blur_internal(lev0_img.get(), lev_img.get(), 5, 2); // this is more robust | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is ok , it is printed...
@@ -35,6 +35,12 @@ class KeyPoints { | |||
this->size = kp.size; | |||
this->kpoints = kp.kpoints; | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added tha allocate function because if you initialize a KeyPoints with the default constructor it will not init the kpoints
.
@@ -84,6 +84,7 @@ class Yape06 { | |||
} | |||
} | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this not printing anything...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now it display some value: Count inside Yape06 detect_internal: 64192
Somewhere the code is broken, infact in the Yape06 |
I discovered that i missed an important step: the pattern image imported by ar2ReadJpegImage it should be converted to grayscale (this is the missed step) but i can't apply because all the methods are specific for emscripten but not to be used internally. Before all i have to make the imgproc methods more flexible and rearrange the code a bit. I will do this in another specific PR. |
emscripten/webarkitJsfeat.cpp
Outdated
std::cout << i << std::endl; | ||
while (--i >= 0) { | ||
lev_corners[lev]->set_size(i); | ||
//lev_corners[lev]->allocate(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to allocate if we create the vector: Array<KeyPoints*> lev_corners(num_train_levels);
Ok with the latest commit 6fe0b12 we recieve a |
Things to do:
|
At this point of the code we got this from te output log:
instead from jsfeatNext:
what is wrong with the c++ code? |
|
with commit 4a0cf97 i added the training for the other levels, but it doesn't correctly calculate. I think there is an issue with the resample method, not sure if it ever worked correctly. |
- using standard lib to speed up
In this Pull request i will try do develop some utilities to train a Orb pattern. Partially following the jsfeat code but also OpenCV implementation as it was the original one.