![]() |
Ansel 0.0
A darktable fork - bloat + design vision
|
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <float.h>
#include "common/math.h"
Go to the source code of this file.
Data Structures | |
struct | coorlist |
struct | point |
struct | ntuple_list_s |
struct | image_char_s |
struct | image_int_s |
struct | image_double_s |
struct | rect |
struct | rect_iter |
Macros | |
#define | FALSE 0 |
#define | TRUE 1 |
#define | NOTDEF -1024.0 |
#define | M_3_2_PI 4.71238898038 |
#define | M_2__PI 6.28318530718 |
#define | NOTUSED 0 |
#define | USED 1 |
#define | RELATIVE_ERROR_FACTOR 100.0 |
#define | log_gamma(x) ((x)>15.0?log_gamma_windschitl(x):log_gamma_lanczos(x)) |
#define | TABSIZE 100000 |
Typedefs | |
typedef struct ntuple_list_s * | ntuple_list |
typedef struct image_char_s * | image_char |
typedef struct image_int_s * | image_int |
typedef struct image_double_s * | image_double |
Functions | |
static void | error (char *msg) |
static int | double_equal (double a, double b) |
static double | dist (double x1, double y1, double x2, double y2) |
static void | free_ntuple_list (ntuple_list in) |
static ntuple_list | new_ntuple_list (unsigned int dim) |
static void | enlarge_ntuple_list (ntuple_list n_tuple) |
static void | add_7tuple (ntuple_list out, double v1, double v2, double v3, double v4, double v5, double v6, double v7) |
static void | free_image_char (image_char i) |
static image_char | new_image_char (unsigned int xsize, unsigned int ysize) |
static image_char | new_image_char_ini (unsigned int xsize, unsigned int ysize, unsigned char fill_value) |
static image_int | new_image_int (unsigned int xsize, unsigned int ysize) |
static image_int | new_image_int_ini (unsigned int xsize, unsigned int ysize, int fill_value) |
static void | free_image_double (image_double i) |
static image_double | new_image_double (unsigned int xsize, unsigned int ysize) |
static image_double | new_image_double_ptr (unsigned int xsize, unsigned int ysize, double *data) |
static void | gaussian_kernel (ntuple_list kernel, double sigma, double mean) |
static image_double | gaussian_sampler (image_double in, double scale, double sigma_scale) |
static image_double | ll_angle (image_double in, double threshold, struct coorlist **list_p, void **mem_p, image_double *modgrad, unsigned int n_bins) |
static int | isaligned (int x, int y, image_double angles, double theta, double prec) |
static double | angle_diff (double a, double b) |
static double | angle_diff_signed (double a, double b) |
static double | log_gamma_lanczos (double x) |
static double | log_gamma_windschitl (double x) |
__attribute__ ((constructor)) | |
__attribute__ ((destructor)) | |
static double | nfa (int n, int k, double p, double logNT) |
static void | rect_copy (struct rect *in, struct rect *out) |
static double | inter_low (double x, double x1, double y1, double x2, double y2) |
static double | inter_hi (double x, double x1, double y1, double x2, double y2) |
static void | ri_del (rect_iter *iter) |
static int | ri_end (rect_iter *i) |
static void | ri_inc (rect_iter *i) |
static rect_iter * | ri_ini (struct rect *r) |
static double | rect_nfa (struct rect *rec, image_double angles, double logNT) |
static double | get_theta (struct point *reg, int reg_size, double x, double y, image_double modgrad, double reg_angle, double prec) |
static void | region2rect (struct point *reg, int reg_size, image_double modgrad, double reg_angle, double prec, double p, struct rect *rec) |
static void | region_grow (int x, int y, image_double angles, struct point *reg, int *reg_size, double *reg_angle, image_char used, double prec) |
static double | rect_improve (struct rect *rec, image_double angles, double logNT, double log_eps) |
static int | reduce_region_radius (struct point *reg, int *reg_size, image_double modgrad, double reg_angle, double prec, double p, struct rect *rec, image_char used, image_double angles, double density_th) |
static int | refine (struct point *reg, int *reg_size, image_double modgrad, double reg_angle, double prec, double p, struct rect *rec, image_char used, image_double angles, double density_th) |
static double * | LineSegmentDetection (int *n_out, double *img, int X, int Y, double scale, double sigma_scale, double quant, double ang_th, double log_eps, double density_th, int n_bins, int **reg_img, int *reg_x, int *reg_y) |
Variables | |
static double * | inv = NULL |
#define FALSE 0 |
#define log_gamma | ( | x | ) | ((x)>15.0?log_gamma_windschitl(x):log_gamma_lanczos(x)) |
Computes the natural logarithm of the absolute value of the gamma function of x. When x>15 use log_gamma_windschitl(), otherwise use log_gamma_lanczos().
#define M_2__PI 6.28318530718 |
2 pi
#define M_3_2_PI 4.71238898038 |
3/2 pi
#define NOTDEF -1024.0 |
Label for pixels with undefined gradient.
#define NOTUSED 0 |
Label for pixels not used in yet.
#define RELATIVE_ERROR_FACTOR 100.0 |
Doubles relative error factor
#define TABSIZE 100000 |
Size of the table to store already computed inverse values.
#define TRUE 1 |
#define USED 1 |
Label for pixels already used in detection.
typedef struct image_char_s * image_char |
char image data type
The pixel value at (x,y) is accessed by:
image->data[ x + y * image->xsize ]
with x and y integer.
typedef struct image_double_s * image_double |
double image data type
The pixel value at (x,y) is accessed by:
image->data[ x + y * image->xsize ]
with x and y integer.
typedef struct image_int_s * image_int |
int image data type
The pixel value at (x,y) is accessed by:
image->data[ x + y * image->xsize ]
with x and y integer.
typedef struct ntuple_list_s * ntuple_list |
'list of n-tuple' data type
The i-th component of the j-th n-tuple of an n-tuple list 'ntl' is accessed with:
ntl->values[ i + j * ntl->dim ]
The dimension of the n-tuple (n) is:
ntl->dim
The number of n-tuples in the list is:
ntl->size
The maximum number of n-tuples that can be stored in the list with the allocated memory at a given time is given by:
ntl->max_size
__attribute__ | ( | (constructor) | ) |
References inv, TABSIZE, and coorlist::y.
__attribute__ | ( | (destructor) | ) |
References inv, and coorlist::y.
|
static |
Add a 7-tuple to an n-tuple list.
References ntuple_list_s::dim, enlarge_ntuple_list(), error(), ntuple_list_s::max_size, ntuple_list_s::size, and ntuple_list_s::values.
Referenced by LineSegmentDetection().
Computes Euclidean distance between point (x1,y1) and point (x2,y2).
Referenced by _area_button_press_callback(), _area_button_press_callback(), _area_motion_notify_callback(), _area_motion_notify_callback(), _area_motion_notify_callback(), _brush_get_distance(), _circle_events_mouse_moved(), _circle_get_distance(), _distort_xtransform(), _ellipse_events_mouse_moved(), _ellipse_events_post_expose(), _ellipse_get_distance(), _find_closest_handle(), _get_control(), _gradient_events_mouse_moved(), _gradient_get_distance(), _group_events_button_released(), _path_events_mouse_moved(), _path_get_distance(), area_motion_notify(), build_round_stamp(), dt_iop_basecurve_button_press(), dt_iop_basecurve_motion_notify(), dt_iop_levels_motion_notify(), dt_iop_tonecurve_button_press(), dt_iop_tonecurve_motion_notify(), dt_printing_get_image_box(), find_nearest_on_curve_t(), get_cluster(), get_cluster(), get_cluster_mapping(), get_cluster_mapping(), get_clusters(), lowlight_motion_notify(), reduce_region_radius(), and refine().
Compare doubles by relative error.
The resulting rounding error after floating point computations depend on the specific operations done. The same number computed by different algorithms could present different rounding errors. For a useful comparison, an estimation of the relative rounding error should be considered and compared to a factor times EPS. The factor should be related to the cumulated rounding error in the chain of computation. Here, as a simplification, a fixed factor is used.
References RELATIVE_ERROR_FACTOR, and TRUE.
Referenced by get_theta(), inter_hi(), inter_low(), and nfa().
|
static |
Enlarge the allocated memory of an n-tuple list.
References ntuple_list_s::dim, double(), error(), ntuple_list_s::max_size, and ntuple_list_s::values.
Referenced by add_7tuple(), and gaussian_kernel().
|
static |
Fatal error, print a message to standard-error output and exit.
Referenced by __attribute__(), _default_process_tiling_ptp(), _default_process_tiling_roi(), _do_get_structure_auto(), _dt_full_locale_name(), _flag_pipe(), _get_structure(), _group_get_mask(), _main_do_event_help(), _non_thread_safe_pixel_pipe_cache_remove_lru(), _piwigo_api_post_internal(), _print_opencl_errors(), _process_vectorscope(), _process_waveform(), _refine_with_detail_mask(), _remove_outliers(), _util_get_svg_img(), _write_xmp_id(), add_7tuple(), array2string(), build_gui_kernel(), char2qstring(), check_error(), color_picker_helper_4ch_parallel(), color_picker_helper_bayer_parallel(), color_picker_helper_xtrans_parallel(), dt_alloc_align(), dt_color_picker_helper(), dt_colorspaces_get_profile_name(), dt_control_progress_init(), dt_database_get_most_recent_snap(), dt_database_init(), dt_database_maybe_snapshot(), dt_database_snaps_to_remove(), dt_dev_get_raster_mask(), dt_dev_pixel_pipe_cache_remove_lru(), dt_dev_pixelpipe_cache_remove(), dt_dev_pixelpipe_process_rec(), dt_dev_write_rawdetail_mask(), dt_film_import(), dt_focuspeaking(), dt_gaussian_init(), dt_gdk_pixbuf_new_from_file_at_size(), dt_gpx_new(), dt_gui_load_theme(), dt_imageio_export_with_flags(), dt_imageio_large_thumbnail(), dt_imageio_open_rawspeed(), dt_ioppr_deserialize_iop_order_list(), dt_ioppr_deserialize_text_iop_order_list(), dt_mipmap_cache_allocate_dynamic(), dt_noiseprofile_init(), dt_osx_file_trash(), dt_pixel_cache_new_entry(), dt_pwstorage_kwallet_get(), dt_pwstorage_kwallet_new(), dt_pwstorage_kwallet_set(), dt_pwstorage_libsecret_get(), dt_pwstorage_libsecret_new(), dt_pwstorage_libsecret_set(), dt_view_manager_switch_by_view(), dt_win_file_trash(), edge_enhance(), eigf_variance_analysis(), eigf_variance_analysis_no_mask(), enlarge_ntuple_list(), free_image_char(), free_image_double(), free_ntuple_list(), gaussian_kernel(), gaussian_sampler(), get_language_names(), get_manifolds(), get_points(), get_theta(), get_wallet_handle(), global_progress_end(), global_progress_set(), global_progress_start(), init_kwallet(), inter_hi(), inter_low(), isaligned(), line_detect(), LineSegmentDetection(), ll_angle(), local_laplacian_internal(), new_image_char(), new_image_char_ini(), new_image_double(), new_image_double_ptr(), new_image_int(), new_ntuple_list(), nfa(), parse_cht(), parse_it8(), process(), process(), process_fusion(), process_image(), process_laplacian_bayer(), pseudo_solve_gaussian(), reconstruct_highlights(), rect_copy(), rect_nfa(), reduce_chromatic_aberrations(), reduce_region_radius(), refine(), region2rect(), region_grow(), ri_del(), ri_end(), ri_inc(), ri_ini(), save_usercss(), start_kwallet(), sync_db_to_xmp(), sync_newest_to_oldest(), sync_oldest_to_newest(), sync_xmp_to_db(), variance_analyse(), view_popup_menu_onSearchFilmroll(), and write_pfm().
|
static |
Free memory used in image_char 'i'.
References image_char_s::data, and error().
Referenced by LineSegmentDetection().
|
static |
Free memory used in image_double 'i'.
References image_double_s::data, and error().
Referenced by gaussian_sampler(), and LineSegmentDetection().
|
static |
Free memory used in n-tuple 'in'.
References error(), and ntuple_list_s::values.
Referenced by gaussian_sampler().
|
static |
Compute a Gaussian kernel of length 'kernel->dim', standard deviation 'sigma', and centered at value 'mean'.
For example, if mean=0.5, the Gaussian will be centered in the middle point between values 'kernel->values[0]' and 'kernel->values[1]'.
References double(), enlarge_ntuple_list(), error(), and kernel().
Referenced by gaussian_sampler().
|
static |
Scale the input image 'in' by a factor 'scale' by Gaussian sub-sampling.
For example, scale=0.8 will give a result at 80% of the original size.
The image is convolved with a Gaussian kernel
before the sub-sampling to prevent aliasing.
The standard deviation sigma given by:
To be able to sub-sample at non-integer steps, some interpolation is needed. In this implementation, the interpolation is done by the Gaussian kernel, so both operations (filtering and sampling) are done at the same time. The Gaussian kernel is computed centered on the coordinates of the required sample. In this way, when applied, it gives directly the result of convolving the image with the kernel and interpolated to that particular position.
A fast algorithm is done using the separability of the Gaussian kernel. Applying the 2D Gaussian kernel is equivalent to applying first a horizontal 1D Gaussian kernel and then a vertical 1D Gaussian kernel (or the other way round). The reason is that
where
The algorithm first applies a combined Gaussian kernel and sampling in the x axis, and then the combined Gaussian kernel and sampling in the y axis.
References image_double_s::data, double(), error(), free_image_double(), free_ntuple_list(), gaussian_kernel(), kernel(), N, new_image_double(), new_ntuple_list(), image_double_s::xsize, and image_double_s::ysize.
Referenced by LineSegmentDetection().
|
static |
Compute region's angle as the principal inertia axis of the region.
The following is the region inertia matrix A:
where
Ixx = sum_i G(i).(y_i - cx)^2
Iyy = sum_i G(i).(x_i - cy)^2
Ixy = - sum_i G(i).(x_i - cx).(y_i - cy)
and
lambda1 and lambda2 are the eigenvalues of matrix A, with lambda1 >= lambda2. They are found by solving the characteristic polynomial:
det( lambda I - A) = 0
that gives:
lambda1 = ( Ixx + Iyy + sqrt( (Ixx-Iyy)^2 + 4.0*Ixy*Ixy) ) / 2
lambda2 = ( Ixx + Iyy - sqrt( (Ixx-Iyy)^2 + 4.0*Ixy*Ixy) ) / 2
To get the line segment direction we want to get the angle the eigenvector associated to the smallest eigenvalue. We have to solve for a,b in:
a.Ixx + b.Ixy = a.lambda2
a.Ixy + b.Iyy = b.lambda2
We want the angle theta = atan(b/a). It can be computed with any of the two equations:
theta = atan( (lambda2-Ixx) / Ixy )
or
theta = atan( Ixy / (lambda2-Iyy) )
When |Ixx| > |Iyy| we use the first, otherwise the second (just to get better numeric precision).
References angle_diff(), image_double_s::data, double(), double_equal(), error(), M_PI, weight(), point::x, image_double_s::xsize, and point::y.
Referenced by region2rect().
Interpolate y value corresponding to 'x' value given, in the line 'x1,y1' to 'x2,y2'; if 'x1=x2' return the larger of 'y1' and 'y2'.
The following restrictions are required:
References double_equal(), and error().
Referenced by ri_inc().
Interpolate y value corresponding to 'x' value given, in the line 'x1,y1' to 'x2,y2'; if 'x1=x2' return the smaller of 'y1' and 'y2'.
The following restrictions are required:
References double_equal(), and error().
Referenced by ri_inc().
|
static |
Is point (x,y) aligned to angle theta, up to precision 'prec'?
References error(), FALSE, M_2__PI, M_3_2_PI, NOTDEF, coorlist::x, and coorlist::y.
Referenced by rect_nfa(), and region_grow().
|
static |
LSD full interface.
References add_7tuple(), image_char_s::data, error(), free_image_char(), free_image_double(), gaussian_sampler(), ll_angle(), M_PI, new_image_char_ini(), new_image_double_ptr(), new_image_int_ini(), new_ntuple_list(), NOTDEF, NOTUSED, rect_improve(), refine(), region2rect(), region_grow(), image_char_s::xsize, coorlist::y, point::y, and rect::y.
Referenced by line_detect().
|
static |
Computes the direction of the level line of 'in' at each point.
The result is:
References error(), new_image_double(), coorlist::next, NOTDEF, coorlist::x, and coorlist::y.
Referenced by LineSegmentDetection().
Computes the natural logarithm of the absolute value of the gamma function of x using the Lanczos approximation. See http://www.rskey.org/gamma.htm
The formula used is
so
and q0 = 75122.6331530, q1 = 80916.6278952, q2 = 36308.2951477, q3 = 8687.24529705, q4 = 1168.92649479, q5 = 83.8676043424, q6 = 2.50662827511.
References coorlist::x, and coorlist::y.
Computes the natural logarithm of the absolute value of the gamma function of x using Windschitl method. See http://www.rskey.org/gamma.htm
The formula used is
so
This formula is a good approximation when x > 15.
References coorlist::x, and coorlist::y.
|
static |
Create a new image_char of size 'xsize' times 'ysize'.
References image_char_s::data, error(), image_char_s::xsize, and image_char_s::ysize.
Referenced by new_image_char_ini().
|
static |
Create a new image_char of size 'xsize' times 'ysize', initialized to the value 'fill_value'.
References image_char_s::data, error(), N, and new_image_char().
Referenced by LineSegmentDetection().
|
static |
Create a new image_double of size 'xsize' times 'ysize'.
References image_double_s::data, error(), image_double_s::xsize, and image_double_s::ysize.
Referenced by gaussian_sampler(), and ll_angle().
|
static |
Create a new image_double of size 'xsize' times 'ysize' with the data pointed by 'data'.
References image_double_s::data, error(), image_double_s::xsize, and image_double_s::ysize.
Referenced by LineSegmentDetection().
|
static |
Create a new image_int of size 'xsize' times 'ysize'.
References image_int_s::data, error(), image_int_s::xsize, and image_int_s::ysize.
Referenced by new_image_int_ini().
|
static |
Create a new image_int of size 'xsize' times 'ysize', initialized to the value 'fill_value'.
References image_int_s::data, N, and new_image_int().
Referenced by LineSegmentDetection().
|
static |
Create an n-tuple list and allocate memory for one element.
dim | the dimension (n) of the n-tuple. |
References ntuple_list_s::dim, error(), ntuple_list_s::max_size, ntuple_list_s::size, and ntuple_list_s::values.
Referenced by gaussian_sampler(), and LineSegmentDetection().
Computes -log10(NFA).
NFA stands for Number of False Alarms:
The value -log10(NFA) is equivalent but more intuitive than NFA:
Used this way, the bigger the value, better the detection, and a logarithmic scale is used.
n,k,p | binomial parameters. |
logNT | logarithm of Number of Tests |
The computation is based in the gamma function by the following relation:
We use efficient algorithms to compute the logarithm of the gamma function.
To make the computation faster, not all the sum is computed, part of the terms are neglected based on a bound to the error obtained (an error of 10% in the result is accepted).
References double(), double_equal(), error(), inv, log_gamma, M_LN10, TABSIZE, and coorlist::y.
Referenced by rect_nfa().
Copy one rectangle structure to another.
References rect::dx, rect::dy, error(), rect::p, rect::prec, rect::theta, rect::width, rect::x, rect::x1, rect::x2, rect::y, rect::y1, and rect::y2.
Referenced by rect_improve().
|
static |
Try some rectangles variations to improve NFA value. Only if the rectangle is not meaningful (i.e., log_nfa <= log_eps).
References M_PI, rect_copy(), rect_nfa(), and rect::y.
Referenced by LineSegmentDetection().
|
static |
Compute a rectangle's NFA value.
References error(), isaligned(), nfa(), rect::p, rect::prec, ri_del(), ri_end(), ri_inc(), ri_ini(), rect::theta, rect_iter::x, image_double_s::xsize, rect_iter::y, and image_double_s::ysize.
Referenced by rect_improve().
|
static |
Reduce the region size, by elimination the points far from the starting point, until that leads to rectangle with the right density of region points or to discard the region if too small.
References image_char_s::data, dist(), double(), error(), FALSE, NOTUSED, rect::p, rect::prec, region2rect(), TRUE, rect::x, image_char_s::xsize, and rect::y.
Referenced by refine().
|
static |
Refine a rectangle.
For that, an estimation of the angle tolerance is performed by the standard deviation of the angle at points near the region's starting point. Then, a new region is grown starting from the same point, but using the estimated angle tolerance. If this fails to produce a rectangle with the right density of region points, 'reduce_region_radius' is called to try to satisfy this condition.
References angle_diff_signed(), image_char_s::data, dist(), double(), error(), FALSE, NOTUSED, rect::p, rect::prec, reduce_region_radius(), region2rect(), region_grow(), TRUE, rect::x, image_char_s::xsize, and rect::y.
Referenced by LineSegmentDetection(), and lmmse_demosaic().
|
static |
Computes a rectangle that covers a region of points.
References image_double_s::data, double(), rect::dx, rect::dy, error(), get_theta(), rect::p, rect::prec, rect::theta, weight(), rect::width, point::x, rect::x, rect::x1, rect::x2, image_double_s::xsize, point::y, rect::y, rect::y1, and rect::y2.
Referenced by LineSegmentDetection(), reduce_region_radius(), and refine().
|
static |
Build a region of pixels that share the same angle, up to a tolerance 'prec', starting at point (x,y).
References image_char_s::data, image_double_s::data, error(), isaligned(), USED, point::x, image_char_s::xsize, image_double_s::xsize, point::y, image_char_s::ysize, and image_double_s::ysize.
Referenced by LineSegmentDetection(), and refine().
|
static |
Check if the iterator finished the full iteration.
See details in rect_iter
References error(), rect_iter::vx, and rect_iter::x.
Referenced by rect_nfa(), and ri_inc().
Increment a rectangle iterator.
See details in rect_iter
References error(), inter_hi(), inter_low(), ri_end(), rect_iter::vx, rect_iter::vy, rect_iter::x, rect_iter::y, rect_iter::ye, and rect_iter::ys.
Referenced by rect_nfa(), and ri_ini().
Create and initialize a rectangle iterator.
See details in rect_iter
References error(), ri_inc(), rect_iter::vx, rect_iter::vy, rect_iter::x, rect_iter::y, rect_iter::ye, and rect_iter::ys.
Referenced by rect_nfa().
|
static |
Referenced by __attribute__(), __attribute__(), _draw_sym(), and nfa().