最近小项目中需要解决一些抗锯齿的问题,刚接触这个的时候查了很多资料,这里特别感觉一个朋友,谢谢他在我解决这个问题的时候给予的建议与帮助。
在horizon App中,屏幕中的矩形框随着手机的角度而不停的变换,但是矩形框在某些角度下会产生明显的锯齿,会影响显示效果。采取两种方案解决锯齿问题。
方案1:opengl的简单实现,刚接触opengl,对一些api不是很熟,在PC端单间做了一下测试:
1)code如下:
float width = 1.0; glEnable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT,GL_NICEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); glLineWidth(width); glBegin(GL_LINE_LOOP); glVertex3f(0, 0.0198, 0.0) ; glColor3f(1.0,1.0,1.0); glVertex3f(0.0301, 0.9877, 0.0) ; glColor3f(1.0,1.0,1.0); glVertex3f(1.0, 0.9802, 0.0) ; glColor3f(1.0,1.0,1.0); glVertex3f(0.9699, 0.01031, 0.0) ; glColor3f(1.0,1.0,1.0); glEnd(); glDisable(GL_LINE_SMOOTH); glDisable(GL_BLEND); glFlush();//先画矩形框的四个边界(这个是在测试过程中) glColor3f(1.0,1.0,1.0); glBegin(GL_QUADS); glVertex3f(0, 0.0198, 0.0) ; glVertex3f(0.0301, 0.9877, 0.0) ; glVertex3f(1.0, 0.9802, 0.0) ; glVertex3f(0.9699, 0.01031, 0.0) ; glEnd();//画矩形框
在实际的测试中,如果没有画出无锯齿的矩形框而直接画出填充的矩形,这样锯齿是解决不了的。
但是这个没有在android端实现,gl_line_smooth在android端没有效果,可能自己没有用对。有在网上查到用FBO,这个需要在3.0以上的版本上才可以用,而且很复杂,没有进行深入的查阅。
2)效果图:
方案2:抗锯齿的边界算法
抗锯齿这里主要用了融合的原理,当处于当前直线点的像素值的时候,融合底层像素值与直线像素的值。
在图像中,先根据旋转角度求取出矩形框在图像中的四个顶点,求出四条直线的函数方程。抗锯齿的过程如下:
1.根据直线方程以及点到直线的距离判断点在矩形框内的分布情况;
2.若当前设置的矩形边界宽度为W,当点到直线的距离小于W/2的时候就认为当前点是直线上的点,距离大于W/2的时候根据点的分布情况设置矩形内外的值。
当直线距离小于W/2的时候,进行融合过程处理。
融合值主要是由距离的exp获取,当距离越大的时候权值越低,exp函数又可以达到平滑的效果。
方案2:抗锯齿的边界算法优化
无需判断点在矩形分布的内外情况。
1. 反向插值。当前的旋转矩形框放大到原始尺寸的大小,并进行旋转到原始方向,若当前点经过反向插值以后不再原始框的区域内,说明此点不在旋转的矩形框内,若在的话说明此点在旋转的矩形框内(如下所示)。
2. 距离计算。最原始的时候:点到直线的距离是计算点到四条旋转曲线的距离。而当前算法中:点到直线的距离,四条直线是不会变换的,就是原始矩形框的四条边界。
3. 融合过程。上一方案的融合过程类似。
这一方案的关键code如下:
rstData = zeros(m,n,k);//结果像素 linew = 1;//线宽 lineData = ones(1,1,3) * 255;//线的像素 for j = 1:m for i = 1:n //遍历图像像素 trans_before = [i;j;1]; trans_end1 = S * trans_before + T; trans_end1 = R * (trans_end1 - T1) + T1; //S、T、R仿射矩阵 y = trans_end1(2);x = trans_end1(1); dis = min( min(y,m - y),min(x,n-x)); ap = abs(abs(dis)) /f/linew ; a = exp(-1.0 * ap^2); a = sqrt(a); y = round(y);x = round(x); if y < 0 | y > m | x < 0 | x > n rstData(j,i,:) = lineData * a + Image(j,i,:) * 0.4 * (1 - a); else rstData(j,i,:) = lineData * a + Image(j,i,:) * (1 - a); end//融合处理过程 end end figure,imshow(uint8(rstData));
效果图如下:
方案2、3效果上可能与opengl的效果有些差别,但是已经很好的去除了锯齿。