aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Roth <roth@stettbacher.ch>2021-07-01 10:56:42 +0200
committerPatrick Roth <roth@stettbacher.ch>2021-07-01 10:56:42 +0200
commit72f4bb57783891dc4a9fbfd3dc387cdf810b932b (patch)
treef3ec2d2256d6f11f6c1b50c2815597c42c3843fd
parentdebug processing time (diff)
parentchange weights to -100.0...+100.0 per cent (diff)
downloado3000-color-pipe-72f4bb57783891dc4a9fbfd3dc387cdf810b932b.tar.gz
o3000-color-pipe-72f4bb57783891dc4a9fbfd3dc387cdf810b932b.zip
Merge branch 'isosceles-trapezoid-correction' into 'master'
Isosceles trapezoid correction See merge request o-3000/color-pipe!1
-rw-r--r--CMakeLists.txt6
-rw-r--r--alg_ccm.h6
-rw-r--r--alg_debayer_bilinear.h6
-rw-r--r--alg_gamma.h4
-rw-r--r--alg_interpolate_mono_scalar.h4
-rw-r--r--alg_interpolate_rgb_scalar.h4
-rw-r--r--alg_rgb_to_yuv.h4
-rw-r--r--alg_yuv_to_rgb.h4
-rw-r--r--camera_calib.c16
-rw-r--r--color.c4
-rw-r--r--color.h4
-rw-r--r--color_pipe.c122
-rw-r--r--color_pipe.h98
-rw-r--r--color_pipe_private.h6
-rw-r--r--cpu_feature.c4
-rw-r--r--cpu_feature.h6
-rw-r--r--debayer.c6
-rw-r--r--filter.c4
-rw-r--r--filter.h6
-rw-r--r--gamma_corr.c4
-rw-r--r--sharpening.c4
-rw-r--r--trapcorr.c317
-rw-r--r--white_balance.c6
23 files changed, 534 insertions, 111 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a8eee6b..d5e82c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,8 +17,8 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
# library version definition
set(VERSION_MAJOR 1)
-set(VERSION_MINOR 0)
-set(VERSION_RELEASE 2)
+set(VERSION_MINOR 1)
+set(VERSION_RELEASE 0)
set(VERSION_STR "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_RELEASE}")
# pass macros to preprocessor
@@ -59,4 +59,4 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/$<TARGET_FILE_NAME:${LIB_NAME}>* ${CMAKE_CURRENT_BINARY_DIR}/libo3000_imgpipe-${VERSION_STR}/MinGW${CC_ARCH}
COMMAND ${CMAKE_COMMAND} -E tar "cfv" "libo3000_imgpipe-${VERSION_STR}-${CC_ARCH}bit.zip" --format=zip libo3000_imgpipe-${VERSION_STR}
COMMAND ${CMAKE_COMMAND} -E remove_directory libo3000_imgpipe-${VERSION_STR}
-) \ No newline at end of file
+)
diff --git a/alg_ccm.h b/alg_ccm.h
index 24d37bc..0bc4ac2 100644
--- a/alg_ccm.h
+++ b/alg_ccm.h
@@ -2,9 +2,7 @@
* @file alg_ccm.h
* @brief color correction algorithm definition
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-26
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -85,4 +83,4 @@
}
}
-} \ No newline at end of file
+}
diff --git a/alg_debayer_bilinear.h b/alg_debayer_bilinear.h
index 45c8a8d..829d615 100644
--- a/alg_debayer_bilinear.h
+++ b/alg_debayer_bilinear.h
@@ -2,9 +2,7 @@
* @file alg_debayer_bilinear.h
* @brief bilinear demosaicing algorithm
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-20
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -268,4 +266,4 @@
img_rgb[index_rgb+2] = blue;
-} \ No newline at end of file
+}
diff --git a/alg_gamma.h b/alg_gamma.h
index 2f9a7ae..b9a1f10 100644
--- a/alg_gamma.h
+++ b/alg_gamma.h
@@ -2,9 +2,7 @@
* @file alg_gamma.h
* @brief gamma correction algorithm definition
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-09-08
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/alg_interpolate_mono_scalar.h b/alg_interpolate_mono_scalar.h
index 9adda8b..25c6d50 100644
--- a/alg_interpolate_mono_scalar.h
+++ b/alg_interpolate_mono_scalar.h
@@ -2,9 +2,7 @@
* @file alg_interpolate_mono_scalar.h
* @brief Monochrome pixel interpolation (scalar code)
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-11-09
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/alg_interpolate_rgb_scalar.h b/alg_interpolate_rgb_scalar.h
index aa17c54..3728e17 100644
--- a/alg_interpolate_rgb_scalar.h
+++ b/alg_interpolate_rgb_scalar.h
@@ -2,9 +2,7 @@
* @file alg_interpolate_rgb_scalar.h
* @brief RGB pixel interpolation (scalar code)
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-11-09
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/alg_rgb_to_yuv.h b/alg_rgb_to_yuv.h
index f75df6a..851a328 100644
--- a/alg_rgb_to_yuv.h
+++ b/alg_rgb_to_yuv.h
@@ -2,9 +2,7 @@
* @file alg_rgb_to_yuv.h
* @brief color space conversion definitions
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-20
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/alg_yuv_to_rgb.h b/alg_yuv_to_rgb.h
index c608a6d..e7885f0 100644
--- a/alg_yuv_to_rgb.h
+++ b/alg_yuv_to_rgb.h
@@ -2,9 +2,7 @@
* @file alg_yuv_to_rgb.h
* @brief color space conversion definitions
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-27
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/camera_calib.c b/camera_calib.c
index 804c40d..b55f954 100644
--- a/camera_calib.c
+++ b/camera_calib.c
@@ -2,9 +2,7 @@
* @file camera_calib.c
* @brief camera calibration algorithm
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-20
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -490,7 +488,7 @@ static void init_undistort_map_scalar(struct cam_calib_data_t *data) {
float dist_radial, dist_tang_x, dist_tang_y, dist_x, dist_y;
float _x, _y, _y_sq, _x_sq, r_sq;
float x_corr, y_corr;
- struct lense_undistort_coord_t *map;
+ struct coord_t *map;
const int scale_fact = (1 << (data->calib_map_scale_fact));
float x_resolution_scaling, y_resolution_scaling; // camera_matrix needs to be scaled depending on the camera resolution
@@ -543,8 +541,8 @@ static void init_undistort_map_scalar(struct cam_calib_data_t *data) {
x_corr = fx*dist_x + cx - fov_x_start;
y_corr = fy*dist_y + cy - fov_y_start;
- map->coord_x = (int)roundf(x_corr*scale_fact);
- map->coord_y = (int)roundf(y_corr*scale_fact);
+ map->x = (int)roundf(x_corr*scale_fact);
+ map->y = (int)roundf(y_corr*scale_fact);
map++;
}
}
@@ -702,7 +700,7 @@ static void calib_scalar(struct cam_calib_data_t *data) {
int x_corr, y_corr;
void *img_calib, *img_uncalib;
int bit_channel;
- struct lense_undistort_coord_t *map;
+ struct coord_t *map;
const int scale_fact = data->calib_map_scale_fact;
const int is_color = data->is_color;
@@ -720,8 +718,8 @@ static void calib_scalar(struct cam_calib_data_t *data) {
for(v = fov_y_start; v <= fov_y_end; v++) {
for(u = fov_x_start; u <= fov_x_end; u++) {
- x_corr = map->coord_x;
- y_corr = map->coord_y;
+ x_corr = map->x;
+ y_corr = map->y;
map++;
if(bit_channel <= 8) {
diff --git a/color.c b/color.c
index 4802083..b1670df 100644
--- a/color.c
+++ b/color.c
@@ -2,9 +2,7 @@
* @file color_space.c
* @brief color space conversion utilities
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-20
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/color.h b/color.h
index 73bff58..a5c1a88 100644
--- a/color.h
+++ b/color.h
@@ -2,9 +2,7 @@
* @file color.h
* @brief color utility function definition
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-20
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/color_pipe.c b/color_pipe.c
index 0b77c61..b0a9ddf 100644
--- a/color_pipe.c
+++ b/color_pipe.c
@@ -2,9 +2,7 @@
* @file main.cpp
* @brief Color Image Processing Pipeline with O-3000 USB camera
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-02-10
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -365,12 +363,12 @@ static void set_default_value(struct color_pipe_t *pipe) {
pipe->debayer_data.alg_new = pipe->debayer_data.alg;
pipe->awb_data.enable = 0;
- pipe->awb_data.gray_threshold = 0.3;
+ pipe->awb_data.gray_threshold = 0.3f;
pipe->awb_data.gray_threshold_new = pipe->awb_data.gray_threshold;
- pipe->awb_data.ctrl_k = 0.01;
+ pipe->awb_data.ctrl_k = 0.01f;
pipe->awb_data.ctrl_k_new = pipe->awb_data.ctrl_k;
- pipe->awb_data.gain_red = 1.0;
- pipe->awb_data.gain_blue = 1.0;
+ pipe->awb_data.gain_red = 1.0f;
+ pipe->awb_data.gain_blue = 1.0f;
pipe->cam_calib_data.enable = 0;
pipe->cam_calib_data.lense = O3000_LS_F2_8;
@@ -385,16 +383,23 @@ static void set_default_value(struct color_pipe_t *pipe) {
memcpy(pipe->color_calib_data.a, ccm_presets[pipe->color_calib_data.ccm], sizeof(pipe->color_calib_data.a));
pipe->sharp_data.enable = 0;
- pipe->sharp_data.sharp_factor = 5.0;
+ pipe->sharp_data.sharp_factor = 5.0f;
pipe->sharp_data.sharp_factor_new = pipe->sharp_data.sharp_factor;
pipe->sharp_data.sharp_alg = SHARP_ALG_LOCAL;
pipe->sharp_data.sharp_alg_new = pipe->sharp_data.sharp_alg;
- pipe->sharp_data.local_sens = 94.0;
+ pipe->sharp_data.local_sens = 94.0f;
pipe->sharp_data.local_sens_new = pipe->sharp_data.local_sens_new;
pipe->gamma_data.enable = 0;
- pipe->gamma_data.gamma = 1.2;
+ pipe->gamma_data.gamma = 1.2f;
pipe->gamma_data.gamma_new = pipe->gamma_data.gamma;
+
+ pipe->trapcorr_data.enable = 0;
+ pipe->trapcorr_data.map_init = 0;
+ pipe->trapcorr_data.wv = 0.0f;
+ pipe->trapcorr_data.wh = 0.0f;
+ pipe->trapcorr_data.wv_new = pipe->trapcorr_data.wv;
+ pipe->trapcorr_data.wh_new = pipe->trapcorr_data.wh;
}
@@ -458,7 +463,7 @@ void __stdcall color_pipe_process(struct color_pipe_t *__restrict__ color_pipe,
#ifdef DEBUG_PROC_TIME
uint64_t ts_start = get_ts();
- uint64_t ts_debayer, ts_awb, ts_calib, ts_ccm, ts_sharp, ts_gamma;
+ uint64_t ts_debayer, ts_awb, ts_calib, ts_ccm, ts_sharp, ts_gamma, ts_trapcorr;
#endif // DEBUG_PROC_TIME
/*
@@ -676,6 +681,41 @@ void __stdcall color_pipe_process(struct color_pipe_t *__restrict__ color_pipe,
/*
+ * Pipeline stage: Isosceles trapezoid correction
+ */
+ if(color_pipe->trapcorr_data.enable) {
+
+ // auto-reinit perspective correction map if image format, resolution or weights have changed
+ if( color_pipe->trapcorr_data.bit_channel != bit_channel ||
+ color_pipe->trapcorr_data.width != width ||
+ color_pipe->trapcorr_data.height != height ||
+ color_pipe->trapcorr_data.wv != color_pipe->trapcorr_data.wv_new ||
+ color_pipe->trapcorr_data.wh != color_pipe->trapcorr_data.wh_new) {
+
+ color_pipe->trapcorr_data.map_init = 0;
+ }
+
+ // apply user parameter (double buffered)
+ color_pipe->trapcorr_data.wv = color_pipe->trapcorr_data.wv_new;
+ color_pipe->trapcorr_data.wh = color_pipe->trapcorr_data.wh_new;
+
+ color_pipe->trapcorr_data.img_in = img_out;
+ color_pipe->trapcorr_data.is_color = is_color;
+ color_pipe->trapcorr_data.bit_channel = bit_channel;
+ color_pipe->trapcorr_data.width = width;
+ color_pipe->trapcorr_data.height = height;
+
+ trapcorr(&(color_pipe->trapcorr_data));
+
+ img_out = color_pipe->trapcorr_data.img_out;
+ }
+#ifdef DEBUG_PROC_TIME
+ ts_trapcorr = get_ts();
+#endif // DEBUG_PROC_TIME
+
+
+
+ /*
* Return processed image depending on active pipeline stages.
*/
color_pipe->img_out = img_out;
@@ -692,6 +732,7 @@ void __stdcall color_pipe_process(struct color_pipe_t *__restrict__ color_pipe,
printf(" color correction: %lld msec\n", ts_ccm - ts_calib);
printf(" sharpening: %lld msec\n", ts_sharp - ts_ccm);
printf(" gamma: %lld msec\n", ts_gamma - ts_sharp);
+ printf(" trapeze correction: %lld msec\n", ts_trapcorr - ts_sharp);
#endif // DEBUG_PROC_TIME
}
@@ -834,6 +875,48 @@ void __stdcall color_pipe_stageconf_gamma(struct color_pipe_t *color_pipe, int e
/**
+ * Pipeline stage configuration: Isosceles Trapeze Correction
+ *
+ * The vertical and horizontal correction weight are per cent values ranging
+ * from -100.0 % to +100.0 %. A positive weight means that the upper horizontal trapeze
+ * is fixed and won't shrink while a negative value means the opposite lower line won't change.
+ * A weight of zero means not correction.
+ *
+ * @param color_pipe Pointer to pipeline context
+ * @param enable not 0: enable, 0: disable
+ * @param wv vertical weight (range: -100.0 to +100.0)
+ * @param wh horizontal weight (range: -100.0 to +100.0)
+ */
+void __stdcall color_pipe_stageconf_trapcorr(struct color_pipe_t *color_pipe, int enable, float wv, float wh) {
+ // paranoia
+ if(color_pipe == NULL) {
+ printf("%s: Pipeline pointer is NULL!\n", __func__);
+ return;
+ }
+
+ // range check
+ if(wv < -100.0f) {
+ wv = -100.0f;
+ }
+ else if(wv > 100.0) {
+ wv = 100.0f;
+ }
+
+ if(wh < -100.0f) {
+ wh = -100.0f;
+ }
+ else if(wh > 100.0) {
+ wh = 100.0f;
+ }
+
+ color_pipe->trapcorr_data.enable = enable;
+ color_pipe->trapcorr_data.wv_new = wv;
+ color_pipe->trapcorr_data.wh_new = wh;
+ color_pipe->trapcorr_data.map_init = 0;
+}
+
+
+/**
* Open color image processing pipeline.
* This function allocates memory for various pipe algorithm. The pipeline is set up for a maximum possible image size defined
* by the height, width and bitdepth per color channel.
@@ -927,7 +1010,7 @@ int __stdcall color_pipe_open(struct color_pipe_t **color_pipe, const int max_im
goto _pipe_open_abort;
}
data->cam_calib_data.calib_map = do_aligned_alloc(ALIGNMENT_SIZE,
- sizeof(struct lense_undistort_coord_t)*max_img_height*max_img_width,
+ sizeof(struct coord_t)*max_img_height*max_img_width,
__func__, __LINE__-1);
if(data->cam_calib_data.calib_map == NULL) {
goto _pipe_open_abort;
@@ -977,6 +1060,19 @@ int __stdcall color_pipe_open(struct color_pipe_t **color_pipe, const int max_im
goto _pipe_open_abort;
}
+ // allocate memory for isosceles trapeze correction algorithm
+ data->trapcorr_data.img_out = do_aligned_alloc(ALIGNMENT_SIZE, max_img_size, __func__, __LINE__-1);
+ if(data->trapcorr_data.img_out == NULL) {
+ goto _pipe_open_abort;
+ }
+ data->trapcorr_data.map = do_aligned_alloc(ALIGNMENT_SIZE,
+ sizeof(struct coord_t)*max_img_height*max_img_width,
+ __func__, __LINE__-1);
+ if(data->trapcorr_data.map == NULL) {
+ goto _pipe_open_abort;
+ }
+
+ // set suitable and valid defaults
set_default_value(data);
*color_pipe = data;
@@ -1022,6 +1118,8 @@ int __stdcall color_pipe_close(struct color_pipe_t *data) {
do_aligned_free(data->sharp_data.sharp_mask);
do_aligned_free(data->gamma_data.img_gamma);
do_aligned_free(data->gamma_data.gamma_table);
+ do_aligned_free(data->trapcorr_data.img_out);
+ do_aligned_free(data->trapcorr_data.map);
// free various image buffers
free(data);
diff --git a/color_pipe.h b/color_pipe.h
index 2833d0f..9b52f23 100644
--- a/color_pipe.h
+++ b/color_pipe.h
@@ -2,9 +2,7 @@
* @file color_pipe.h
* @brief Color Processing Pipeline Definitions
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2016-03-01
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -36,6 +34,15 @@
/**
+ * Coordinate definition.
+ */
+struct coord_t {
+ int x; ///< x-coordinate of calibrated pixel
+ int y; ///< y-coordinate of calibrated pixel
+};
+
+
+/**
* demosaicing algorithm definition
*/
enum bayer_alg_t {
@@ -55,7 +62,7 @@ struct debayer_data_t {
enum enumDataFormat_t format; ///< data format of input image
enum enumBayerPattern_t start_pattern; ///< first pixel starts with this bayer pattern
enum bayer_alg_t alg; ///< debayer algorithm type
- enum bayer_alg_t alg_new; ///< this debayer algorithm type is changed by API call (use double buffering concept)
+ enum bayer_alg_t alg_new; ///< this debayer algorithm type is changed by API call (use double buffering)
};
@@ -71,9 +78,9 @@ struct awb_data_t {
int width; ///< image width in number of pixels
int16_t *img_yuv; ///< Image buffer holding YUV image. This buffer must be allocated externly.
float gray_threshold; ///< gray value threshold
- float gray_threshold_new; ///< this gray value threshold is changed by API call (use double buffering concept)
+ float gray_threshold_new; ///< this gray value threshold is changed by API call (use double buffering)
float ctrl_k; ///< controller gain
- float ctrl_k_new; ///< this controller gain is changed by API call (use double buffering concept)
+ float ctrl_k_new; ///< this controller gain is changed by API call (use double buffering)
float gain_red; ///< red color gain
float gain_blue; ///< blue color gain
};
@@ -131,19 +138,6 @@ enum o3000_lenses_t {
/**
- * Lense undistortion coordinate definition.
- * This coordinate pair defines the undistorted pixel location.
- *
- * NOTE The pixel location may lay between a pixel pair. Therefore this coordinates are
- * scaled by a defined factor defined at @ref cam_calib_data_t.
- */
-struct lense_undistort_coord_t {
- int coord_x; ///< x-coordinate of calibrated pixel
- int coord_y; ///< y-coordinate of calibrated pixel
-};
-
-
-/**
* camera calibration structure
*
* The total width @ref tot_width and height @ref tot_height define the image size take during calibration processs.
@@ -164,10 +158,23 @@ struct cam_calib_data_t {
struct dist_coeff_t dist_coeff; ///< distortion coefficients
struct camera_matrix_t camera_matrix; ///< camera matrix
enum o3000_lenses_t lense; ///< lense type
- enum o3000_lenses_t lense_new; ///< lense type is changed by API call (use double buffering concept)
+ enum o3000_lenses_t lense_new; ///< lense type is changed by API call (use double buffering)
int undistort_map_init; ///< flag indicating if lens undistortion map is initialized
- struct lense_undistort_coord_t *calib_map; ///< Lense undistortion map. This buffer must be allocated externly.
- int calib_map_scale_fact; ///< Bit shifts applied on undistortion map.
+
+ /**
+ * Lense undistortion map.
+ * A coordinate pair defines the undistorted pixel location. It may be shifted (see @ref calib_map_scale_fact).
+ *
+ * This buffer must be allocated externly.
+ */
+ struct coord_t *calib_map;
+
+ /**
+ * Bit shift applied on undistortion map @ref calib_map.
+ * The pixel location may lay between a pixel pair. Therefore the coordinates defined at the undistortion map
+ * @ref calib_map are (scaled) shifted by this factor.
+ */
+ int calib_map_scale_fact;
};
@@ -218,7 +225,7 @@ struct color_calib_data_t {
int height; ///< image height in number of pixels
float a[3][3]; ///< 3x3 color correction matrix
enum ccm_preset_t ccm; ///< color correction matrix type loaded
- enum ccm_preset_t ccm_new; ///< this color correction matrix type is changed by API call (use double buffering concept)
+ enum ccm_preset_t ccm_new; ///< this color correction matrix type is changed by API call (use double buffering)
};
@@ -244,11 +251,11 @@ struct sharp_data_t {
int height; ///< image height in number of pixels
int16_t *img_yuv; ///< YUV image buffer. This buffer must be allocated externly.
float sharp_factor; ///< Sharpening factor: As higher as stronger sharpening is done.
- float sharp_factor_new; ///< this sharpening factor is changed by API call (use double buffering concept)
+ float sharp_factor_new; ///< this sharpening factor is changed by API call (use double buffering)
enum sharp_alg_t sharp_alg; ///< sharpening algorithm type
- enum sharp_alg_t sharp_alg_new; ///< this algorithm type is changed by API call (use double buffering concept)
+ enum sharp_alg_t sharp_alg_new; ///< this algorithm type is changed by API call (use double buffering)
float local_sens; ///< Sensitivity setting of local sharpening algorithm in per cent. 100 % means everything is sharpened like the global algorithm does
- float local_sens_new; ///< this sensitivity setting is changed by API call (use double buffering concept)
+ float local_sens_new; ///< this sensitivity setting is changed by API call (use double buffering)
int16_t *img_yuv_sharp; ///< YUV image buffer holding sharpened Y-channel. This buffer must be allocated externly.
int16_t *img_sobel; ///< Sobel image in YUV color space used by local sharpening algorithm. This buffer must be allocated externly.
int16_t *img_gauss; ///< Gaussian low-pass filtered image in YUV color space used by local sharpening algorithm. This buffer must be allocated externly.
@@ -268,7 +275,7 @@ struct gamma_data_t {
int width; ///< image width in number of pixels
int height; ///< image height in number of pixels
float gamma; ///< gamma coefficient
- float gamma_new; ///< this gamma coefficient is changed by API call (use double buffering concept)
+ float gamma_new; ///< this gamma coefficient is changed by API call (use double buffering)
int gamma_table_bitdepth; ///< gamma table is initialized with this bit-depth
float gamma_table_init; ///< gamma table is initialized with this coefficient
int *gamma_table; ///< Lookup table containg gamma corrected value. This buffer must be allocated externly.
@@ -276,6 +283,41 @@ struct gamma_data_t {
/**
+ * Isosceles trapezoid correction definition
+ */
+struct trapcorr_data_t {
+ int enable; ///< flag to enable this algorithm
+ void *img_out; ///< Isosceles corrected output image. This buffer must be allocated externly.
+ void *img_in; ///< Input image.
+ int is_color; ///< Not 0 if it's a color image
+ int bit_channel; ///< Bits per color channel.
+ int width; ///< image width in number of pixels
+ int height; ///< image height in number of pixels
+ float wv; ///< vertical correction weight in per cent (range: -100.0 to +100.0) (NOTE not implemented yet!)
+ float wh; ///< horizontal correction weight in per cent (range: -100.0 to +100.0)
+ float wv_new; ///< double buffered vertical correction weight
+ float wh_new; ///< double buffered horizontal correction weight
+
+ int map_init; ///< flag indicating perspective correction map is initialized
+
+ /**
+ * perspective correction map
+ * A coordinate pair defines the pixel location to be corrected. It may be shifted (see @ref map_scale_fact).
+ *
+ * This buffer must be allocated externly.
+ */
+ struct coord_t *map;
+
+ /**
+ * Bit shift applied on correction map @ref map.
+ * The pixel location may lay between a pixel pair. Therefore the coordinates defined at the correction map
+ * @ref map are (scaled) shifted by this factor.
+ */
+ int map_scale_fact;
+};
+
+
+/**
* Color pipe definition structure holding all memory data from different pipeline
* stages. This structure and image buffers are allocated dynamically.
*/
@@ -293,6 +335,7 @@ struct color_pipe_t {
struct color_calib_data_t color_calib_data; ///< color calibration data used for color corretion
struct sharp_data_t sharp_data; ///< image sharpening data
struct gamma_data_t gamma_data; ///< gamma correction data
+ struct trapcorr_data_t trapcorr_data; ///< isosceles trapezoid correction data
};
@@ -312,6 +355,7 @@ void __stdcall color_pipe_stageconf_cam_calib(struct color_pipe_t *color_pipe, i
void __stdcall color_pipe_stageconf_color_calib(struct color_pipe_t *color_pipe, int enable, enum ccm_preset_t ccm_preset);
void __stdcall color_pipe_stageconf_sharp(struct color_pipe_t *color_pipe, int enable, float factor, enum sharp_alg_t alg, float sens);
void __stdcall color_pipe_stageconf_gamma(struct color_pipe_t *color_pipe, int enable, float gamma);
+void __stdcall color_pipe_stageconf_trapcorr(struct color_pipe_t *color_pipe, int enable, float wv, float wh);
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
diff --git a/color_pipe_private.h b/color_pipe_private.h
index bf412fe..b2954ac 100644
--- a/color_pipe_private.h
+++ b/color_pipe_private.h
@@ -2,9 +2,7 @@
* @file color_pipe_private.c
* @brief Color Processing Pipeline definitions for internal use only
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-20
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -49,6 +47,8 @@ int sharpening(struct sharp_data_t *sharp_data);
int gamma_corr(struct gamma_data_t *gamma_data);
+int trapcorr(struct trapcorr_data_t *trapcorr_data);
+
#if defined(__cplusplus) || defined(c_plusplus)
} // extern "C"
#endif
diff --git a/cpu_feature.c b/cpu_feature.c
index 62080a5..e709366 100644
--- a/cpu_feature.c
+++ b/cpu_feature.c
@@ -2,9 +2,7 @@
* @file cpu_feature.c
* @brief CPU feature detection (CPU ID)
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-11-12
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/cpu_feature.h b/cpu_feature.h
index 11b5008..bdd4d48 100644
--- a/cpu_feature.h
+++ b/cpu_feature.h
@@ -2,9 +2,7 @@
* @file cpu_feature.h
* @brief CPU feature detection definitions (CPU ID)
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-11-12
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -45,4 +43,4 @@ enum cpu_feature_t {
int cpu_feature_support(enum cpu_feature_t type);
int cpu_feature_init(void);
-#endif // _CPU_FEATURE_H \ No newline at end of file
+#endif // _CPU_FEATURE_H
diff --git a/debayer.c b/debayer.c
index 1733496..984f928 100644
--- a/debayer.c
+++ b/debayer.c
@@ -2,9 +2,7 @@
* @file debayer.c
* @brief demosaicing algorithms
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-20
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -240,4 +238,4 @@ int debayer(struct debayer_data_t *debayer_data) {
ret = -1;
}
return ret;
-} \ No newline at end of file
+}
diff --git a/filter.c b/filter.c
index 6c8d51a..91b5376 100644
--- a/filter.c
+++ b/filter.c
@@ -2,9 +2,7 @@
* @file filter.c
* @brief various filtering algorithm
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-28
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/filter.h b/filter.h
index 5b70294..7299ceb 100644
--- a/filter.h
+++ b/filter.h
@@ -2,9 +2,7 @@
* @file filter.h
* @brief various filtering algorithm definitions
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-28
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -49,4 +47,4 @@ void filter_binary_3s16(int8_t *img_bin, const int16_t *img_in, const int height
#endif
-#endif // _FILTER_H \ No newline at end of file
+#endif // _FILTER_H
diff --git a/gamma_corr.c b/gamma_corr.c
index 2a85b1e..7b344c1 100644
--- a/gamma_corr.c
+++ b/gamma_corr.c
@@ -2,9 +2,7 @@
* @file gamma_corr.c
* @brief gamma correction algorithm
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-09-08
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/sharpening.c b/sharpening.c
index d997b73..4b114c6 100644
--- a/sharpening.c
+++ b/sharpening.c
@@ -2,9 +2,7 @@
* @file sharp.c
* @brief sharpening algorithm
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-27
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
diff --git a/trapcorr.c b/trapcorr.c
new file mode 100644
index 0000000..aef2411
--- /dev/null
+++ b/trapcorr.c
@@ -0,0 +1,317 @@
+/**
+* @file trapcorr.c
+* @brief isosceles trapeze correction algorithm
+* @author Patrick Roth - roth@stettbacher.ch
+* @copyright Stettbacher Signal Processing AG
+*
+* @remarks
+*
+* <PRE>
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+* </PRE>
+*
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include "color_pipe_private.h"
+
+
+
+/**
+ * Pixel value interpolation of RGB image (8 bit per color channel).
+ * If a pixel coordinate with a fraction part is of interest, do interpolate the correct value from their neighbor's pixel.
+ *
+ * E. g. the pixel coordinate x/y = 1.8/2.3 gives the following weights:
+ * +------+------+
+ * | | |
+ * | 14% | 56% | 14% = 20%*70%, 56% = 80%*70%
+ * | | |
+ * +------+------+
+ * | | |
+ * | 6% | 24% | 6% = 20%*30%, 24% = 80%*30%
+ * | | |
+ * +------+------+
+ *
+ * The weights are applied to the neighors and the resulting pixel value is saved at the given location.
+ *
+ * NOTE
+ * The input and output image must have the same pixel size.
+ *
+ * @param img_out On return: image with interpolated values
+ * @param x saved interpolated pixel value at this x-coordinate
+ * @param y saved interpolated pixel value at this y-coordinate
+ * @param height image height of input and output image in number of pixels
+ * @param width image width of input and output image in number of pixels
+ * @param img_in input image to interpolate pixel values
+ * @param coord_x x-coordinate to interpolate
+ * @param coord_y y-coordinate to interpolate
+ * @param scale_fact coordinates are scaled by this factor
+ */
+static void interpolate_rgb8_scalar(uint8_t *img_out, const int x, const int y, const int height, const int width,
+ const uint8_t *img_in, const int coord_x, const int coord_y, const int scale_fact)
+#include "alg_interpolate_rgb_scalar.h"
+
+
+/**
+ * Pixel value interpolation of RGB image (16 bit per color channel).
+ * If a pixel coordinate with a fraction part is of interest, do interpolate the correct value from their neighbor's pixel.
+ *
+ * E. g. the pixel coordinate x/y = 1.8/2.3 gives the following weights:
+ * +------+------+
+ * | | |
+ * | 14% | 56% | 14% = 20%*70%, 56% = 80%*70%
+ * | | |
+ * +------+------+
+ * | | |
+ * | 6% | 24% | 6% = 20%*30%, 24% = 80%*30%
+ * | | |
+ * +------+------+
+ *
+ * The weights are applied to the neighors and the resulting pixel value is saved at the given location.
+ *
+ * NOTE
+ * The input and output image must have the same pixel size.
+ *
+ * @param img_out On return: image with interpolated values
+ * @param x saved interpolated pixel value at this x-coordinate
+ * @param y saved interpolated pixel value at this y-coordinate
+ * @param height image height of input and output image in number of pixels
+ * @param width image width of input and output image in number of pixels
+ * @param img_in input image to interpolate pixel values
+ * @param coord_x x-coordinate to interpolate
+ * @param coord_y y-coordinate to interpolate
+ * @param scale_fact coordinates are scaled by this factor
+ */
+static void interpolate_rgb16_scalar(uint16_t *img_out, const int x, const int y, const int height, const int width,
+ const uint16_t *img_in, const int coord_x, const int coord_y, const int scale_fact)
+#include "alg_interpolate_rgb_scalar.h"
+
+
+/**
+ * Pixel value interpolation of monochrome image (8 bit per pixel).
+ * If a pixel coordinate with a fraction part is of interest, do interpolate the correct value from their neighbor's pixel.
+ *
+ * E. g. the pixel coordinate x/y = 1.8/2.3 gives the following weights:
+ * +------+------+
+ * | | |
+ * | 14% | 56% | 14% = 20%*70%, 56% = 80%*70%
+ * | | |
+ * +------+------+
+ * | | |
+ * | 6% | 24% | 6% = 20%*30%, 24% = 80%*30%
+ * | | |
+ * +------+------+
+ *
+ * The weights are applied to the neighors and the resulting pixel value is saved at the given location.
+ *
+ * NOTE
+ * The input and output image must have the same pixel size.
+ *
+ * @param img_out On return: image with interpolated values
+ * @param x saved interpolated pixel value at this x-coordinate
+ * @param y saved interpolated pixel value at this y-coordinate
+ * @param height image height of input and output image in number of pixels
+ * @param width image width of input and output image in number of pixels
+ * @param img_in input image to interpolate pixel values
+ * @param coord_x x-coordinate to interpolate
+ * @param coord_y y-coordinate to interpolate
+ * @param scale_fact coordinates are scaled by this factor
+ */
+static void interpolate_mono8_scalar(uint8_t *img_out, const int x, const int y, const int height, const int width,
+ const uint8_t *img_in, const int coord_x, const int coord_y, const int scale_fact)
+#include "alg_interpolate_mono_scalar.h"
+
+
+/**
+ * Pixel value interpolation of monochrome image (16 bit per pixel).
+ * If a pixel coordinate with a fraction part is of interest, do interpolate the correct value from their neighbor's pixel.
+ *
+ * E. g. the pixel coordinate x/y = 1.8/2.3 gives the following weights:
+ * +------+------+
+ * | | |
+ * | 14% | 56% | 14% = 20%*70%, 56% = 80%*70%
+ * | | |
+ * +------+------+
+ * | | |
+ * | 6% | 24% | 6% = 20%*30%, 24% = 80%*30%
+ * | | |
+ * +------+------+
+ *
+ * The weights are applied to the neighors and the resulting pixel value is saved at the given location.
+ *
+ * NOTE
+ * The input and output image must have the same pixel size.
+ *
+ * @param img_out On return: image with interpolated values
+ * @param x saved interpolated pixel value at this x-coordinate
+ * @param y saved interpolated pixel value at this y-coordinate
+ * @param height image height of input and output image in number of pixels
+ * @param width image width of input and output image in number of pixels
+ * @param img_in input image to interpolate pixel values
+ * @param coord_x x-coordinate to interpolate
+ * @param coord_y y-coordinate to interpolate
+ * @param scale_fact coordinates are scaled by this factor
+ */
+static void interpolate_mono16_scalar(uint16_t *img_out, const int x, const int y, const int height, const int width,
+ const uint16_t *img_in, const int coord_x, const int coord_y, const int scale_fact)
+#include "alg_interpolate_mono_scalar.h"
+
+
+/**
+ * Apply iosceles trapez correction.
+ *
+ * @param data correction data
+ */
+static void correct(struct trapcorr_data_t *data) {
+ int x, y, x_corr, y_corr;
+ const int width = data->width;
+ const int height = data->height;
+ int bit_channel = data->bit_channel;
+ struct coord_t *map = data->map;
+ void *img_calib = data->img_out;
+ void *img_uncalib = data->img_in;
+ const int scale_fact = data->map_scale_fact;
+ const int is_color = data->is_color;
+
+ for(y = 0; y < height; y++) {
+ for(x = 0; x < width; x++) {
+ x_corr = map->x;
+ y_corr = map->y;
+ map++;
+
+ if(bit_channel <= 8) {
+ if(is_color) {
+ interpolate_rgb8_scalar(img_calib, x, y, height, width, img_uncalib, x_corr, y_corr, scale_fact);
+ }
+ else {
+ interpolate_mono8_scalar(img_calib, x, y, height, width, img_uncalib, x_corr, y_corr, scale_fact);
+ }
+ }
+ else if(bit_channel <= 16) {
+ if(is_color) {
+ interpolate_rgb16_scalar(img_calib, x, y, height, width, img_uncalib, x_corr, y_corr, scale_fact);
+ }
+ else {
+ interpolate_mono16_scalar(img_calib, x, y, height, width, img_uncalib, x_corr, y_corr, scale_fact);
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * Initialze perspective correction map.
+ *
+ * @param data required correction data
+ */
+static void init_map(struct trapcorr_data_t *data) {
+
+ int x, y;
+ struct coord_t *map = data->map;
+ const int scale_fact = (1 << (data->map_scale_fact));
+ const int width = data->width;
+ const int height = data->height;
+ float p, p_i, row_scale, x_corr, y_corr;
+ int x_start, x_end;
+ int shrink_upper;
+
+ // convert -100.0...+100.0 ---> 0.0...2.0
+ const float fact = data->wh/100.0f+1.0f;
+
+ /*
+ * Checking whether we shrink upper or lower horizontal
+ * trapeze line.
+ */
+ if(data->wh <= 1.0f) {
+ // upper line shrinks
+ shrink_upper = 1;
+ p = fact * (width/2.0f);
+ }
+ else {
+ // lower line shrinks
+ shrink_upper = 0;
+ p = (2.0f - fact) * (width/2.0f);
+ }
+
+ /*
+ * We'll loop through image with y-axis symmetrically centered.
+ * So the image is horizontally shifted to left. Do calculate
+ * the start and end values on x-axis.
+ */
+ if((width%2) == 0) {
+ // even width
+ x_start = (-1)*width/2;
+ x_end = width/2-1;
+ }
+ else {
+ // odd width
+ x_start = (-1)*(width-1)/2;
+ x_end = (width-1)/2;
+ }
+
+ // loop through image
+ for(y = 0; y < height; y++) {
+ if(shrink_upper) {
+ p_i = ((width/2.0f - p) / height) * y + p;
+ }
+ else {
+ p_i = (-1.0f*((width/2.0f - p) / height)) * y + width/2.0f;
+ }
+
+ row_scale = 2.0f * p_i / width;
+
+ // we don't correct vertically
+ y_corr = y;
+
+ for(x = x_start; x <= x_end; x++) {
+ x_corr = x/row_scale;
+
+ // trapeze is horizontally symmetrically centered --> shift right
+ x_corr -= x_start;
+
+ // apply scaling factor
+ map->x = (int)roundf(x_corr*scale_fact);
+ map->y = (int)roundf(y_corr*scale_fact);
+ map++;
+ }
+ }
+}
+
+
+/**
+ * Apply iosceles trapez correction to given image type.
+ *
+ * @param trapcorr_data required data for trapez correction
+ * @return 0 on success otherwise -1
+ */
+int trapcorr(struct trapcorr_data_t *trapcorr_data) {
+
+ /*
+ * Create perspective correction map if needed.
+ */
+ if(trapcorr_data->map_init == 0) {
+ trapcorr_data->map_scale_fact = 9; // scale by 9 means 2^9 = 512
+ init_map(trapcorr_data);
+ trapcorr_data->map_init = 1;
+ }
+
+ // apply perspective correction
+ correct(trapcorr_data);
+ return 0;
+}
diff --git a/white_balance.c b/white_balance.c
index 0040fb9..fd66f8a 100644
--- a/white_balance.c
+++ b/white_balance.c
@@ -2,9 +2,7 @@
* @file white_balance.c
* @brief white balance algorithm
* @author Patrick Roth - roth@stettbacher.ch
-* @version 1.0
-* @date 2015-08-20
-* @copyright 2012-2016 Stettbacher Signal Processing AG
+* @copyright Stettbacher Signal Processing AG
*
* @remarks
*
@@ -282,4 +280,4 @@ int white_balance(struct awb_data_t *awb_data) {
// printf("XXX u_avg = %.4f, v_avg = %.4f, red = %.4f, blue = %.4f, bit_channel = %d\n", u_avg, v_avg, awb_data->gain_red, awb_data->gain_blue, bit_channel);
return 0;
-} \ No newline at end of file
+}