请问TQueue的使用(100分)

  • 主题发起人 主题发起人 kippy
  • 开始时间 开始时间
K

kippy

Unregistered / Unconfirmed
GUEST, unregistred user!
TQueue怎么初始化?是不是能存储所有类型的指针?如下代码
var
mousePointQueue: TQueue;
currMousePoint,oldMousePoint: ^TMousePoint;
begin
{初始化currMousePoint并赋值}
mousePointQueue.Push(currMousePoint)
//在这里出错!!
oldMousePoint := mousePointQueue.Peek;
while ((oldMousePoint^.timeOfPoint+5000)>currMousePoint^.timeOfPoint) do
begin
mousePointQueue.Pop;
oldMousePoint := mousePointQueue.Peek;
end;
end;
 
解决了,要先TQueue.Create;
 
各位大虾,本人刚刚学delphi很多菜鸟问题,不好意思了!
用这100分继续问一个问题:
在delphi里如何判断鼠标停留了1秒钟??我要在鼠标不动后一秒钟的时候触发一个过程,谢谢!
 
下面这个问题有难度了,你看看hint提示的原理就可以了。
 
已用队列TQueue和TTimer解决鼠标一秒的问题。
 
谢谢cqwty的提示,俺没有查到hit的原理...
本人现在正在做一个鼠标轨迹识别的小工具,现在的情况是鼠标轨迹的点序列(5秒内)都有了,如何根据点序列来判断其轨迹形状?比如圆,椭圆,矩形,直线,曲线....
希望各位发表发表意见!!谢谢!
 
各位高手给想想办法呀!!着急呢....
 
帮你顶,接个分!
 
顶一下啊!圆(计算各点和中心点的距离)和直线(计算各点和中心点的斜率)好判断,
椭圆和矩形就麻烦得很了!大家帮忙想想办法啊!多谢了!
 
先把点序列变成 有向线段 每相邻2点组成一个有向线段
 
To xusong168:然后呢?说说往下的思路
 
传感器输入到计算机的信息,包括X(t),Y(t),抬笔,落笔等。
产生的轨迹假设为(1,2)(3,4)(5,6)(7,8)
则array中存储array = {8,1,2,3,4,5,6,7,8};
平滑处理:

for(i = 4
i <= (array[0]/2-3)
i++)
{
array[2*i] = (array[2*(i-3)] + array[2*(i-2)] + array[2*(i-1)] + array[2*i] +array[2*(i+1)] + array[2*(i+2)] + array[2*(i+3)])/7;
array[2*i-1] = (array[2*(i-3)-1] + array[2*(i-2)-1] + array[2*(i-1)-1] + array[2*i-1] +array[2*(i+1)-1] + array[2*(i+2)-1] + array[2*(i+3)-1])/7;
}




冗余处理:


for(i = 2
i <= array[0]/2 &amp;&amp
i<=NUMMAX
i++)
{
d = sqrt(( (array[2*i] - array[2*(i-1)])*(array[2*i] - array[2*(i-1)]) ) + ( (array[2*i-1] - array[2*(i-1)-1])*(array[2*i-1] - array[2*(i-1)-1]) ));
if(d < 8)
{
array[2*i] = array[2*i-1] = 0
//del vertex

}
}




然后去除标记为删除的点


if(array == 0)
{
for(j=i;j<array[0] &amp;&amp
array[j] == 0 &amp;&amp
j<=NUMMAX;j++)
;
array = array[j] + array;
array[j] = array - array[j];
array = array - array[j];
}
if(j >= array[0])
array[0] = i-1;




经过这些预处理,得到的笔迹将能真实的反应用户的输入情况。

下一步就为获取方向码。

我们规定二维平面上有8个方向,分别规定为1,2,3,4,5,6,7,8

在根据以下公式计算以下两个偏移值:

dx = array[2*i-1] - array[2*i-3];

dy = array[2*i] - array[2*i-2];

求得:

d = sqrt(dx*dx + dy*dy);





再建立一个满三叉树如下,通过类似于决策树的方法来得到方向码。





从第0层到第1层选择时,计算dx/d 若

if(dx / d >= 0.37) //left child

if(dx / d > -0.37 &amp;&amp
dx/d < 0.37) //middle child

if(dx / d <= -0.37) //right child

从第1层到第2层选择时,计算dy/d若

if(dy / d >= 0.37) //left child

if(dy / d > -0.37 &amp;&amp
dx/d < 0.37) //middle child

if(dy / d <= -0.37) //right child

0.37为MIT经过试验总结出来的比较能够有区分度的值。



贴不上全文 请直接看下面网址:
http://blog.chinaunix.net/u/25661/showart.php?id=331622
大概是这样一条横线方向码就是:1,1,1
横竖横方向码就是:1,3,1
 
转帖的
向原作者致敬
 
谢谢susong168,参考你帖子的平滑处理和冗余剔除,考虑到时间复杂度没有用方向码用的是曲线拟合,已经解决问题,结贴,谢谢大家!!都有分啊,呵呵...
 
TO susong168, 你给的链接需要用户密码才能进去,郁闷...
 
我可以进去呀
不需要密码的啊
 
一种通过分析方向码的简易手写识别方法


一种通过分析方向码的简易手写识别方法

李国镇



摘要:本文介绍一种在线手写识别方法,属于智能草稿纸的一个分课题。通过实时采集用户输入,并对采集到的数据进行快速,准确的预处理,采用决策树方法,得到对应的方向码序列。用此方向码与设备内预存的每一个数据计算,采用经过改造的Levenshtein Distance算法求得LD值,计算得到的最小值就为用户输入的内容。



手写识别是计算机智能的接受用户手写输入的一种能力。这种对计算机的输入可能是写在一张纸上的,要通过扫描仪输入计算机的“离线”情况。另一种是,通过触控笔的移动“在线”获得用户输入的情况。以下讨论的输入为第二种输入情况。

在线手写识别能够实时的自动处理由传感器输入到计算机的信息,包括X(t),Y(t),抬笔,落笔等。这种数据被称之为数字墨水,并且可以动态的表示用户输入的笔迹。

下面从用户落笔开始对手写识别过程进行分析。

当用户落笔后,我们的程序截获penDown事件,从系统提供的参数可以得知触控笔落笔处的坐标(x , y)。首先要判断此点是否在程序允许输入的范围之内,若不是,则抛弃此事件,若是,则处理此事件。

有两种情况要产生penDown事件,第一种为用户输入新的字符的开始,第二种为用户还未完成此字符,而是要输入此字符的下一个笔划。要分别对两种情况的penDown事件进行处理,把坐标值存入相应的存储空间。

下一个事件就为penMove事件。也要同上一个事件一样分两种情况,把对应的坐标存入对应的存储空间。此处还要注意一点,若输入的内容过多,就要返回错误。因为用户可能为了测试程序的健壮性,随意的在屏幕上连续输入,不抬笔。如果没有考虑到这种情况,很可能产生溢出,导致系统崩溃。

再下一个事件自然为penUp事件。这个事件要特别注意,要判断这个事件的产生代表了什么意义,可能是这个字符输入完了,也可能是这个字符没有输入完,而是要输入另一个字符。要处理这一点就要费一点功夫。我采取得办法是,当产生下一个penDown事件时计算两个事件之间的间隔,据本人体验,23个时钟周期比较合适。当时间大于此数证明要输入下一笔,当时间小于这个数则说明这个字符还没有输入完全。下一步就要对存取的这个笔迹进行处理了。

此时采集到的笔迹有很多无关因素,这些无关因素可能来自用户输入时,由于屏幕太滑而产生的抖动,使得锯齿过多。或者在开始和结束处产生的干扰笔迹。因此就要对这些情况进行处理。

产生的轨迹假设为(1,2)(3,4)(5,6)(7,8)

则array中存储array = {8,1,2,3,4,5,6,7,8};



平滑处理:

for(i = 4
i <= (array[0]/2-3)
i++)
{
array[2*i] = (array[2*(i-3)] + array[2*(i-2)] + array[2*(i-1)] + array[2*i] +array[2*(i+1)] + array[2*(i+2)] + array[2*(i+3)])/7;
array[2*i-1] = (array[2*(i-3)-1] + array[2*(i-2)-1] + array[2*(i-1)-1] + array[2*i-1] +array[2*(i+1)-1] + array[2*(i+2)-1] + array[2*(i+3)-1])/7;
}




冗余处理:


for(i = 2
i <= array[0]/2 &amp;&amp
i<=NUMMAX
i++)
{
d = sqrt(( (array[2*i] - array[2*(i-1)])*(array[2*i] - array[2*(i-1)]) ) + ( (array[2*i-1] - array[2*(i-1)-1])*(array[2*i-1] - array[2*(i-1)-1]) ));
if(d < 8)
{
array[2*i] = array[2*i-1] = 0
//del vertex

}
}




然后去除标记为删除的点


if(array == 0)
{
for(j=i;j<array[0] &amp;&amp
array[j] == 0 &amp;&amp
j<=NUMMAX;j++)
;
array = array[j] + array;
array[j] = array - array[j];
array = array - array[j];
}
if(j >= array[0])
array[0] = i-1;




经过这些预处理,得到的笔迹将能真实的反应用户的输入情况。

下一步就为获取方向码。

我们规定二维平面上有8个方向,分别规定为1,2,3,4,5,6,7,8




在根据以下公式计算以下两个偏移值:

dx = array[2*i-1] - array[2*i-3];

dy = array[2*i] - array[2*i-2];

求得:

d = sqrt(dx*dx + dy*dy);





再建立一个满三叉树如下,通过类似于决策树的方法来得到方向码。





从第0层到第1层选择时,计算dx/d 若

if(dx / d >= 0.37) //left child

if(dx / d > -0.37 &amp;&amp
dx/d < 0.37) //middle child

if(dx / d <= -0.37) //right child

从第1层到第2层选择时,计算dy/d若

if(dy / d >= 0.37) //left child

if(dy / d > -0.37 &amp;&amp
dx/d < 0.37) //middle child

if(dy / d <= -0.37) //right child

0.37为MIT经过试验总结出来的比较能够有区分度的值。




这样用户输入的字符的方向码就得到了。

下一步就是要进行匹配计算,看这个方向码与存储的那个字符相似度最大。

本文采用了1965年由Vladimir Levenshtein发明的Levenshtein distance算法,并通过此算法地原理加以改进,使之适应我们的需要。







原理:

要想得到两个字符串的相似度(距离),也就是要计算一个字符串转换为另一个要比较的字符串时,所要经历的变化此数。

这里把461123 转变成 5611637,看看他的相似度是多少。

461123 → 561123 (把 4 替换成 5)

561123 → 561163 (把2 替换成 6)

561163 → 5611637 (在最后增加 7)

可以看出,从4661123转变成5611637至少需要3步。那么我们怎么让计算机也这样计算呢?

首先创建一个D[m][n]这里就是D[6][7]矩阵,来存放每次比较得到的距离。

从两个字符串的左边开始比较,记录已经比较过的子串相似度,然后进一步得到下一个字符位置时的相似度。

D[x][y]代表第一个字符串的0—x位,转变到第二个字符串的0---y位所经历的插入,删除,替换的总数。

D[x-1][y], D[x][y-1], D[x-1][y-1] 表示经过若干步的计算已经使字符串相等。



计算D[x][y]的值的过程:

如果这两位的字符相等,则取min(D[x-1][y], D[x][y-1], D[x-1][y-1])。说明此步不需要再进行改动。

如果这两位的字符不相等,则取min(D[x-1][y], D[x][y-1], D[x-1][y-1]) + 1。因为不相等所以就要进行插入,删除,替换中的一个替换工作。



例如当算到矩阵D[3,3]位置时,也就是当比较到461和561时,要从已经比较过的3对子串46-561, 461-56和46-56之中选一个差别最小的来当它的值. 所以要从左上到右下构造矩阵。所以最终答案就是最又下脚的值。






代码如下:







static Int8 levenshtein_distance(UInt8 s[] ,UInt8 x[])
{
UInt8 t,i=1,j,n,m,cost,distance;
UInt8 d[BKMAX + 1][BKMAX + 1];

n = s[0];
m = x[0];

if(n!=0 &amp;&amp
m!=0 &amp;&amp
n<=BKMAX &amp;&amp
m<=BKMAX)
{
m++;
n++;

for(t=0;t<n &amp;&amp
i<=NUMMAX;t++)
d[t][0] = t;
for(t=0;t<m &amp;&amp
i<=NUMMAX;t++)
d[0][t] = t;

for(i=1;i<n &amp;&amp
i<=NUMMAX;i++)
for(j=1;j<m &amp;&amp
i<=NUMMAX;j++)
{
if( s==x[j] )
cost=0;
else
cost=1
// 1:此处可以进行改进

d[j] = minimum( d[i-1][j]+1, d[j-1]+1, d[i-1][j-1] + cost );
}
distance = d[n-1][m-1];

return distance;
}
else
return MAXD


}




把用户输入的数据经过处理得到的方向码序列,并与以存储在计算机内部的方向码逐个进行比较,放入一个数组中。再从这个数组中查找最小值。得到的最小值的角标就是所输入的数字。

这样数字手写识别的工作就完成了。
转贴请注明出处。

若有错误尽情指出,不胜感激。
 
后退
顶部