我正在开发一个像Camera鼠标或其他面部控制鼠标的系统,我已经实现了所有的功能,鼠标指针也运行良好,但我想创建运动平滑就像鼠标控制指针一样。我正在使用的代码是:
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);
}
}
}
答案 0 :(得分:0)
好的,我确信还有很多其他更好的方法,但这是一种快速而又肮脏的方式,可以从“点”到“点”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();
}
}
}
}
此方法基于this answer