diff --git a/configure.ac b/configure.ac index 6e1c0d83..cb994b14 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,7 @@ AC_CANONICAL_HOST AC_CONFIG_MACRO_DIR([m4]) AM_GNU_GETTEXT([external]) -AM_GNU_GETTEXT_VERSION([0.18]) +AM_GNU_GETTEXT_VERSION([0.19]) ############################################################################## ### Check additional system headers diff --git a/src/alg_sec.cpp b/src/alg_sec.cpp index 30a174c9..d1b11ce9 100644 --- a/src/alg_sec.cpp +++ b/src/alg_sec.cpp @@ -29,24 +29,47 @@ using namespace cv; +static void myltrim(std::string &vstr){ + vstr.erase( + vstr.begin() + , std::find_if( vstr.begin() , vstr.end() , [](int ch) + { return !std::isspace(ch);} + ) + ); +} +static void myrtrim(std::string &vstr){ + vstr.erase( + std::find_if(vstr.rbegin(), vstr.rend(), [](int ch) + {return !std::isspace(ch);} + ).base() + , vstr.end() + ); +} +static void mytrim(std::string &vstr){ + myltrim(vstr); + myrtrim(vstr); +} + static void algsec_img_show(ctx_cam *cam, Mat &mat_src , std::vector &src_pos, std::vector &src_weights - , std::string algmethod, float min_weight ){ + , std::string algmethod, ctx_algsec_model &algmdl){ std::vector fltr_pos; std::vector fltr_weights; std::string testdir; std::size_t indx0, indx1; - std::vector buff;//buffer for coding + std::vector buff; //buffer for coding std::vector param(2); - bool isdetected; char wstr[10]; + float min_weight; + + min_weight = algmdl.threshold_motion/100; testdir = cam->conf->target_dir; imwrite(testdir + "/src_" + algmethod + ".jpg", mat_src); - isdetected = false; + algmdl.isdetected = false; for (indx0=0; indx0 min_weight)){ fltr_pos.push_back(r); fltr_weights.push_back(w); - isdetected = true; + algmdl.isdetected = true; } } - if (isdetected){ + if (algmdl.isdetected){ for (indx0=0; indx0algsec->mutex); - std::copy(buff.begin(), buff.end(), cam->imgs.image_secondary); - cam->imgs.size_secondary = (int)buff.size(); - pthread_mutex_unlock(&cam->algsec->mutex); - + /* We check the size so that we at least fill in the first image so the + * web stream will have something to start with. After feeding in at least + * the first image, we rely upon the connection count to tell us whether we + * need to expend the CPU to compress and load the secondary images */ + if ((cam->stream.secondary.cnct_count >0) || + (cam->imgs.size_secondary == 0)){ + param[0] = cv::IMWRITE_JPEG_QUALITY; + param[1] = 75; + cv::imencode(".jpg", mat_src, buff, param); + pthread_mutex_lock(&cam->algsec->mutex); + std::copy(buff.begin(), buff.end(), cam->imgs.image_secondary); + cam->imgs.size_secondary = (int)buff.size(); + pthread_mutex_unlock(&cam->algsec->mutex); + } } static void algsec_img_roi(ctx_cam *cam, Mat &mat_src, Mat &mat_dst){ @@ -127,13 +156,6 @@ static void algsec_img_roi(ctx_cam *cam, Mat &mat_src, Mat &mat_dst){ } -static void algsec_detect_yolo(ctx_cam *cam, ctx_algsec_model &algmdl){ - - (void)cam; - (void)algmdl; - -} - static void algsec_detect_hog(ctx_cam *cam, ctx_algsec_model &algmdl){ std::vector detect_weights; @@ -142,13 +164,13 @@ static void algsec_detect_hog(ctx_cam *cam, ctx_algsec_model &algmdl){ Mat mat_dst; try { - if (algmdl.parms[0][0] == "color"){ + if (algmdl.imagetype == "color"){ /* AFAIK, the detector uses grey so users shouldn't really use this*/ Mat mat_src = Mat(cam->imgs.height*3/2, cam->imgs.width , CV_8UC1, (void*)cam->algsec->image_norm); cvtColor(mat_src, mat_dst, COLOR_YUV2RGB_YV12); - } else if (algmdl.parms[0][0] == "full"){ + } else if (algmdl.imagetype == "full"){ mat_dst = Mat(cam->imgs.height, cam->imgs.width , CV_8UC1, (void*)cam->algsec->image_norm); @@ -170,24 +192,15 @@ static void algsec_detect_hog(ctx_cam *cam, ctx_algsec_model &algmdl){ hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector()); hog.detectMultiScale(mat_dst, detect_pos, detect_weights, 0 - ,Size(algmdl.parms_int[0][2], algmdl.parms_int[0][2]) - ,Size(algmdl.parms_int[0][3], algmdl.parms_int[0][3]) - ,algmdl.parms_float[0][4] - ,algmdl.parms_int[0][5] + ,Size(algmdl.hog_winstride, algmdl.hog_winstride) + ,Size(algmdl.hog_padding, algmdl.hog_padding) + ,algmdl.scalefactor + ,algmdl.threshold_model ,false); - MOTION_LOG(INF, TYPE_ALL, NO_ERRNO - , _("Parms: winstride %d,%d padding %d,%d scale %.2f theshold %d") - ,algmdl.parms_int[0][2], algmdl.parms_int[0][2] - ,algmdl.parms_int[0][3], algmdl.parms_int[0][3] - ,algmdl.parms_float[0][4] - ,algmdl.parms_int[0][5]); + algsec_img_show(cam, mat_dst, detect_pos, detect_weights, "hog",algmdl); - algsec_img_show(cam, mat_dst, detect_pos, detect_weights, "hog" - ,algmdl.parms_float[0][1]); - - } - catch ( cv::Exception& e ) { + } 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, _("Disabling secondary detection")); @@ -208,11 +221,14 @@ static void algsec_detect_haar(ctx_cam *cam, ctx_algsec_model &algmdl){ equalizeHist(mat_src, mat_src); algmdl.haar_cascade.detectMultiScale( - mat_src, detect_pos, levels, detect_weights, 1.1, 1, 0, Size(), Size(), true); + mat_src, detect_pos, levels, detect_weights + ,algmdl.scalefactor, algmdl.haar_minneighbors,algmdl.haar_flags + , Size(algmdl.haar_minsize,algmdl.haar_minsize) + , Size(algmdl.haar_maxsize,algmdl.haar_maxsize), true); - algsec_img_show(cam, mat_src, detect_pos, detect_weights, "haar", 0.6); - } - catch ( cv::Exception& e ) { + algsec_img_show(cam, mat_src, detect_pos, detect_weights, "haar", algmdl); + + } 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, _("Disabling secondary detection")); @@ -220,72 +236,52 @@ static void algsec_detect_haar(ctx_cam *cam, ctx_algsec_model &algmdl){ } } -static void algsec_load_yolo(ctx_algsec_model &algmdl){ - /* Placeholder for implementation of yolo classifier */ - algmdl.method = 0; - -} - -static void algsec_load_haar(ctx_algsec_model &algsec){ +static void algsec_load_haar(ctx_algsec_model &algmdl){ /* If loading fails, reset the method to invalidate detection */ try { - if (!algsec.haar_cascade.load(algsec.modelfile)){ + if (!algmdl.haar_cascade.load(algmdl.modelfile)){ /* Loading failed, reset method*/ - algsec.method = 0; + algmdl.method = 0; MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, _("Failed loading model %s") - ,algsec.modelfile.c_str()); + ,algmdl.modelfile.c_str()); }; - } - catch ( cv::Exception& e ) { + } 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") - ,algsec.modelfile.c_str()); - algsec.method = 0; + ,algmdl.modelfile.c_str()); + algmdl.method = 0; } } -static void algsec_parms_hog(ctx_algsec_model &model){ - /* These conversions put the applicable parms into int or float variables - * This is done once here upon parsing the parms so that we do not have to - * do the conversion upon every single image being processed and we can directly - * reference the converted parameter - */ - int indx0, indx1; - - for (indx0=0;indx0<3;indx0++){ - for (indx1=0;indx1<10;indx1++){ - model.parms_int[indx0][indx1] = 0; - model.parms_float[indx0][indx1] = 0; - if (model.parms[indx0][indx1] != ""){ - model.parms_int[indx0][indx1] = std::atoi(model.parms[indx0][indx1].c_str()); - model.parms_float[indx0][indx1] = std::atof(model.parms[indx0][indx1].c_str()); - } - } - /*parm[0] is color/full/area */ - if (model.parms_float[indx0][1] <= 0) model.parms_int[indx0][1] = 0.6; /*Min weigtht */ - if (model.parms_int[indx0][2] <= 0) model.parms_int[indx0][2] = 8; /* */ - if (model.parms_int[indx0][3] <= 0) model.parms_int[indx0][3] = 32; /* */ - if (model.parms_float[indx0][4] <= 0.01) model.parms_float[indx0][4] = 1.05; /* */ - if (model.parms_int[indx0][5] <= 0) model.parms_int[indx0][5] = 2; /* */ - - } +static void algsec_parms_default_hog(ctx_algsec_model &algmdl){ + algmdl.hog_padding = 8; + algmdl.scalefactor = 1.05; + algmdl.threshold_model = 1.4; + algmdl.hog_winstride = 8; + algmdl.threshold_motion = 50; +} +static void algsec_parms_default_haar(ctx_algsec_model &algmdl){ + algmdl.scalefactor = 1.1; + algmdl.threshold_model = 2; + algmdl.haar_flags = 0; + algmdl.haar_maxsize = 8; + algmdl.haar_minsize = 8; + algmdl.haar_minneighbors = 8; + algmdl.threshold_motion = 50; } /**Parse parm based upon colons*/ -static void algsec_parms_parse_detail( - std::string &vin, ctx_algsec_model &model,int indx0) { - +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; - for (indx1=0;indx1<10;indx1++){ - if (model.parms[indx0][indx1] != "") model.parms[indx0][indx1].clear(); - } - + return; if (vin == "") return; en_colon = -1; @@ -293,58 +289,116 @@ static void algsec_parms_parse_detail( st_colon = en_colon+1; en_colon = vin.find(':',st_colon); tmp = vin.substr(st_colon,en_colon-st_colon); - model.parms[indx0][indx1] = tmp; + //algmdl???? = tmp; if (en_colon == std::string::npos) return; } return; } +/* modelfile=/home/whatever/model.xml,threshold_motion=50 + +/**Parse parm based upon equals*/ +static void algsec_parms_parse_detail(std::string &vin, ctx_algsec_model &algmdl){ + + std::size_t stpos; + std::string tmpvar, tmpparm; + int indx1; + + if (vin == "") return; + + stpos = vin.find('='); + if (stpos != std::string::npos){ + + tmpvar = vin.substr(0, stpos-1); + 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 == "scale"){ + algmdl.scalefactor = std::atof(tmpparm.c_str()); + } else if (tmpvar == "threshold_model"){ + algmdl.threshold_model= std::atoi(tmpparm.c_str()); + } else if (tmpvar == "threshold_motion"){ + algmdl.threshold_motion= std::atoi(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()); + } + + } + + return; +} + /**Parse parms based upon commas */ static void algsec_parms_parse(ctx_cam *cam){ - /* Parse out the comma separated parms - * exampe source config line: human:75:25,car:60:30,dog:90:70 - */ - int indx1, indx2; + std::size_t st_comma, en_comma; std::string tmp; - for (indx1=0;indx1<3;indx1++){ - if (cam->algsec->models[indx1].config != ""){ - indx2=0; - st_comma = 0; - en_comma = cam->algsec->models[indx1].config.find(',', st_comma); - while ((en_comma != std::string::npos) && (indx2 < 2)){ - tmp = cam->algsec->models[indx1].config.substr(st_comma, en_comma - st_comma); - algsec_parms_parse_detail(tmp, cam->algsec->models[indx1],indx2); - st_comma = en_comma + 1; - en_comma = cam->algsec->models[indx1].config.find(',', st_comma); - indx2++; - } - tmp = cam->algsec->models[indx1].config.substr( - st_comma, cam->algsec->models[indx1].config.length()); - algsec_parms_parse_detail(tmp, cam->algsec->models[indx1], indx2); - } - switch (cam->algsec->models[indx1].method) { - case 1: //Haar Method - break; - case 2: //HoG Method - algsec_parms_hog(cam->algsec->models[indx1]); - break; - case 3: //YoLo Method - break; - } + cam->algsec->models.method = cam->conf->secondary_method; + cam->algsec->models.config = cam->conf->secondary_config; + + switch (cam->algsec->models.method) { + case 1: //Haar Method + algsec_parms_default_haar(cam->algsec->models); + break; + case 2: //HoG Method + algsec_parms_default_hog(cam->algsec->models); + break; + default: + cam->algsec->models.method = 0; + break; } + + 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); + } + } /**Load the parms from the config to algsec struct */ -static void algsec_load_parms(ctx_cam *cam){ +static int algsec_load_parms(ctx_cam *cam){ - /* Copy the model file names and config into the ctx_cam - * For "simplicity", these are all fixed size arrays for - * both the models and parms. If there is a need later - * they can be changed to vectors - */ + if (cam->conf->secondary_method == 0){ + cam->algsec->models.method = 0; + return -1; + } cam->algsec->height = cam->imgs.height; cam->algsec->width = cam->imgs.width; @@ -361,44 +415,9 @@ static void algsec_load_parms(ctx_cam *cam){ */ cam->algsec->closing = true; - if (cam->conf->secondary_method != 0) { - cam->algsec->models[0].method = cam->conf->secondary_method; - if (cam->conf->secondary_model != NULL){ - cam->algsec->models[0].modelfile = cam->conf->secondary_model; - } - if (cam->conf->secondary_config != NULL) { - cam->algsec->models[0].config = cam->conf->secondary_config; - } - } else { - cam->algsec->models[0].method = 0; - } - - if (cam->conf->secondary_method2 != 0) { - cam->algsec->models[1].method = cam->conf->secondary_method2; - if (cam->conf->secondary_model2 != NULL){ - cam->algsec->models[1].modelfile = cam->conf->secondary_model2; - } - if (cam->conf->secondary_config2 != NULL) { - cam->algsec->models[1].config = cam->conf->secondary_config2; - } - } else { - cam->algsec->models[1].method = 0; - } - - if (cam->conf->secondary_method3 != 0) { - cam->algsec->models[2].method = cam->conf->secondary_method3; - if (cam->conf->secondary_model3 != NULL) { - cam->algsec->models[2].modelfile = cam->conf->secondary_model3; - } - if (cam->conf->secondary_config3 != NULL) { - cam->algsec->models[2].config = cam->conf->secondary_config3; - } - } else { - cam->algsec->models[2].method = 0; - } - algsec_parms_parse(cam); + return 0; } /**If possible preload the models and initialize them */ @@ -406,25 +425,21 @@ static int algsec_load_models(ctx_cam *cam){ int indx; - for (indx=0;indx<3;indx++){ - if (cam->algsec->models[indx].method != 0){ - switch (cam->algsec->models[indx].method) { - case 1: //Haar Method - algsec_load_haar(cam->algsec->models[indx]); - break; - case 2: //HoG Method - break; - case 3: //YoLo Method - algsec_load_yolo(cam->algsec->models[indx]); - break; - default: - cam->algsec->models[indx].method = 0; - } + if (cam->algsec->models.method != 0){ + switch (cam->algsec->models.method) { + case 1: //Haar Method + algsec_load_haar(cam->algsec->models); + break; + case 2: //HoG Method + //algsec_load_hog(cam->algsec->models); + break; + default: + cam->algsec->models.method = 0; } } /* If model fails to load, it sets method to zero*/ - if (cam->algsec->models[0].method != 0){ + if (cam->algsec->models.method != 0){ cam->algsec_inuse = TRUE; return 0; } else { @@ -448,20 +463,17 @@ static void *algsec_handler(void *arg) { while (!cam->algsec->closing){ if (cam->algsec->detecting){ - for (indx=0;indx<3;indx++){ - switch (cam->algsec->models[indx].method) { - case 1: //Haar Method - algsec_detect_haar(cam, cam->algsec->models[indx]); - break; - case 2: //HoG Method - algsec_detect_hog(cam, cam->algsec->models[indx]); - break; - case 3: //YoLo Method - algsec_detect_yolo(cam, cam->algsec->models[indx]); - break; - } + switch (cam->algsec->models.method) { + case 1: //Haar Method + algsec_detect_haar(cam, cam->algsec->models); + break; + case 2: //HoG Method + algsec_detect_hog(cam, cam->algsec->models); + break; } cam->algsec->detecting = false; + /*Set the event based isdetected bool */ + if (cam->algsec->models.isdetected) cam->algsec->isdetected = true; } else { SLEEP(0,interval) } @@ -485,9 +497,7 @@ static void algsec_start_handler(ctx_cam *cam){ if (retcd < 0) { MOTION_LOG(ALR, TYPE_NETCAM, SHOW_ERRNO ,_("Error starting algsec handler thread")); - for (indx=0;indx<3;indx++){ - cam->algsec->models[indx].method = 0; - } + cam->algsec->models.method = 0; } pthread_attr_destroy(&handler_attribute); return; @@ -511,10 +521,8 @@ void algsec_init(ctx_cam *cam){ pthread_mutex_init(&cam->algsec->mutex, NULL); - algsec_load_parms(cam); - - retcd = algsec_load_models(cam); - + retcd = algsec_load_parms(cam); + if (retcd == 0) retcd = algsec_load_models(cam); if (retcd == 0) algsec_start_handler(cam); mythreadname_set("ml",cam->threadnr,cam->conf->camera_name.c_str()); diff --git a/src/alg_sec.hpp b/src/alg_sec.hpp index 6053c419..154ce3a3 100644 --- a/src/alg_sec.hpp +++ b/src/alg_sec.hpp @@ -24,12 +24,26 @@ //example source config line: human:75:25,car:60:30:4:15:A:1.012:3,dog:90:70 struct ctx_algsec_model { + std::string config; //Source config line + int method; std::string modelfile; //Source model file - std::string config; //Source config line - std::string parms[3][10]; //Parms as strings - int parms_int[3][10]; //Parms convert to int - float parms_float[3][10]; //Parms converted to float + std::string imagetype; + int rotate; + + float scalefactor; + float threshold_model; /* Threshold fed into the opencv model*/ + int threshold_motion; /* Threshold for motion to use on detection*/ + + int hog_winstride; + int hog_padding; + + + int haar_minneighbors; + int haar_flags; + int haar_minsize; + int haar_maxsize; + bool isdetected; /* Bool reset for each image as to whether a detection occurred */ #ifdef HAVE_OPENCV cv::CascadeClassifier haar_cascade; //Haar Cascade (if applicable) #endif @@ -46,8 +60,9 @@ struct ctx_algsec { unsigned char *image_norm; int width; int height; + bool isdetected; /* Bool reset for each Motion event as to whether a detection occurred */ pthread_mutex_t mutex; - struct ctx_algsec_model models[3]; + struct ctx_algsec_model models; }; diff --git a/src/conf.cpp b/src/conf.cpp index bdb05748..e99d538d 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -234,36 +234,8 @@ struct ctx_parm config_parms[] = { "# The method to use for secondary detection.", 0,PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, { - "secondary_model", - "# Full path name for the secondary model.", - 0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, - { "secondary_config", - "# Configuration parameters for the secondary model.", - 0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, - { - "secondary_method2", - "# The method to use for secondary detection 2.", - 0,PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, - { - "secondary_model2", - "# Full path name for the secondary model 2.", - 0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, - { - "secondary_config2", - "# Configuration parameters for the secondary model 2.", - 0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, - { - "secondary_method3", - "# The method to use for secondary detection 3.", - 0,PARM_TYP_INT, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, - { - "secondary_model3", - "# Full path name for the secondary model 3.", - 0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, - { - "secondary_config3", - "# Configuration parameters for the secondary model 3.", + "# Full path name for the secondary model and configuration.", 0,PARM_TYP_STRING, PARM_CAT_02, WEBUI_LEVEL_LIMITED }, { "noise_level", @@ -358,6 +330,10 @@ struct ctx_parm config_parms[] = { "# Command to be executed when a camera that was lost has been found.", 0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED}, { + "on_secondary_detect", + "# Command to be executed when the secondary detection has triggered.", + 0, PARM_TYP_STRING, PARM_CAT_03, WEBUI_LEVEL_RESTRICTED}, + { "picture_output", "############################################################\n" "# Picture output configuration parameters\n" diff --git a/src/conf.hpp b/src/conf.hpp index 14e622b7..f6438092 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -72,14 +72,7 @@ int threshold_tune; int secondary_interval; int secondary_method; - std::string secondary_model; std::string secondary_config; - int secondary_method2; - std::string secondary_model2; - std::string secondary_config2; - int secondary_method3; - std::string secondary_model3; - std::string secondary_config3; int noise_level; int noise_tune; std::string despeckle_filter; @@ -104,6 +97,7 @@ std::string on_movie_end; std::string on_camera_lost; std::string on_camera_found; + std::string on_secondary_detect; /* Picture output configuration parameters */ std::string picture_output; diff --git a/src/conf_edit.cpp b/src/conf_edit.cpp index 64ac35ba..f82d6b9f 100644 --- a/src/conf_edit.cpp +++ b/src/conf_edit.cpp @@ -792,17 +792,6 @@ static void conf_edit_secondary_method(struct ctx_cam *cam, std::string &parm, e return; MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_method",_("secondary_method")); } -static void conf_edit_secondary_model(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { - if (pact == PARM_ACT_DFLT) { - cam->conf->secondary_model = ""; - } else if (pact == PARM_ACT_SET){ - cam->conf->secondary_model = parm; - } else if (pact == PARM_ACT_GET){ - parm = cam->conf->secondary_model; - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_model",_("secondary_model")); -} static void conf_edit_secondary_config(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { if (pact == PARM_ACT_DFLT) { cam->conf->secondary_config = ""; @@ -814,84 +803,6 @@ static void conf_edit_secondary_config(struct ctx_cam *cam, std::string &parm, e return; MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_config",_("secondary_config")); } -static void conf_edit_secondary_method2(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { - int parm_in; - if (pact == PARM_ACT_DFLT){ - cam->conf->secondary_method2 = 0; - } else if (pact == PARM_ACT_SET){ - parm_in = atoi(parm.c_str()); - if ((parm_in < 0) ) { - MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Invalid secondary_method2 %d"),parm_in); - } else { - cam->conf->secondary_method2 = parm_in; - } - } else if (pact == PARM_ACT_GET){ - parm = std::to_string(cam->conf->secondary_method2); - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_method2",_("secondary_method2")); -} -static void conf_edit_secondary_model2(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { - if (pact == PARM_ACT_DFLT) { - cam->conf->secondary_model2 = ""; - } else if (pact == PARM_ACT_SET){ - cam->conf->secondary_model2 = parm; - } else if (pact == PARM_ACT_GET){ - parm = cam->conf->secondary_model2; - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_model2",_("secondary_model2")); -} -static void conf_edit_secondary_config2(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { - if (pact == PARM_ACT_DFLT) { - cam->conf->secondary_config2 = ""; - } else if (pact == PARM_ACT_SET){ - cam->conf->secondary_config2 = parm; - } else if (pact == PARM_ACT_GET){ - parm = cam->conf->secondary_config2; - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_config2",_("secondary_config2")); -} -static void conf_edit_secondary_method3(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { - int parm_in; - if (pact == PARM_ACT_DFLT){ - cam->conf->secondary_method3 = 0; - } else if (pact == PARM_ACT_SET){ - parm_in = atoi(parm.c_str()); - if ((parm_in < 0) ) { - MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Invalid secondary_method3 %d"),parm_in); - } else { - cam->conf->secondary_method3 = parm_in; - } - } else if (pact == PARM_ACT_GET){ - parm = std::to_string(cam->conf->secondary_method3); - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_method3",_("secondary_method3")); -} -static void conf_edit_secondary_model3(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { - if (pact == PARM_ACT_DFLT) { - cam->conf->secondary_model3 = ""; - } else if (pact == PARM_ACT_SET){ - cam->conf->secondary_model3 = parm; - } else if (pact == PARM_ACT_GET){ - parm = cam->conf->secondary_model3; - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_model3",_("secondary_model3")); -} -static void conf_edit_secondary_config3(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { - if (pact == PARM_ACT_DFLT) { - cam->conf->secondary_config3 = ""; - } else if (pact == PARM_ACT_SET){ - cam->conf->secondary_config3 = parm; - } else if (pact == PARM_ACT_GET){ - parm = cam->conf->secondary_config3; - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","secondary_config3",_("secondary_config3")); -} static void conf_edit_noise_level(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { int parm_in; if (pact == PARM_ACT_DFLT){ @@ -1183,6 +1094,17 @@ static void conf_edit_on_camera_found(struct ctx_cam *cam, std::string &parm, en return; MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","on_camera_found",_("on_camera_found")); } +static void conf_edit_on_secondary_detect(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { + if (pact == PARM_ACT_DFLT) { + cam->conf->on_secondary_detect = ""; + } else if (pact == PARM_ACT_SET){ + cam->conf->on_secondary_detect = parm; + } else if (pact == PARM_ACT_GET){ + parm = cam->conf->on_secondary_detect; + } + return; + MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","on_secondary_detect",_("on_secondary_detect")); +} static void conf_edit_picture_output(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { if (pact == PARM_ACT_DFLT) { @@ -2207,14 +2129,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_model"){ conf_edit_secondary_model(cam, parm_val, pact); } else if (parm_nm == "secondary_config"){ conf_edit_secondary_config(cam, parm_val, pact); - } else if (parm_nm == "secondary_method2"){ conf_edit_secondary_method2(cam, parm_val, pact); - } else if (parm_nm == "secondary_model2"){ conf_edit_secondary_model2(cam, parm_val, pact); - } else if (parm_nm == "secondary_config2"){ conf_edit_secondary_config2(cam, parm_val, pact); - } else if (parm_nm == "secondary_method3"){ conf_edit_secondary_method3(cam, parm_val, pact); - } else if (parm_nm == "secondary_model3"){ conf_edit_secondary_model3(cam, parm_val, pact); - } else if (parm_nm == "secondary_config3"){ conf_edit_secondary_config3(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); @@ -2242,6 +2157,7 @@ static void conf_edit_cat03(struct ctx_cam *cam, std::string parm_nm, std::strin } else if (parm_nm == "on_movie_end"){ conf_edit_on_movie_end(cam, parm_val, pact); } else if (parm_nm == "on_camera_lost"){ conf_edit_on_camera_lost(cam, parm_val, pact); } else if (parm_nm == "on_camera_found"){ conf_edit_on_camera_found(cam, parm_val, pact); + } else if (parm_nm == "on_secondary_detect"){ conf_edit_on_secondary_detect(cam, parm_val, pact); } else if (parm_nm == "picture_output"){ conf_edit_picture_output(cam, parm_val, pact); } else if (parm_nm == "picture_output_motion"){ conf_edit_picture_output_motion(cam, parm_val, pact); } else if (parm_nm == "picture_type"){ conf_edit_picture_type(cam, parm_val, pact); diff --git a/src/event.cpp b/src/event.cpp index 1e2633e0..f63860a0 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -468,6 +468,20 @@ static void event_camera_lost(struct ctx_cam *cam, motion_event evnt exec_command(cam, cam->conf->on_camera_lost.c_str(), NULL, 0); } +static void event_secondary_detect(struct ctx_cam *cam, motion_event evnt + ,struct ctx_image_data *img_data, char *fname + ,void *ftype, struct timespec *ts1) { + + (void)evnt; + (void)img_data; + (void)fname; + (void)ftype; + (void)ts1; + + if (cam->conf->on_secondary_detect != "") + exec_command(cam, cam->conf->on_secondary_detect.c_str(), NULL, 0); +} + static void event_camera_found(struct ctx_cam *cam, motion_event evnt ,struct ctx_image_data *img_data, char *fname ,void *ftype, struct timespec *ts1) { @@ -895,6 +909,10 @@ struct event_handlers event_handlers[] = { EVENT_CAMERA_FOUND, event_camera_found }, + { + EVENT_SECDETECT, + event_secondary_detect + }, {(motion_event)0, NULL} }; diff --git a/src/event.hpp b/src/event.hpp index 81a3d64f..9cea6164 100644 --- a/src/event.hpp +++ b/src/event.hpp @@ -32,6 +32,7 @@ typedef enum { EVENT_CAMERA_LOST, EVENT_CAMERA_FOUND, EVENT_MOVIE_PUT, + EVENT_SECDETECT, EVENT_LAST, } motion_event; diff --git a/src/mmalcam.cpp b/src/mmalcam.cpp index fc50afdc..818dcaac 100644 --- a/src/mmalcam.cpp +++ b/src/mmalcam.cpp @@ -302,8 +302,8 @@ int mmalcam_start(struct ctx_cam *cam) { mmalcam->height = cam->conf->height; mmalcam->framerate = cam->conf->framerate; - if (cam->conf->mmalcam_control_params) { - parse_camera_control_params(cam->conf->mmalcam_control_params, mmalcam->camera_parameters); + if (cam->conf->mmalcam_control_params != "") { + parse_camera_control_params(cam->conf->mmalcam_control_params.c_str(), mmalcam->camera_parameters); } cam->imgs.width = mmalcam->width; diff --git a/src/motion_loop.cpp b/src/motion_loop.cpp index 7af8caa2..9d056a92 100644 --- a/src/motion_loop.cpp +++ b/src/motion_loop.cpp @@ -1095,6 +1095,13 @@ static void mlp_actions_event(struct ctx_cam *cam){ cam->frame_skip = track_center(cam, cam->video_dev, 0, 0, 0); } + if (cam->algsec_inuse){ + if (cam->algsec->isdetected){ + event(cam, EVENT_SECDETECT, NULL, NULL, NULL, &cam->current_image->imgts); + } + cam->algsec->isdetected = false; + } + MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, _("End of event %d"), cam->event_nr); cam->event_stop = FALSE;