繁体   English   中英

如何使用emguCV C#控制头部移动的鼠标指针?

[英]how to control mouse pointer with head movement using emguCV C#?

我正在开发一个像相机鼠标或其他面部控制鼠标一样的系统,我已经实现了所有功能,鼠标指针也可以很好地移动,但是我想像鼠标控件指针一样创建平滑的移动。 我使用的代码是:

        if (startButton == true)
        {
            try
            {
                cap = new Capture();
                pictureBox1.Image = cap.QueryFrame().ToImage<Bgr, Byte>().Bitmap;
            }
            catch (Exception exp)
            {
                MessageBox.Show("Error:" + exp);
            }
            _cascadeClassifier = new CascadeClassifier(Application.StartupPath + "/haarcascade_frontalface_default.xml");
            eye_cascadeClassifier = new CascadeClassifier(Application.StartupPath + "/haarcascade_eye.xml");

            timer1.Start();
        }

    private void timer1_Tick(object sender, EventArgs e)
    {
        using (var imageFrame = cap.QueryFrame().ToImage<Bgr, Byte>().Flip(FlipType.Horizontal))
        {
            if (imageFrame != null)
            {
                var grayframe = imageFrame.Convert<Gray, byte>();

                var faces = _cascadeClassifier.DetectMultiScale(grayframe, 1.1, 10, Size.Empty); //the actual face detection happens here

                foreach (var face in faces)
                {
                    if(Configure.FaceBoxCheck==true)
                    imageFrame.Draw(face, new Bgr(Color.LightGreen), 2); //the detected face(s) is highlighted here using a box that is drawn around it/them
                    Int32 yCoordStartSearchEyes = face.Top + (face.Height * 3 / 11);
                    Point startingPointSearchEyes = new Point(face.X, yCoordStartSearchEyes);
                    Size searchEyesAreaSize = new Size(face.Width, (face.Height * 3 / 11));
                    Rectangle possibleROI_eyes = new Rectangle(startingPointSearchEyes, searchEyesAreaSize);

                    int widthNav = (imageFrame.Width / 11 * 3);
                    int heightNav = (imageFrame.Height / 11 * 3);
                    Rectangle nav = new Rectangle(new Point(imageFrame.Width / 2 - widthNav / 2, imageFrame.Height / 2 - heightNav / 2), new Size(widthNav, heightNav));
                    imageFrame.Draw(nav, new Bgr(Color.Lavender), 3);
                    Point cursor = new Point(face.X + searchEyesAreaSize.Width / 2, yCoordStartSearchEyes + searchEyesAreaSize.Height / 2);
                    grayframe.ROI = possibleROI_eyes;
                    var eyes = eye_cascadeClassifier.DetectMultiScale(grayframe, 2.15, 3, Size.Empty);

                    foreach (var eye in eyes)
                    {
                      //imageFrame.Draw(eye, new Bgr(Color.Red), 2);
                        if(Configure.EyeBoxCheck==true)
                        imageFrame.Draw(possibleROI_eyes, new Bgr(Color.DarkGreen), 2);
                        if (nav.Left < cursor.X && cursor.X < (nav.Left + nav.Width) && nav.Top < cursor.Y && cursor.Y < nav.Top + nav.Height)
                        {
                            LineSegment2D CursorDraw = new LineSegment2D(cursor, new Point(cursor.X, cursor.Y + 1));

                            imageFrame.Draw(CursorDraw, new Bgr(Color.White), 3);
                            //we compute new cursor coordinate using a simple scale based on frame width and height
                            int xCoord = (imageFrame.Width * (cursor.X - nav.Left)) / nav.Width;
                            int yCoord = (imageFrame.Height * (cursor.Y - nav.Top)) / nav.Height;
                            //We set our new cursor position
                            Cursor.Position = new Point(xCoord * 2, yCoord *2);
                    }
                }
            }

好的,我敢肯定还有很多其他更好的方法,但这是一种以“平滑”的方式从a点到b点移动光标位置的快捷方法。 当然,可以并且应该使用其他线程而不是使用Application.DoEvents()来优化此实现,以避免阻塞UI线程,但是我希望这能使您步入正轨。 首先,应该如何使用它。 代替:

Cursor.Position = new Point(xCoord * 2, yCoord *2);

你应该做这个:

MoveCursorSmooth(Cursor.Position, new Point(xCoord * 2, yCoord *2));

现在,执行MoveCursorSmooth

    private void MoveCursorSmooth(Point a, Point b)
    {
        var step = 5;
        var left = Math.Min(a.X, b.X);
        var right = Math.Max(a.X, b.X);
        int width = right - left;

        var top = a.Y;
        var bottom = b.Y;
        int height = bottom - top;

        if (width > height)
        {
            double slope = (double)height / (double)width;
            if (a.X <= b.X) 
                for (int x = 1; x < width; ++x) 
                {
                    Cursor.Position = new Point((left + x), (a.Y + ((int)(slope * x + 0.5))));
                    System.Threading.Thread.Sleep(step);
                    Application.DoEvents();
                }
            else
                for (int x = 1; x < width; ++x) // xOffset
                {
                    Cursor.Position = new Point((right - x), (a.Y + ((int)(slope * x + 0.5))));
                    System.Threading.Thread.Sleep(step);
                    Application.DoEvents();
                }
        }
        else
        {

            double slope = (double)width / (double)height;
            if (a.X <= b.X)
            {
                for (int y = 1; y < height; ++y)
                {
                    Cursor.Position = new Point((a.X + ((int)(slope * y + 0.5))), (top + y));
                    System.Threading.Thread.Sleep(step);
                    Application.DoEvents();
                }
            }
            else
            {
                for (int y = 1; y < height; ++y)
                {
                    Cursor.Position = new Point((b.X + ((int)(slope * y + 0.5))), (bottom - y));
                    System.Threading.Thread.Sleep(step);
                    Application.DoEvents();
                }
            }
        }
    }

此方法基于此答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM