前言
投影仪作为家庭影院和商务演示的重要设备,其画面质量至关重要。然而,在实际使用过程中,由于投影角度和距离的限制,投影画面常常会出现梯形失真,影响观感体验。
近期工作项目上,用到了三轴陀螺仪进行投影梯形的校正,此篇博文将对近期工作的一个技术总结,对投影梯形原理、校正进行全方面的概述总结。
一、投影仪梯形形成的原因
梯形失真是指投影画面呈现梯形而非矩形的现象,主要由以下因素导致:
1.投影角度问题
当投影仪与投影屏幕不成直角时,画面就会出现梯形失真。例如,投影仪放置在桌面上向上投影到墙壁,或悬挂在天花板上向下投影,都会因为投影角度倾斜而产生梯形,一般分为垂直梯形和水平梯形。
2.投影距离不均匀
如果投影仪与屏幕的距离左右或上下不均匀,也会导致画面变形。例如,投影仪放置在房间一侧,投影到对面墙壁时,左右距离不同,画面就会出现梯形。
3.投影仪摆放位置不当
投影仪如果放置在不平整的表面,或摆放位置过高、过低,都会影响投影角度和距离,导致梯形失真。
二、市面上常见梯形校正解决方案
2.1 光学梯形校正
它是指通过调整镜头的物理位置来达到调整梯形的目的,它不会压缩画面,因此不会对画质造成损失。然而,实现光学梯形校正需要更高的技术要求和成本,因此多见于高端投影仪或工程机领域。
这里对光学梯形校正就不深入了解了,技术成本太高,一般的公司也绝对不会使用此方法,更多的是通过软件算法去解决。
2.2 数码梯形校正
目前大部分投影机产品都采用的是数码梯形校正技术,通过软件的算法实现梯形校正的效果,例如将垂直梯形和水平梯形通过算法达到校正的效果。
缺点是画面有压缩、可能带来画质的下降,图像经校正后,画面的一些线条和字符边缘会出现毛刺和不平滑现象,导致清晰度不是特别理想,所以,如果对图像精度要求特别高的场景不适用。
现在市面上很多投影仪采用的都是3D ToF技术,使用该项技术之后就可以通过机器至墙面之间的距离,计算出实际的焦距,从而带来全向无感自动对焦、梯形矫正、自动入幕、自动感应护眼等画面调整功能。
三、陀螺仪实现自动梯形
在一些比较高端的投影仪中,通常都是会使用比较前言的技术方案去实现,但也不乏有很多中低端的产品,需要去控制硬件成本等,只能通过其它方案途径去实现大致的效果。
很多都是通过陀螺仪去实现自动梯形的效果,这对算法的要求就比较高了,一个好的算法也可以达到比较好的梯形校正效果。
以下将对陀螺仪的简单介绍、以及陀螺仪对实现梯形校正的简单阐明。
3.1 陀螺仪概述
我这里使用到的是sc7a20的一款三轴陀螺仪芯片。
三轴陀螺仪由三个独立的陀螺仪组成,分别安装在三个相互垂直的轴上(通常是x、y、z轴)。每个陀螺仪都包含一个旋转体和一个感应器。太深层次的概念就不去了解了,只需要知道,陀螺仪通过测量物体旋转体的偏离角度来获取角速度信息,并将其转化为电子信号输出,我们从中可以获取到物体的大致运动轨迹。
在投影仪中,三轴陀螺仪可以实时监测投影仪的倾斜角度和方向变化。当投影仪发生倾斜或移动时,陀螺仪会将检测到的角度数据传递给投影仪的处理器,根据这些数据计算出需要校正的角度和方向,并进行相应的调整,从而实现自动梯形校正。
3.1.1 陀螺仪驱动实现
陀螺仪驱动的调试是整个方案实现的基本盘,也是比较重要的一个环节。
驱动调试一般优先参考芯片厂家提供的驱动demo进行初始化配置,再根据实际效果进行优化。
通常需要我们更多的关注对应的芯片数据手册,修改些寄存器的值,
例如全量程选择也是要关注的点,全量程是指陀螺仪能够准确测量的最大角速度值,全量程越大,陀螺仪的分辨率就会降低,因此需要权衡准确性和灵敏度。
3.2 自动梯形实现原理
陀螺仪的驱动调试完成后,进一步就是根据获取的三轴数据去实现梯形校正。
在我的工作项目中,主控芯片只能调节上下两边的梯形(即垂直梯形)。
在投影仪位置摆动的过程中,通过三轴陀螺仪获取其中两轴的数据,从而可以计算出摆动的弧度和度数,既然知道了摆动的角度,我们就可以通过软件写一个算法进行相应的校正梯形。
这里大致可以分为两步走:将梯形调正成矩形,再将矩形按比例调整(例如调整成16:9或者4:3的矩形)。这些调整都需要自己去写一个比较精准的算法,写这个调整算法也算是一个难点,在实际测试中去不断修正算法。
写好梯形修正算法后,还需要对陀螺仪获取的三轴数据进行滤波处理。
首先,我们知道即使陀螺仪平放在桌面,获取到的三轴数据也不会是一直固定的,它都是会在一个范围内不断波动的,我们得到的会是一串不平稳的数值,这个时候需要我们对数据进行滤波处理,从而得带一个比较平稳的数值。
在调试过程中,我们可以发现在噪声干扰源小的情况下,它的数值相对会比较平稳,但是在高噪音下(例如播放视频音乐等等)它的数值波动就比较大了,处理这种情况,将是一个难点,那么如何让它尽量处于一个平稳值呢?
以下是我的处理方法,仅供参考!有更好的方法欢迎大家评论区赐教。
①在低噪音情况下:
即使在低噪音情况下,陀螺仪的数值也是会有波动的,在检测到数值变化的时候,我们不应该都去调整梯形画面,这会造成画面一直调整,看起来会一直抖动、变化;此时,我们可以设置一个范围值或者角度值,实时检测获取陀螺仪数据,如果获取的值超过了当前设定值一定的范围,就去调整梯形,否则小范围波动就不调整。
②在高噪音情况下:
高噪音就是投影仪周围的噪声比较大,严重影响了陀螺仪的准确性,此时如果还是按照低噪音的情况处理,画面就会跳动的比较厉害,因为我们无法获取一个准确的数据来进行调整,既然数据都是不准确的,那么我们拿错误的数据去校准,得到的也是错误的校准画面;因此我们需要对这种情况去做处理。
我的方法是:先获取每个轴一定量的数据,可以是二三十个数值,比如是每个轴获取20个数值,然后对获取到的数值进行从小到大排序,排好序后对这串数据进行首、尾数据比较,如果首尾数值差大于某个数值(例如30),那就把首尾数据剔除掉,再从剔除掉后的数组中去首尾数值比较,直到首尾数值差不超过这个数值为止,对剩下的数组数据求平均值,就可以获得一个比较平稳的数值了。这种方法我经过数次测试验证也是比较可靠的。
贴出部分代码作为参考:
/********** 数据从小到大排序 ***********/
static void bubbleSort(double *arr,int size)
{
int i, j;
for (i = 0; i < size - 1; i++) {
for (j = 0; j < size - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
/************************************************
* function:单轴数据平滑处理
* arr: 轴数据数组
* mean_value:返回的轴平均值
* near:数据数组长度
* **********************************************/
static void gsensor_data_process(double *arr, double *mean_value,int near)
{
bool ret = false;
int head = 0;
double sum =0.0;
bubbleSort(arr,near);
for(int i=0; i<(near/2-1); i++){
if(fabs(arr[i]-arr[near-1-i])> DIFF_VALUE){
continue;
}else{
ret= true;
head = i;
near = near-i;
break;
}
}
if(ret){
for(int i=head; i<near; i++){
sum +=arr[i];
}
*mean_value = sum / (near-head);
}
}