diff options
author | alejandro-colomar <colomar.6.4.3@gmail.com> | 2019-07-29 15:21:50 +0200 |
---|---|---|
committer | alejandro-colomar <colomar.6.4.3@gmail.com> | 2019-07-29 15:21:50 +0200 |
commit | 4eb42d6627529c79c95d8cf12a4f4748c8eb2318 (patch) | |
tree | 204b8b870d0c27d637251c05cb38ac7a79eace64 | |
parent | 5f184bb288ba81622d42ac67d03f941473d4ebcd (diff) |
Improve algorithm
-rw-r--r-- | src/coins.c | 103 |
1 files changed, 56 insertions, 47 deletions
diff --git a/src/coins.c b/src/coins.c index a1806de..3504107 100644 --- a/src/coins.c +++ b/src/coins.c @@ -19,24 +19,31 @@ #include "libalx/base/compiler/size.h" #include "libalx/base/errno/error.h" -#include "libalx/base/stdlib/average.h" #include "libalx/base/stdlib/maximum.h" #include "libalx/extra/cv/alx.h" #include "libalx/extra/cv/core.h" #include "libalx/extra/cv/highgui.h" #include "libalx/extra/cv/imgproc.h" +#include "libalx/extra/cv/ximgproc.h" /****************************************************************************** ******* macros *************************************************************** ******************************************************************************/ #define COIN_DIAMETER_2E (25.75) +#define COIN_LIM_2E_50c (25.00) #define COIN_DIAMETER_50c (24.25) +#define COIN_LIM_50c_1E (23.70) #define COIN_DIAMETER_1E (23.25) -#define COIN_DIAMETER_20c (22.25) +#define COIN_LIM_1E_20c (22.65) +#define COIN_DIAMETER_20c (22.25) // That's the outer diameter! +#define COIN_LIM_20c_5c (21.40) #define COIN_DIAMETER_5c (21.25) +#define COIN_LIM_5c_10c (20.50) #define COIN_DIAMETER_10c (19.75) +#define COIN_LIM_10c_2c (19.25) #define COIN_DIAMETER_2c (18.75) +#define COIN_LIM_2c_1c (17.50) #define COIN_DIAMETER_1c (16.25) @@ -51,7 +58,7 @@ struct Coins { ptrdiff_t x; ptrdiff_t y; - uint16_t diameter_pix; + float diameter_pix; double diameter_mm; double value; }; @@ -66,7 +73,6 @@ struct Coins { ******* static functions (prototypes) **************************************** ******************************************************************************/ static int proc_coins_steps (const char *restrict fname); -static int coins_segmentate (img_s *restrict img); static int coins_positions (img_s *restrict img, ptrdiff_t nmemb, struct Coins coins[static restrict nmemb], @@ -117,7 +123,7 @@ int proc_coins (const char *restrict fname) static int proc_coins_steps (const char *restrict fname) { img_s *img; - img_s *cpy; + img_s *img_dt; struct Coins coins[BUFSIZ]; ptrdiff_t ncoins; int status; @@ -131,34 +137,52 @@ static int proc_coins_steps (const char *restrict fname) goto out_free_img; if (alx_cv_imread(img, fname)) goto out_deinit_img; - if (alx_cv_alloc_img(&cpy)) + if (alx_cv_alloc_img(&img_dt)) goto out_deinit_img; - if (alx_cv_init_img(cpy, 1, 1)) - goto out_free; + if (alx_cv_init_img(img_dt, 1, 1)) + goto out_free_dt; - if (coins_segmentate(img)) - goto out_deinit; - alx_cv_clone(cpy, img); - if (coins_positions(cpy, ARRAY_SIZE(coins), coins, &ncoins)) - goto out_deinit; - if (coins_diameters_pix(img, ncoins, coins)) - goto out_deinit; + if (alx_cv_component(img, ALX_CV_CMP_BLUE)) + goto out_deinit_dt; + if (alx_cv_threshold(img, CV_THRESH_BINARY_INV, ALX_CV_THR_OTSU)) + goto out_deinit_dt; +//alx_cv_invert(img); + alx_cv_imwrite(img, "/home/alex/Downloads/coins_thr.png"); + if (alx_cv_distance_transform(img)) + goto out_deinit_dt; + alx_cv_clone(img_dt, img); + alx_cv_imwrite(img_dt, "/home/alex/Downloads/coins_img_dt.png"); + if (alx_cv_local_max(img)) + goto out_deinit_dt; + if (alx_cv_dilate(img, 2)) + goto out_deinit_dt; + alx_cv_imwrite(img, "/home/alex/Downloads/coins_locmax.png"); + + if (coins_positions(img, ARRAY_SIZE(coins), coins, &ncoins)) + goto out_deinit_dt; + alx_cv_imwrite(img, "/home/alex/Downloads/coins_contours.png"); + alx_cv_imwrite(img_dt, "/home/alex/Downloads/coins_img_dt2.png"); + if (coins_diameters_pix(img_dt, ncoins, coins)) + goto out_deinit_dt; /* Calibrate with the biggest coin; every img should have a 2 € coin */ /* TODO: Fix this: should calibrate with a pattern */ mm_per_pix = calibrate_mm_per_pix(ncoins, coins); /* Get coins diameters in mm */ coins_diameters_mm(mm_per_pix, ncoins, coins); /* Get coins values (by their sizes) */ + printf("mm/pix = %lf\n", mm_per_pix); + if (coins_values(ncoins, coins)) - goto out_deinit; + goto out_deinit_dt; /* Add total value */ value_total = coins_total_value(ncoins, coins); report(ncoins, coins, value_total); status = 0; -out_deinit: - alx_cv_deinit_img(cpy); -out_free: - alx_cv_free_img(cpy); + +out_deinit_dt: + alx_cv_deinit_img(img_dt); +out_free_dt: + alx_cv_free_img(img_dt); out_deinit_img: alx_cv_deinit_img(img); out_free_img: @@ -166,22 +190,6 @@ out_free_img: return status; } -static int coins_segmentate (img_s *restrict img) -{ - - if (alx_cv_component(img, ALX_CV_CMP_BLUE)) - return -1; - if (alx_cv_threshold(img, CV_THRESH_BINARY_INV, ALX_CV_THR_OTSU)) - return -1; - if (alx_cv_distance_transform(img)) - return -1; - if (alx_cv_local_max(img)) - return -1; - if (alx_cv_dilate(img, 1)) - return -1; - return 0; -} - static int coins_positions (img_s *restrict img, ptrdiff_t nmemb, struct Coins coins[static restrict nmemb], ptrdiff_t *ncoins) @@ -209,6 +217,7 @@ static int coins_positions (img_s *restrict img, ptrdiff_t nmemb, if (alx_cv_contours_contour((const cont_s **)&cont, conts, i)) goto out_free; alx_cv_bounding_rect(rect, cont); +alx_cv_draw_rect(img, rect); alx_cv_extract_rect(rect, &x, &y, &w, &h); coins[i].x = x + w / 2; coins[i].y = y + h / 2; @@ -225,12 +234,12 @@ out_deinit_conts: static int coins_diameters_pix (const img_s *restrict img, ptrdiff_t n, struct Coins coins[static restrict n]) { - uint8_t tmp; + float tmp; for (ptrdiff_t i = 0; i < n; i++) { - if (alx_cv_pixel_get(img, &tmp, coins[i].x, coins[i].y)) + if (alx_cv_pixel_get_flt(img, &tmp, coins[i].x, coins[i].y)) return -1; - coins[i].diameter_pix = tmp * 2; + coins[i].diameter_pix = tmp * 2.0f; } return 0; } @@ -278,19 +287,19 @@ static double coin_value (double diameter_mm) if (diameter_mm > (COIN_DIAMETER_2E + 1.5)) return -1; - if (diameter_mm > ALX_AVG(COIN_DIAMETER_2E, COIN_DIAMETER_50c)) + if (diameter_mm > COIN_LIM_2E_50c) return 2.00; - if (diameter_mm > ALX_AVG(COIN_DIAMETER_50c, COIN_DIAMETER_1E)) + if (diameter_mm > COIN_LIM_50c_1E) return 0.50; - if (diameter_mm > ALX_AVG(COIN_DIAMETER_1E, COIN_DIAMETER_20c)) + if (diameter_mm > COIN_LIM_1E_20c) return 1.00; - if (diameter_mm > ALX_AVG(COIN_DIAMETER_20c, COIN_DIAMETER_5c)) + if (diameter_mm > COIN_LIM_20c_5c) return 0.20; - if (diameter_mm > ALX_AVG(COIN_DIAMETER_5c, COIN_DIAMETER_10c)) + if (diameter_mm > COIN_LIM_5c_10c) return 0.05; - if (diameter_mm > ALX_AVG(COIN_DIAMETER_10c, COIN_DIAMETER_2c)) + if (diameter_mm > COIN_LIM_10c_2c) return 0.10; - if (diameter_mm > ALX_AVG(COIN_DIAMETER_2c, COIN_DIAMETER_1c)) + if (diameter_mm > COIN_LIM_2c_1c) return 0.02; if (diameter_mm > (COIN_DIAMETER_1c - 1.5)) return 0.01; @@ -320,7 +329,7 @@ static void report (ptrdiff_t n, printf("Coin[%ti]:\n", i); printf(" pos = (%4ti, %4ti);\n", coins[i].x, coins[i].y); - printf(" d = %3"PRIu16" pix = %5.2lf mm;\n", + printf(" d = %3.1f pix = %5.2lf mm;\n", coins[i].diameter_pix, coins[i].diameter_mm); printf(" val = %5.2lf EUR;\n", coins[i].value); } |