WebCamViewForm.cs 7.64 KB
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using ImageFilters;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MoyaSignup
{
    public partial class WebCamViewForm : Form
    {
        int RetangleHeight = 410;
        int RetangleWidth = 280;

        int camHeight = 720;

        List<Capture> webCams;

        Dictionary<Capture, Image<Bgr, byte>> currentFrames = new Dictionary<Emgu.CV.Capture, Image<Bgr, byte>>();

        Image<Bgr, Byte> currentFrame;
        Image<Bgr, Byte> currentFullFrame;
        HaarCascade face;
        Image<Gray, byte> gray = null;

        Dictionary<Capture, decimal> scores = new Dictionary<Capture, decimal>();

        public WebCamViewForm(List<Capture> webCams)
        {
            InitializeComponent();

            this.webCams = webCams;
        }

        private void WebCamViewForm_Load(object sender, EventArgs e)
        {
            foreach(Capture cam in webCams)
            {
                ImageBox box = new ImageBox();
                box.Size = new Size(640, 360);
                box.Tag = cam;

                /*
                FlowLayoutPanel flowPanel = new FlowLayoutPanel();
                flowPanel.FlowDirection = FlowDirection.LeftToRight;
                flowPanel.Size = new Size(300, 410);
                ImageBox box2 = new ImageBox();
                box2.Size = new Size(280, 410);
                box2.Tag = cam;
                Label label = new Label();
                label.Text = "0";
                flowPanel.Controls.Add(box2);
                flowPanel.Controls.Add(label);
                */

                CroppedImageControl croppedImageCtrl = new CroppedImageControl();
                
                flowLayoutPanel1.Controls.Add(box);
                flowLayoutPanel2.Controls.Add(croppedImageCtrl);
            }

            timer1.Enabled = true;
            timer1.Start();

            face = new HaarCascade("haarcascade_frontalface_default.xml");
            //Application.Idle += FrameGrapper;
        }

        private void FrameGrapper(object sender, EventArgs e)
        {
            for(int i=0; i < webCams.Count; i++)
            {
                Capture cam = webCams[i];
                Image<Bgr, byte> currentFullFrame = cam.QueryFrame();

                /*
                lock (currentFrames)
                {
                    if (currentFrames.ContainsKey(cam))
                        currentFrames[cam] = currentFullFrame;
                    else
                        currentFrames.Add(cam, currentFullFrame);
                }*/

                if (i <= flowLayoutPanel1.Controls.Count && flowLayoutPanel1.Controls[i] is ImageBox)
                {
                    currentFrame = currentFullFrame.Resize(640, 360, Emgu.CV.CvEnum.INTER.CV_INTER_CUBIC); //640x360
                    
                    ImageBox box = (ImageBox)flowLayoutPanel1.Controls[i];
                    

                    //Dictionary<Image<Bgr, byte>, decimal> croppedImages = new Dictionary<Image<Bgr, byte>, decimal>();

                    decimal score = 0;
                    
                    gray = currentFrame.Convert<Gray, Byte>();

                    MCvAvgComp[][] facesDetected = null;

                    if (gray != null)
                    {
                        //Face Detector
                        facesDetected = gray.DetectHaarCascade(
                      face,
                      1.1,
                      10,
                      Emgu.CV.CvEnum.HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
                      new Size(50, 50));
                    }

                    //Action for each element detected
                    if (facesDetected != null && facesDetected[0].Length > 0)
                    {
                        

                        MCvAvgComp f = facesDetected[0][0];

                        //decimal width = ((decimal)f.rect.Width) * 2.9M;
                        //decimal height = width * 1.464285M;

                        decimal width = ((decimal)f.rect.Width) * 2.8M;
                        
                        decimal height = width * 1.464285M;


                        int x = (f.rect.X + f.rect.Width / 2) * 2;
                        x = (int)(x - width / 2);

                        int y = (f.rect.Y + f.rect.Height / 2) * 2;
                        y = (int)(y - height / 2);


                        int x1 = (int)(x + width / 2);
                        if (x1 >= 1280)
                            x1 = 1279;
                        int y1 = (int)(y + height / 2);
                        if (y1 >= camHeight)
                            y1 = 719;

                        decimal distance = (decimal)Math.Sqrt(Math.Pow((double)(x1 - 640), 2) + Math.Pow((double)(y1 - 360), 2));

                        score += distance;

                        /*
                        Rectangle cropRectangle2 = new Rectangle(x, y, (int)width, (int)height);
                        currentFullFrame.Draw(cropRectangle, new Bgr(Color.Red), 2);

                        currentFrame = currentFullFrame.Resize(640, 360, INTER.CV_INTER_CUBIC);

                        Image<Bgr, byte> croppedImage = currentFullFrame.Copy(cropRectangle);

                        croppedImage = croppedImage.Resize(280, 410, INTER.CV_INTER_CUBIC);
                        */
                        
                        currentFullFrame.Draw(new Rectangle(x, y, (int)width, (int)height), new Bgr(Color.Blue), 2);

                        // allow offset
                        if (y < 0 && y > -50)
                            y = 0;

                        if (y + height > camHeight && y + height < camHeight + 150)
                            y = camHeight - (int)height -1 ;


                        if (x + width <= 1280 && y + height <= camHeight && x >= 0 && y >= 0)
                        {
                            Debug.WriteLine("[webcamviewform] Found a face in frame");
                            Rectangle cropRectangle = new Rectangle(x, y, (int)width, (int)height);
                            currentFullFrame.Draw(cropRectangle, new Bgr(Color.Red), 2);
                            
                            currentFrame = currentFullFrame.Resize(640, 360, INTER.CV_INTER_CUBIC);

                            Image<Bgr, byte> croppedImage = currentFullFrame.Copy(cropRectangle);

                            croppedImage = croppedImage.Resize(280, 410, INTER.CV_INTER_CUBIC);



                            //Bitmap latestFrame = BitmapFilter.Crop(croppedImage.Bitmap, RetangleWidth, RetangleHeight, ImageFilters.BitmapFilter.AnchorPosition.Free);
                            if(flowLayoutPanel2.Controls != null && flowLayoutPanel2.Controls.Count > i && flowLayoutPanel2.Controls[i] is CroppedImageControl)
                            {
                                CroppedImageControl croppedImageCtrl = (CroppedImageControl)flowLayoutPanel2.Controls[i];
                                croppedImageCtrl.SetScore(score);
                                croppedImageCtrl.SetPicture(croppedImage.Bitmap);
                            }
                            
                        }
                        //draw face box to image
                        currentFrame.Draw(f.rect, new Bgr(Color.Green), 2);

                    }

                    box.Image = currentFrame;


                }
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            FrameGrapper(sender, null);
        }
    }
}