Portfolio


Friday, March 19, 2010

CAMSHIFT in EmguCV

Hey Assalam-O-Alikum..

Atlast im successsful in making a program that can track object using CAMSHIFT algorithim with the help of EmguCV.. EmguCv is basically an openCV wrapper class.. it can be downloaded from EmguCv website.. ( ) it is free and open source... :)

here is a piece of code how i accomplished my MISSION.. :P :)




namespace WindowsFormsApplication1
{
public partial class frmCamShift : Form
{

private Capture cap;
private HaarCascade haar;

private Image faceS;

private static RangeF range = new RangeF(0, 180);
private DenseHistogram hist = new DenseHistogram(16, range);

private Image hue = null;
private Image mask = null;
private Image backproject = null;
private Image hsv = null;

private IntPtr[] img = null;
private Rectangle trackwin;
private MCvConnectedComp trackcomp = new MCvConnectedComp();
private MCvBox2D trackbox = new MCvBox2D();

private bool isTrack = false;

public frmCamShift()
{
InitializeComponent();
}

private void frmCamShift_Load(object sender, EventArgs e)
{
cap = new Capture(0);
//haar = new HaarCascade("haarcascade_frontalface_alt.xml");
haar = new HaarCascade("haarcascade.xml");
cap.FlipHorizontal = true;
}

private void timer1_Tick(object sender, EventArgs e)
{
using(Image nextframe=cap.QueryFrame())
{
if (nextframe != null)
{
if (isTrack == false)
{
Image grayframe = nextframe.Convert();
grayframe._EqualizeHist();

var faces = grayframe.DetectHaarCascade(haar, 1.4, 4, HAAR_DETECTION_TYPE.FIND_BIGGEST_OBJECT | HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(40, 40))[0];

hsv = new Image(grayframe.Width, grayframe.Height);
hsv = nextframe.Convert();
hsv._EqualizeHist();

hue = new Image(grayframe.Width, grayframe.Height);
mask = new Image(grayframe.Width, grayframe.Height);
backproject = new Image(grayframe.Width, grayframe.Height);

Emgu.CV.CvInvoke.cvInRangeS(hsv, new MCvScalar(0, 30, Math.Min(10, 255), 0), new MCvScalar(180, 256, Math.Max(10, 255), 0), mask);
Emgu.CV.CvInvoke.cvSplit(hsv, hue, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);

picHue.Image = hue.ToBitmap();


foreach (var face in faces)
{

// Rectangle roi = new Rectangle(face.rect.X + face.rect.Width / 4, face.rect.Y + face.rect.Height / 4, face.rect.Width / 2, face.rect.Height / 2);
// Rectangle roi = new Rectangle(face.rect.X, face.rect.Y, face.rect.Width / 2, face.rect.Height / 2);

Emgu.CV.CvInvoke.cvSetImageROI(hue, face.rect);
Emgu.CV.CvInvoke.cvSetImageROI(mask, face.rect);

nextframe.Draw(face.rect, new Bgr(0, double.MaxValue, 1), 2);
picMask.Image = mask.ToBitmap();
trackwin = face.rect;

}
img = new IntPtr[1]
{
hue
};

Emgu.CV.CvInvoke.cvCalcHist(img, hist, false, mask);

Emgu.CV.CvInvoke.cvResetImageROI(hue);
Emgu.CV.CvInvoke.cvResetImageROI(mask);

CapImg.Image = nextframe.ToBitmap();
isTrack = true;
// isTrack = true;
}
else
{
if (trackwin != null)
{
hsv = nextframe.Convert();
Emgu.CV.CvInvoke.cvInRangeS(hsv, new MCvScalar(0, 30, 10, 0), new MCvScalar(180, 256, 256, 0), mask);
Emgu.CV.CvInvoke.cvSplit(hsv, hue, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
picMask.Image = mask.ToBitmap();
picHue.Image = hue.ToBitmap();

}

img = new IntPtr[1]
{
hue
};

Emgu.CV.CvInvoke.cvCalcBackProject(img, backproject, hist);
Emgu.CV.CvInvoke.cvAnd(backproject, mask, backproject, IntPtr.Zero);

Image grayframe = nextframe.Convert();
grayframe._EqualizeHist();


var faces = grayframe.DetectHaarCascade(haar, 1.4, 4, HAAR_DETECTION_TYPE.FIND_BIGGEST_OBJECT | HAAR_DETECTION_TYPE.DO_CANNY_PRUNING, new Size(40, 40))[0];
foreach (var face in faces)
{
nextframe.Draw(face.rect, new Bgr(Color.Black), 2);
}


if (trackwin.Width == 0) trackwin.Width = 40;
if (trackwin.Height == 0) trackwin.Height = 40;

Emgu.CV.CvInvoke.cvCamShift(backproject, trackwin, new MCvTermCriteria(10,0.1), out trackcomp, out trackbox);
trackwin = trackcomp.rect;

// CvInvoke.cvEllipseBox(nextframe, trackbox, new MCvScalar(0, 255, 0), 2, LINE_TYPE.CV_AA, 0);


nextframe.Draw(trackwin, new Bgr(Color.Blue), 3);
CapImg.Image = nextframe.ToBitmap();
faceS = nextframe.Copy(trackwin);
picFace.Image = faceS.ToBitmap();

}
}


}
}

private void cmdRefresh_Click(object sender, EventArgs e)
{
//timer1.Enabled = false;
//isTrack = false;
//trackwin.Width = 0;
//trackwin.Height = 0;
//hue.Dispose();
//mask.Dispose();
//hsv.Dispose();
//backproject.Dispose();
//img = null;
//timer1.Enabled = true;
}
}
}


i wish i could put some comments on it but unfortunatly i cant do that right now..

here is a video of how it worked.. my Webcam gives really really BAD result :(.. just 2-4 fps... maybe its because of my slow processor and freaking webcam.. any way, it was big achievement for me as i was working on it for a month... :)



my hair style looks Ugly.. LOlZzzzXXX

it detects the face using haar classifiers and then tracks it using CAMShift algorithim.. im trying to do some more work on it as i want to disply in my univesity's IT fair, so NO cheating allowed till MAY 2010.. :)

You can find another post of mine here face and facial parts detection using emgucv and haar classifiers

Dont forget to comment.. :)

Ca ya Later..
Jazak-Allah

11 comments:

  1. Nice work. Have you tested it with multiple faces? How about distance?

    ReplyDelete
  2. hi, can I have a copy of this program? thanks!

    ReplyDelete
  3. Hello,

    Is there a way to download your example?

    Thanks.

    ReplyDelete
  4. thanks brother to share such a great information. i really like this blog and i find it very help full and very informative
    CV Translation

    ReplyDelete
  5. Thanks to all of you for comments..

    @ david : i've tested it with 3,4 faces and distance between 1ft - 8 ft and it worked gr8.. however it greatly depends upon the camera ur using..

    ReplyDelete
  6. @ nazia : i'm looking forward to post more work on mine soon :)

    ReplyDelete
  7. Dear WahaB Kotwal,

    Really nice work!! i am working on a similar project can u please send me a working application. i can't run the code u post here. thank you!

    ReplyDelete
  8. Hi bro. thank you very much. I am not good at english.but could you help me. i follow your code in my app at visual studio 2012.but not at all work. i make a troule with line code :
    Emgu.CV.CvInvoke.cvInRangeS(hsv, new MCvScalar(0, 30, 10, 0), new MCvScalar(180, 256, 256, 0), mask);
    it is not really run.my app is exit when he run this line code.
    thank bro.help me

    ReplyDelete
  9. Dear Wahab.

    Which version of EmguCV did you use? I'm using EmguCV 2.4.2, but so many error with your code (e.g replace HaarCascade with Cascade Classifier).
    What are dll files did you add to reference?

    Can you send me the project please? I need this for my thesis. My thesis is about Camshift+Kalman Filter.

    Thanks

    ReplyDelete
  10. Hi Wahab,

    I have been struggling with this function. Are you making your sample code available.

    It sure would help a dummy like me out!

    Thanks
    Doug

    ReplyDelete
  11. Dear Wahab,
    very nice work.
    I want to create project to detect facial emotion detection.
    Does the algorithm work for this purpose?
    Could you give some guidance to build facial emotion detection?
    Thank you very much
    Henry

    ReplyDelete