diff --git a/sod.c b/sod.c index 4e0b30b..379daba 100644 --- a/sod.c +++ b/sod.c @@ -1,7 +1,7 @@ -/* +/* * SOD - An Embedded Computer Vision & Machine Learning Library. -* Copyright (C) 2018 PixLab| Symisc Systems. https://sod.pixlab.io -* Version 1.1.7 +* Copyright (C) 2018 - 2019 PixLab| Symisc Systems. https://sod.pixlab.io +* Version 1.1.8 * * Symisc Systems employs a dual licensing model that offers customers * a choice of either our open source license (GPLv3) or a commercial @@ -30,7 +30,7 @@ * You should have received a copy of the GNU General Public License * along with SOD. If not, see . */ -/* $SymiscID: sod.c v1.1.7 Win10 2018-02-02 05:34 stable $ */ +/* $SymiscID: sod.c v1.1.8 Win10 2018-02-02 05:34 stable $ */ #ifdef _MSC_VER #ifndef _CRT_SECURE_NO_WARNINGS /* @@ -9701,7 +9701,7 @@ static int hilditch_func_nc8(int *b) */ sod_img sod_hilditch_thin_image(sod_img im) { - /* thinning of binary image by Hilditch's algorithm */ + /* thinning of binary image via Hilditch's algorithm */ int offset[9][2] = { { 0,0 },{ 1,0 },{ 1,-1 },{ 0,-1 },{ -1,-1 }, { -1,0 },{ -1,1 },{ 0,1 },{ 1,1 } }; /* offsets for neighbors */ int n_odd[4] = { 1, 3, 5, 7 }; /* odd-number neighbors */ @@ -10666,6 +10666,94 @@ static void canny_hysteresis(int high, int low, sod_img * img_in, sod_img * img_ } } } +/* Based on the work: http://cis.k.hosei.ac.jp/~wakahara/ */ +static int minutiae_crossnumber(float *pixels,int y, int x, int w) +{ + int i, data[8]; + int cross; + + data[0] = pixels[y * w + x + 1] == 0 ? 1 : 0; + data[1] = pixels[(y - 1) * w + x + 1] == 0 ? 1 : 0; + data[2] = pixels[(y - 1) * w + x] == 0 ? 1 : 0; + data[3] = pixels[(y - 1) * w + (x - 1)] == 0 ? 1 : 0; + data[4] = pixels[y * w + (x - 1)] == 0 ? 1 : 0; + data[5] = pixels[(y + 1) * w + (x - 1)] == 0 ? 1 : 0; + data[6] = pixels[(y + 1) * w + x] == 0 ? 1 : 0; + data[7] = pixels[(y + 1) * w + x + 1] == 0 ? 1 : 0; + cross = 0; + for (i = 0; i < 8; i++) { + cross += abs(data[(i + 1) % 8] - data[i]); + } + cross /= 2; + return cross; +} +/* + * CAPIREF: Refer to the official documentation at https://sod.pixlab.io/api.html for the expected parameters this interface takes. + */ +SOD_APIEXPORT sod_img sod_minutiae(sod_img bin, int *pTotal, int *pEp, int *pBp) +{ + if (pTotal) { + *pTotal = 0; + } + if (pEp) { + *pEp = 0; + } + if (pBp) { + *pBp = 0; + } + /* Extraction of minutiae candidates in skeletonized fingerprint image */ + if (bin.data == 0 || bin.c != SOD_IMG_GRAYSCALE) { + /* Must be a binary image processed via sod_hilditch_thin_image() */ + return sod_make_empty_image(0, 0, 0); + } + sod_img out = sod_make_image(bin.w, bin.h, bin.c); + if (out.data) { + int x, y; + int total, np1, np2; /* number of black and minutiae points */ + int cross; + int i; + for (i = 0; i < out.w*out.h; i++) { + if (bin.data[i] == 1) { + out.data[i] = 200; + } + else { + out.data[i] = 1; + } + } + /* finding minutiae in 3 x 3 window + * Minutiae extraction is applied to skeletonized fingerprint. + */ + total = 0; + np1 = 0; /* number of ending points */ + np2 = 0; /* number of bifurcations */ + for (y = 1; y < bin.h - 1; y++) { + for (x = 1; x < bin.w - 1; x++) { + if (bin.data[y * bin.w + x] == 0) { + total++; + cross = minutiae_crossnumber(bin.data, y, x, bin.w); + if (cross == 1) { + np1++; + out.data[y * bin.w + x] = 0; + } + else if (cross >= 3) { + np2++; + out.data[y * bin.w + x] = 0; + } + } + } + } + if (pTotal) { + *pTotal = total; + } + if (pEp) { + *pEp = np1; + } + if (pBp) { + *pBp = np2; + } + } + return out; +} /* * Gaussian Noise Reduce on a grayscale image. * apply 5x5 Gaussian convolution filter, shrinks the image by 4 pixels in each direction, using Gaussian filter found here: @@ -13870,4 +13958,4 @@ void sod_img_save_to_cv_jpg(sod_img im, const char *zPath) const char * sod_lib_copyright(void) { return SOD_LIB_INFO; -} \ No newline at end of file +}