JWS C Library
C language utility library
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00046 #include <jwsc/config.h> 00047 00048 #include <stdlib.h> 00049 #include <inttypes.h> 00050 #include <math.h> 00051 #include <assert.h> 00052 00053 #include "jwsc/base/error.h" 00054 #include "jwsc/prob/pdf.h" 00055 #include "jwsc/matrix/matrix.h" 00056 #include "jwsc/matrix/matrix_math.h" 00057 #include "jwsc/filter/2d.h" 00058 00059 00061 #define PI 3.14159265358979323846 00062 00063 00079 void create_sobel_x_filter_f(Matrix_f** sobel_out) 00080 { 00081 Matrix_f* sobel; 00082 00083 create_zero_matrix_f(sobel_out, 3, 3); 00084 sobel = *sobel_out; 00085 00086 sobel->elts[ 0 ][ 0 ] = -1; 00087 sobel->elts[ 0 ][ 2 ] = 1; 00088 sobel->elts[ 1 ][ 0 ] = -2; 00089 sobel->elts[ 1 ][ 2 ] = 2; 00090 sobel->elts[ 2 ][ 0 ] = -1; 00091 sobel->elts[ 2 ][ 2 ] = 1; 00092 } 00093 00102 void create_sobel_x_filter_d(Matrix_d** sobel_out) 00103 { 00104 Matrix_d* sobel; 00105 00106 create_zero_matrix_d(sobel_out, 3, 3); 00107 sobel = *sobel_out; 00108 00109 sobel->elts[ 0 ][ 0 ] = -1; 00110 sobel->elts[ 0 ][ 2 ] = 1; 00111 sobel->elts[ 1 ][ 0 ] = -2; 00112 sobel->elts[ 1 ][ 2 ] = 2; 00113 sobel->elts[ 2 ][ 0 ] = -1; 00114 sobel->elts[ 2 ][ 2 ] = 1; 00115 } 00116 00137 void create_sobel_y_filter_f(Matrix_f** sobel_out) 00138 { 00139 Matrix_f* sobel; 00140 00141 create_zero_matrix_f(sobel_out, 3, 3); 00142 sobel = *sobel_out; 00143 00144 sobel->elts[ 0 ][ 0 ] = 1; 00145 sobel->elts[ 2 ][ 0 ] = -1; 00146 sobel->elts[ 0 ][ 1 ] = 2; 00147 sobel->elts[ 2 ][ 1 ] = -2; 00148 sobel->elts[ 0 ][ 2 ] = 1; 00149 sobel->elts[ 2 ][ 2 ] = -1; 00150 } 00151 00160 void create_sobel_y_filter_d(Matrix_d** sobel_out) 00161 { 00162 Matrix_d* sobel; 00163 00164 create_zero_matrix_d(sobel_out, 3, 3); 00165 sobel = *sobel_out; 00166 00167 sobel->elts[ 0 ][ 0 ] = 1; 00168 sobel->elts[ 2 ][ 0 ] = -1; 00169 sobel->elts[ 0 ][ 1 ] = 2; 00170 sobel->elts[ 2 ][ 1 ] = -2; 00171 sobel->elts[ 0 ][ 2 ] = 1; 00172 sobel->elts[ 2 ][ 2 ] = -1; 00173 } 00174 00201 Error* create_LoG_filter_f(Matrix_f** LoG_out, float sigma) 00202 { 00203 uint32_t width, center; 00204 uint32_t r, c; 00205 00206 float x_2, y_2; 00207 float sigma_sqr; 00208 00209 Matrix_f* LoG; 00210 00211 if (sigma < 0.01) 00212 { 00213 return JWSC_EARG("Sigma for LoG is too small"); 00214 } 00215 00216 if ((width = ceil(6.0 * sqrt(2.0) * sigma)) % 2 == 0) width++; 00217 center = width / 2; 00218 00219 create_matrix_f(LoG_out, width, width); 00220 LoG = *LoG_out; 00221 00222 sigma_sqr = sigma*sigma; 00223 00224 for (r = 0; r < width; r++) 00225 { 00226 y_2 = (r - center)*(r - center); 00227 for (c = 0; c < width; c++) 00228 { 00229 x_2 = (c - center)*(c - center); 00230 00231 LoG->elts[ r ][ c ] = (x_2 + y_2 - 2*sigma_sqr) * 00232 exp(-0.5*(x_2 + y_2)/sigma_sqr) / (sigma_sqr*sigma_sqr); 00233 } 00234 } 00235 00236 return NULL; 00237 } 00238 00267 Error* create_auto_2d_gaussian_filter_f 00268 ( 00269 Matrix_f** h_out, 00270 float row_sigma, 00271 float col_sigma 00272 ) 00273 { 00274 uint32_t num_rows, num_cols; 00275 00276 if ((num_rows = ceil(sqrt(2) * 6.0 * row_sigma)) % 2 == 0) num_rows++; 00277 if ((num_cols = ceil(sqrt(2) * 6.0 * col_sigma)) % 2 == 0) num_cols++; 00278 00279 return create_2d_gaussian_filter_f(h_out, row_sigma, col_sigma, 00280 num_rows, num_cols); 00281 } 00282 00299 Error* create_auto_2d_gaussian_filter_d 00300 ( 00301 Matrix_d** h_out, 00302 double row_sigma, 00303 double col_sigma 00304 ) 00305 { 00306 uint32_t num_rows, num_cols; 00307 00308 if ((num_rows = ceil(sqrt(2) * 6.0 * row_sigma)) % 2 == 0) num_rows++; 00309 if ((num_cols = ceil(sqrt(2) * 6.0 * col_sigma)) % 2 == 0) num_cols++; 00310 00311 return create_2d_gaussian_filter_d(h_out, row_sigma, col_sigma, 00312 num_rows, num_cols); 00313 } 00314 00347 Error* create_2d_gaussian_filter_f 00348 ( 00349 Matrix_f** h_out, 00350 float row_sigma, 00351 float col_sigma, 00352 uint32_t num_rows, 00353 uint32_t num_cols 00354 ) 00355 { 00356 uint32_t row, col; 00357 uint32_t r, c; 00358 float x, y; 00359 float x_gauss, y_gauss; 00360 float gauss; 00361 Matrix_f* h; 00362 00363 if (row_sigma < 0.01 || col_sigma < 0.01) 00364 { 00365 return JWSC_EARG("Sigma for Gaussian is too small"); 00366 } 00367 00368 assert(num_rows > 0 && num_cols > 0); 00369 00370 create_matrix_f(h_out, num_rows, num_cols); 00371 h = *h_out; 00372 00373 #if defined JWSC_HAVE_SLATEC || defined JWSC_HAVE_ERF 00374 for (row = 0; row < ceil(0.5*num_rows); row++) 00375 { 00376 y = (ceil(0.5*num_rows) - row - 1); 00377 y_gauss = integrate_gaussian_pdf_d(0, row_sigma, y, y+1); 00378 for (col = 0; col < ceil(0.5*num_cols); col++) 00379 { 00380 x = (ceil(0.5*num_cols) - col - 1); 00381 x_gauss = integrate_gaussian_pdf_d(0, col_sigma, x, x+1); 00382 gauss = x_gauss*y_gauss; 00383 00384 r = row; c = col; 00385 h->elts[ r ][ c ] = gauss; 00386 00387 r = row; c = num_cols-col-1; 00388 h->elts[ r ][ c ] = gauss; 00389 00390 r = num_rows-row-1; c = col; 00391 h->elts[ r ][ c ] = gauss; 00392 00393 r = num_rows-row-1; c = num_cols-col-1; 00394 h->elts[ r ][ c ] = gauss; 00395 } 00396 } 00397 #else 00398 for (row = 0; row < ceil(0.5*num_rows); row++) 00399 { 00400 y = (ceil(0.5*num_rows) - row - 1); 00401 y_gauss = gaussian_pdf_d(0, row_sigma, y+0.5); 00402 for (col = 0; col < ceil(0.5*num_cols); col++) 00403 { 00404 x = (ceil(0.5*num_cols) - col - 1); 00405 x_gauss = gaussian_pdf_d(0, col_sigma, x+0.5); 00406 gauss = x_gauss*y_gauss; 00407 00408 r = row; c = col; 00409 h->elts[ r ][ c ] = gauss; 00410 00411 r = row; c = num_cols-col-1; 00412 h->elts[ r ][ c ] = gauss; 00413 00414 r = num_rows-row-1; c = col; 00415 h->elts[ r ][ c ] = gauss; 00416 00417 r = num_rows-row-1; c = num_cols-col-1; 00418 h->elts[ r ][ c ] = gauss; 00419 } 00420 } 00421 #endif 00422 00423 return NULL; 00424 } 00425 00446 Error* create_2d_gaussian_filter_d 00447 ( 00448 Matrix_d** h_out, 00449 double row_sigma, 00450 double col_sigma, 00451 uint32_t num_rows, 00452 uint32_t num_cols 00453 ) 00454 { 00455 uint32_t row, col; 00456 uint32_t r, c; 00457 double x, y; 00458 double x_gauss, y_gauss; 00459 double gauss; 00460 Matrix_d* h; 00461 00462 if (row_sigma < 0.01 || col_sigma < 0.01) 00463 { 00464 return JWSC_EARG("Sigma for Gaussian is too small"); 00465 } 00466 00467 assert(num_rows > 0 && num_cols > 0); 00468 00469 create_matrix_d(h_out, num_rows, num_cols); 00470 h = *h_out; 00471 00472 #if defined JWSC_HAVE_SLATEC || defined JWSC_HAVE_ERF 00473 for (row = 0; row < ceil(0.5*num_rows); row++) 00474 { 00475 y = (ceil(0.5*num_rows) - row - 1); 00476 y_gauss = integrate_gaussian_pdf_d(0, row_sigma, y, y+1); 00477 for (col = 0; col < ceil(0.5*num_cols); col++) 00478 { 00479 x = (ceil(0.5*num_cols) - col - 1); 00480 x_gauss = integrate_gaussian_pdf_d(0, col_sigma, x, x+1); 00481 gauss = x_gauss*y_gauss; 00482 00483 r = row; c = col; 00484 h->elts[ r ][ c ] = gauss; 00485 00486 r = row; c = num_cols-col-1; 00487 h->elts[ r ][ c ] = gauss; 00488 00489 r = num_rows-row-1; c = col; 00490 h->elts[ r ][ c ] = gauss; 00491 00492 r = num_rows-row-1; c = num_cols-col-1; 00493 h->elts[ r ][ c ] = gauss; 00494 } 00495 } 00496 #else 00497 for (row = 0; row < ceil(0.5*num_rows); row++) 00498 { 00499 y = (ceil(0.5*num_rows) - row - 1); 00500 y_gauss = gaussian_pdf_d(0, row_sigma, y+0.5); 00501 for (col = 0; col < ceil(0.5*num_cols); col++) 00502 { 00503 x = (ceil(0.5*num_cols) - col - 1); 00504 x_gauss = gaussian_pdf_d(0, col_sigma, x+0.5); 00505 gauss = x_gauss*y_gauss; 00506 00507 r = row; c = col; 00508 h->elts[ r ][ c ] = gauss; 00509 00510 r = row; c = num_cols-col-1; 00511 h->elts[ r ][ c ] = gauss; 00512 00513 r = num_rows-row-1; c = col; 00514 h->elts[ r ][ c ] = gauss; 00515 00516 r = num_rows-row-1; c = num_cols-col-1; 00517 h->elts[ r ][ c ] = gauss; 00518 } 00519 } 00520 #endif 00521 00522 return NULL; 00523 } 00524 00554 Error* create_auto_2d_gaussian_dx_filter_f 00555 ( 00556 Matrix_f** h_out, 00557 float row_sigma, 00558 float col_sigma 00559 ) 00560 { 00561 uint32_t num_rows, num_cols; 00562 00563 if ((num_rows = ceil(sqrt(2) * 6.0 * row_sigma)) % 2 == 0) num_rows++; 00564 if ((num_cols = ceil(sqrt(2) * 6.0 * col_sigma)) % 2 == 0) num_cols++; 00565 00566 return create_2d_gaussian_dx_filter_f(h_out, row_sigma, col_sigma, 00567 num_rows, num_cols); 00568 } 00569 00586 Error* create_auto_2d_gaussian_dx_filter_d 00587 ( 00588 Matrix_d** h_out, 00589 double row_sigma, 00590 double col_sigma 00591 ) 00592 { 00593 uint32_t num_rows, num_cols; 00594 00595 if ((num_rows = ceil(sqrt(2) * 6.0 * row_sigma)) % 2 == 0) num_rows++; 00596 if ((num_cols = ceil(sqrt(2) * 6.0 * col_sigma)) % 2 == 0) num_cols++; 00597 00598 return create_2d_gaussian_dx_filter_d(h_out, row_sigma, col_sigma, 00599 num_rows, num_cols); 00600 } 00601 00631 Error* create_2d_gaussian_dx_filter_f 00632 ( 00633 Matrix_f** h_out, 00634 float row_sigma, 00635 float col_sigma, 00636 uint32_t num_rows, 00637 uint32_t num_cols 00638 ) 00639 { 00640 int64_t row, col; 00641 int64_t rows_center; 00642 int64_t cols_center; 00643 00644 float inv_row_sigma_sqr; 00645 float inv_col_sigma_sqr; 00646 float gauss_val; 00647 float val; 00648 00649 Matrix_f* h; 00650 00651 if (row_sigma < 0.01 || col_sigma < 0.01) 00652 { 00653 return JWSC_EARG("Sigma for Gaussian is too small"); 00654 } 00655 00656 create_matrix_f(h_out, num_rows, num_cols); 00657 h = *h_out; 00658 00659 rows_center = num_rows / 2; 00660 cols_center = num_cols / 2; 00661 inv_row_sigma_sqr = 1.0 / (row_sigma*row_sigma); 00662 inv_col_sigma_sqr = 1.0 / (col_sigma*col_sigma); 00663 00664 for (row = 0; row < num_rows; row++) 00665 { 00666 for (col = 0; col < num_cols; col++) 00667 { 00668 val = (row-rows_center)*(row-rows_center)*inv_row_sigma_sqr + 00669 (col-cols_center)*(col-cols_center)*inv_col_sigma_sqr; 00670 gauss_val = -1*(col - cols_center)*exp(-0.5 * val); 00671 h->elts[ row ][ col ] = gauss_val; 00672 } 00673 } 00674 00675 val = (inv_row_sigma_sqr*inv_col_sigma_sqr) / (2 * PI); 00676 multiply_matrix_by_scalar_f(h_out, h, val); 00677 00678 return NULL; 00679 } 00680 00698 Error* create_2d_gaussian_dx_filter_d 00699 ( 00700 Matrix_d** h_out, 00701 double row_sigma, 00702 double col_sigma, 00703 uint32_t num_rows, 00704 uint32_t num_cols 00705 ) 00706 { 00707 int64_t row, col; 00708 int64_t rows_center; 00709 int64_t cols_center; 00710 00711 double inv_row_sigma_sqr; 00712 double inv_col_sigma_sqr; 00713 double gauss_val; 00714 double val; 00715 00716 Matrix_d* h; 00717 00718 if (row_sigma < 0.01 || col_sigma < 0.01) 00719 { 00720 return JWSC_EARG("Sigma for Gaussian is too small"); 00721 } 00722 00723 create_matrix_d(h_out, num_rows, num_cols); 00724 h = *h_out; 00725 00726 rows_center = num_rows / 2; 00727 cols_center = num_cols / 2; 00728 inv_row_sigma_sqr = 1.0 / (row_sigma*row_sigma); 00729 inv_col_sigma_sqr = 1.0 / (col_sigma*col_sigma); 00730 00731 for (row = 0; row < num_rows; row++) 00732 { 00733 for (col = 0; col < num_cols; col++) 00734 { 00735 val = (row-rows_center)*(row-rows_center)*inv_row_sigma_sqr + 00736 (col-cols_center)*(col-cols_center)*inv_col_sigma_sqr; 00737 gauss_val = -1*(col - cols_center)*exp(-0.5 * val); 00738 h->elts[ row ][ col ] = gauss_val; 00739 } 00740 } 00741 00742 val = (inv_row_sigma_sqr*inv_col_sigma_sqr) / (2 * PI); 00743 multiply_matrix_by_scalar_d(h_out, h, val); 00744 00745 00746 return NULL; 00747 } 00748 00778 Error* create_auto_2d_gaussian_dy_filter_f 00779 ( 00780 Matrix_f** h_out, 00781 float row_sigma, 00782 float col_sigma 00783 ) 00784 { 00785 uint32_t num_rows, num_cols; 00786 00787 if ((num_rows = ceil(sqrt(2) * 6.0 * row_sigma)) % 2 == 0) num_rows++; 00788 if ((num_cols = ceil(sqrt(2) * 6.0 * col_sigma)) % 2 == 0) num_cols++; 00789 00790 return create_2d_gaussian_dy_filter_f(h_out, row_sigma, col_sigma, 00791 num_rows, num_cols); 00792 } 00793 00810 Error* create_auto_2d_gaussian_dy_filter_d 00811 ( 00812 Matrix_d** h_out, 00813 double row_sigma, 00814 double col_sigma 00815 ) 00816 { 00817 uint32_t num_rows, num_cols; 00818 00819 if ((num_rows = ceil(sqrt(2) * 6.0 * row_sigma)) % 2 == 0) num_rows++; 00820 if ((num_cols = ceil(sqrt(2) * 6.0 * col_sigma)) % 2 == 0) num_cols++; 00821 00822 return create_2d_gaussian_dy_filter_d(h_out, row_sigma, col_sigma, 00823 num_rows, num_cols); 00824 } 00825 00855 Error* create_2d_gaussian_dy_filter_f 00856 ( 00857 Matrix_f** h_out, 00858 float row_sigma, 00859 float col_sigma, 00860 uint32_t num_rows, 00861 uint32_t num_cols 00862 ) 00863 { 00864 int64_t row, col; 00865 int64_t rows_center; 00866 int64_t cols_center; 00867 00868 float inv_row_sigma_sqr; 00869 float inv_col_sigma_sqr; 00870 float gauss_val; 00871 float val; 00872 00873 Matrix_f* h; 00874 00875 if (row_sigma < 0.01 || col_sigma < 0.01) 00876 { 00877 return JWSC_EARG("Sigma for Gaussian is too small"); 00878 } 00879 00880 create_matrix_f(h_out, num_rows, num_cols); 00881 h = *h_out; 00882 00883 rows_center = num_rows / 2; 00884 cols_center = num_cols / 2; 00885 inv_row_sigma_sqr = 1.0 / (row_sigma*row_sigma); 00886 inv_col_sigma_sqr = 1.0 / (col_sigma*col_sigma); 00887 00888 for (row = 0; row < num_rows; row++) 00889 { 00890 for (col = 0; col < num_cols; col++) 00891 { 00892 val = (row-rows_center)*(row-rows_center)*inv_row_sigma_sqr + 00893 (col-cols_center)*(col-cols_center)*inv_col_sigma_sqr; 00894 gauss_val = -1*(row - rows_center)*exp(-0.5 * val); 00895 h->elts[ row ][ col ] = gauss_val; 00896 } 00897 } 00898 00899 val = (inv_row_sigma_sqr*inv_col_sigma_sqr) / (2 * PI); 00900 multiply_matrix_by_scalar_f(h_out, h, val); 00901 00902 return NULL; 00903 } 00904 00922 Error* create_2d_gaussian_dy_filter_d 00923 ( 00924 Matrix_d** h_out, 00925 double row_sigma, 00926 double col_sigma, 00927 uint32_t num_rows, 00928 uint32_t num_cols 00929 ) 00930 { 00931 int64_t row, col; 00932 int64_t rows_center; 00933 int64_t cols_center; 00934 00935 double inv_row_sigma_sqr; 00936 double inv_col_sigma_sqr; 00937 double gauss_val; 00938 double val; 00939 00940 Matrix_d* h; 00941 00942 if (row_sigma < 0.01 || col_sigma < 0.01) 00943 { 00944 return JWSC_EARG("Sigma for Gaussian is too small"); 00945 } 00946 00947 create_matrix_d(h_out, num_rows, num_cols); 00948 h = *h_out; 00949 00950 rows_center = num_rows / 2; 00951 cols_center = num_cols / 2; 00952 inv_row_sigma_sqr = 1.0 / (row_sigma*row_sigma); 00953 inv_col_sigma_sqr = 1.0 / (col_sigma*col_sigma); 00954 00955 for (row = 0; row < num_rows; row++) 00956 { 00957 for (col = 0; col < num_cols; col++) 00958 { 00959 val = (row-rows_center)*(row-rows_center)*inv_row_sigma_sqr + 00960 (col-cols_center)*(col-cols_center)*inv_col_sigma_sqr; 00961 gauss_val = -1*(row - rows_center)*exp(-0.5 * val); 00962 h->elts[ row ][ col ] = gauss_val; 00963 } 00964 } 00965 00966 val = (inv_row_sigma_sqr*inv_col_sigma_sqr) / (2 * PI); 00967 multiply_matrix_by_scalar_d(h_out, h, val); 00968 00969 return NULL; 00970 } 00971