zoukankan      html  css  js  c++  java
  • [译]径向镜片反畸变滤波

    操作系统:Windows8.1

    显卡:Nivida GTX965M

    开发工具:Unity2017.2.0f3


    原文出处 : Radial lens undistortion filtering

    在处理涉及广角相机的计算机视觉任务时可能发生畸变,这种畸变是由于镜头中心处的放大倍数大于在边缘处的放大倍数造成的桶形畸变,英文称之为 barrel distortion

    Zhang, 1999 证明了具有两个系数的多项式径向畸变模型可以模拟为如下公式:

    我们也可以考虑一个更简单的近似这个模型的径向畸变 Fitzgibbon, 2001

    其中 ru rd 分别是非畸变和畸变后的图像中心距离。α 是每一个镜片固有的常量系数。

    为了实际实现这样的近似模型,需要图像中的点的原始坐标与归一化的 [-1; +1] [-1; +1] 坐标系中的坐标进行映射。

    (xn,yn) 代表归一化后的坐标系,wh 代表宽和高,变换后的公式为:

    Implementing with OpenGL shaders


    给定一个简单的带纹理的四边形映射到一个径向畸变的图像,滤波的功能可以有效的在片段着色器中执行。

    precision mediump float;
    
    uniform sampler2D texture_diffuse;
    uniform vec2 image_dimensions;
    uniform float alphax;
    uniform float alphay;
    
    varying vec4 pass_Color;
    varying vec2 pass_TextureCoord;
    
    void main(void) {
    
      // Normalize the u,v coordinates in the range [-1;+1]
      float x = (2.0 * pass_TextureCoord.x - 1.0) / 1.0;
      float y = (2.0 * pass_TextureCoord.y - 1.0) / 1.0;
      
      // Calculate l2 norm
      float r = x*x + y*y;
      
      // Calculate the deflated or inflated new coordinate (reverse transform)
      float x3 = x / (1.0 - alphax * r);
      float y3 = y / (1.0 - alphay * r); 
      float x2 = x / (1.0 - alphax * (x3 * x3 + y3 * y3));
      float y2 = y / (1.0 - alphay * (x3 * x3 + y3 * y3));    
      
      // Forward transform
      // float x2 = x * (1.0 - alphax * r);
      // float y2 = y * (1.0 - alphay * r);
    
      // De-normalize to the original range
      float i2 = (x2 + 1.0) * 1.0 / 2.0;
      float j2 = (y2 + 1.0) * 1.0 / 2.0;
    
      if(i2 >= 0.0 && i2 <= 1.0 && j2 >= 0.0 && j2 <= 1.0)
        gl_FragColor = texture2D(texture_diffuse, vec2(i2, j2));
      else
        gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
    }

    考虑目前基于U3D的项目比较多,同样提供一份基于Unity Shader编写的Shader。

    Shader "Heitao/VR/Distortion"
    {
        Properties
        {
            _MainTex ("Texture", 2D) = "white" {}
            _AlphaScaleX ("Alpha scale x", Range(0.0, 0.25)) = 0.0
            _AlphaScaleY ("Alpha scale y", Range(0.0, 0.25)) = 0.0
    
        }
        SubShader
        {
            Tags { "RenderType"="Opaque" }
            LOD 100
    
            Pass
            {
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                
                #include "UnityCG.cginc"
    
                struct appdata
                {
                    float4 vertex : POSITION;
                    float2 uv : TEXCOORD0;
                };
    
                struct v2f
                {
                    float2 uv : TEXCOORD0;
                    float4 vertex : SV_POSITION;
                };
    
                sampler2D _MainTex;
                float4 _MainTex_ST;
                float _AlphaScaleX;
                float _AlphaScaleY;
    
                v2f vert (appdata v)
                {
                    v2f o;
                    o.vertex = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                    return o;
                }
                
                fixed4 frag (v2f i) : SV_Target
                {    
                    float x = (2.0 * i.uv.x - 1.0) / 1.0f;
                    float y = (2.0 * i.uv.y - 1.0) / 1.0f;
    
                    float r = x * x + y * y;
                    float x3 = x / (1.0 - _AlphaScaleX * r);
                    float y3 = y / (1.0 - _AlphaScaleY * r);
                    float x2 = x / (1.0 - _AlphaScaleX * (x3 * x3 + y3 * y3));
                    float y2 = y / (1.0 - _AlphaScaleY * (x3 * x3 + y3 * y3));
    
                    // Forward transform
                    // float x2 = x * (1.0 - _AlphaScaleX * r);
                    // float y2 = y * (1.0 - _AlphaScaleY * r);
    
                    float i2 = (x2 + 1.0) * 1.0 / 2.0;
                    float j2 = (y2 + 1.0) * 1.0 / 2.0;
    
                    fixed4 col = fixed4(0.0, 0.0, 0.0, 1.0);
                    if (i2 >= 0.0 && i2 <= 1.0 && j2 >= 0.0 && j2 <= 1.0)
                    {
                        col = tex2D(_MainTex, fixed2(i2, j2));
                    }
    
                    return col;
                }
                ENDCG
            }
        }
    }

    AlphaScaleXAlphaScaleY0 的时候:

    调整畸变系数 AlphaScaleX = AlphaScaleY = 0.25 后:

    通过调整参数观测畸变与反畸变的转换关系。

    References


    Zhang Z. (1999). Flexible camera calibration by viewing a plane from unknown orientation

    Andrew W. Fitzgibbon (2001). Simultaneous linear estimation of multiple view geometry and lens distortion

  • 相关阅读:
    阿里云上的Centos 7.6的一次Nginx+Mysql+PHP7.3 部署
    Spring系列-SpringBoot 学习路径
    想做公众号,总要写点什么--第008期博文
    我关注的那些公众号-第007期博文
    Ruby on Rails,一对多关联(One-to-Many)
    ruby新建web项目步骤,使用mysql数据库
    ruby select 方法,可用于先查询结果后,再次用条件限制
    cron和crontab命令详解 crontab 每分钟、每小时、每天、每周、每月、每年定时执行 crontab每5分钟执行一次
    nginx做rails项目web服务器缓存配置方法
    ruby----%使用法
  • 原文地址:https://www.cnblogs.com/heitao/p/8076521.html
Copyright © 2011-2022 走看看