问题分析
现代生活,触摸屏手机已是非常普及,可以说人手一只。我们只要用手指轻轻在屏幕上触碰,手机就能感应到我们的操作,并且执行相应的功能。那么,手机是怎样定位到触摸点的呢?这个就是我们今天要讨论算法所重点要模拟解决的问题。
解决的思路是:把我们手机屏幕看成一个二维坐标系,横竖分别分为X轴和Y轴,这样我们就可以通过坐标值来定位某个点。知道如何表示触摸点还不足够,我们怎样确定定位点呢?这就涉及到硬件了,每个屏幕TP上面都会有电容感应器,当你用手触摸某个地方时,那里对应的电容值便会升高。多点触摸,就会有多个地方电容值升高。
但问题又来了,我们触摸的地方往往是一个区域,因为我们手指有一定的宽度。所以,我们需要按电容值的高低对屏幕坐标先进行分簇,即局部最大值聚类。对np_values搜索局部极大值。如果只找到一个局部最大值,则有一个单点触摸。如果找到多个局部极大值,则有多个接触。
分簇完成,接下来就好办了,可以通过计算电容加权平均值得出每个分簇的精确定位。
分簇实现
下面是一个屏幕电容值的模拟数据表:
可以看到,表中所给电容值横轴方向、纵轴方向都有所变化,当触摸屏某个位置有触摸动作发生时,该处电容值会升高,由此可判断出,上图中有两处按压。
可得到两个序列:
x轴序列是{0,6,137,84,9,4},Y轴序列是{1,4,45,25,2,2,13,52,58,15,4}。
分簇要找的就是所给序列的突峰区间,如果用索引(坐标索引从0开始计)来表示的话,上述x轴序列有一个分簇区间[0,5],y轴序列有两个分簇区间[0,4]和[5,10]。图示如下:
最后,我们需要输出分簇结果:x轴分簇[0,5],y轴分簇[0,4]、[5,10]。
分簇算法实现的难点在哪儿呢?我觉得应该是如何判断一个分簇的开始与结束。为了实现判断,我在遍历索引的时候,加上了标志变量(如果当前电容值比它的前者大的话,标志变量置1,否则置2)。然后在输出分簇的时候,我们就可以通过判断标志变量,准确输出区间。主要实现代码如下:
|
|
精确定位实现
有了分簇结果,我们就可以借用分簇结果来计算每个分簇对应的精确坐标值了。计算的过程:首先需要找到分簇区间中每个索引对应的电容值,把电容值累加到变量CapacitanceALL,然后将每个索引值*对应电容值累加到变量AddAll,最后就可通过AddAll / CapacitanceALL来计算出每个分簇的精确值location。
主要实现代码如下:
|
|
算法测试
测试数据用的是上面提供电容模拟表中的数值,分别输入X、Y方向上的电容值,测试结果如下:
后言
关于这个算法就介绍这么多了,有什么不对的地方还望多多指教,也欢迎大家关注我(简书/GitHub)
谢谢观看此文。