opencv_contrib: Using Facemark API (Python), Version 4.0.0 - pre : bad alloc error
System information (version) OpenCV => 4.0.0 - pre Operating System / Platform => Ubuntu 18.04
Detailed Description
I’m trying to implement FacemarkLBF testing version in Python (OpenCV Version : 4.0.0 - pre), but there is not enough documentation on it. Addition to that, when am trying to run, it shows std::bad alloc error.
Gist of the functions am using:
obj = cv2.face.createFacemarkLBF()
cv2.face_Facemark.loadModel(obj, <model_name>)
retVal, landmarks = cv2.face_Facemark.fit(obj, img, faces)
While trying to debug, the problem is mainly with roi.getObj() line in fit function definition (https://github.com/opencv/opencv_contrib/blob/master/modules/face/src/facemarkLBF.cpp : 376 line), which doesn’t work because of which when faces[i] is accessed, there’s an error of bad allocation.
Any solutions / comments on this, please?
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 2
- Comments: 30 (26 by maintainers)
finally:
https://github.com/berak/opencv_contrib/blob/b6e631bdc87c40260995080abce5f52cdbd453d9/modules/face/src/facemarkLBF.cpp#L375-L397
and all my tests pass (travis code here)
but it’s ugly. fixing the deficiancies of the python bindings from the inside of opencv code – can’t be really the answer. however, it’s far less invasive, than changing the interfaces.
thanks for all your help, btw !
it’s weird, roimat.type() is CV_32SC4 when the input comes from c++ or java, but CV_32S, when it’s from python. i guess, it’s better, to check
instead.
(that’s why it returned an empty landmarks list)
hi, @krshrimali
well, i added the python / java bindings, but could only test the java ones properly, so this is probably my bad here.
indeed the
roi.getObj()code is the problem:https://github.com/opencv/opencv_contrib/blob/2231018c839d728811a39556ec83741bf9a27614/modules/face/src/facemarkLBF.cpp#L373-L376
the generated python wrappers for the fit() function produce this:
see the
Mat facesthere ? the situation is similar to this:the java wrappers are a bit more lucky here:
but they had to be told, to do so:
https://github.com/opencv/opencv_contrib/blob/2231018c839d728811a39556ec83741bf9a27614/modules/face/misc/java/gen_dict.json#L12-L13
solution ? i have no immediate one. maybe the python wrapppers can be made smarter ? maybe the interface can be refactored (swap
InputArrayfor avector<Rect>) ? maybe we can find a way to retrieve a vector from an InputArray without a horrible cast ? none of it nice or easy.Maybe you miss the face_landmark_model.dat download_link? The code has passed in my environment.
Besides it’s my fault that I should have made a new branch… If it’s possible to change the existing pr?
@berak Sorry, I just submitted the pr1 for opencv_contrib and pr2 for opencv, which should solve the problem and works fine on your tests. Since I’m not quite familiar with the whole process of pull request and it may take some time to merge into the master branch, you can try the one on my github page.
Thanks a lot for the hints you provided!
@berak : Thanks. Let me see if I can ask a student interested in GSOC to pick up this problem.
@krshrimali usually a pr (making a proper solution available to everyone else) should close this, please rather leave this open for now (mainly, – so other folks with the same problem have a better chance getting here).
exactly. it’s a duct-tape fix. it’s mending the symptom (segfaults all over), not the problem (python bindings are not smart enough)
well, no solution yet.
while
would fix problem #1 ,it still segfaults with the landmarks now (similar problem).
c++ and java use a
vector<vector<Point2f>>, while python has avector_Matthere (look at the gennerated code above). and it segfaults after leaving the fit() function, in pyopencv_to().there are even correct pyopencv_to() versions for
vector_Rectandvector_vector_Point2fin cv2.cpp , but as long as the parser generates wrong signatures, they can’t do the right thing.yes, i get the segfault too, still inquiring. java & python wrappers are handling std::vector differently (unfortunately)
for a single face, i get a
[1 x 1]Mat with type CV_32SC4, while from python i get[4 x 1]with type CV_32S (so, channels vs. columns)and the python version crashes then, because the MatIterator tries to makes 4 Rects of it, and goesout of bounds this way.
i’ll try with a reshape(4,matroi.rows)
Update:
Earlier I was using cascade detector to detect faces, this time I used
getFacesHAAR()function and since it returns a tuple, I had to inputlist(faces)[1]tofitfunction.This returns segmentation fault though, but passes
faces.empty()stage.EDIT : The segmentation fault is in
fitImpl()function, in the beginning where it accesseslandmarks.size(). And there is furthersegmentation faultin:landmarks = Mat(shape.reshape(2) + Scalar(min_x, min_y)i might have found a solution: just accept, that we have a Mat here, and treat it like that.
instead of casting a void pointer:
retrieve the
vector<Rect>from a Mat:this would work with both
vector<Rect>andMatalso add a bit of type safety, imho. (ofc. the AAM and kazemi classes would need the same treatment)@krshrimali , could you try it ? also, i’d be glad about any comments !