From a9152e2841ff1f20994f32f1a55838ae20d38bd4 Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Tue, 4 Jul 2023 19:54:20 +0200 Subject: [PATCH] better way of finding the best level. --- README.md | 4 ++- image.c | 4 +-- main.c | 94 +++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index ebfdbbb..5b9f065 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ # VidOilTank -measure the level of a hearoiltank via RPi Cammera \ No newline at end of file +measure the level of a hearoiltank via RPi Cammera + + diff --git a/image.c b/image.c index 5492972..928953b 100644 --- a/image.c +++ b/image.c @@ -40,7 +40,7 @@ int image_save(ImageRaw *i, char *fn, int quality) { int row_stride; /* physical row width in image buffer */ if (i == NULL) { - printf ("image_save no image i == NULL\n"); + printf ("%s:%d image_save no image i == NULL\n", __FILE__, __LINE__); exit (1); } @@ -48,7 +48,7 @@ int image_save(ImageRaw *i, char *fn, int quality) { jpeg_create_compress(&cinfo); if ((outfile = fopen(fn, "wb")) == NULL) { - fprintf(stderr, "can't open %s\n", fn); + fprintf(stderr, "%s:%d can't open %s error:%s\n", __FILE__, __LINE__, fn, strerror(errno)); exit(1); } jpeg_stdio_dest(&cinfo, outfile); diff --git a/main.c b/main.c index 5fcc066..d3cfd3b 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,8 @@ +// +// for testing: make && ./vidoiltank -rotate 270 -samples 1 -debug /mnt/heizoel-data +// + #include #include #include @@ -13,6 +17,7 @@ int conf_iomode = IOM_MMAP; int conf_samples = 25; int conf_rotate = 0; Rect conf_rect = { .x = 315, .y = 0, .w = 70, .h = 1910 }; +char conf_outdate[LEN_FILENAME]; int detect_level(ImageFloat *imgf); @@ -44,14 +49,13 @@ int main(int argc, char **argv) { ImageRaw *tmpimg = NULL; ImageFloat *imgf = NULL; char fn[3*LEN_FILENAME]; - char outdate[LEN_FILENAME]; - time_t curtime = time(NULL); - struct tm *curtime_tm = NULL; int i, c, b, level, cont, bright, min, max; // for debugging only + time_t curtime = time(NULL); + struct tm *curtime_tm = NULL; curtime_tm = localtime(&curtime); - strftime(outdate, LEN_FILENAME-1, "%Y%m%d-%H%M%S", curtime_tm); + strftime(conf_outdate, LEN_FILENAME-1, "%Y%m%d-%H%M%S", curtime_tm); for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "-dev") == 0) { @@ -141,7 +145,7 @@ int main(int argc, char **argv) { } if (i == 0) { - snprintf (fn, 3*LEN_FILENAME, "%s/%s-img-%02d-%02d.jpg", conf_debugout, outdate, bright, cont); + snprintf (fn, 3*LEN_FILENAME, "%s/%s-img-%02d-%02d.jpg", conf_debugout, conf_outdate, bright, cont); image_draw_rect(img, &conf_rect, 0x00FFFF); if (strlen(conf_debugout) > 0) image_save(img, fn, 98); } @@ -151,7 +155,7 @@ int main(int argc, char **argv) { video = NULL; tmpimg = image_copyF(imgf); - snprintf (fn, 3*LEN_FILENAME, "%s/%s-imgf-%03d.jpg", conf_debugout, outdate, conf_samples); + snprintf (fn, 3*LEN_FILENAME, "%s/%s-imgf-%03d.jpg", conf_debugout, conf_outdate, conf_samples); if (strlen(conf_debugout) > 0) image_save(tmpimg, fn, 98); printf ("detect level\n"); @@ -160,18 +164,28 @@ int main(int argc, char **argv) { tmpimg = image_copyF(imgf); Rect r = {.x = 0, .y = level, .w = 10, .h = 1}; image_draw_rect(tmpimg, &r, 0x0000FF00); - snprintf (fn, 3*LEN_FILENAME, "%s/%s-img-data.jpg", conf_debugout, outdate); + snprintf (fn, 3*LEN_FILENAME, "%s/%s-img-data.jpg", conf_debugout, conf_outdate); if (strlen(conf_debugout) > 0) image_save(tmpimg, fn, 98); - printf ("%s Found Level: %5.2f Y-Pos: %d\n", outdate, 100.0 * (1.0-(float)level/(float)imgf->h), level); - + printf ("%s Found Level: %5.2f Y-Pos: %d\n", conf_outdate, 100.0 * (1.0-(float)level/(float)imgf->h), level); return 0; }; int detect_level(ImageFloat *imgf) { - int y, x, ylow, level; + int y, x, level; float v = 0.0, vmin, vmax; + FILE * outfile; + float deltamin = 0, deltamax = 0; + int deltamin_y = 0, deltamax_y = 0; + + if (imgf == NULL) return -1; + + float *deltas = malloc(sizeof(float) * imgf->h); + if (deltas == NULL) { + printf ("%s:%d could not allocate memory. Error:%s\n", __FILE__, __LINE__, strerror(errno)); + return -1; + } // // calculate average, and save value in left row @@ -194,28 +208,60 @@ int detect_level(ImageFloat *imgf) { imgf->data[x + y * imgf->w] = (imgf->data[x + y * imgf->w]-vmin)/(vmax-vmin); } - // - // search for the level from below vmin = 1.0; vmax = 0.0; - int avg = 8; + int outavg_with = 8; + // generate average and delta level = 0; - for (ylow = 0; ylow < imgf->h; ylow++) { - if (ylow == 0) v = imgf->data[(ylow) * imgf->w]; - v = ((float)avg-1.0) * v/(float)avg + imgf->data[(ylow) * imgf->w]/(float) avg; - for (x = 0; x < 8; x++) imgf->data[x + (ylow) * imgf->w] = v; + float delta = 0.0; + for (y = 0; y < imgf->h; y++) { + // average + v = 0.0; + for (x = 0; x < imgf->w; x++) v += imgf->data[x + (y) * imgf->w]; + v /= (float)imgf->h; + + // output + for (x = 0; x < outavg_with; x++) imgf->data[x + (y) * imgf->w] = v; + + // delta + if (y > 0) delta = imgf->data[0 + y * imgf->w] - imgf->data[0 + (y-1) * imgf->w]; + else { + deltamin_y = 0; + deltamax_y = 0; + deltamin = delta; + deltamax = delta; + } + if (deltamin > delta) { + deltamin = delta; + deltamin_y = y; + } + if (deltamax > delta) { + deltamax = delta; + deltamax_y = y; + } + deltas[y] = delta; } - for (ylow = imgf->h - 1; ylow >= 0; ylow--) { - if (ylow == imgf->h - 1) v = imgf->data[(ylow) * imgf->w]; - v = ((float)avg-1.0) * v/(float)avg + imgf->data[(ylow) * imgf->w]/(float) avg; - for (x = 4; x < 16; x++) imgf->data[x + (ylow) * imgf->w] = v; - if (v > 0.1) { - level = ylow; - break; + + // debugging write output + if (strlen(conf_debugout) > 0) { + char fn[3*LEN_FILENAME]; + snprintf (fn, 3*LEN_FILENAME, "%s/%s-data.csv", conf_debugout, conf_outdate); + if ((outfile = fopen(fn, "wb")) == NULL) { + fprintf(stderr, "%s:%d can't open %s error:%s\n", __FILE__, __LINE__, fn, strerror(errno)); + exit(1); + } + for (y = 0; y < imgf->h; y++) { + fprintf(outfile, "%05d\t%f\t%f\n", y, imgf->data[y * imgf->w], deltas[y]); } + fclose (outfile); } + // + // search for the level from below + level = deltamin_y; + + free(deltas); return level; };