JWS C Library
C language utility library
2d.c
Go to the documentation of this file.
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