Tslib的触摸屏5点校准算法原理和实现
最近搞个触摸屏校准,参考了Tslib,感觉这个算法挺巧妙。
⼀般触摸屏校准⽆⾮以下⼏种情况:
根据触摸的AD值和LCD分辨率不同,两者会有⽐例关系。触摸屏安装的时候可能会和LCD不太契合,⽐如贴歪了,可能会有移动和旋转的
误差,使得两者坐标有偏差。
正因为有这些误差,才需要校正。假设屏上有个P点,在LCD的坐标是(X,Y),在触摸屏上是(X’,Y’)。在⼆维坐标下上⾯三种情况分别
可以⽤如下三个矩阵表⽰(不是我编的):
咱也不⽤考虑当前哪种情况了,假设三个误差都存在(某项不存在的话,后⾯带⼊计算⾃然会去除掉),就全部乘⼀下:
其中X,Y是LCD坐标由⾃⼰设定,X′和Y′触摸屏的坐标,由测量得知。⽽我们⽬的就是求αx,βx,ΔX和αy,βy,ΔY这6个未知
数⽽已,那只要构建6个⽅程,只需要取屏幕上3个点即可。
注意:重点来了不要被上⾯的推导过程吓到,⼜是三⾓函数⼜是矩阵相乘,其实没⼈会关⼼触摸屏和LCD到底贴歪了多少度,移动了多少个
像素点,只要知道我们的⽬的是为了求这些系数,这些值能帮助我们将触摸屏坐标转化为LCD坐标就可以了,更简化且平易近⼈的写法如
下:
解⽅程的话,可以⽤克拉默法则,⾃⼰玩的话随便取3个点⼿算也⾏,注意3点法需要取独⽴点,即在屏幕上画出三个已知LCD坐标的点,
最好不要连成⼀条线,然后记录下这些点的触摸屏坐标,代⼊⽅程可得:
这样可以求出A,B,C,D,E和F,若按矩阵写法(还是换回α和β的写法)如下:
写成⽅程就是b=A∙x,或x=A-1∙b,其中A是系数矩阵,b是常数列向量,x是未知数列向量。对应上⾯x坐标的公式b就是,未知
数列向量就是。
注:要求的线性⽅程x=A-1∙b中,A-1=A*/|A|,设Δ=|A|也就是系数矩阵A的⾏列式值,伴随矩阵A*与b相乘之后得到Aj,那么未知
数解xj=|Aj|/|A|。本⽅程3个未知数的|A1|,|A2|和|A3|标记为为Δx1、Δx2和Δx3,那么3个未知数解分别是αx=Δx1/Δ,βx=
Δx2/Δ,ΔX=Δx3/Δ。这是克拉默法则。
以上铺垫完毕,通通不⽤记,下⾯说说Tslib⾥⾯的5点法,或者叫n点法,改写上⾯的矩阵如下:
按照之前3点法的解法我们也⽤克拉默法则,但是忽然发现A居然不是⽅阵!!A是nx3(n>3)的矩阵!A-1都没有意义了!x=A-1∙b都
没了!和还有啥⽤!!
等等,有点⼤惊⼩怪了,不是⽅阵的话A-1就是个伪逆矩阵吧!n>3左逆矩阵为A-1=(ATA)-1AT,那么公式变为
为啥要这么变?别和我说什么最⼩⼆乘解左逆右逆什么最优解之类的,我就是想要搞个⽅阵,A的转置AT和A相乘就变成⽅阵,令A=
ATA,b=,这样x=A-1∙b⼜来了!接下来只要求出ATA和就可以⽤克拉默法则了。
为了计算⽅便我们定义如下:
那么可以放⼼求解:
重点来了,以上公式统统不⽤纠结,带⼊上⾯公式可以发现⼀个规律:
ts_calibration_common.c
intperform_calibration(calibration*cal)
{
intj;
floatn,x,y,x2,y2,xy,z,zx,zy;
floatdet,a,b,c,e,f,i;
floatscaling=65536.0;
/*Getsumsformatrix*/
n=x=y=x2=y2=xy=0;
for(j=0;j<5;j++){
n+=1.0;
x+=(float)cal->x[j];
y+=(float)cal->y[j];
x2+=(float)(cal->x[j]*cal->x[j]);
y2+=(float)(cal->y[j]*cal->y[j]);
xy+=(float)(cal->x[j]*cal->y[j]);
}
/*Getdeterminantofmatrix--checkifdeterminantistoosmall*/
det=n*(x2*y2-xy*xy)+x*(xy*y-x*y2)+y*(x*xy-y*x2);
if(det<0.1&&det>-0.1){
printf("ts_calibrate:determinantistoosmall--%fn",det);
return0;
}
/*Getelementsofinvermatrix*/
a=(x2*y2-xy*xy)/det;
b=(xy*y-x*y2)/det;
c=(x*xy-y*x2)/det;
e=(n*y2-y*y)/det;
f=(x*y-n*xy)/det;
i=(n*x2-x*x)/det;
/*Getsumsforxcalibration*/
z=zx=zy=0;
for(j=0;j<5;j++){
z+=(float)cal->xfb[j];
zx+=(float)(cal->xfb[j]*cal->x[j]);
zy+=(float)(cal->xfb[j]*cal->y[j]);
}
/*Nowmultiplyouttogetthecalibrationforframebufferxcoord*/
cal->a[0]=(int)((a*z+b*zx+c*zy)*(scaling));
cal->a[1]=(int)((b*z+e*zx+f*zy)*(scaling));
cal->a[2]=(int)((c*z+f*zx+i*zy)*(scaling));
printf("%f%f%fn",(a*z+b*zx+c*zy),
(b*z+e*zx+f*zy),
(c*z+f*zx+i*zy));
(c*z+f*zx+i*zy));
/*Getsumsforycalibration*/
z=zx=zy=0;
for(j=0;j<5;j++){
z+=(float)cal->yfb[j];
zx+=(float)(cal->yfb[j]*cal->x[j]);
zy+=(float)(cal->yfb[j]*cal->y[j]);
}
/*Nowmultiplyouttogetthecalibrationforframebufferycoord*/
cal->a[3]=(int)((a*z+b*zx+c*zy)*(scaling));
cal->a[4]=(int)((b*z+e*zx+f*zy)*(scaling));
cal->a[5]=(int)((c*z+f*zx+i*zy)*(scaling));
printf("%f%f%fn",(a*z+b*zx+c*zy),
(b*z+e*zx+f*zy),
(c*z+f*zx+i*zy));
/*Ifwegothere,we'reOK,soassignscalingtoa[6]andreturn*/
cal->a[6]=(int)scaling;
return1;
}
此时会发现算出的这些红⾊的系数公式和Tslib内的perform_calibration函数内的⼀模⼀样。
完结撒花。
本文发布于:2023-03-10 18:48:17,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/1678445298206742.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:屏幕校正.doc
本文 PDF 下载地址:屏幕校正.pdf
留言与评论(共有 0 条评论) |