# detectMultiScale and CascadeClassifier: get better ROI

I try to get a better ROI of face because I am not very satisfied, I want to try to get a better ROI. To achieve that I am using landmark (I am using dlib and it predictor). I am trying to make something like that.

Some definitions:

dlib::shape_predictor predictor;
dlib::full_object_detection shape;


faceCascade.load(baseDatabasePath + "/" + cascadeDataName2);


Iterate on each image:

std::vector<cv::Rect> faces;
faceCascade.detectMultiScale(output, faces, 1.01, 6, 0, cv::Size(50, 50));
getBetterOverlapRectIndex();
faceROI = output(faces[bestIndex]);


At this point a get a ROI, but I am not satisfied, I wanna something more focus on face.

shape = predictor(cimg, openCVRectToDlib(faces[bestIndex]));

cv::Point centerEyeRight = cv::Point((shape.part(42).x() + shape.part(47).x()) / 2,(shape.part(42).y() + shape.part(47).y()) / 2);
cv::Point centerEyeLeft = cv::Point((shape.part(36).x() + shape.part(41).x()) / 2, (shape.part(36).y() + shape.part(41).y()) / 2);

int widthEyeRight = abs(shape.part(42).x() - shape.part(47).x());
int widthEyeLeft = abs(shape.part(36).x() - shape.part(41).x());
int widthFace = (centerEyeRight.x + widthEyeRight) - (centerEyeLeft.x - widthEyeLeft);
int heightFace = widthFace * 1.1;
faceROIAlt = output(cv::Rect(centerEyeLeft.x - (widthFace / 4), centerEyeLeft.y - (heightFace / 4), widthFace, heightFace));


But I get this (white line), but I want something like red line. Where Am I failing? I think It is so easy, but I am trapped.

edit retag close merge delete

Sort by » oldest newest most voted

First of all, let's check that you are using the right indices for each part,

The image below is sort of a map for all the coordinates of the face components and structures. But we have to make sure to decrease them by one since the cpp indexing starts by 0.

Let's take the example of the right eye, its coordinates are basically from 42 to 47 but you should use the point 45 to compute the width and the center and not 47, so your code should be as follows instead:

cv::Point centerEyeRight = cv::Point((shape.part(42).x() + shape.part(45).x()) / 2,(shape.part(42).y() + shape.part(45).y()) / 2);
int widthEyeRight = abs(shape.part(45).x() - shape.part(42).x());


For the left eye the coordinates 36 and 39 are those who matters in your case.

This will normally give you a centered ROI, but regarding its size and if it contains the interesting parts of the face. I'm not sure why you are focusing on the eyes and why you are using these "eyes based" formulas to get your ROI ?

I think that it would be much simpler and better to use other coordinates instead. What about 19, 24, 3, 14, 6 and 10 you can get from them the center and dimensions of a ROI that matches perfectly the red desired one!

Good luck!

more

If I say that I am with the same image of landmark but I did not notice it from two days, what can you say about that? I forgot to change back the last index from the try to meaning all point of right and left eye to get center. Well, at least you save my day. Moreover, I do not know motivation behind this decision, I think I tried it after reading some papers around internet and noticed that I can subdivide my image into four parts. Why you chose 19, 24, 3, 14, 6 and 10? It is not symmetric like that.

( 2017-10-29 17:07:33 -0500 )edit

It was just a random though (you can make the ROI symmetrical using some min and max operations), for example the left high corner's y would be perfect having the min between shape.part(19).y() and shape.part(24).y(), the width can be computed as shape.part(14).x()-shape.part(3).x() etc.

( 2017-10-30 03:41:07 -0500 )edit

Official site

GitHub

Wiki

Documentation