通过 OpenCV 的 camshift 算法控制鼠标指针(或鼠标的基本功能)

Controlling mouse pointer through camshift algorithm of OpenCV (or how mouse basically functions)(通过 OpenCV 的 camshift 算法控制鼠标指针(或鼠标的基本功能))
本文介绍了通过 OpenCV 的 camshift 算法控制鼠标指针(或鼠标的基本功能)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我使用 EmguCV(openCV 的包装器)在 C# 中编写了一个程序.该程序使用 camshift 算法跟踪对象.围绕对象绘制一个矩形.光标移动到矩形的中心.输入来自网络摄像头.

I have written a program in C# using EmguCV (wrapper of openCV). The program tracks an object using camshift algorithm. A rectangle is drawn around the object. The cursor is moved by center of the rectangle. Input is taken from a webcam.

最初的问题是光标无法覆盖整个屏幕.它的运动仅限于框架尺寸.所以我应用了一个乘法因子:

Initially the problem was that the cursor couldn't cover the entire screen. Its movement was limited to frame size. And so i applied a multiplication factor:

X 方向移动的屏幕宽度/帧宽度.

screenwidth/framewidth for movement in X direction.

Y 方向移动的屏幕高度/帧高度

screenheight/frameheight for movement in Y direction

这样鼠标就可以覆盖整个区域.但是鼠标移动不再流畅了.我无法指出靠近的两个图标.如何在覆盖整个屏幕时使鼠标移动平滑,就像使用真正的鼠标一样?

With this the mouse covers entire area. But the mouse movement is not smooth any more. I am unable to point to two icons closely situated. How can I make mouse movement smooth while covering the entire screen, just as it happens with a real mouse?

推荐答案

指出明显的一点: 你的鼠标实现的不流畅是因为 camshift 给出的矩形只是精确到一帧像素的精度,因此可能的最小移动将屏幕大小/帧大小四舍五入到最近的屏幕像素.

To point out the obvious: the non-smoothness of your mouse implementation comes from the fact that the rectangle given by camshift is only accurate to the accuracy of one frame pixel, so the smallest movement possible will be screensize/framesize rounded to the nearest screen pixel.

如果是这种情况,可以应用某种指针加速,就像使用真实的低质量鼠标时那样(当然,如果有数千个 dpi 激光鼠标,则无需这样的事情).基本上,光标在屏幕上移动的距离不是指针输入所走的距离(在本例中为 camshift 矩形位移),而是它的一个巧妙选择的函数.因此,使用加速度函数 f(x),移动指针的步骤如下:

If that is the case, some kind of pointer acceleration could be applied, just like it is done when real, low-quality mice are used (of course, in case of multiple thousand dpi laser mice, there is no need for such thing). Basically, the distance the cursor moves on screen is not the distance taken by the pointer input (in this case, camshift rectangle displacement), but a cleverly chosen function of it. So, using an acceleration function f(x), the steps of moving the pointer will be like this:

  1. 计算指针输入位移向量,记为v.
  2. 计算对应的单位长度向量,记为u.
  3. 屏幕指针位移为v'=f(|v|) * u
  1. Calculate vector of pointer input displacement, let that be denoted by v.
  2. Calculate the corresponding unit-length vector, let that be denoted by u.
  3. The on-screen pointer displacement is v'=f(|v|) * u

我会以 beta * e^(alpha * x - 1) 之类的形式选择 f(x),其中 0 <alpha 和 0 <beta <= 1 是应该根据经验选择的参数.

I'd chose f(x) in a form like beta * e^(alpha * x - 1), where 0 < alpha and 0 < beta <= 1 are parameters which should be empirically chosen.

基本上,任何在 0 处导数为 1 或更少的函数都会执行此操作(允许您使用输入的完全准确度来进行精确的光标移动),随着 x 的增加变为无穷大(大的移动应该对应于大光标的移动),是单调递增的,并且具有单调递增的一阶导数.还需要加速函数在0时的值为0,否则会出现很奇怪的动作.:)

Basically, any function will do it that has a derivate of 1 or less at 0 (allows you to use the full accuracy of the input for precise cursor movements), goes to infinity as x increases (large movements should correspond to large movements of the cursor), is monotonically increasing and has a monotonically increasing first derivate. It is also needed that the acceleration function has a value of 0 at 0, otherwise very strange movements will happen. :)

还需要 f(framewidth) = screenwidth,这样在框架上移动被跟踪对象会导致光标在屏幕上移动.指数公式很容易使用,但使用二次或更高次多项式可能会在计算上更简单,具体取决于那里的性能要求......

It is also desirable to have f(framewidth) = screenwidth so that moving the tracked object across the frame results in the cursor being moved across the screen. An exponential formula is quite pleasing to work with, but using a quadratic or higher degree polynomial may turn out to be computationally simpler, depending on what performance requirements are there...

这篇关于通过 OpenCV 的 camshift 算法控制鼠标指针(或鼠标的基本功能)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

Custom Error Queue Name when using EasyNetQ for RabbitMQ?(使用 EasyNetQ for RabbitMQ 时自定义错误队列名称?)
How to generate password_hash for RabbitMQ Management HTTP API(如何为 RabbitMQ 管理 HTTP API 生成密码哈希)
Rabbitmq Ack or Nack, leaving messages on the queue(Rabbitmq Ack 或 Nack,将消息留在队列中)
Setup RabbitMQ consumer in ASP.NET Core application(在 ASP.NET Core 应用程序中设置 RabbitMQ 消费者)
Specify Publish timeouts in mass transit(指定公共交通中的发布超时)
RabbitMQ asynchronous support(RabbitMQ 异步支持)