From 9021f82f9ba96c178135b2f82e276152b46ef93e Mon Sep 17 00:00:00 2001 From: MrDave Date: Thu, 26 Nov 2020 13:08:43 -0700 Subject: [PATCH] Revise parsing for secondary parameters --- src/alg_sec.cpp | 256 ++++++++++++++++++++------------------------- src/alg_sec.hpp | 9 +- src/conf.cpp | 14 +-- src/conf.hpp | 2 +- src/util.cpp | 19 +++- src/util.hpp | 2 + src/video_v4l2.cpp | 22 +--- 7 files changed, 151 insertions(+), 173 deletions(-) diff --git a/src/alg_sec.cpp b/src/alg_sec.cpp index a6a84437..ac829501 100644 --- a/src/alg_sec.cpp +++ b/src/alg_sec.cpp @@ -269,188 +269,148 @@ static void algsec_detect_haar(ctx_cam *cam, ctx_algsec_model &algmdl) static void algsec_load_haar(ctx_algsec_model &algmdl) { + int indx; + std::string model_file; /* If loading fails, reset the method to invalidate detection */ + model_file = ""; try { - if (algmdl.modelfile == "") { + for (indx = 0; indx < algmdl.algsec_params->params_count; indx++) { + } + if (model_file == "") { algmdl.method = 0; MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, _("No secondary model specified.")); return; } - if (!algmdl.haar_cascade.load(algmdl.modelfile)) { + if (!algmdl.haar_cascade.load(model_file)) { /* Loading failed, reset method*/ algmdl.method = 0; MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Failed loading model %s") - ,algmdl.modelfile.c_str()); + ,model_file.c_str()); }; } catch ( cv::Exception& e ) { const char* err_msg = e.what(); MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Error %s"),err_msg); - MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Failed loading model %s") - ,algmdl.modelfile.c_str()); + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Failed loading model %s"),model_file.c_str()); algmdl.method = 0; } } -static void algsec_parms_log(ctx_algsec_model &algmdl) +static void algsec_params_log(ctx_algsec_model &algmdl) { + int indx; - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %s","modelfile", algmdl.modelfile.c_str()); - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %0.6f","threshold_motion", algmdl.threshold_motion); - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %s","imagetype", algmdl.imagetype.c_str() ); - - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %0.6f","scalefactor", algmdl.scalefactor); - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %0.6f","threshold_model", algmdl.threshold_model); - - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %d","haar_flags", algmdl.haar_flags); - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %d","haar_maxsize", algmdl.haar_maxsize); - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %d","haar_minsize", algmdl.haar_minsize); - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %d","haar_minneighbors", algmdl.haar_minneighbors); - - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %d","hog_padding", algmdl.hog_padding); - motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %d","hog_winstride", algmdl.hog_winstride); + for (indx = 0; indx < algmdl.algsec_params->params_count; indx++) { + motion_log(INF, TYPE_ALL, NO_ERRNO,0, "%-25s %s" + ,algmdl.algsec_params->params_array[indx].param_name + ,algmdl.algsec_params->params_array[indx].param_value); + } } -static void algsec_parms_defaults(ctx_algsec_model &algmdl) +static void algsec_params_model(ctx_algsec_model &algmdl) { + /* To avoid looping through the parms for each image detection to get + * the parameters, we put them into variables easily found by the model. + * As the secondary method processing gets refined, this method will need + * to be adjusted to be something more efficient. + */ + int indx; + for (indx = 0; indx < algmdl.algsec_params->params_count; indx++) { + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"model_file")) { + algmdl.model_file = algmdl.algsec_params->params_array[indx].param_value; + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"frame_interval")) { + algmdl.frame_interval = atoi(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"imagetype")) { + algmdl.imagetype = algmdl.algsec_params->params_array[indx].param_value; + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"threshold_motion")) { + algmdl.threshold_motion = atof(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"threshold_model")) { + algmdl.threshold_model = atof(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"scalefactor")) { + algmdl.scalefactor = atof(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"rotate")) { + algmdl.rotate = atoi(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"hog_padding")) { + algmdl.hog_padding = atoi(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"hog_winstride")) { + algmdl.hog_winstride = atoi(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"haar_flags")) { + algmdl.haar_flags = atoi(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"haar_maxsize")) { + algmdl.haar_maxsize = atoi(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"haar_minsize")) { + algmdl.haar_minsize = atoi(algmdl.algsec_params->params_array[indx].param_value); + } + if (mystreq(algmdl.algsec_params->params_array[indx].param_name,"haar_minneighbors")) { + algmdl.haar_minneighbors = atoi(algmdl.algsec_params->params_array[indx].param_value); + } + } +} - algmdl.threshold_motion = 1.1; - algmdl.imagetype = "full"; +static void algsec_params_defaults(ctx_algsec_model &algmdl) +{ + util_parms_add_default(algmdl.algsec_params, "model_file", ""); - algmdl.hog_padding = 8; - algmdl.hog_winstride = 8; - - algmdl.haar_flags = 0; - algmdl.haar_maxsize = 1024; - algmdl.haar_minsize = 8; - algmdl.haar_minneighbors = 8; + util_parms_add_default(algmdl.algsec_params, "frame_interval", "5"); + util_parms_add_default(algmdl.algsec_params, "imagetype", "full"); + util_parms_add_default(algmdl.algsec_params, "threshold_motion", "1.1"); if (algmdl.method == 1) { - algmdl.scalefactor = 1.1; - algmdl.threshold_model = 1.4; + util_parms_add_default(algmdl.algsec_params, "threshold_model", "1.4"); + util_parms_add_default(algmdl.algsec_params, "scalefactor", "1.1"); } else { - algmdl.scalefactor = 1.05; - algmdl.threshold_model = 2; + util_parms_add_default(algmdl.algsec_params, "threshold_model", "2"); + util_parms_add_default(algmdl.algsec_params, "scalefactor", "1.05"); } + util_parms_add_default(algmdl.algsec_params, "rotate", "0"); + + util_parms_add_default(algmdl.algsec_params, "hog_padding", "8"); + util_parms_add_default(algmdl.algsec_params, "hog_winstride", "8"); + + util_parms_add_default(algmdl.algsec_params, "haar_flags", "0"); + util_parms_add_default(algmdl.algsec_params, "haar_maxsize", "1024"); + util_parms_add_default(algmdl.algsec_params, "haar_minsize", "8"); + util_parms_add_default(algmdl.algsec_params, "haar_minneighbors", "8"); } -/**Parse parm based upon colons*/ -static void algsec_parms_parse_microdetail(std::string &vin, ctx_algsec_model &algmdl) { - /* This is a place holder for now. It is thought that we will need some subparameters - * associated with the configuration in the future...*/ - std::size_t st_colon, en_colon; - std::string tmp; - int indx1; - - return; - if (vin == "") return; - - en_colon = -1; - for (indx1=0;indx1<10;indx1++){ - st_colon = en_colon+1; - en_colon = vin.find(':',st_colon); - tmp = vin.substr(st_colon,en_colon-st_colon); - (void)algmdl; /*tbd */ - if (en_colon == std::string::npos) return; - } - - return; -} - -/* Parse parm based upon equals*/ -static void algsec_parms_parse_detail(std::string &vin, ctx_algsec_model &algmdl) +static void algsec_params_deinit(ctx_algsec_model &algmdl) { + if (algmdl.algsec_params != NULL){ + util_parms_free(algmdl.algsec_params); - /* modelfile=/home/whatever/model.xml,threshold_motion=50*/ - - std::size_t stpos; - std::string tmpvar, tmpparm; - - if (vin == "") return; - - stpos = vin.find('='); - if (stpos != std::string::npos){ - - tmpvar = vin.substr(0, stpos); - tmpparm = vin.substr(stpos+1); - mytrim(tmpvar); - mytrim(tmpparm); - - if (tmpvar == "modelfile"){ - algmdl.modelfile = tmpparm; - } else if (tmpvar == "config"){ - algsec_parms_parse_microdetail(tmpparm, algmdl); - } else if (tmpvar == "imagetype"){ - algmdl.imagetype = tmpparm; - } else if (tmpvar == "rotate"){ - algmdl.rotate = std::atoi(tmpparm.c_str()); - } else if (tmpvar == "scalefactor"){ - algmdl.scalefactor = std::atof(tmpparm.c_str()); - } else if (tmpvar == "threshold_model"){ - algmdl.threshold_model= std::atof(tmpparm.c_str()); - } else if (tmpvar == "threshold_motion"){ - algmdl.threshold_motion= std::atof(tmpparm.c_str()); - } - - /* Hog specific parms below */ - /* These need edits on acceptable values. Is this full list?*/ - if (tmpvar == "winstride"){ - algmdl.hog_winstride = std::atoi(tmpparm.c_str()); - } else if (tmpvar == "padding"){ - algmdl.hog_padding= std::atoi(tmpparm.c_str()); - } - - /* Haar specific parms below */ - /* These need edits on acceptable values. Is this full list?*/ - if (tmpvar == "minneighbors"){ - algmdl.haar_minneighbors = std::atoi(tmpparm.c_str()); - } else if (tmpvar == "flags"){ - algmdl.haar_flags = std::atoi(tmpparm.c_str()); - } else if (tmpvar == "minsize"){ - algmdl.haar_minsize = std::atoi(tmpparm.c_str()); - } else if (tmpvar == "maxsize"){ - algmdl.haar_maxsize= std::atoi(tmpparm.c_str()); - } - + free(algmdl.algsec_params); + algmdl.algsec_params = NULL; } - - return; } -/**Parse parms based upon commas */ -static void algsec_parms_parse(ctx_cam *cam){ - - std::size_t st_comma, en_comma; - std::string tmp; - - - if (cam->algsec->models.config != "") { - st_comma = 0; - en_comma = cam->algsec->models.config.find(',', st_comma); - while (en_comma != std::string::npos){ - tmp = cam->algsec->models.config.substr(st_comma, en_comma - st_comma); - algsec_parms_parse_detail(tmp, cam->algsec->models); - st_comma = en_comma + 1; - en_comma = cam->algsec->models.config.find(',', st_comma); - } - tmp = cam->algsec->models.config.substr(st_comma); - algsec_parms_parse_detail(tmp, cam->algsec->models); - } - +static void algsec_params_init(ctx_algsec_model &algmdl) +{ + algmdl.algsec_params = (struct ctx_params*) mymalloc(sizeof(struct ctx_params)); + memset(algmdl.algsec_params, 0, sizeof(struct ctx_params)); + algmdl.algsec_params->params_array = NULL; + algmdl.algsec_params->params_count = 0; + algmdl.algsec_params->update_params = TRUE; /*Set trigger that we have updated user parameters */ } /**Load the parms from the config to algsec struct */ -static int algsec_load_parms(ctx_cam *cam){ - +static int algsec_load_params(ctx_cam *cam) +{ cam->algsec->height = cam->imgs.height; cam->algsec->width = cam->imgs.width; - - cam->algsec->frame_interval = cam->conf->secondary_interval; cam->algsec->models.method = cam->conf->secondary_method; - cam->algsec->models.config = cam->conf->secondary_config; - cam->algsec->frame_cnt = cam->algsec->frame_interval; cam->algsec->image_norm = (unsigned char*)mymalloc(cam->imgs.size_norm); cam->algsec->frame_missed = 0; cam->algsec->too_slow = 0; @@ -461,17 +421,22 @@ static int algsec_load_parms(ctx_cam *cam){ */ cam->algsec->closing = true; - algsec_parms_defaults(cam->algsec->models); + algsec_params_init(cam->algsec->models); - algsec_parms_parse(cam); + util_parms_parse(cam->algsec->models.algsec_params, cam->conf->secondary_params); - algsec_parms_log(cam->algsec->models); + algsec_params_defaults(cam->algsec->models); + + algsec_params_log(cam->algsec->models); + + algsec_params_model(cam->algsec->models); return 0; } /**If possible preload the models and initialize them */ -static int algsec_load_models(ctx_cam *cam){ +static int algsec_load_models(ctx_cam *cam) +{ if (cam->algsec->models.method != 0){ switch (cam->algsec->models.method) { @@ -568,7 +533,7 @@ void algsec_init(ctx_cam *cam){ pthread_mutex_init(&cam->algsec->mutex, NULL); - retcd = algsec_load_parms(cam); + retcd = algsec_load_params(cam); if (retcd == 0) retcd = algsec_load_models(cam); if (retcd == 0) algsec_start_handler(cam); @@ -584,6 +549,8 @@ void algsec_deinit(ctx_cam *cam){ #ifdef HAVE_OPENCV int waitcnt = 0; + algsec_params_deinit(cam->algsec->models); + if (!cam->algsec->closing) { cam->algsec->closing = true; while ((cam->algsec->closing) && (waitcnt <1000)){ @@ -595,6 +562,7 @@ void algsec_deinit(ctx_cam *cam){ free(cam->algsec->image_norm); cam->algsec->image_norm = NULL; } + if (waitcnt == 1000){ MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO ,_("Graceful shutdown of secondary detector thread failed")); @@ -626,7 +594,7 @@ void algsec_detect(ctx_cam *cam){ /*Set the bool to detect on the new image and reset interval */ cam->algsec->detecting = true; - cam->algsec->frame_cnt = cam->algsec->frame_interval; + cam->algsec->frame_cnt = cam->algsec->models.frame_interval; if (cam->algsec->frame_missed >10){ if (cam->algsec->too_slow == 0) { MOTION_LOG(WRN, TYPE_NETCAM, NO_ERRNO diff --git a/src/alg_sec.hpp b/src/alg_sec.hpp index 57134821..a288d697 100644 --- a/src/alg_sec.hpp +++ b/src/alg_sec.hpp @@ -32,10 +32,14 @@ struct ctx_algsec_model { - std::string config; //Source config line + std::string config; //Source params line + struct ctx_params *algsec_params; + + + std::string model_file; + int frame_interval; int method; - std::string modelfile; //Source model file std::string imagetype; int rotate; @@ -62,7 +66,6 @@ struct ctx_algsec { pthread_t threadid; /* thread i.d. for a secondary detection thread (if required). */ volatile bool closing; volatile bool detecting; - int frame_interval; int frame_cnt; int frame_missed; int too_slow; diff --git a/src/conf.cpp b/src/conf.cpp index 428f3a46..a282eb0f 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -265,7 +265,7 @@ struct ctx_parm config_parms[] = { "# The method to use for secondary detection.", 0,PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, { - "secondary_config", + "secondary_params", "# Full path name for the secondary model and configuration.", 0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, { @@ -1807,17 +1807,17 @@ static void conf_edit_secondary_method(struct ctx_cam *cam, std::string &parm, e MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_method",_("secondary_method")); } -static void conf_edit_secondary_config(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) +static void conf_edit_secondary_params(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { if (pact == PARM_ACT_DFLT) { - cam->conf->secondary_config = ""; + cam->conf->secondary_params = ""; } else if (pact == PARM_ACT_SET){ - cam->conf->secondary_config = parm; + cam->conf->secondary_params = parm; } else if (pact == PARM_ACT_GET){ - parm = cam->conf->secondary_config; + parm = cam->conf->secondary_params; } return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_config",_("secondary_config")); + MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_params",_("secondary_params")); } static void conf_edit_noise_level(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) @@ -3339,7 +3339,7 @@ static void conf_edit_cat02(struct ctx_cam *cam, std::string parm_nm, std::strin } else if (parm_nm == "threshold_tune"){ conf_edit_threshold_tune(cam, parm_val, pact); } else if (parm_nm == "secondary_interval"){ conf_edit_secondary_interval(cam, parm_val, pact); } else if (parm_nm == "secondary_method"){ conf_edit_secondary_method(cam, parm_val, pact); - } else if (parm_nm == "secondary_config"){ conf_edit_secondary_config(cam, parm_val, pact); + } else if (parm_nm == "secondary_params"){ conf_edit_secondary_params(cam, parm_val, pact); } else if (parm_nm == "noise_level"){ conf_edit_noise_level(cam, parm_val, pact); } else if (parm_nm == "noise_tune"){ conf_edit_noise_tune(cam, parm_val, pact); } else if (parm_nm == "despeckle_filter"){ conf_edit_despeckle_filter(cam, parm_val, pact); diff --git a/src/conf.hpp b/src/conf.hpp index 55a12f27..d96c8a65 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -81,7 +81,7 @@ int threshold_tune; int secondary_interval; int secondary_method; - std::string secondary_config; + std::string secondary_params; int noise_level; int noise_tune; std::string despeckle_filter; diff --git a/src/util.cpp b/src/util.cpp index cf10e603..0e55060d 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -820,7 +820,7 @@ int mycopy_packet(AVPacket *dest_pkt, AVPacket *src_pkt){ } /*********************************************/ -static void util_parms_free(struct ctx_params *params) +void util_parms_free(struct ctx_params *params) { int indx_parm; @@ -1118,3 +1118,20 @@ int util_parms_parse(struct ctx_params *params, std::string confline) return 0; } + +void util_parms_add_default(ctx_params *params, std::string parm_nm, std::string parm_vl) +{ + + int indx, dflt; + + dflt = TRUE; + for (indx = 0; indx < params->params_count; indx++) { + if ( mystreq(params->params_array[indx].param_name, parm_nm.c_str()) ) { + dflt = FALSE; + } + } + if (dflt == TRUE) { + util_parms_add(params, parm_nm.c_str(), parm_vl.c_str()); + } + +} diff --git a/src/util.hpp b/src/util.hpp index 8c2cf6a9..b2f73005 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -116,5 +116,7 @@ int mycopy_packet(AVPacket *dest_pkt, AVPacket *src_pkt); int util_parms_parse(struct ctx_params *params, std::string confline); + void util_parms_add_default(ctx_params *params, std::string parm_nm, std::string parm_vl); + void util_parms_free(struct ctx_params *params); #endif diff --git a/src/video_v4l2.cpp b/src/video_v4l2.cpp index cd5f0eca..11b8ca5e 100644 --- a/src/video_v4l2.cpp +++ b/src/video_v4l2.cpp @@ -130,33 +130,21 @@ static int xioctl(src_v4l2_t *vid_source, unsigned long request, void *arg) return ret; } -static void v4l2_vdev_free(struct ctx_cam *cam) +static void v4l2_vdev_deinit(struct ctx_cam *cam) { - int indx; - /* free the information we collected regarding the controls */ if (cam->vdev != NULL){ - if (cam->vdev->params_count > 0){ - for (indx=0;indxvdev->params_count;indx++){ - free(cam->vdev->params_array[indx].param_name); - cam->vdev->params_array[indx].param_name=NULL; - } - } - cam->vdev->params_count = 0; - if (cam->vdev->params_array != NULL){ - free(cam->vdev->params_array); - cam->vdev->params_array = NULL; - } + util_parms_free(cam->vdev); free(cam->vdev); cam->vdev = NULL; } + } static int v4l2_vdev_init(struct ctx_cam *cam) { - /* Create the v4l2 ctx_cam within the main thread ctx_cam */ cam->vdev =(struct ctx_params*) mymalloc(sizeof(struct ctx_params)); memset(cam->vdev, 0, sizeof(struct ctx_params)); cam->vdev->params_array = NULL; @@ -1319,7 +1307,7 @@ int v4l2_start(struct ctx_cam *cam) } pthread_mutexattr_destroy(&curdev->attr); pthread_mutex_destroy(&curdev->mutex); - v4l2_vdev_free(cam); + v4l2_vdev_deinit(cam); if (curdev->fd_device != -1) close(curdev->fd_device); free(curdev); pthread_mutex_unlock(&v4l2_mutex); @@ -1361,7 +1349,7 @@ void v4l2_cleanup(struct ctx_cam *cam) /* Set it as closed in thread ctx_cam. */ cam->video_dev = -1; - v4l2_vdev_free(cam); + v4l2_vdev_deinit(cam); if (dev == NULL) { MOTION_LOG(CRT, TYPE_VIDEO, NO_ERRNO, _("Unable to find video device"));