diff --git a/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp b/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp index 2324fd3cf..d677b40e8 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp @@ -56,8 +56,9 @@ ClassFlowAlignment::ClassFlowAlignment(std::vector *lfc) bool ClassFlowAlignment::ReadParameter(FILE *pfile, string &aktparamgraph) { std::vector splitted; - int suchex = 40; - int suchey = 40; + int suchex = 20; + int suchey = 20; + int maxangle = 45; int alg_algo = 0; // default=0; 1 =HIGHACCURACY; 2= FAST; 3= OFF //add disable aligment algo |01.2023 aktparamgraph = trim(aktparamgraph); @@ -97,6 +98,11 @@ bool ClassFlowAlignment::ReadParameter(FILE *pfile, string &aktparamgraph) suchey = std::stod(splitted[1]); } } + else if ((toUpper(splitted[0]) == "SEARCHMAXANGLE") && (splitted.size() > 1)) { + if (isStringNumeric(splitted[1])) { + maxangle = std::stod(splitted[1]); + } + } else if ((toUpper(splitted[0]) == "ANTIALIASING") && (splitted.size() > 1)) { use_antialiasing = alphanumericToBoolean(splitted[1]); } @@ -141,6 +147,7 @@ bool ClassFlowAlignment::ReadParameter(FILE *pfile, string &aktparamgraph) for (int i = 0; i < anz_ref; ++i) { References[i].search_x = suchex; References[i].search_y = suchey; + References[i].search_max_angle = maxangle; References[i].fastalg_SAD_criteria = SAD_criteria; References[i].alignment_algo = alg_algo; #ifdef DEBUG_DETAIL_ON @@ -169,6 +176,14 @@ string ClassFlowAlignment::getHTMLSingleStep(string host) bool ClassFlowAlignment::doFlow(string time) { + // no align algo if set to 3 = off + if (References[0].alignment_algo == 3) { + flowctrl.alignmentOk = true; + } + else { + flowctrl.alignmentOk = false; + } + #ifdef ALGROI_LOAD_FROM_MEM_AS_JPG // AlgROI needs to be allocated before ImageTMP to avoid heap fragmentation if (!AlgROI) { @@ -231,8 +246,16 @@ bool ClassFlowAlignment::doFlow(string time) // no align algo if set to 3 = off //add disable aligment algo |01.2023 if (References[0].alignment_algo != 3) { - if (!AlignAndCutImage->Align(&References[0], &References[1])) { + int AlignRetval = AlignAndCutImage->Align(&References[0], &References[1]); + if (AlignRetval >= 0) { SaveReferenceAlignmentValues(); + flowctrl.alignmentOk = true; + } + else if (AlignRetval == -1) { + // Alignment failed + flowctrl.alignmentOk = false; + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate Align -> Exec this round aborted!"); + LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow"); } } // no align diff --git a/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp b/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp index 146063f3d..2cdd4236a 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp @@ -78,7 +78,7 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution if ((CNNType == DoubleHyprid10) || (CNNType == Digit100)) { float number = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float; // NaN? - if (number >= 0) { + if ((number >= 0) && (number < 10)) { // is only set if it is the first digit (no analogue before!) if (_extendedResolution) { int result_after_decimal_point = ((int) floor(number * 10)) % 10; @@ -107,7 +107,7 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution } for (int i = GENERAL[_analog]->ROI.size() - 2; i >= 0; --i) { - if (GENERAL[_analog]->ROI[i]->result_float >= 0) { + if ((GENERAL[_analog]->ROI[i]->result_float >= 0) && (GENERAL[_analog]->ROI[i]->result_float < 10)) { prev = PointerEvalHybridNew(GENERAL[_analog]->ROI[i]->result_float, GENERAL[_analog]->ROI[i+1]->result_float, prev); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout#PointerEvalHybridNew()= " + std::to_string(prev)); result = std::to_string(prev) + result; diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.h b/code/components/jomjol_flowcontroll/ClassFlowControll.h index 40b5ba112..e3f7cb4d1 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.h +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.h @@ -22,8 +22,7 @@ #endif //ENABLE_WEBHOOK #include "ClassFlowCNNGeneral.h" -class ClassFlowControll : - public ClassFlow +class ClassFlowControll : public ClassFlow { protected: std::vector FlowControll; @@ -35,14 +34,16 @@ class ClassFlowControll : ClassFlowTakeImage* flowtakeimage; ClassFlow* CreateClassFlow(std::string _type); - bool AutoStart; - float AutoInterval; void SetInitialParameter(void); std::string aktstatusWithTime; std::string aktstatus; int aktRunNr; public: + bool AutoStart; + float AutoInterval; + + bool alignmentOk; bool SetupModeActive; void InitFlow(std::string config); @@ -93,6 +94,3 @@ class ClassFlowControll : }; #endif - - - diff --git a/code/components/jomjol_flowcontroll/ClassFlowDefineTypes.h b/code/components/jomjol_flowcontroll/ClassFlowDefineTypes.h index 466f92efe..2c63c6682 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowDefineTypes.h +++ b/code/components/jomjol_flowcontroll/ClassFlowDefineTypes.h @@ -31,7 +31,6 @@ enum t_RateType { RateChange // time difference is considered and a normalized rate is used for comparison with NumberPost.maxRate }; - /** * Holds all properties and settings of a sequence. A sequence is a set of digit and/or analog ROIs that are combined to * provide one meter reading (value). @@ -46,6 +45,7 @@ struct NumberPost { bool PreValueOkay; // previousValueValid; indicates that the reading of the previous round has no errors bool AllowNegativeRates; // allowNegativeRate; defines if the consistency checks allow negative rates between consecutive meter readings. bool checkDigitIncreaseConsistency; // extendedConsistencyCheck; performs an additional consistency check to avoid wrong readings + // bool AlignmentFailsValue; // Use the value even if alignment fails time_t timeStampLastValue; // Timestamp for the last read value; is used for the log time_t timeStampLastPreValue; // Timestamp for the last PreValue set; is used for useMaxRateValue time_t timeStampTimeUTC; // FIXME: not used; can be removed. @@ -83,4 +83,3 @@ struct NumberPost { }; #endif - diff --git a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp index d16e9d43c..b9586c821 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp @@ -1,13 +1,14 @@ -#include "ClassFlowPostProcessing.h" -#include "Helper.h" -#include "ClassFlowTakeImage.h" -#include "ClassLogFile.h" - #include #include #include +#include "ClassFlowPostProcessing.h" +#include "ClassFlowTakeImage.h" +#include "ClassLogFile.h" +#include "MainFlowControl.h" + +#include "Helper.h" #include "time_sntp.h" #include "esp_log.h" @@ -484,6 +485,35 @@ void ClassFlowPostProcessing::handleMaxRateValue(string _decsep, string _value) } } +/* +void ClassFlowPostProcessing::handleAlignmentFailsValue(string _decsep, string _value) +{ + string _digit, _decpos; + int _pospunkt = _decsep.find_first_of("."); + // ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt); + + if (_pospunkt > -1) + { + _digit = _decsep.substr(0, _pospunkt); + } + else + { + _digit = "default"; + } + + for (int j = 0; j < NUMBERS.size(); ++j) + { + bool _zwdc = alphanumericToBoolean(_value); + + // Set to default first (if nothing else is set) + if ((_digit == "default") || (NUMBERS[j]->name == _digit)) + { + NUMBERS[j]->AlignmentFailsValue = _zwdc; + } + } +} +*/ + void ClassFlowPostProcessing::handleChangeRateThreshold(string _decsep, string _value) { string _digit, _decpos; int _pospunkt = _decsep.find_first_of("."); @@ -592,6 +622,13 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph) } } } + +/* + if ((toUpper(_param) == "ALIGNMENTFAILSVALUE") && (splitted.size() > 1)) + { + handleAlignmentFailsValue(splitted[0], splitted[1]); + } +*/ if ((toUpper(_param) == "ALLOWNEGATIVERATES") && (splitted.size() > 1)) { handleAllowNegativeRate(splitted[0], splitted[1]); @@ -677,8 +714,9 @@ void ClassFlowPostProcessing::InitNUMBERS() { _number->DecimalShift = 0; _number->DecimalShiftInitial = 0; _number->isExtendedResolution = false; - _number->AnalogToDigitTransitionStart=9.2; + _number->AnalogToDigitTransitionStart = 9.2; _number->ChangeRateThreshold = 2; + // _number->AlignmentFailsValue = true; _number->Value = 0; // last value read out, incl. corrections _number->ReturnValue = ""; // corrected return value, possibly with error message @@ -777,6 +815,18 @@ bool ClassFlowPostProcessing::doFlow(string zwtime) { // calculate time difference // double LastValueTimeDifference = difftime(imagetime, NUMBERS[j]->timeStampLastValue); // in seconds double LastPreValueTimeDifference = difftime(imagetime, NUMBERS[j]->timeStampLastPreValue); // in seconds + + // if ((!flowctrl.alignmentOk) && (!NUMBERS[j]->AlignmentFailsValue)) { + if (!flowctrl.alignmentOk) { + NUMBERS[j]->ErrorMessageText = "Alignment failed"; + + NUMBERS[j]->timeStampLastValue = imagetime; + + std::string _zw = NUMBERS[j]->name + ": Raw: " + NUMBERS[j]->ReturnRawValue + ", Value: " + NUMBERS[j]->ReturnValue + ", Status: " + NUMBERS[j]->ErrorMessageText; + LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _zw); + WriteDataLog(j); + continue; + } UpdateNachkommaDecimalShift(); diff --git a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h index e16aa618c..c1ac87827 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h +++ b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h @@ -10,9 +10,7 @@ #include - -class ClassFlowPostProcessing : - public ClassFlow +class ClassFlowPostProcessing : public ClassFlow { protected: bool UpdatePreValueINI; @@ -41,9 +39,8 @@ class ClassFlowPostProcessing : void handleMaxRateType(string _decsep, string _value); void handleAnalogToDigitTransitionStart(string _decsep, string _value); void handleAllowNegativeRate(string _decsep, string _value); + // void handleAlignmentFailsValue(string _decsep, string _value); void handleChangeRateThreshold(string _decsep, string _value); - - std::string GetStringReadouts(general); void WriteDataLog(int _index); @@ -75,5 +72,4 @@ class ClassFlowPostProcessing : string name(){return "ClassFlowPostProcessing";}; }; - #endif //CLASSFFLOWPOSTPROCESSING_H diff --git a/code/components/jomjol_image_proc/CAlignAndCutImage.cpp b/code/components/jomjol_image_proc/CAlignAndCutImage.cpp index b7f7afbda..ee0ec51a3 100644 --- a/code/components/jomjol_image_proc/CAlignAndCutImage.cpp +++ b/code/components/jomjol_image_proc/CAlignAndCutImage.cpp @@ -33,71 +33,99 @@ void CAlignAndCutImage::GetRefSize(int *ref_dx, int *ref_dy) ref_dy[1] = t1_dy; } -bool CAlignAndCutImage::Align(RefInfo *_temp1, RefInfo *_temp2) +int CAlignAndCutImage::Align(RefInfo *_temp1, RefInfo *_temp2) { - int dx, dy; - int r0_x, r0_y, r1_x, r1_y; - bool isSimilar1, isSimilar2; + CFindTemplate *ft = new CFindTemplate("align", rgb_image, channels, width, height, bpp); - CFindTemplate* ft = new CFindTemplate("align", rgb_image, channels, width, height, bpp); + ////////////////////////////////////////////// + int r1_x = _temp1->target_x; + int r1_y = _temp1->target_y; - r0_x = _temp1->target_x; - r0_y = _temp1->target_y; ESP_LOGD(TAG, "Before ft->FindTemplate(_temp1); %s", _temp1->image_file.c_str()); - isSimilar1 = ft->FindTemplate(_temp1); - _temp1->width = ft->tpl_width; - _temp1->height = ft->tpl_height; + bool isSimilar1 = ft->FindTemplate(_temp1); - r1_x = _temp2->target_x; - r1_y = _temp2->target_y; - ESP_LOGD(TAG, "Before ft->FindTemplate(_temp2); %s", _temp2->image_file.c_str()); - isSimilar2 = ft->FindTemplate(_temp2); - _temp2->width = ft->tpl_width; - _temp2->height = ft->tpl_height; + _temp1->width = ft->tpl_width; + _temp1->height = ft->tpl_height; - delete ft; + int dx1 = _temp1->target_x - _temp1->found_x; + int dy1 = _temp1->target_y - _temp1->found_y; + r1_x += dx1; + r1_y += dy1; - dx = _temp1->target_x - _temp1->found_x; - dy = _temp1->target_y - _temp1->found_y; + ////////////////////////////////////////////// + int r2_x = _temp2->target_x; + int r2_y = _temp2->target_y; - r0_x += dx; - r0_y += dy; + ESP_LOGD(TAG, "Before ft->FindTemplate(_temp2); %s", _temp2->image_file.c_str()); + bool isSimilar2 = ft->FindTemplate(_temp2); - r1_x += dx; - r1_y += dy; + _temp2->width = ft->tpl_width; + _temp2->height = ft->tpl_height; - float w_org, w_ist, d_winkel; + int dx2 = _temp2->target_x - _temp2->found_x; + int dy2 = _temp2->target_y - _temp2->found_y; - w_org = atan2(_temp2->found_y - _temp1->found_y, _temp2->found_x - _temp1->found_x); - w_ist = atan2(r1_y - r0_y, r1_x - r0_x); + r2_x += dx1; + r2_y += dy1; - d_winkel = (w_ist - w_org) * 180 / M_PI; + delete ft; -/*#ifdef DEBUG_DETAIL_ON - std::string zw = "\tdx:\t" + std::to_string(dx) + "\tdy:\t" + std::to_string(dy) + "\td_winkel:\t" + std::to_string(d_winkel); - zw = zw + "\tt1_x_y:\t" + std::to_string(_temp1->found_x) + "\t" + std::to_string(_temp1->found_y); - zw = zw + "\tpara1_found_min_avg_max_SAD:\t" + std::to_string(_temp1->fastalg_min) + "\t" + std::to_string(_temp1->fastalg_avg) + "\t" + std::to_string(_temp1->fastalg_max) + "\t"+ std::to_string(_temp1->fastalg_SAD); - zw = zw + "\tt2_x_y:\t" + std::to_string(_temp2->found_x) + "\t" + std::to_string(_temp2->found_y); - zw = zw + "\tpara2_found_min_avg_max:\t" + std::to_string(_temp2->fastalg_min) + "\t" + std::to_string(_temp2->fastalg_avg) + "\t" + std::to_string(_temp2->fastalg_max) + "\t"+ std::to_string(_temp2->fastalg_SAD); - LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw); -#endif*/ + ////////////////////////////////////////////// + float angle_org = atan2(_temp2->found_y - _temp1->found_y, _temp2->found_x - _temp1->found_x); + float angle_cur = atan2(r2_y - r1_y, r2_x - r1_x); - CRotateImage rt("Align", this, ImageTMP); - rt.Translate(dx, dy); - rt.Rotate(d_winkel, _temp1->target_x, _temp1->target_y); - ESP_LOGD(TAG, "Alignment: dx %d - dy %d - rot %f", dx, dy, d_winkel); + float angle_dif = (angle_cur - angle_org) * 180 / M_PI; - return (isSimilar1 && isSimilar2); -} + if ((fabs(angle_dif) > (_temp1->search_max_angle || _temp2->search_max_angle)) || (abs(dx1) >= _temp1->search_x) || (abs(dy1) >= _temp1->search_y) || (abs(dx2) >= _temp2->search_x) || (abs(dy2) >= _temp2->search_y)) + { + ESP_LOGD(TAG, "Alignment failed: dx1 %d - dy1 %d - dx2 %d - dy2 %d - rot %f", dx1, dy1, dx2, dy2, angle_dif); + return -1; // ALIGNMENT FAILED + } + CRotateImage rt("Align", this, ImageTMP); + if ((dx1 > 0 && dx2 > 0 && dy1 > 0 && dy2 > 0) || (dx1 < 0 && dx2 < 0 && dy1 < 0 && dy2 < 0)) + { + // only move linaer because no rotative motion obviuos + ESP_LOGD(TAG, "Align: Correction by linear dx + dy only"); + rt.Translate(dx1, dy1); + } + else if ((dx1 > 0 && dx2 > 0) || (dx1 < 0 && dx2 < 0)) + { + // only rotate + move x direction + ESP_LOGD(TAG, "Align: Correction by rotation + linear dx"); + rt.Rotate(angle_dif, width / 2, height / 2); + rt.Translate(dx1 / 2, 0); // correct only by half because some correction already happen with rotation + } + else if ((dy1 > 0 && dy2 > 0) || (dy1 < 0 && dy2 < 0)) + { + // only rotate + move y direction + ESP_LOGD(TAG, "Align: Correction by rotation + linear dy"); + rt.Rotate(angle_dif, width / 2, height / 2); + rt.Translate(0, dy1 / 2); // correct only by half because some correction already happen with rotation + } + else + { + // only rotate because no obviuos linear motion detected + ESP_LOGD(TAG, "Align: Correction by rotation only"); + rt.Rotate(angle_dif, width / 2, height / 2); + } + ESP_LOGD(TAG, "Alignment: dx1 %d - dy1 %d - dx2 %d - dy2 %d - rot %f", dx1, dy1, dx2, dy2, angle_dif); + if (isSimilar1 && isSimilar2) + { + return 1; // ALGO FAST match + } + else + { + return 0; // ALGO STANDARD done + } +} void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int dx, int dy) { - int x2, y2; x2 = x1 + dx; @@ -117,13 +145,17 @@ void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int d RGBImageLock(); for (int x = x1; x < x2; ++x) + { for (int y = y1; y < y2; ++y) { p_target = odata + (channels * ((y - y1) * dx + (x - x1))); p_source = rgb_image + (channels * (y * width + x)); for (int _channels = 0; _channels < channels; ++_channels) + { p_target[_channels] = p_source[_channels]; + } } + } #ifdef STBI_ONLY_JPEG stbi_write_jpg(_template1.c_str(), dx, dy, channels, odata, 100); @@ -162,19 +194,22 @@ void CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy, CImageBasis * stbi_uc* p_source; for (int x = x1; x < x2; ++x) + { for (int y = y1; y < y2; ++y) { p_target = odata + (channels * ((y - y1) * dx + (x - x1))); p_source = rgb_image + (channels * (y * width + x)); for (int _channels = 0; _channels < channels; ++_channels) + { p_target[_channels] = p_source[_channels]; + } } + } RGBImageRelease(); _target->RGBImageRelease(); } - CImageBasis* CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy) { int x2, y2; @@ -196,13 +231,17 @@ CImageBasis* CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy) RGBImageLock(); for (int x = x1; x < x2; ++x) + { for (int y = y1; y < y2; ++y) { p_target = odata + (channels * ((y - y1) * dx + (x - x1))); p_source = rgb_image + (channels * (y * width + x)); for (int _channels = 0; _channels < channels; ++_channels) + { p_target[_channels] = p_source[_channels]; + } } + } CImageBasis* rs = new CImageBasis("CutAndSave", odata, channels, dx, dy, bpp); RGBImageRelease(); diff --git a/code/components/jomjol_image_proc/CAlignAndCutImage.h b/code/components/jomjol_image_proc/CAlignAndCutImage.h index 46f5016e4..1a918ff55 100644 --- a/code/components/jomjol_image_proc/CAlignAndCutImage.h +++ b/code/components/jomjol_image_proc/CAlignAndCutImage.h @@ -6,7 +6,6 @@ #include "CImageBasis.h" #include "CFindTemplate.h" - class CAlignAndCutImage : public CImageBasis { public: @@ -16,7 +15,7 @@ class CAlignAndCutImage : public CImageBasis CAlignAndCutImage(std::string name, uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL;}; CAlignAndCutImage(std::string name, CImageBasis *_org, CImageBasis *_temp); - bool Align(RefInfo *_temp1, RefInfo *_temp2); + int Align(RefInfo *_temp1, RefInfo *_temp2); // void Align(std::string _template1, int x1, int y1, std::string _template2, int x2, int y2, int deltax = 40, int deltay = 40, std::string imageROI = ""); void CutAndSave(std::string _template1, int x1, int y1, int dx, int dy); CImageBasis* CutAndSave(int x1, int y1, int dx, int dy); diff --git a/code/components/jomjol_image_proc/CFindTemplate.h b/code/components/jomjol_image_proc/CFindTemplate.h index 14b0261b1..b687340e1 100644 --- a/code/components/jomjol_image_proc/CFindTemplate.h +++ b/code/components/jomjol_image_proc/CFindTemplate.h @@ -15,6 +15,7 @@ struct RefInfo { int found_y; int search_x; int search_y; + int search_max_angle; int fastalg_x = -1; int fastalg_y = -1; int fastalg_min = -256; @@ -25,9 +26,6 @@ struct RefInfo { int alignment_algo = 0; // 0 = "Default" (nur R-Kanal), 1 = "HighAccuracy" (RGB-Kanal), 2 = "Fast" (1.x RGB, dann isSimilar) }; - - - class CFindTemplate : public CImageBasis { public: diff --git a/param-docs/expert-params.txt b/param-docs/expert-params.txt index 056b71288..0ba202d97 100644 --- a/param-docs/expert-params.txt +++ b/param-docs/expert-params.txt @@ -27,6 +27,7 @@ CamZoomOffsetY demo SearchFieldX SearchFieldY +SearchMaxAngle AlignmentAlgo CNNGoodThreshold PreValueAgeStartup diff --git a/param-docs/parameter-pages/Alignment/SearchMaxAngle.md b/param-docs/parameter-pages/Alignment/SearchMaxAngle.md new file mode 100644 index 000000000..12ee188cb --- /dev/null +++ b/param-docs/parameter-pages/Alignment/SearchMaxAngle.md @@ -0,0 +1,14 @@ +# Parameter `SearchMaxAngle` +Default Value: `45` + +Unit: degree + +!!! Warning + This is an **Expert Parameter**! Only change it if you understand what it does! + +Angle, by which the reference is max rotated when searching. + +!!! Note + Since the alignment is one of the steps using a lot of computation time, + the max angle should be as small as possible. + The calculation time goes quadratic with the angle. diff --git a/sd-card/config/config.ini b/sd-card/config/config.ini index 851c96bf3..4e094ddb6 100644 --- a/sd-card/config/config.ini +++ b/sd-card/config/config.ini @@ -38,6 +38,7 @@ Demo = false InitialRotate = 0.0 SearchFieldX = 20 SearchFieldY = 20 +SearchMaxAngle = 45 AlignmentAlgo = default /config/ref0.jpg 103 271 /config/ref1.jpg 442 142 diff --git a/sd-card/html/edit_config_template.html b/sd-card/html/edit_config_template.html index 535717d6e..8755e92f5 100644 --- a/sd-card/html/edit_config_template.html +++ b/sd-card/html/edit_config_template.html @@ -714,6 +714,17 @@

Configuration

$TOOLTIP_Alignment_SearchFieldY + + + + Search Max Angle + + + ° + + $TOOLTIP_Alignment_SearchMaxAngle + @@ -994,7 +1005,22 @@