38#ifndef LENSSERIOUS_EVAL_H
39#define LENSSERIOUS_EVAL_H
47#if defined(__OPENCL_VERSION__) || defined(__OPENCL_C_VERSION__) || defined(__OPENCL__)
48 #define LS_EVAL_IS_OPENCL 1
63#ifdef LS_EVAL_IS_OPENCL
64 #define LS_SQRT(x) sqrt(x)
65 #define LS_ATAN(x) atan(x)
66 #define LS_ASIN(x) asin(x)
67 #define LS_SIN(x) sin(x)
68 #define LS_TAN(x) tan(x)
69 #define LS_FABS(x) fabs(x)
72 #define LS_SQRT(x) sqrtf(x)
73 #define LS_ATAN(x) atanf(x)
74 #define LS_ASIN(x) asinf(x)
75 #define LS_SIN(x) sinf(x)
76 #define LS_TAN(x) tanf(x)
77 #define LS_FABS(x) fabsf(x)
88#define LS_EVAL_DIST_KNOTS 4
89#define LS_EVAL_VIG_KNOTS 2
97#define LS_MAX_KNOTS 16
99#define LS_EVAL_DIST_NONE 0
100#define LS_EVAL_DIST_POLY3 1
101#define LS_EVAL_DIST_POLY5 2
102#define LS_EVAL_DIST_PTLENS 3
104#define LS_EVAL_TCA_NONE 0
105#define LS_EVAL_TCA_LINEAR 1
106#define LS_EVAL_TCA_POLY3 2
108#define LS_EVAL_VIG_NONE 0
109#define LS_EVAL_VIG_PA 1
113#define LS_EVAL_FULL_FRAME_HALF_DIAG_MM 21.633307f
116#define LS_EVAL_LENS_UNKNOWN 0
117#define LS_EVAL_LENS_RECTILINEAR 1
118#define LS_EVAL_LENS_FISHEYE 2
119#define LS_EVAL_LENS_PANORAMIC 3
120#define LS_EVAL_LENS_EQUIRECTANGULAR 4
121#define LS_EVAL_LENS_FISHEYE_ORTHOGRAPHIC 5
122#define LS_EVAL_LENS_FISHEYE_STEREOGRAPHIC 6
123#define LS_EVAL_LENS_FISHEYE_EQUISOLID 7
124#define LS_EVAL_LENS_FISHEYE_THOBY 8
126#define LS_EVAL_ENABLE_DISTORTION (1 << 0)
127#define LS_EVAL_ENABLE_TCA (1 << 1)
128#define LS_EVAL_ENABLE_VIGNETTING (1 << 2)
129#define LS_EVAL_ENABLE_SCALE (1 << 3)
130#define LS_EVAL_ENABLE_GEOMETRY (1 << 4)
219 if(n <= 0)
return 1.f;
220 if(x <= xs[0])
return ys[0];
222 for(
int i = 1; i < n; i++)
226 const float d = xs[i] - xs[i - 1];
227 if(d <= 0.f)
return ys[i - 1];
228 return ys[i - 1] + (x - xs[i - 1]) * (ys[i] - ys[i - 1]) / d;
250 const float r =
LS_SQRT(x * x + y * y);
257 const float xu = *x, yu = *y;
258 const float ru2 = xu * xu + yu * yu;
264 m = (1.f - k1) + k1 * ru2;
274 m = a * ru2 * r + b * ru2 + c * r + (1.f - a - b - c);
287 *xr *= kr; *yr *= kr;
288 *xb *= kb; *yb *= kb;
296 float x = *xr, y = *yr;
297 float ru2 = x * x + y * y;
298 float m = br * ru2 + vr + ((cr != 0.f) ? cr *
LS_SQRT(ru2) : 0.f);
299 *xr = x * m; *yr = y * m;
303 m = bb * ru2 + vb + ((cb != 0.f) ? cb *
LS_SQRT(ru2) : 0.f);
304 *xb = x * m; *yb = y * m;
318 if(f <= 0.f)
return -1.f;
327 return (r <= 1.47f * f) ?
LS_ASIN(r / (1.47f * f)) / 0.713f : -1.f;
328 default:
return -1.f;
335 if(f <= 0.f || theta < 0.f)
return -1.f;
341 return (theta < 1.5707963f) ? f *
LS_TAN(theta) : -1.f;
347 default:
return -1.f;
362 const float r =
LS_SQRT((*x) * (*x) + (*y) * (*y));
363 if(r <= 0.f)
return 1;
366 if(theta < 0.f)
return 0;
368 if(r_src < 0.f)
return 0;
370 const float k = r_src / r;
398#define LS_NEWTON_STEPS 6
399#define LS_NEWTON_RTOL 1e-6f
412 if(rd == 0.f)
return 1.f;
421 const float k1 = p->
dist_terms[0], one_minus_k1 = 1.f - k1;
424 const float f = k1 * ru * ru * ru + one_minus_k1 * ru - rd;
425 const float fp = 3.f * k1 * ru * ru + one_minus_k1;
426 if(fp == 0.f)
return 1.f;
427 const float d = f / fp;
437 const float ru2 = ru * ru;
438 const float f = ru * (1.f + k1 * ru2 + k2 * ru2 * ru2) - rd;
439 const float fp = 1.f + 3.f * k1 * ru2 + 5.f * k2 * ru2 * ru2;
440 if(fp == 0.f)
return 1.f;
441 const float d = f / fp;
449 const float d0 = 1.f - a - b - c;
452 const float f = ru * (a * ru * ru * ru + b * ru * ru + c * ru + d0) - rd;
453 const float fp = 4.f * a * ru * ru * ru + 3.f * b * ru * ru + 2.f * c * ru + d0;
454 if(fp == 0.f)
return 1.f;
455 const float d = f / fp;
463 if(!converged || ru < 0.f)
return 1.f;
470 const float rd =
LS_SQRT(*x * *x + *y * *y);
489 *xr *= kr; *yr *= kr;
490 *xb *= kb; *yb *= kb;
498 for(
int ch = 0; ch < 2; ch++)
500 const float v = ch ? vb : vr, c = ch ? cb : cr, b = ch ? bb : br;
501 float *px = ch ? xb : xr, *py = ch ? yb : yr;
502 const float rd =
LS_SQRT(*px * *px + *py * *py);
503 if(rd == 0.f)
continue;
509 const float ru2 = ru * ru;
510 const float f = b * ru2 * ru + c * ru2 + v * ru - rd;
511 const float fp = 3.f * b * ru2 + 2.f * c * ru + v;
513 const float dd = f / fp;
521 const float m = ru / rd;
624 float xr = x, yr = y, xb = x, yb = y;
646 for(
int k = 0; k < 6; k++) out[k] = (
float)(0.0f / 0.0f);
657 for(
int k = 0; k < 6; k++) out[k] = (
float)(0.0f / 0.0f);
660 xr = x; yr = y; xb = x; yb = y;
708 const float m = p->
reverse ? v : ((v != 0.f) ? (1.f / v) : 0.f);
709 return (m > 0.f) ? m : 0.f;
712 const float r4 = r2 * r2;
744 const float m = p->
reverse ? c : (1.f / c);
745 return (m > 0.f) ? m : 0.f;
#define LS_EVAL_DIST_POLY3
#define LS_EVAL_TCA_POLY3
static int ls_eval_coord_chain(const ls_eval_t *p, const int c, float *x, float *y)
The coordinate chain: scale, projection and distortion, in direction order.
#define LS_EVAL_ENABLE_DISTORTION
#define LS_EVAL_DIST_PTLENS
static float ls_eval_geom_angle(const int model, const float f, const float r)
Field angle for a radius, under one projection. Negative if model has none.
static void ls_eval_tca(const ls_eval_t *p, float *xr, float *yr, float *xb, float *yb)
Transverse chromatic aberration: the red and blue coordinates diverge from green.
#define LS_EVAL_LENS_FISHEYE_ORTHOGRAPHIC
static float ls_eval_knot_factor(const ls_eval_t *p, const int c, const float x, const float y)
The per-channel radial scale a knot table gives at this point.
static void ls_eval_dist(const ls_eval_t *p, float *x, float *y)
Distortion, in place, in normalized coordinates.
static float ls_eval_vignette_from_r2(const ls_eval_t *p, const float r2)
The vignetting multiplier for ONE output pixel. Multiply the pixel by it.
#define LS_EVAL_LENS_FISHEYE_EQUISOLID
#define LS_EVAL_ENABLE_VIGNETTING
#define LS_EVAL_LENS_FISHEYE_THOBY
#define LS_EVAL_LENS_RECTILINEAR
#define LS_EVAL_ENABLE_SCALE
static void ls_eval_untca(const ls_eval_t *p, float *xr, float *yr, float *xb, float *yb)
The reverse of ls_eval_tca(): recover each channel's undistorted radius.
#define LS_EVAL_DIST_KNOTS
#define LS_EVAL_VIG_KNOTS
static float ls_eval_undist_factor(const ls_eval_t *p, const float rd)
Solve Rd = f(Ru) for Ru, given a radius Rd. The inverse of ls_eval_dist().
#define LS_EVAL_LENS_FISHEYE_STEREOGRAPHIC
#define LS_EVAL_LENS_FISHEYE
static float ls_eval_geom_radius(const int model, const float f, const float theta)
Radius for a field angle, under one projection. The inverse of the above.
#define LS_EVAL_DIST_POLY5
#define LS_EVAL_ENABLE_GEOMETRY
static void ls_eval_map(const ls_eval_t *p, float xu, float yu, float *out)
The map for ONE output pixel: six floats, source coordinates for R, G, B.
struct ls_eval_t ls_eval_t
One lens resolved at one shooting configuration, as a flat block of scalars.
static float ls_eval_vignette_factor(const ls_eval_t *p, float xu, float yu)
The vignetting multiplier for ONE output pixel. Multiply the pixel by it.
#define LS_EVAL_ENABLE_TCA
#define LS_EVAL_TCA_LINEAR
static float ls_eval_knot_lookup(const float *xs, const float *ys, const int n, const float x)
Piecewise-linear lookup over a knot table.
static int ls_eval_geometry(const ls_eval_t *p, float *x, float *y)
Reproject one point from the target geometry into the lens's own.
static void ls_eval_undist(const ls_eval_t *p, float *x, float *y)
Undistort in place. The reverse of ls_eval_dist().
One lens resolved at one shooting configuration, as a flat block of scalars.