Search code examples
c#face-detectionbiometrics

Crop off Parts of the Image that does not include the Face


I have detected the Face in an Image(Only 1 Person) and have the coordinates of the Face Rectangle.

enter image description here

Since the image can be of any size,I need only the part of the image that is important(head.shoulders).What intent to do is extend the bounds of the detected rectangle by some factor so that the important parts are included. Is this the right approach?

Update:
I have tried this .. but its not giving the correct result.Note that i have changed 1.7 to 2 since it only takes integer arguments.And Top and Left are readonly properties.

foreach (Rectangle f in objects)
{
    int x, y;
    x = f.Top - (f.Height / 8);
    y = f.Left - (f.Width / 2);

    Rectangle myrect = new Rectangle(x, y, f.Width * 2, f.Height * 2);

    g.DrawRectangle(Pens.Gray, myrect);
}

Detected Face Rectangle

Top----->62
Right----->470
Left----->217
Bottom----->315

Extended Rectangle as per answer

Top----->91
Right----->537
Left----->31
Bottom----->597

Extended rectangle

enter image description here


Solution

  • As my previous answer as off-topic, I will write my correct answer here:


    As I am not completely familiar with Emgu CV, I would have the following approaches:

    1. As Emgu CV is open-source, you could spend restless nights and change the code inside the libraries and recompile them etc.

    or (my preferable approach):

    1. You think about it biologically, meaning:
      You know the position and size of your face rectangle. If you also know body proporions, you can calculate the estimated width of the shoulders and there vertical offset (relative to the face's center).

    More details for the biological approach:

    Imagine fig. №1 begin true, and imagine that you have the following image and face rectangle:

    Bitmap
      | .Width == 100
      | .Height == 160
    
    Face // type: System.Drawing.Rectangle
      | .Top == 20
      | .Left == 50
      | .Width == 60
      | .Height == 60
    

    then, according to the provided image, the new Rectangle should be:

    f := Face // face rectangle
    
    Face_and_Shoulder
      | .Top = f.Top - (f.Height / 8)
      | .Left = f.Left - (f.Width / 2)
      | .Width = f.Width * 2
      | .Height = f.Height * 1.7
    

    which would result in the following values:

    Face_and_Shoulder
      | .Top == 12.5
      | .Left == 20
      | .Width == 120
      | .Height == 102
    

    The resulted rectangle (Face_and_Shoulder) should include the shoulder and hair etc. when drawing it over your image.

    This method has however a minor drawback: It will not work, if the face is rotated by a certain number of degrees (I believe more than 5..10°).


    To calculated the respective rectangle, I would advise you to use this code (you seem to have confused X and Y in your code sample):

    foreach (Rectangle f in objects)
    {
        float x = f.Left - (f.Width / 2f);
        float y = f.Top - (f.Height / 8f);
    
        Rectangle myrect = new Rectangle((int)x, (int)y, f.Width * 2, (int)(f.Height * 1.3));
    
        g.DrawRectangle(Pens.Gray, myrect);
    }
    

    fig. №1
    fig. №1 (source: http://www.idrawdigital.com/wp-content/uploads/2009/01/prop_var.gif)