Fisheye Undistort?
-
Hi all,
Does anyone know a way to undistort a feed from a fisheye lens? I know there is an actor to create a fisheye effect, but I wondered if there is some way of undoing the distortion?
Nic
-
Here is a GLSL shader, that will unwarp a 'fisheye' (its not going to be perfect, since its not calibrated to any specific lens), but it should provide a decent result.
/* Fisheye Correction - Fragment Shader For Isadora GLSL Shader actor */ // ISADORA_PLUGIN_NAME("Fisheye Correction") // ISADORA_PLUGIN_DESC("Corrects fisheye lens distortion from an input video stream to create a flatter, non-fisheye output.") // ISADORA_FLOAT_PARAM(strength, strn, 0.0, 200.0, 100.0, "Amount of fisheye correction. Higher values remove more barrel distortion.") uniform float strength; // ISADORA_FLOAT_PARAM(zoom, zoom, 50.0, 200.0, 115.0, "Zooms the corrected image to hide curved black edges.") uniform float zoom; // ISADORA_FLOAT_PARAM(horz_center, ctrx, -100.0, 100.0, 0.0, "Horizontal center of the lens correction.") uniform float horz_center; // ISADORA_FLOAT_PARAM(vert_center, ctry, -100.0, 100.0, 0.0, "Vertical center of the lens correction.") uniform float vert_center; // ISADORA_FLOAT_PARAM(edge_softness, edge, 0.0, 20.0, 2.0, "Softens the edge where the corrected image runs outside the source.") uniform float edge_softness; // Built-in Isadora uniforms uniform vec2 resolution; uniform sampler2D tex0; void main(void) { vec2 uv = gl_TexCoord[0].xy; // Move coordinates so that 0,0 is the image center. vec2 center = vec2(0.5) + vec2(horz_center, vert_center) / 200.0; vec2 p = uv - center; // Correct for non-square aspect ratio. float aspect = resolution.x / resolution.y; p.x *= aspect; // Zoom after correction. Higher zoom crops the outer edges. p /= zoom / 100.0; // Distance from lens center. float r = length(p); // Barrel/fisheye correction. // The shader samples farther outward as pixels move from the center, // which visually straightens fisheye-curved lines. float k = strength / 100.0; float corrected_r = r * (1.0 + k * r * r); vec2 corrected_p = p; if (r > 0.00001) { corrected_p = normalize(p) * corrected_r; } // Undo aspect correction and return to texture coordinates. corrected_p.x /= aspect; vec2 sample_uv = corrected_p + center; // Create a soft mask so out-of-range areas fade to black. float soft = edge_softness / 100.0; float mask_x = smoothstep(0.0, soft, sample_uv.x) * smoothstep(0.0, soft, 1.0 - sample_uv.x); float mask_y = smoothstep(0.0, soft, sample_uv.y) * smoothstep(0.0, soft, 1.0 - sample_uv.y); float mask = mask_x * mask_y; // Clamp sampling to avoid texture wrapping artifacts. sample_uv = clamp(sample_uv, vec2(0.0), vec2(1.0)); vec4 color = texture2D(tex0, sample_uv); gl_FragColor = vec4(color.rgb * mask, color.a); }