summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralejandro-colomar <colomar.6.4.3@gmail.com>2019-07-29 15:21:50 +0200
committeralejandro-colomar <colomar.6.4.3@gmail.com>2019-07-29 15:21:50 +0200
commit4eb42d6627529c79c95d8cf12a4f4748c8eb2318 (patch)
tree204b8b870d0c27d637251c05cb38ac7a79eace64
parent5f184bb288ba81622d42ac67d03f941473d4ebcd (diff)
Improve algorithm
-rw-r--r--src/coins.c103
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);
}