2

I have a project to create a face detection program. One of the requirements is for me to draw a line across the center of the face.

Now the way I have done this is by first drawing a line across the two eyes (by getting each eye's coordinates and using them as line points) and then drawing a perpendicular line to that. This way I can account for face rotation aswell.

However this line is the same length as the line across the eyes. I want this perpendicular line to cut across the entire face if possible. Attached is an example of my output for one the rotated face images. I need the green line to be longer.

Sheraz
  • 23
  • 1
  • 4
  • is this green value fixed for each image? will inRange with that rgb value give you a nice segmentation of the green line? – Micka Dec 01 '15 at 17:44
  • @Micka The green line is calculated differently for each image. The line is simply the centre of the face drawn. I just want that line longer. – Sheraz Dec 01 '15 at 19:28
  • I mean the color, is it always the very same rgb value for the green color? – Micka Dec 01 '15 at 22:40
  • isn't it easier to adjust the face detection code to draw differently right in the beginning? – Micka Dec 04 '15 at 08:09

2 Answers2

3

unfortunately your image is a jpeg so it has compression artifacts.

I first tried to extract the line, but that didnt give good angle information, so I use cv::minAreaRect after green area segmentation.

cv::Mat green;
cv::inRange(input, cv::Scalar(0,100,0), cv::Scalar(100,255,100),green);


// instead of this, maybe try to find contours and choose the right one, if there are more green "objects" in the image
std::vector<cv::Point2i> locations; 
cv::findNonZero(green, locations);

// find the used color to draw in same color later
cv::Vec3d averageColorTmp(0,0,0);
for(unsigned int i=0; i<locations.size(); ++i)
{
    averageColorTmp += input.at<cv::Vec3b>(locations[i]);
}
averageColorTmp *= 1.0/locations.size();

// compute direction of the segmented region
cv::RotatedRect line = cv::minAreaRect(locations);

// extract directions:
cv::Point2f start = line.center;
cv::Point2f rect_points[4];
line.points(rect_points);
cv::Point2f direction1 = rect_points[0] - rect_points[1];
cv::Point2f direction2 = rect_points[0] - rect_points[3];

// use dominant direction
cv::Point2f lineWidthDirection;
lineWidthDirection = (cv::norm(direction1) < cv::norm(direction2)) ? direction1 : direction2;
double lineWidth = cv::norm(lineWidthDirection);
cv::Point2f lineLengthDirection;
lineLengthDirection = (cv::norm(direction1) > cv::norm(direction2)) ? direction1 : direction2;
lineLengthDirection = 0.5*lineLengthDirection; // because we operate from center;

// input parameter:
// how much do you like to increase the line size?
// value of 1.0 is original size
// value of > 1 is increase of line
double scaleFactor = 3.0;

// draw the line
cv::line(input, start- scaleFactor*lineLengthDirection, start+ scaleFactor*lineLengthDirection, cv::Scalar(averageColorTmp[0],averageColorTmp[1],averageColorTmp[2]), lineWidth);

giving this result:

enter image description here

This method should be quite robust, IF there is no other green in the image but only the green line. If there are other green parts in the image you should extract contours first and choose the right contour to assign the variable locations

Micka
  • 19,585
  • 4
  • 56
  • 74
0

Ill write it out in pseudocode

  • Take the furthest right hand edge coordinate (row1,col1) in your image
  • Take the right hand point of your line (row2,col2)
  • Draw a line from that your line (row2,col2) to (row2,col1)
  • Repeat for the left hand side

This will result in drawing two additional lines from either side of your line to the edge of your image.

GPPK
  • 6,546
  • 4
  • 32
  • 57
  • 1
    Will this not resullt in two vertical lines stemming from the original line's ends, these lines wouldn't have the same gradient as the original green line? – Sheraz Dec 01 '15 at 15:27