4

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

techno
  • 6,100
  • 16
  • 86
  • 192

2 Answers2

1

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)

Community
  • 1
  • 1
unknown6656
  • 2,765
  • 2
  • 36
  • 52
  • Thanks but what do you mean by .Top and .Left – techno Dec 25 '15 at 10:14
  • @techno: Your rectangle structure should have the properties { Top, Left, Width, Height } and the the 'dot' accesses the different properties – unknown6656 Dec 25 '15 at 10:24
  • @techno: I have seen your update, and I will continue to search for solutions. However, I have to visit my family (_christmas_), so you will probably have to wait until this evening... – unknown6656 Dec 25 '15 at 11:56
  • @techno: Thank you. Merry Christmas to you, too :) You said, that my method did not return the correct result - in which way? – unknown6656 Dec 26 '15 at 10:19
  • sorry for the late reply.Was busy with Christmas and other stuff.Have you seen the code i have posted.It returns a wrong rectangle. – techno Dec 29 '15 at 05:53
  • @techno: No problem :) I have seen your code, but I do not see, in which way it is wrong... Is it to large or to thin or at the wrong position? Maybe you could upload a second image in your post update, so that we know, in which way it is wrong :) – unknown6656 Dec 29 '15 at 07:52
  • Please see my update.I dont know if my math is right.Im using the X and Y coordinates – techno Dec 29 '15 at 09:33
  • @techno: I will recalculate everything and notify you later when I found a good result :) – unknown6656 Dec 29 '15 at 09:39
  • @techno: how big is your total image (in px)? – unknown6656 Dec 29 '15 at 09:51
  • This is the image http://cdn2.thr.com/sites/default/files/imagecache/675x380/2014/11/leonardo_dicaprio.jpg Its 675X380 – techno Dec 29 '15 at 09:54
  • @techno: I edited my answer and added a code sample :) ... maybe it will work now.... *notice the `1.3` inside the integer multiplication* – unknown6656 Dec 29 '15 at 10:11
  • I keep getting --> Error 2 Cannot implicitly convert type 'double' to 'float'. An explicit conversion exists (are you missing a cast?) .Should i convert it – techno Dec 29 '15 at 10:33
  • @techno: I have forgotten about float literals. Change this here: `... 2.0` or `... 8.0` to: `... 2f` or `... 8f` (I also editd my answer) – unknown6656 Dec 29 '15 at 10:37
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/99187/discussion-between-techno-and-unknown6656). – techno Dec 29 '15 at 10:39
  • Sorry for the accepting the answer late.I had already upvoted it.I had another doubt.How do you suggest to implement a Custom Sized Crop? – techno Dec 22 '18 at 13:39
0

I would create a second bitmap and draw the first one into the second one as follows:

Bitmap source = Image.FromFile("/my/path/to/myimage.png") as Bitmap;

Rectangle facerectangle = /* your face detection logic */;
Bitmap target = new Bitmap(facerectangle.Width, facerectangle.Height);

using (Graphics g = Graphics.FromImage(target))
{
    g.DrawImage(source, new Rectangle(0, 0, target.Width, target.Height),
                facerectangle, GraphicsUnit.Pixel);
}

The code should be rather easy to understand :)
You first load your bitmap source, then create your rectangle using your face recognition logic and create the bitmap target, in which you draw the first segment using GDI+'s DrawImage.

unknown6656
  • 2,765
  • 2
  • 36
  • 52
  • I dont think you understand my question.I can crop of the detected face easily.What i need is a logic to extend the detected rectangle properly so that it includes the face and shoulders.Currently the rectangle only has the face in it. – techno Dec 25 '15 at 09:35
  • @techno: Oh, I am so sorry, Sir. I will search for a solution and edit my response appropriately. – unknown6656 Dec 25 '15 at 09:38
  • Hey Man.Don't call me sir :) .Thanks for your help. – techno Dec 25 '15 at 09:40
  • @techno: OK ^^. Which code/library are you using for your face recognition? – unknown6656 Dec 25 '15 at 09:45