Compare commits

..

40 Commits

Author SHA1 Message Date
Slider0007
919ede0e7c Update edit_config_template.html 2024-07-16 19:09:32 +02:00
Frank Haverland
b0a7c7716f Fixed case on early transition 2024-05-13 20:08:43 +02:00
Frank Haverland
aff08fafee add test cases 2024-05-07 21:17:41 +02:00
Slider0007
ed746f96b9 Readd missing test case 2024-04-29 22:46:58 +02:00
Slider0007
fa08a02e12 Test case adaptions 2024-04-29 21:38:39 +02:00
Frank Haverland
57715b5bdd added test cases from rainman110:fix_issue_2857 2024-04-28 21:56:59 +02:00
Frank Haverland
53f3b99f05 log error to tests 2024-04-28 21:12:56 +02:00
Frank Haverland
ba63d0a589 added tests from PR/2887 2024-04-28 21:10:13 +02:00
Frank Haverland
0309620fd6 fix merge failure in earlier merges 2024-04-28 20:13:18 +02:00
Frank Haverland
295038a881 merge fixes 2024-04-28 19:56:50 +02:00
Frank Haverland
488ae174a4 Merge remote-tracking branch 'upstream/rolling' into analog-digit-early-digit-test 2024-04-28 19:40:03 +02:00
michael
4049d752ba Update overview.html
CamFrameSize is no longer needed/used for zoom
2024-04-27 00:03:26 +02:00
Slider0007
4b4b42d4c5 Modifcation to cover new test case
https://github.com/jomjol/AI-on-the-edge-device/pull/2887#issuecomment-1941018311
2024-04-26 12:17:37 +02:00
Slider0007
135b03d505 Add one more test case
https://github.com/jomjol/AI-on-the-edge-device/pull/2887#issuecomment-1941018311
2024-04-26 12:15:42 +02:00
Frank Haverland
74c09ac023 added transistion tests. 2024-04-25 19:55:29 +02:00
michael
dc90972659 Update info.html
function loadWLANSSID() was present three times
2024-04-24 07:25:14 +02:00
michael
32282ecfe2 fix edit_config_template.html
TakeImage_CamZoomMode_value1 was replaced by TakeImage_CamZoomSize_value1, but not deleted.
This caused problems when saving the camera settings.
2024-04-16 13:14:27 +02:00
michael
ae6a94544b fix readconfigparam.js
Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^
2024-04-16 04:26:35 +02:00
michael
70b031eacc fix edit_config_template.html
Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^
2024-04-16 04:25:51 +02:00
michael
c3fadf5c2a Source code formatting, ClassFlowPostProcessing.cpp 2024-04-15 22:12:02 +02:00
Marco H
7e5f6bf4a5 Fix minor typo and harmonize spaces (#3030)
* Update edit_digits.html

* Update edit_analog.html

* Update overview.html

* Update edit_reference.html

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
2024-04-11 21:28:33 +02:00
michael
88b531ae8b Camera settings (#3029)
* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload
2024-04-11 21:12:40 +02:00
jomjol
8481cc4b26 Update tflite 2024-03-30 14:47:26 +01:00
jomjol
ecaed38c1d Update tflite 2024-03-30 09:07:42 +01:00
jomjol
d6a1838d47 Create dig-class11_1701_s2.tflite 2024-03-25 08:25:47 +01:00
kub3let
5194c466be always reset change absolute (#2956) 2024-03-22 21:55:11 +01:00
Frank Haverland
043de9265a Fix test (#2933) 2024-03-20 19:22:33 +01:00
CaCO3
08a350172d renamed model file to make naming consistent 2024-03-13 22:28:41 +01:00
CaCO3
7e806df64d Renamed menu entry Alignment -> References 2024-02-18 09:52:24 +01:00
CaCO3
dccfb5e91e The parameter "negative" is processed on the MCU 2024-02-17 22:01:31 +01:00
michael
fbe4609bb9 Update edit_config_template.html (#2925)
Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist +
Kameraeinstellungen nicht nur in der config.ini speichern, sondern auch setzen
2024-02-17 10:17:08 +01:00
michael
3e85cfb456 Update edit_reference.html (#2924)
Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist
2024-02-17 10:17:00 +01:00
jomjol
5dff4ca8cf Create dig-cont_0640_s3_q.tflite 2024-02-17 08:25:12 +01:00
Slider0007
1f4b8807fb Merge branch 'analog-digit-early-digit-test' of https://github.com/jomjol/AI-on-the-edge-device into analog-digit-early-digit-test 2024-02-12 14:20:34 +01:00
Slider0007
827ca1cf61 Add analogdigit early zero crossing case 2024-02-12 14:20:19 +01:00
Slider0007
dc640d7bce Update edit_config_param.html 2024-02-12 02:35:34 +01:00
Slider0007
b551eadf8a PointerEvalAnalogToDigitNew-TEST 2024-02-12 00:32:24 +01:00
Slider0007
8e8ac621dd tflite heap fix 2024-02-12 00:30:04 +01:00
Slider0007
54d4990d16 test fixes from haverland 2024-02-12 00:29:12 +01:00
Slider0007
f8dd986e4f Test with AnalogDigitTransition min lowered to 3 2024-02-12 00:28:42 +01:00
72 changed files with 8805 additions and 5909 deletions

View File

@@ -1,3 +1,16 @@
## [update] - 2024-03-30
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.6.0...v15.7.0)
#### Core Changes
- New tflite-Model for Analog (v13.0.0)
- New tflite-Model for Digital Hybrid (v7.0.0)
#### Bug Fixes
- tbd
## [15.7.0] - 2024-02-17
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.6.0...v15.7.0)

File diff suppressed because it is too large Load Diff

View File

@@ -15,66 +15,100 @@
#include "CImageBasis.h"
#include "../../include/defines.h"
class CCamera {
protected:
int ActualQuality;
framesize_t ActualResolution;
int brightness, contrast, saturation, autoExposureLevel;
bool isFixedExposure;
int waitbeforepicture_org;
int led_intensity = 4095;
typedef enum
{
OV2640_MODE_UXGA,
OV2640_MODE_SVGA,
OV2640_MODE_CIF
} ov2640_sensor_mode_t;
void ledc_init(void);
bool CameraInitSuccessful = false;
bool demoMode = false;
typedef struct
{
framesize_t ImageFrameSize = FRAMESIZE_VGA; // 0 - 10
gainceiling_t ImageGainceiling; // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
bool loadNextDemoImage(camera_fb_t *fb);
long GetFileSize(std::string filename);
int ImageQuality; // 0 - 63
int ImageBrightness; // (-2 to 2) - set brightness
int ImageContrast; //-2 - 2
int ImageSaturation; //-2 - 2
int ImageSharpness; //-2 - 2
bool ImageAutoSharpness;
int ImageSpecialEffect; // 0 - 6
int ImageWbMode; // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
int ImageAwb; // white balance enable (0 or 1)
int ImageAwbGain; // Auto White Balance enable (0 or 1)
int ImageAec; // auto exposure off (1 or 0)
int ImageAec2; // automatic exposure sensor (0 or 1)
int ImageAeLevel; // auto exposure levels (-2 to 2)
int ImageAecValue; // set exposure manually (0-1200)
int ImageAgc; // auto gain off (1 or 0)
int ImageAgcGain; // set gain manually (0 - 30)
int ImageBpc; // black pixel correction
int ImageWpc; // white pixel correction
int ImageRawGma; // (1 or 0)
int ImageLenc; // lens correction (1 or 0)
int ImageHmirror; // (0 or 1) flip horizontally
int ImageVflip; // Invert image (0 or 1)
int ImageDcw; // downsize enable (1 or 0)
void SetCamWindow(sensor_t *s, int resolution, int xOffset, int yOffset, int xLength, int yLength);
void SetImageWidthHeightFromResolution(framesize_t resol);
int ImageWidth;
int ImageHeight;
public:
int image_height, image_width;
bool imageZoomEnabled = false;
int imageZoomMode = 0;
int imageZoomOffsetX = 0;
int imageZoomOffsetY = 0;
bool imageNegative = false;
bool imageAec2 = false;
bool imageAutoSharpness = false;
int imageSharpnessLevel = 0;
#ifdef GRAYSCALE_AS_DEFAULT
bool imageGrayscale = true;
#else
bool imageGrayscale = false;
#endif
CCamera();
esp_err_t InitCam();
int ImageLedIntensity;
void LightOnOff(bool status);
void LEDOnOff(bool status);
esp_err_t CaptureToHTTP(httpd_req_t *req, int delay = 0);
esp_err_t CaptureToStream(httpd_req_t *req, bool FlashlightOn);
void SetQualitySize(int qual, framesize_t resol, bool zoomEnabled, int zoomMode, int zoomOffsetX, int zoomOffsetY);
bool SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation, int _autoExposureLevel, bool _grayscale, bool _negative, bool _aec2, int _sharpnessLevel);
void SetZoom(bool zoomEnabled, int zoomMode, int zoomOffsetX, int zoomOffsetY);
void GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol, bool &zoomEnabled, int &zoomMode, int &zoomOffsetX, int &zoomOffsetY);
void SetLEDIntensity(float _intrel);
bool testCamera(void);
void EnableAutoExposure(int flash_duration);
bool getCameraInitSuccessful();
void useDemoMode(void);
bool ImageZoomEnabled;
int ImageZoomMode;
int ImageZoomOffsetX;
int ImageZoomOffsetY;
int ImageZoomSize;
framesize_t TextToFramesize(const char * text);
int WaitBeforePicture;
bool isImageSize;
esp_err_t CaptureToFile(std::string nm, int delay = 0);
esp_err_t CaptureToBasisImage(CImageBasis *_Image, int delay = 0);
bool CameraInitSuccessful;
bool changedCameraSettings;
bool DemoMode;
bool SaveAllFiles;
} camera_controll_config_temp_t;
extern camera_controll_config_temp_t CCstatus;
class CCamera
{
protected:
void ledc_init(void);
bool loadNextDemoImage(camera_fb_t *fb);
long GetFileSize(std::string filename);
void SetCamWindow(sensor_t *s, int resolution, int xOffset, int yOffset, int xTotal, int yTotal, int xOutput, int yOutput);
void SetImageWidthHeightFromResolution(framesize_t resol);
public:
CCamera(void);
esp_err_t InitCam(void);
void LightOnOff(bool status);
void LEDOnOff(bool status);
esp_err_t setSensorDatenFromCCstatus(void);
esp_err_t getSensorDatenToCCstatus(void);
esp_err_t CaptureToHTTP(httpd_req_t *req, int delay = 0);
esp_err_t CaptureToStream(httpd_req_t *req, bool FlashlightOn);
void SetQualityZoomSize(int qual, framesize_t resol, bool zoomEnabled, int zoomOffsetX, int zoomOffsetY, int imageSize);
void SetZoomSize(bool zoomEnabled, int zoomOffsetX, int zoomOffsetY, int imageSize);
void SetCamSharpness(bool _autoSharpnessEnabled, int _sharpnessLevel);
void SetLEDIntensity(float _intrel);
bool testCamera(void);
bool getCameraInitSuccessful(void);
void useDemoMode(void);
framesize_t TextToFramesize(const char *text);
esp_err_t CaptureToFile(std::string nm, int delay = 0);
esp_err_t CaptureToBasisImage(CImageBasis *_Image, int delay = 0);
};
extern CCamera Camera;
#endif

View File

@@ -3,71 +3,78 @@
#include "ov2640_sharpness.h"
#define OV2640_MAXLEVEL_SHARPNESS 6
const static uint8_t OV2640_SHARPNESS_AUTO[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0x20, 0x20,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_MANUAL[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0x00, 0x20,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL0[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc0, 0x1f,
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC0, 0x1F,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL1[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc1, 0x1f,
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC1, 0x1F,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL2[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc2, 0x1f,
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC2, 0x1F,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL3[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc4, 0x1f,
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC4, 0x1F,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL4[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xc8, 0x1f,
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC8, 0x1F,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL5[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xd0, 0x1f,
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xD0, 0x1F,
0x00, 0x00, 0x00
};
const static uint8_t OV2640_SHARPNESS_LEVEL6[]=
{
0xFF, 0x00, 0xff,
0x92, 0x01, 0xff,
0x93, 0xdf, 0x1f,
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xDF, 0x1F,
0x00, 0x00, 0x00
};
@@ -82,6 +89,9 @@ const static uint8_t *OV2640_SETTING_SHARPNESS[]=
OV2640_SHARPNESS_LEVEL6 // +3 sharpness
};
#define OV2640_MAXLEVEL_SHARPNESS 6
static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
{
uint8_t address;
@@ -91,34 +101,52 @@ static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
const uint8_t *pdata = ptab;
if (pdata == NULL)
{
return -1;
}
while (1)
{
address = *pdata++;
value = *pdata++;
mask = *pdata++;
if ((address == 0) && (value == 0) && (mask == 0))
{
break;
}
sensor->set_reg(sensor, address, mask, value);
}
return 0;
}
int ov2640_enable_auto_sharpness(sensor_t *sensor)
{
table_mask_write(sensor, OV2640_SHARPNESS_AUTO);
return 0;
}
int ov2640_set_sharpness(sensor_t *sensor, int sharpness)
{
if ((sharpness < -3) || (sharpness > OV2640_MAXLEVEL_SHARPNESS - 3))
return -1;
int sharpness_temp = 0;
if (sharpness < -3)
{
sharpness_temp = -3;
}
if (sharpness > OV2640_MAXLEVEL_SHARPNESS - 3)
{
sharpness_temp = OV2640_MAXLEVEL_SHARPNESS - 3;
}
table_mask_write(sensor, OV2640_SHARPNESS_MANUAL);
table_mask_write(sensor, OV2640_SETTING_SHARPNESS[sharpness + 3]);
table_mask_write(sensor, OV2640_SETTING_SHARPNESS[sharpness_temp + 3]);
return 0;
}

View File

@@ -5,6 +5,7 @@
#include "esp_camera.h"
#include "ClassControllCamera.h"
#include "MainFlowControl.h"
#include "ClassLogFile.h"
#include "esp_log.h"
@@ -13,191 +14,183 @@
static const char *TAG = "server_cam";
void PowerResetCamera()
{
ESP_LOGD(TAG, "Resetting camera by power down line");
gpio_config_t conf;
conf.intr_type = GPIO_INTR_DISABLE;
conf.pin_bit_mask = 1LL << GPIO_NUM_32;
conf.mode = GPIO_MODE_OUTPUT;
conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&conf);
void PowerResetCamera(){
ESP_LOGD(TAG, "Resetting camera by power down line");
gpio_config_t conf;
conf.intr_type = GPIO_INTR_DISABLE;
conf.pin_bit_mask = 1LL << GPIO_NUM_32;
conf.mode = GPIO_MODE_OUTPUT;
conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
conf.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config(&conf);
// carefull, logic is inverted compared to reset pin
gpio_set_level(GPIO_NUM_32, 1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(GPIO_NUM_32, 0);
vTaskDelay(1000 / portTICK_PERIOD_MS);
// carefull, logic is inverted compared to reset pin
gpio_set_level(GPIO_NUM_32, 1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(GPIO_NUM_32, 0);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
esp_err_t handler_lightOn(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_lightOn - Start");
ESP_LOGD(TAG, "handler_lightOn uri: %s", req->uri);
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_lightOn - Start");
ESP_LOGD(TAG, "handler_lightOn uri: %s", req->uri);
#endif
if (Camera.getCameraInitSuccessful())
if (Camera.getCameraInitSuccessful())
{
Camera.LightOnOff(true);
const char* resp_str = (const char*) req->user_ctx;
const char *resp_str = (const char *)req->user_ctx;
httpd_resp_send(req, resp_str, strlen(resp_str));
}
else
else
{
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lighton not available!");
return ESP_ERR_NOT_FOUND;
}
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_lightOn - Done");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_lightOn - Done");
#endif
return ESP_OK;
}
esp_err_t handler_lightOff(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_lightOff - Start");
ESP_LOGD(TAG, "handler_lightOff uri: %s", req->uri);
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_lightOff - Start");
ESP_LOGD(TAG, "handler_lightOff uri: %s", req->uri);
#endif
if (Camera.getCameraInitSuccessful())
if (Camera.getCameraInitSuccessful())
{
Camera.LightOnOff(false);
const char* resp_str = (const char*) req->user_ctx;
httpd_resp_send(req, resp_str, strlen(resp_str));
const char *resp_str = (const char *)req->user_ctx;
httpd_resp_send(req, resp_str, strlen(resp_str));
}
else
else
{
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lightoff not available!");
return ESP_ERR_NOT_FOUND;
}
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_lightOff - Done");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_lightOff - Done");
#endif
return ESP_OK;
}
esp_err_t handler_capture(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture - Start");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture - Start");
#endif
if (Camera.getCameraInitSuccessful())
if (Camera.getCameraInitSuccessful())
{
int quality;
framesize_t res;
bool zoomEnabled;
int zoomMode;
int zoomOffsetX;
int zoomOffsetY;
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
#endif
Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
#endif
Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
// wenn die Kameraeinstellungen durch Erstellen eines neuen Referenzbildes verändert wurden, müssen sie neu gesetzt werden
if (CFstatus.changedCameraSettings)
{
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
CFstatus.changedCameraSettings = false;
}
esp_err_t result;
result = Camera.CaptureToHTTP(req);
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture - Done");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture - Done");
#endif
return result;
}
else
else
{
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture not available!");
return ESP_ERR_NOT_FOUND;
}
}
esp_err_t handler_capture_with_light(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture_with_light - Start");
#endif
if (Camera.getCameraInitSuccessful())
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture_with_light - Start");
#endif
if (Camera.getCameraInitSuccessful())
{
char _query[100];
char _delay[10];
int quality;
framesize_t res;
bool zoomEnabled;
int zoomMode;
int zoomOffsetX;
int zoomOffsetY;
int delay = 2500;
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
{
ESP_LOGD(TAG, "Query: %s", _query);
if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
{
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Delay: %s", _delay);
#endif
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Delay: %s", _delay);
#endif
delay = atoi(_delay);
if (delay < 0)
{
delay = 0;
}
}
}
Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
#endif
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
#endif
// wenn die Kameraeinstellungen durch Erstellen eines neuen Referenzbildes verändert wurden, müssen sie neu gesetzt werden
if (CFstatus.changedCameraSettings)
{
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
CFstatus.changedCameraSettings = false;
}
Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
Camera.LightOnOff(true);
const TickType_t xDelay = delay / portTICK_PERIOD_MS;
vTaskDelay( xDelay );
vTaskDelay(xDelay);
esp_err_t result;
result = Camera.CaptureToHTTP(req);
result = Camera.CaptureToHTTP(req);
Camera.LightOnOff(false);
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture_with_light - Done");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture_with_light - Done");
#endif
return result;
}
else
else
{
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture_with_flashlight not available!");
return ESP_ERR_NOT_FOUND;
}
}
esp_err_t handler_capture_save_to_file(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture_save_to_file - Start");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture_save_to_file - Start");
#endif
if (Camera.getCameraInitSuccessful())
if (Camera.getCameraInitSuccessful())
{
char _query[100];
char _delay[10];
@@ -205,98 +198,102 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
char filename[100];
std::string fn = "/sdcard/";
int quality;
framesize_t res;
bool zoomEnabled;
int zoomMode;
int zoomOffsetX;
int zoomOffsetY;
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
{
ESP_LOGD(TAG, "Query: %s", _query);
if (httpd_query_key_value(_query, "filename", filename, 100) == ESP_OK)
{
fn.append(filename);
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Filename: %s", fn.c_str());
#endif
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Filename: %s", fn.c_str());
#endif
}
else
{
fn.append("noname.jpg");
}
if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
{
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Delay: %s", _delay);
#endif
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Delay: %s", _delay);
#endif
delay = atoi(_delay);
if (delay < 0)
{
delay = 0;
}
}
}
else
{
fn.append("noname.jpg");
}
Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
#endif
Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
#ifdef DEBUG_DETAIL_ON
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
#endif
// wenn die Kameraeinstellungen durch Erstellen eines neuen Referenzbildes verändert wurden, müssen sie neu gesetzt werden
if (CFstatus.changedCameraSettings)
{
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
CFstatus.changedCameraSettings = false;
}
esp_err_t result;
result = Camera.CaptureToFile(fn, delay);
result = Camera.CaptureToFile(fn, delay);
const char* resp_str = (const char*) fn.c_str();
const char *resp_str = (const char *)fn.c_str();
httpd_resp_send(req, resp_str, strlen(resp_str));
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture_save_to_file - Done");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_capture_save_to_file - Done");
#endif
return result;
}
else
else
{
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /save not available!");
return ESP_ERR_NOT_FOUND;
}
}
void register_server_camera_uri(httpd_handle_t server)
{
#ifdef DEBUG_DETAIL_ON
#ifdef DEBUG_DETAIL_ON
ESP_LOGI(TAG, "server_part_camera - Registering URI handlers");
#endif
httpd_uri_t camuri = { };
camuri.method = HTTP_GET;
httpd_uri_t camuri = {};
camuri.method = HTTP_GET;
camuri.uri = "/lighton";
camuri.handler = handler_lightOn;
camuri.user_ctx = (void*) "Light On";
camuri.uri = "/lighton";
camuri.handler = handler_lightOn;
camuri.user_ctx = (void *)"Light On";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/lightoff";
camuri.handler = handler_lightOff;
camuri.user_ctx = (void*) "Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/lightoff";
camuri.handler = handler_lightOff;
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/capture";
camuri.handler = handler_capture;
camuri.user_ctx = NULL;
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/capture";
camuri.handler = handler_capture;
camuri.user_ctx = NULL;
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/capture_with_flashlight";
camuri.handler = handler_capture_with_light;
camuri.user_ctx = NULL;
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/capture_with_flashlight";
camuri.handler = handler_capture_with_light;
camuri.user_ctx = NULL;
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/save";
camuri.handler = handler_capture_save_to_file;
camuri.user_ctx = NULL;
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/save";
camuri.handler = handler_capture_save_to_file;
camuri.user_ctx = NULL;
httpd_register_uri_handler(server, &camuri);
}

View File

@@ -10,7 +10,6 @@
//#include "ClassControllCamera.h"
void register_server_camera_uri(httpd_handle_t server);
void PowerResetCamera();
#endif

View File

@@ -1,393 +1,402 @@
#include "ClassFlowAlignment.h"
#include "ClassFlowTakeImage.h"
#include "ClassFlow.h"
#include "MainFlowControl.h"
#include "CRotateImage.h"
#include "esp_log.h"
#include "ClassLogFile.h"
#include "psram.h"
#include "../../include/defines.h"
static const char *TAG = "ALIGN";
// #define DEBUG_DETAIL_ON
void ClassFlowAlignment::SetInitialParameter(void)
{
initialrotate = 0;
anz_ref = 0;
initialmirror = false;
use_antialiasing = false;
initialflip = false;
SaveAllFiles = false;
namerawimage = "/sdcard/img_tmp/raw.jpg";
FileStoreRefAlignment = "/sdcard/config/align.txt";
ListFlowControll = NULL;
AlignAndCutImage = NULL;
ImageBasis = NULL;
ImageTMP = NULL;
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
AlgROI = (ImageData*)malloc_psram_heap(std::string(TAG) + "->AlgROI", sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
#endif
previousElement = NULL;
disabled = false;
SAD_criteria = 0.05;
}
ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
{
SetInitialParameter();
ListFlowControll = lfc;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowTakeImage") == 0)
{
ImageBasis = ((ClassFlowTakeImage*) (*ListFlowControll)[i])->rawImage;
}
}
if (!ImageBasis) // the function take pictures does not exist --> must be created first ONLY FOR TEST PURPOSES
{
ESP_LOGD(TAG, "CImageBasis had to be created");
ImageBasis = new CImageBasis("ImageBasis", namerawimage);
}
}
bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> splitted;
int suchex = 40;
int suchey = 40;
int alg_algo = 0; //default=0; 1 =HIGHACCURACY; 2= FAST; 3= OFF //add disable aligment algo |01.2023
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if (aktparamgraph.compare("[Alignment]") != 0) //Paragraph does not fit Alignment
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
splitted = ZerlegeZeile(aktparamgraph);
if ((toUpper(splitted[0]) == "FLIPIMAGESIZE") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
initialflip = true;
}
if ((toUpper(splitted[0]) == "INITIALMIRROR") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
initialmirror = true;
}
if (((toUpper(splitted[0]) == "initialrotate") || (toUpper(splitted[0]) == "INITIALROTATE")) && (splitted.size() > 1))
{
this->initialrotate = std::stod(splitted[1]);
}
if ((toUpper(splitted[0]) == "SEARCHFIELDX") && (splitted.size() > 1))
{
suchex = std::stod(splitted[1]);
}
if ((toUpper(splitted[0]) == "SEARCHFIELDY") && (splitted.size() > 1))
{
suchey = std::stod(splitted[1]);
}
if ((toUpper(splitted[0]) == "ANTIALIASING") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
use_antialiasing = true;
}
if ((splitted.size() == 3) && (anz_ref < 2))
{
References[anz_ref].image_file = FormatFileName("/sdcard" + splitted[0]);
References[anz_ref].target_x = std::stod(splitted[1]);
References[anz_ref].target_y = std::stod(splitted[2]);
anz_ref++;
}
if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
SaveAllFiles = true;
}
if ((toUpper(splitted[0]) == "ALIGNMENTALGO") && (splitted.size() > 1))
{
#ifdef DEBUG_DETAIL_ON
std::string zw2 = "Alignment mode selected: " + splitted[1];
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
#endif
if (toUpper(splitted[1]) == "HIGHACCURACY")
alg_algo = 1;
if (toUpper(splitted[1]) == "FAST")
alg_algo = 2;
if (toUpper(splitted[1]) == "OFF") //no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
alg_algo = 3;
}
}
for (int i = 0; i < anz_ref; ++i)
{
References[i].search_x = suchex;
References[i].search_y = suchey;
References[i].fastalg_SAD_criteria = SAD_criteria;
References[i].alignment_algo = alg_algo;
#ifdef DEBUG_DETAIL_ON
std::string zw2 = "Alignment mode written: " + std::to_string(alg_algo);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
#endif
}
//no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
if(References[0].alignment_algo != 3){
LoadReferenceAlignmentValues();
}
return true;
}
string ClassFlowAlignment::getHTMLSingleStep(string host)
{
string result;
result = "<p>Rotated Image: </p> <p><img src=\"" + host + "/img_tmp/rot.jpg\"></p>\n";
result = result + "<p>Found Alignment: </p> <p><img src=\"" + host + "/img_tmp/rot_roi.jpg\"></p>\n";
result = result + "<p>Aligned Image: </p> <p><img src=\"" + host + "/img_tmp/alg.jpg\"></p>\n";
return result;
}
bool ClassFlowAlignment::doFlow(string time)
{
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
if (!AlgROI) // AlgROI needs to be allocated before ImageTMP to avoid heap fragmentation
{
AlgROI = (ImageData*)heap_caps_realloc(AlgROI, sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
if (!AlgROI)
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlgROI");
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
}
}
if (AlgROI)
{
ImageBasis->writeToMemoryAsJPG((ImageData*)AlgROI, 90);
}
#endif
if (!ImageTMP)
{
ImageTMP = new CImageBasis("tmpImage", ImageBasis); // Make sure the name does not get change, it is relevant for the PSRAM allocation!
if (!ImageTMP)
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tmpImage -> Exec this round aborted!");
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
return false;
}
}
delete AlignAndCutImage;
AlignAndCutImage = new CAlignAndCutImage("AlignAndCutImage", ImageBasis, ImageTMP);
if (!AlignAndCutImage)
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlignAndCutImage -> Exec this round aborted!");
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
return false;
}
CRotateImage rt("rawImage", AlignAndCutImage, ImageTMP, initialflip);
if (initialflip)
{
int _zw = ImageBasis->height;
ImageBasis->height = ImageBasis->width;
ImageBasis->width = _zw;
_zw = ImageTMP->width;
ImageTMP->width = ImageTMP->height;
ImageTMP->height = _zw;
}
if (initialmirror)
{
ESP_LOGD(TAG, "do mirror");
rt.Mirror();
if (SaveAllFiles)
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
}
if ((initialrotate != 0) || initialflip)
{
if (use_antialiasing)
rt.RotateAntiAliasing(initialrotate);
else
rt.Rotate(initialrotate);
if (SaveAllFiles)
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
}
//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]))
{
SaveReferenceAlignmentValues();
}
}// no align
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
if (AlgROI) {
//no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
if(References[0].alignment_algo != 3){
DrawRef(ImageTMP);
}
flowctrl.DigitalDrawROI(ImageTMP);
flowctrl.AnalogDrawROI(ImageTMP);
ImageTMP->writeToMemoryAsJPG((ImageData*)AlgROI, 90);
}
#endif
if (SaveAllFiles)
{
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
ImageTMP->SaveToFile(FormatFileName("/sdcard/img_tmp/alg_roi.jpg"));
}
// must be deleted to have memory space for loading tflite
delete ImageTMP;
ImageTMP = NULL;
//no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
if(References[0].alignment_algo != 3){
LoadReferenceAlignmentValues();
}
return true;
}
void ClassFlowAlignment::SaveReferenceAlignmentValues()
{
FILE* pFile;
std::string zwtime, zwvalue;
pFile = fopen(FileStoreRefAlignment.c_str(), "w");
if (strlen(zwtime.c_str()) == 0)
{
time_t rawtime;
struct tm* timeinfo;
char buffer[80];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, 80, "%Y-%m-%dT%H:%M:%S", timeinfo);
zwtime = std::string(buffer);
}
fputs(zwtime.c_str(), pFile);
fputs("\n", pFile);
zwvalue = std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_y);
zwvalue = zwvalue + "\t" +std::to_string(References[0].fastalg_SAD)+ "\t" +std::to_string(References[0].fastalg_min);
zwvalue = zwvalue + "\t" +std::to_string(References[0].fastalg_max)+ "\t" +std::to_string(References[0].fastalg_avg);
fputs(zwvalue.c_str(), pFile);
fputs("\n", pFile);
zwvalue = std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_y);
zwvalue = zwvalue + "\t" +std::to_string(References[1].fastalg_SAD)+ "\t" +std::to_string(References[1].fastalg_min);
zwvalue = zwvalue + "\t" +std::to_string(References[1].fastalg_max)+ "\t" +std::to_string(References[1].fastalg_avg);
fputs(zwvalue.c_str(), pFile);
fputs("\n", pFile);
fclose(pFile);
}
bool ClassFlowAlignment::LoadReferenceAlignmentValues(void)
{
FILE* pFile;
char zw[1024];
string zwvalue;
std::vector<string> splitted;
pFile = fopen(FileStoreRefAlignment.c_str(), "r");
if (pFile == NULL)
return false;
fgets(zw, 1024, pFile);
ESP_LOGD(TAG, "%s", zw);
fgets(zw, 1024, pFile);
splitted = ZerlegeZeile(std::string(zw), " \t");
if (splitted.size() < 6)
{
fclose(pFile);
return false;
}
References[0].fastalg_x = stoi(splitted[0]);
References[0].fastalg_y = stoi(splitted[1]);
References[0].fastalg_SAD = stof(splitted[2]);
References[0].fastalg_min = stoi(splitted[3]);
References[0].fastalg_max = stoi(splitted[4]);
References[0].fastalg_avg = stof(splitted[5]);
fgets(zw, 1024, pFile);
splitted = ZerlegeZeile(std::string(zw));
if (splitted.size() < 6)
{
fclose(pFile);
return false;
}
References[1].fastalg_x = stoi(splitted[0]);
References[1].fastalg_y = stoi(splitted[1]);
References[1].fastalg_SAD = stof(splitted[2]);
References[1].fastalg_min = stoi(splitted[3]);
References[1].fastalg_max = stoi(splitted[4]);
References[1].fastalg_avg = stof(splitted[5]);
fclose(pFile);
/*#ifdef DEBUG_DETAIL_ON
std::string _zw = "\tLoadReferences[0]\tx,y:\t" + std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_x);
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
_zw = _zw + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
_zw = "\tLoadReferences[1]\tx,y:\t" + std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_x);
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
_zw = _zw + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
#endif*/
return true;
}
void ClassFlowAlignment::DrawRef(CImageBasis *_zw)
{
if (_zw->ImageOkay())
{
_zw->drawRect(References[0].target_x, References[0].target_y, References[0].width, References[0].height, 255, 0, 0, 2);
_zw->drawRect(References[1].target_x, References[1].target_y, References[1].width, References[1].height, 255, 0, 0, 2);
}
}
#include "ClassFlowAlignment.h"
#include "ClassFlowTakeImage.h"
#include "ClassFlow.h"
#include "MainFlowControl.h"
#include "CRotateImage.h"
#include "esp_log.h"
#include "ClassLogFile.h"
#include "psram.h"
#include "../../include/defines.h"
static const char *TAG = "ALIGN";
// #define DEBUG_DETAIL_ON
void ClassFlowAlignment::SetInitialParameter(void)
{
initialrotate = 0;
anz_ref = 0;
use_antialiasing = false;
initialflip = false;
SaveAllFiles = false;
namerawimage = "/sdcard/img_tmp/raw.jpg";
FileStoreRefAlignment = "/sdcard/config/align.txt";
ListFlowControll = NULL;
AlignAndCutImage = NULL;
ImageBasis = NULL;
ImageTMP = NULL;
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
AlgROI = (ImageData *)malloc_psram_heap(std::string(TAG) + "->AlgROI", sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
#endif
previousElement = NULL;
disabled = false;
SAD_criteria = 0.05;
}
ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow *> *lfc)
{
SetInitialParameter();
ListFlowControll = lfc;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowTakeImage") == 0)
{
ImageBasis = ((ClassFlowTakeImage *)(*ListFlowControll)[i])->rawImage;
}
}
if (!ImageBasis) // the function take pictures does not exist --> must be created first ONLY FOR TEST PURPOSES
{
ESP_LOGD(TAG, "CImageBasis had to be created");
ImageBasis = new CImageBasis("ImageBasis", namerawimage);
}
}
bool ClassFlowAlignment::ReadParameter(FILE *pfile, string &aktparamgraph)
{
std::vector<string> splitted;
int suchex = 40;
int suchey = 40;
int alg_algo = 0; // default=0; 1 =HIGHACCURACY; 2= FAST; 3= OFF //add disable aligment algo |01.2023
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
{
if (!this->GetNextParagraph(pfile, aktparamgraph))
{
return false;
}
}
if (aktparamgraph.compare("[Alignment]") != 0)
{
// Paragraph does not fit Alignment
return false;
}
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
splitted = ZerlegeZeile(aktparamgraph);
if ((toUpper(splitted[0]) == "FLIPIMAGESIZE") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
initialflip = true;
}
}
else if (((toUpper(splitted[0]) == "initialrotate") || (toUpper(splitted[0]) == "INITIALROTATE")) && (splitted.size() > 1))
{
this->initialrotate = std::stod(splitted[1]);
}
else if ((toUpper(splitted[0]) == "SEARCHFIELDX") && (splitted.size() > 1))
{
suchex = std::stod(splitted[1]);
}
else if ((toUpper(splitted[0]) == "SEARCHFIELDY") && (splitted.size() > 1))
{
suchey = std::stod(splitted[1]);
}
else if ((toUpper(splitted[0]) == "ANTIALIASING") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
use_antialiasing = true;
}
}
else if ((splitted.size() == 3) && (anz_ref < 2))
{
References[anz_ref].image_file = FormatFileName("/sdcard" + splitted[0]);
References[anz_ref].target_x = std::stod(splitted[1]);
References[anz_ref].target_y = std::stod(splitted[2]);
anz_ref++;
}
else if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
SaveAllFiles = true;
}
}
else if ((toUpper(splitted[0]) == "ALIGNMENTALGO") && (splitted.size() > 1))
{
#ifdef DEBUG_DETAIL_ON
std::string zw2 = "Alignment mode selected: " + splitted[1];
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
#endif
if (toUpper(splitted[1]) == "HIGHACCURACY")
{
alg_algo = 1;
}
if (toUpper(splitted[1]) == "FAST")
{
alg_algo = 2;
}
if (toUpper(splitted[1]) == "OFF")
{
// no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
alg_algo = 3;
}
}
}
for (int i = 0; i < anz_ref; ++i)
{
References[i].search_x = suchex;
References[i].search_y = suchey;
References[i].fastalg_SAD_criteria = SAD_criteria;
References[i].alignment_algo = alg_algo;
#ifdef DEBUG_DETAIL_ON
std::string zw2 = "Alignment mode written: " + std::to_string(alg_algo);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
#endif
}
// no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
if (References[0].alignment_algo != 3)
{
LoadReferenceAlignmentValues();
}
return true;
}
string ClassFlowAlignment::getHTMLSingleStep(string host)
{
string result;
result = "<p>Rotated Image: </p> <p><img src=\"" + host + "/img_tmp/rot.jpg\"></p>\n";
result = result + "<p>Found Alignment: </p> <p><img src=\"" + host + "/img_tmp/rot_roi.jpg\"></p>\n";
result = result + "<p>Aligned Image: </p> <p><img src=\"" + host + "/img_tmp/alg.jpg\"></p>\n";
return result;
}
bool ClassFlowAlignment::doFlow(string time)
{
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
if (!AlgROI) // AlgROI needs to be allocated before ImageTMP to avoid heap fragmentation
{
AlgROI = (ImageData *)heap_caps_realloc(AlgROI, sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
if (!AlgROI)
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlgROI");
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
}
}
if (AlgROI)
{
ImageBasis->writeToMemoryAsJPG((ImageData *)AlgROI, 90);
}
#endif
if (!ImageTMP)
{
ImageTMP = new CImageBasis("tmpImage", ImageBasis); // Make sure the name does not get change, it is relevant for the PSRAM allocation!
if (!ImageTMP)
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tmpImage -> Exec this round aborted!");
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
return false;
}
}
delete AlignAndCutImage;
AlignAndCutImage = new CAlignAndCutImage("AlignAndCutImage", ImageBasis, ImageTMP);
if (!AlignAndCutImage)
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlignAndCutImage -> Exec this round aborted!");
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
return false;
}
CRotateImage rt("rawImage", AlignAndCutImage, ImageTMP, initialflip);
if (initialflip)
{
int _zw = ImageBasis->height;
ImageBasis->height = ImageBasis->width;
ImageBasis->width = _zw;
_zw = ImageTMP->width;
ImageTMP->width = ImageTMP->height;
ImageTMP->height = _zw;
}
if ((initialrotate != 0) || initialflip)
{
if (use_antialiasing)
{
rt.RotateAntiAliasing(initialrotate);
}
else
{
rt.Rotate(initialrotate);
}
if (SaveAllFiles)
{
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
}
}
// 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]))
{
SaveReferenceAlignmentValues();
}
} // no align
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
if (AlgROI)
{
// no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
if (References[0].alignment_algo != 3)
{
DrawRef(ImageTMP);
}
flowctrl.DigitalDrawROI(ImageTMP);
flowctrl.AnalogDrawROI(ImageTMP);
ImageTMP->writeToMemoryAsJPG((ImageData *)AlgROI, 90);
}
#endif
if (SaveAllFiles)
{
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
ImageTMP->SaveToFile(FormatFileName("/sdcard/img_tmp/alg_roi.jpg"));
}
// must be deleted to have memory space for loading tflite
delete ImageTMP;
ImageTMP = NULL;
// no align algo if set to 3 = off => no draw ref //add disable aligment algo |01.2023
if (References[0].alignment_algo != 3)
{
LoadReferenceAlignmentValues();
}
return true;
}
void ClassFlowAlignment::SaveReferenceAlignmentValues()
{
FILE *pFile;
std::string zwtime, zwvalue;
pFile = fopen(FileStoreRefAlignment.c_str(), "w");
if (strlen(zwtime.c_str()) == 0)
{
time_t rawtime;
struct tm *timeinfo;
char buffer[80];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, 80, "%Y-%m-%dT%H:%M:%S", timeinfo);
zwtime = std::string(buffer);
}
fputs(zwtime.c_str(), pFile);
fputs("\n", pFile);
zwvalue = std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_y);
zwvalue = zwvalue + "\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
zwvalue = zwvalue + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
fputs(zwvalue.c_str(), pFile);
fputs("\n", pFile);
zwvalue = std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_y);
zwvalue = zwvalue + "\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
zwvalue = zwvalue + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
fputs(zwvalue.c_str(), pFile);
fputs("\n", pFile);
fclose(pFile);
}
bool ClassFlowAlignment::LoadReferenceAlignmentValues(void)
{
FILE *pFile;
char zw[1024];
string zwvalue;
std::vector<string> splitted;
pFile = fopen(FileStoreRefAlignment.c_str(), "r");
if (pFile == NULL)
return false;
fgets(zw, 1024, pFile);
ESP_LOGD(TAG, "%s", zw);
fgets(zw, 1024, pFile);
splitted = ZerlegeZeile(std::string(zw), " \t");
if (splitted.size() < 6)
{
fclose(pFile);
return false;
}
References[0].fastalg_x = stoi(splitted[0]);
References[0].fastalg_y = stoi(splitted[1]);
References[0].fastalg_SAD = stof(splitted[2]);
References[0].fastalg_min = stoi(splitted[3]);
References[0].fastalg_max = stoi(splitted[4]);
References[0].fastalg_avg = stof(splitted[5]);
fgets(zw, 1024, pFile);
splitted = ZerlegeZeile(std::string(zw));
if (splitted.size() < 6)
{
fclose(pFile);
return false;
}
References[1].fastalg_x = stoi(splitted[0]);
References[1].fastalg_y = stoi(splitted[1]);
References[1].fastalg_SAD = stof(splitted[2]);
References[1].fastalg_min = stoi(splitted[3]);
References[1].fastalg_max = stoi(splitted[4]);
References[1].fastalg_avg = stof(splitted[5]);
fclose(pFile);
/*#ifdef DEBUG_DETAIL_ON
std::string _zw = "\tLoadReferences[0]\tx,y:\t" + std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_x);
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
_zw = _zw + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
_zw = "\tLoadReferences[1]\tx,y:\t" + std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_x);
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
_zw = _zw + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
#endif*/
return true;
}
void ClassFlowAlignment::DrawRef(CImageBasis *_zw)
{
if (_zw->ImageOkay())
{
_zw->drawRect(References[0].target_x, References[0].target_y, References[0].width, References[0].height, 255, 0, 0, 2);
_zw->drawRect(References[1].target_x, References[1].target_y, References[1].width, References[1].height, 255, 0, 0, 2);
}
}

View File

@@ -1,54 +1,51 @@
#pragma once
#ifndef CLASSFLOWALIGNMENT_H
#define CLASSFLOWALIGNMENT_H
#include "ClassFlow.h"
#include "Helper.h"
#include "CAlignAndCutImage.h"
#include "CFindTemplate.h"
#include <string>
using namespace std;
class ClassFlowAlignment :
public ClassFlow
{
protected:
float initialrotate;
bool initialmirror;
bool initialflip;
bool use_antialiasing;
RefInfo References[2];
int anz_ref;
string namerawimage;
bool SaveAllFiles;
CAlignAndCutImage *AlignAndCutImage;
std::string FileStoreRefAlignment;
float SAD_criteria;
void SetInitialParameter(void);
bool LoadReferenceAlignmentValues(void);
void SaveReferenceAlignmentValues();
public:
CImageBasis *ImageBasis, *ImageTMP;
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
ImageData *AlgROI;
#endif
ClassFlowAlignment(std::vector<ClassFlow*>* lfc);
CAlignAndCutImage* GetAlignAndCutImage(){return AlignAndCutImage;};
void DrawRef(CImageBasis *_zw);
bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time);
string getHTMLSingleStep(string host);
string name(){return "ClassFlowAlignment";};
};
#endif //CLASSFLOWALIGNMENT_H
#pragma once
#ifndef CLASSFLOWALIGNMENT_H
#define CLASSFLOWALIGNMENT_H
#include "ClassFlow.h"
#include "Helper.h"
#include "CAlignAndCutImage.h"
#include "CFindTemplate.h"
#include <string>
using namespace std;
class ClassFlowAlignment : public ClassFlow
{
protected:
float initialrotate;
bool initialflip;
bool use_antialiasing;
RefInfo References[2];
int anz_ref;
string namerawimage;
bool SaveAllFiles;
CAlignAndCutImage *AlignAndCutImage;
std::string FileStoreRefAlignment;
float SAD_criteria;
void SetInitialParameter(void);
bool LoadReferenceAlignmentValues(void);
void SaveReferenceAlignmentValues();
public:
CImageBasis *ImageBasis, *ImageTMP;
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
ImageData *AlgROI;
#endif
ClassFlowAlignment(std::vector<ClassFlow *> *lfc);
CAlignAndCutImage *GetAlignAndCutImage() { return AlignAndCutImage; };
void DrawRef(CImageBasis *_zw);
bool ReadParameter(FILE *pfile, string &aktparamgraph);
bool doFlow(string time);
string getHTMLSingleStep(string host);
string name() { return "ClassFlowAlignment"; };
};
#endif // CLASSFLOWALIGNMENT_H

View File

@@ -166,7 +166,8 @@ int ClassFlowCNNGeneral::PointerEvalHybridNew(float number, float number_of_pred
return result;
}
if ((number_of_predecessors >= Digital_Transition_Area_Predecessor ) && (number_of_predecessors <= (10.0 - Digital_Transition_Area_Predecessor))) {
if ((number_of_predecessors > Digital_Transition_Area_Predecessor ) && (number_of_predecessors < (10.0 - Digital_Transition_Area_Predecessor)))
{
// no digit change, because predecessor is far enough away (0+/-DigitalTransitionRangePredecessor) --> number is rounded
// Band around the digit --> Round off, as digit reaches inaccuracy in the frame
if ((result_after_decimal_point <= DigitalBand) || (result_after_decimal_point >= (10-DigitalBand))) {
@@ -204,7 +205,8 @@ int ClassFlowCNNGeneral::PointerEvalHybridNew(float number, float number_of_pred
// everything >=x.4 can be considered as current number in transition. With 9.x predecessor the current
// number can still be x.6 - x.7.
// Preceding (else - branch) does not already happen from 9.
if (Digital_Transition_Area_Forward>=number_of_predecessors || result_after_decimal_point >= 4) {
if (((Digital_Transition_Area_Forward>=number_of_predecessors) && (eval_predecessors == (int)number_of_predecessors))
|| result_after_decimal_point >= 4) {
// The current digit, like the previous digit, does not yet have a zero crossing.
result = result_before_decimal_point % 10;
}
@@ -227,8 +229,8 @@ int ClassFlowCNNGeneral::PointerEvalAnalogToDigitNew(float number, float numeral
bool roundedUp = false;
// Within the digital inequalities
if ((result_after_decimal_point >= (10-Digital_Uncertainty * 10)) // Band around the digit --> Round off, as digit reaches inaccuracy in the frame
|| (eval_predecessors <= 4 && result_after_decimal_point>=6)) { // or digit runs after (analogue =0..4, digit >=6)
if ((result_after_decimal_point >= (10-Digital_Uncertainty * 10) && ((int)numeral_preceder == eval_predecessors)) // Band around the digit --> Round off, as digit reaches inaccuracy in the frame
|| (eval_predecessors <= 4 && result_after_decimal_point>=6)) { // or digit runs after (analogue =0..4, digit >=6)
result = (int) (round(number) + 10) % 10;
roundedUp = true;
// before/ after decimal point, because we adjust the number based on the uncertainty.
@@ -238,7 +240,14 @@ int ClassFlowCNNGeneral::PointerEvalAnalogToDigitNew(float number, float numeral
" number: " + std::to_string(number) + " numeral_preceder: " + std::to_string(numeral_preceder) +
" erg before comma: " + std::to_string(result_before_decimal_point) +
" erg after comma: " + std::to_string(result_after_decimal_point));
}
}
else if (result_after_decimal_point < Digital_Uncertainty && numeral_preceder > analogDigitalTransitionStart) {
result = ((result_before_decimal_point+10) - 1) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - Digital Uncertainty - Too early zero crossing - Result = " + std::to_string(result) +
" number: " + std::to_string(number) + " numeral_preceder: " + std::to_string(numeral_preceder) +
" erg before comma: " + std::to_string(result_before_decimal_point) +
" erg after comma: " + std::to_string(result_after_decimal_point));
}
else {
result = (int) ((int) trunc(number) + 10) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - NO digital Uncertainty - Result = " + std::to_string(result) +
@@ -248,9 +257,10 @@ int ClassFlowCNNGeneral::PointerEvalAnalogToDigitNew(float number, float numeral
// No zero crossing has taken place.
// Only eval_predecessors used because numeral_preceder could be wrong here.
// numeral_preceder<=0.1 & eval_predecessors=9 corresponds to analogue was reset because of previous analogue that are not yet at 0.
if ((eval_predecessors>=6 && (numeral_preceder>analogDigitalTransitionStart || numeral_preceder<=0.2) && roundedUp)) {
result = ((result_before_decimal_point+10) - 1) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - Nulldurchgang noch nicht stattgefunden = " + std::to_string(result) +
if ((eval_predecessors >= 3 && (numeral_preceder > analogDigitalTransitionStart) && roundedUp))
{
result = ((result_before_decimal_point+10) - 1) % 10;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - No correction = " + std::to_string(result) +
" number: " + std::to_string(number) +
" numeral_preceder = " + std::to_string(numeral_preceder) +
" eerg after comma = " + std::to_string(result_after_decimal_point));

View File

@@ -1,9 +1,15 @@
#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include "ClassFlowTakeImage.h"
#include "Helper.h"
#include "ClassLogFile.h"
#include "CImageBasis.h"
#include "ClassControllCamera.h"
#include "MainFlowControl.h"
#include "esp_wifi.h"
#include "esp_log.h"
@@ -12,14 +18,14 @@
#include <time.h>
// #define DEBUG_DETAIL_ON
// #define DEBUG_DETAIL_ON
// #define WIFITURNOFF
static const char* TAG = "TAKEIMAGE";
static const char *TAG = "TAKEIMAGE";
esp_err_t ClassFlowTakeImage::camera_capture(){
string nm = namerawimage;
esp_err_t ClassFlowTakeImage::camera_capture(void)
{
string nm = namerawimage;
Camera.CaptureToFile(nm);
time(&TimeImageTaken);
localtime(&TimeImageTaken);
@@ -30,205 +36,480 @@ esp_err_t ClassFlowTakeImage::camera_capture(){
void ClassFlowTakeImage::takePictureWithFlash(int flash_duration)
{
// in case the image is flipped, it must be reset here //
rawImage->width = image_width;
rawImage->height = image_height;
/////////////////////////////////////////////////////////////////////////////////////
rawImage->width = CCstatus.ImageWidth;
rawImage->height = CCstatus.ImageHeight;
ESP_LOGD(TAG, "flash_duration: %d", flash_duration);
Camera.CaptureToBasisImage(rawImage, flash_duration);
time(&TimeImageTaken);
localtime(&TimeImageTaken);
if (SaveAllFiles) rawImage->SaveToFile(namerawimage);
if (CCstatus.SaveAllFiles)
{
rawImage->SaveToFile(namerawimage);
}
}
void ClassFlowTakeImage::SetInitialParameter(void)
{
waitbeforepicture = 5;
isImageSize = false;
ImageQuality = -1;
TimeImageTaken = 0;
ImageQuality = 5;
rawImage = NULL;
ImageSize = FRAMESIZE_VGA;
ZoomEnabled = false;
ZoomMode = 0;
zoomOffsetX = 0;
zoomOffsetY = 0;
ImageNegative = false;
ImageAec2 = false;
#ifdef GRAYSCALE_AS_DEFAULT
ImageGrayscale = true;
#else
ImageGrayscale = false;
#endif
SaveAllFiles = false;
disabled = false;
FixedExposure = false;
namerawimage = "/sdcard/img_tmp/raw.jpg";
}
}
// auslesen der Kameraeinstellungen aus der config.ini
// wird beim Start aufgerufen
bool ClassFlowTakeImage::ReadParameter(FILE *pfile, string &aktparamgraph)
{
Camera.getSensorDatenToCCstatus(); // Kamera >>> CCstatus
ClassFlowTakeImage::ClassFlowTakeImage(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
std::vector<string> splitted;
aktparamgraph = trim(aktparamgraph);
if (aktparamgraph.size() == 0)
{
if (!this->GetNextParagraph(pfile, aktparamgraph))
{
return false;
}
}
if (aktparamgraph.compare("[TakeImage]") != 0)
{
// Paragraph does not fit TakeImage
return false;
}
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
splitted = ZerlegeZeile(aktparamgraph);
if ((toUpper(splitted[0]) == "RAWIMAGESLOCATION") && (splitted.size() > 1))
{
imagesLocation = "/sdcard" + splitted[1];
isLogImage = true;
}
else if ((toUpper(splitted[0]) == "RAWIMAGESRETENTION") && (splitted.size() > 1))
{
this->imagesRetention = std::stod(splitted[1]);
}
else if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.SaveAllFiles = 1;
}
else
{
CCstatus.SaveAllFiles = 0;
}
}
else if ((toUpper(splitted[0]) == "WAITBEFORETAKINGPICTURE") && (splitted.size() > 1))
{
int _WaitBeforePicture = std::stoi(splitted[1]);
if (_WaitBeforePicture != 0)
{
CCstatus.WaitBeforePicture = _WaitBeforePicture;
}
else
{
CCstatus.WaitBeforePicture = 2;
}
}
else if ((toUpper(splitted[0]) == "CAMGAINCEILING") && (splitted.size() > 1))
{
std::string _ImageGainceiling = toUpper(splitted[1]);
if (_ImageGainceiling == "X4")
{
CCstatus.ImageGainceiling = GAINCEILING_4X;
}
else if (_ImageGainceiling == "X8")
{
CCstatus.ImageGainceiling = GAINCEILING_8X;
}
else if (_ImageGainceiling == "X16")
{
CCstatus.ImageGainceiling = GAINCEILING_16X;
}
else if (_ImageGainceiling == "X32")
{
CCstatus.ImageGainceiling = GAINCEILING_32X;
}
else if (_ImageGainceiling == "X64")
{
CCstatus.ImageGainceiling = GAINCEILING_64X;
}
else if (_ImageGainceiling == "X128")
{
CCstatus.ImageGainceiling = GAINCEILING_128X;
}
else
{
CCstatus.ImageGainceiling = GAINCEILING_2X;
}
}
else if ((toUpper(splitted[0]) == "CAMQUALITY") && (splitted.size() > 1))
{
int _ImageQuality = std::stoi(splitted[1]);
if ((_ImageQuality >= 0) && (_ImageQuality <= 63))
{
CCstatus.ImageQuality = _ImageQuality;
}
}
else if ((toUpper(splitted[0]) == "CAMBRIGHTNESS") && (splitted.size() > 1))
{
int _ImageBrightness = std::stoi(splitted[1]);
if ((_ImageBrightness >= -2) && (_ImageBrightness <= 2))
{
CCstatus.ImageBrightness = _ImageBrightness;
}
}
else if ((toUpper(splitted[0]) == "CAMCONTRAST") && (splitted.size() > 1))
{
int _ImageContrast = std::stoi(splitted[1]);
if ((_ImageContrast >= -2) && (_ImageContrast <= 2))
{
CCstatus.ImageContrast = _ImageContrast;
}
}
else if ((toUpper(splitted[0]) == "CAMSATURATION") && (splitted.size() > 1))
{
int _ImageSaturation = std::stoi(splitted[1]);
if ((_ImageSaturation >= -2) && (_ImageSaturation <= 2))
{
CCstatus.ImageSaturation = _ImageSaturation;
}
}
else if ((toUpper(splitted[0]) == "CAMSHARPNESS") && (splitted.size() > 1))
{
int _ImageSharpness = std::stoi(splitted[1]);
if ((_ImageSharpness >= -2) && (_ImageSharpness <= 2))
{
CCstatus.ImageSharpness = _ImageSharpness;
}
}
else if ((toUpper(splitted[0]) == "CAMAUTOSHARPNESS") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageAutoSharpness = 1;
}
else
{
CCstatus.ImageAutoSharpness = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMSPECIALEFFECT") && (splitted.size() > 1))
{
std::string _ImageSpecialEffect = toUpper(splitted[1]);
if (_ImageSpecialEffect == "NEGATIVE")
{
CCstatus.ImageSpecialEffect = 1;
}
else if (_ImageSpecialEffect == "GRAYSCALE")
{
CCstatus.ImageSpecialEffect = 2;
}
else if (_ImageSpecialEffect == "RED")
{
CCstatus.ImageSpecialEffect = 3;
}
else if (_ImageSpecialEffect == "GREEN")
{
CCstatus.ImageSpecialEffect = 4;
}
else if (_ImageSpecialEffect == "BLUE")
{
CCstatus.ImageSpecialEffect = 5;
}
else if (_ImageSpecialEffect == "RETRO")
{
CCstatus.ImageSpecialEffect = 6;
}
else
{
CCstatus.ImageSpecialEffect = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMWBMODE") && (splitted.size() > 1))
{
std::string _ImageWbMode = toUpper(splitted[1]);
if (_ImageWbMode == "SUNNY")
{
CCstatus.ImageWbMode = 1;
}
else if (_ImageWbMode == "CLOUDY")
{
CCstatus.ImageWbMode = 2;
}
else if (_ImageWbMode == "OFFICE")
{
CCstatus.ImageWbMode = 3;
}
else if (_ImageWbMode == "HOME")
{
CCstatus.ImageWbMode = 4;
}
else
{
CCstatus.ImageWbMode = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMAWB") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageAwb = 1;
}
else
{
CCstatus.ImageAwb = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMAWBGAIN") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageAwbGain = 1;
}
else
{
CCstatus.ImageAwbGain = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMAEC") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageAec = 1;
}
else
{
CCstatus.ImageAec = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMAEC2") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageAec2 = 1;
}
else
{
CCstatus.ImageAec2 = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMAELEVEL") && (splitted.size() > 1))
{
int _ImageAeLevel = std::stoi(splitted[1]);
if ((_ImageAeLevel >= -2) && (_ImageAeLevel <= 2))
{
CCstatus.ImageAeLevel = _ImageAeLevel;
}
}
else if ((toUpper(splitted[0]) == "CAMAECVALUE") && (splitted.size() > 1))
{
int _ImageAecValue = std::stoi(splitted[1]);
if ((_ImageAecValue >= 0) && (_ImageAecValue <= 1200))
{
CCstatus.ImageAecValue = _ImageAecValue;
}
}
else if ((toUpper(splitted[0]) == "CAMAGC") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageAgc = 1;
}
else
{
CCstatus.ImageAgc = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMAGCGAIN") && (splitted.size() > 1))
{
int _ImageAgcGain = std::stoi(splitted[1]);
if ((_ImageAgcGain >= 0) && (_ImageAgcGain <= 30))
{
CCstatus.ImageAgcGain = _ImageAgcGain;
}
}
else if ((toUpper(splitted[0]) == "CAMBPC") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageBpc = 1;
}
else
{
CCstatus.ImageBpc = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMWPC") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageWpc = 1;
}
else
{
CCstatus.ImageWpc = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMRAWGMA") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageRawGma = 1;
}
else
{
CCstatus.ImageRawGma = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMLENC") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageLenc = 1;
}
else
{
CCstatus.ImageLenc = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMHMIRROR") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageHmirror = 1;
}
else
{
CCstatus.ImageHmirror = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMVFLIP") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageVflip = 1;
}
else
{
CCstatus.ImageVflip = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMDCW") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageDcw = 1;
}
else
{
CCstatus.ImageDcw = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMZOOM") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.ImageZoomEnabled = 1;
}
else
{
CCstatus.ImageZoomEnabled = 0;
}
}
else if ((toUpper(splitted[0]) == "CAMZOOMOFFSETX") && (splitted.size() > 1))
{
CCstatus.ImageZoomOffsetX = std::stoi(splitted[1]);
}
else if ((toUpper(splitted[0]) == "CAMZOOMOFFSETY") && (splitted.size() > 1))
{
CCstatus.ImageZoomOffsetY = std::stoi(splitted[1]);
}
else if ((toUpper(splitted[0]) == "CAMZOOMSIZE") && (splitted.size() > 1))
{
int _ImageZoomSize = std::stoi(splitted[1]);
if (_ImageZoomSize >= 0)
{
CCstatus.ImageZoomSize = _ImageZoomSize;
}
}
else if ((toUpper(splitted[0]) == "LEDINTENSITY") && (splitted.size() > 1))
{
float ledintensity = std::stof(splitted[1]);
Camera.SetLEDIntensity(ledintensity);
}
else if ((toUpper(splitted[0]) == "DEMO") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
{
CCstatus.DemoMode = true;
Camera.useDemoMode();
}
else
{
CCstatus.DemoMode = false;
}
}
}
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
rawImage = new CImageBasis("rawImage");
rawImage->CreateEmptyImage(CCstatus.ImageWidth, CCstatus.ImageHeight, 3);
return true;
}
ClassFlowTakeImage::ClassFlowTakeImage(std::vector<ClassFlow *> *lfc) : ClassFlowImage(lfc, TAG)
{
imagesLocation = "/log/source";
imagesRetention = 5;
SetInitialParameter();
}
bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector<string> splitted;
aktparamgraph = trim(aktparamgraph);
int _brightness = 0;
int _contrast = 0;
int _saturation = 0;
int _sharpness = 0;
int _autoExposureLevel = 0;
if (aktparamgraph.size() == 0)
if (!this->GetNextParagraph(pfile, aktparamgraph))
return false;
if (aktparamgraph.compare("[TakeImage]") != 0) // Paragraph does not fit TakeImage
return false;
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
splitted = ZerlegeZeile(aktparamgraph);
if ((toUpper(splitted[0]) == "RAWIMAGESLOCATION") && (splitted.size() > 1))
{
imagesLocation = "/sdcard" + splitted[1];
isLogImage = true;
}
if ((toUpper(splitted[0]) == "IMAGEQUALITY") && (splitted.size() > 1))
ImageQuality = std::stod(splitted[1]);
if ((toUpper(splitted[0]) == "ZOOM") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
ZoomEnabled = true;
else if (toUpper(splitted[1]) == "FALSE")
ZoomEnabled = false;
}
if ((toUpper(splitted[0]) == "ZOOMMODE") && (splitted.size() > 1))
ZoomMode = std::stod(splitted[1]);
if ((toUpper(splitted[0]) == "ZOOMOFFSETX") && (splitted.size() > 1))
zoomOffsetX = std::stod(splitted[1]);
if ((toUpper(splitted[0]) == "ZOOMOFFSETY") && (splitted.size() > 1))
zoomOffsetY = std::stod(splitted[1]);
if ((toUpper(splitted[0]) == "GRAYSCALE") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
ImageGrayscale = true;
else if (toUpper(splitted[1]) == "FALSE")
ImageGrayscale = false;
}
if ((toUpper(splitted[0]) == "NEGATIVE") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
ImageNegative = true;
else if (toUpper(splitted[1]) == "FALSE")
ImageNegative = false;
}
if ((toUpper(splitted[0]) == "AEC2") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
ImageAec2 = true;
else if (toUpper(splitted[1]) == "FALSE")
ImageAec2 = false;
}
if ((toUpper(splitted[0]) == "AUTOEXPOSURELEVEL") && (splitted.size() > 1))
_autoExposureLevel = std::stod(splitted[1]);
if ((toUpper(splitted[0]) == "IMAGESIZE") && (splitted.size() > 1))
{
ImageSize = Camera.TextToFramesize(splitted[1].c_str());
isImageSize = true;
}
if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
SaveAllFiles = true;
}
if ((toUpper(splitted[0]) == "WAITBEFORETAKINGPICTURE") && (splitted.size() > 1))
{
waitbeforepicture = stoi(splitted[1]);
}
if ((toUpper(splitted[0]) == "RAWIMAGESRETENTION") && (splitted.size() > 1))
{
this->imagesRetention = std::stoi(splitted[1]);
}
if ((toUpper(splitted[0]) == "BRIGHTNESS") && (splitted.size() > 1))
{
_brightness = stoi(splitted[1]);
}
if ((toUpper(splitted[0]) == "CONTRAST") && (splitted.size() > 1))
{
_contrast = stoi(splitted[1]);
}
if ((toUpper(splitted[0]) == "SATURATION") && (splitted.size() > 1))
{
_saturation = stoi(splitted[1]);
}
if ((toUpper(splitted[0]) == "SHARPNESS") && (splitted.size() > 1))
{
_sharpness = stoi(splitted[1]);
}
if ((toUpper(splitted[0]) == "FIXEDEXPOSURE") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
FixedExposure = true;
}
if ((toUpper(splitted[0]) == "LEDINTENSITY") && (splitted.size() > 1))
{
float ledintensity = stof(splitted[1]);
ledintensity = min((float) 100, ledintensity);
ledintensity = max((float) 0, ledintensity);
Camera.SetLEDIntensity(ledintensity);
}
if ((toUpper(splitted[0]) == "DEMO") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
Camera.useDemoMode();
}
}
Camera.SetBrightnessContrastSaturation(_brightness, _contrast, _saturation, _autoExposureLevel, ImageGrayscale, ImageNegative, ImageAec2, _sharpness);
Camera.SetQualitySize(ImageQuality, ImageSize, ZoomEnabled, ZoomMode, zoomOffsetX, zoomOffsetY);
image_width = Camera.image_width;
image_height = Camera.image_height;
rawImage = new CImageBasis("rawImage");
rawImage->CreateEmptyImage(image_width, image_height, 3);
waitbeforepicture_store = waitbeforepicture;
if (FixedExposure && (waitbeforepicture > 0))
{
// ESP_LOGD(TAG, "Fixed Exposure enabled!");
int flash_duration = (int) (waitbeforepicture * 1000);
Camera.EnableAutoExposure(flash_duration);
waitbeforepicture = 0.2;
// flash_duration = (int) (waitbeforepicture * 1000);
// takePictureWithFlash(flash_duration);
// rawImage->SaveToFile("/sdcard/init2.jpg");
}
return true;
}
string ClassFlowTakeImage::getHTMLSingleStep(string host)
{
string result;
@@ -236,74 +517,78 @@ string ClassFlowTakeImage::getHTMLSingleStep(string host)
return result;
}
// wird bei jeder Auswertrunde aufgerufen
bool ClassFlowTakeImage::doFlow(string zwtime)
{
psram_init_shared_memory_for_take_image_step();
string logPath = CreateLogFolder(zwtime);
int flash_duration = (int) (waitbeforepicture * 1000);
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - Before takePictureWithFlash");
#endif
int flash_duration = (int)(CCstatus.WaitBeforePicture * 1000);
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - Before takePictureWithFlash");
#endif
#ifdef WIFITURNOFF
esp_wifi_stop(); // to save power usage and
#endif
#ifdef WIFITURNOFF
esp_wifi_stop(); // to save power usage and
#endif
// wenn die Kameraeinstellungen durch Erstellen eines neuen Referenzbildes verändert wurden, müssen sie neu gesetzt werden
if (CFstatus.changedCameraSettings)
{
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize);
CFstatus.changedCameraSettings = false;
}
takePictureWithFlash(flash_duration);
#ifdef WIFITURNOFF
esp_wifi_start();
#endif
#ifdef WIFITURNOFF
esp_wifi_start();
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - After takePictureWithFlash");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - After takePictureWithFlash");
#endif
LogImage(logPath, "raw", NULL, NULL, zwtime, rawImage);
RemoveOldLogs();
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - After RemoveOldLogs");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("ClassFlowTakeImage::doFlow - After RemoveOldLogs");
#endif
psram_deinit_shared_memory_for_take_image_step();
return true;
}
esp_err_t ClassFlowTakeImage::SendRawJPG(httpd_req_t *req)
{
int flash_duration = (int) (waitbeforepicture * 1000);
int flash_duration = (int)(CCstatus.WaitBeforePicture * 1000);
time(&TimeImageTaken);
localtime(&TimeImageTaken);
return Camera.CaptureToHTTP(req, flash_duration);
}
ImageData* ClassFlowTakeImage::SendRawImage()
ImageData *ClassFlowTakeImage::SendRawImage(void)
{
CImageBasis *zw = new CImageBasis("SendRawImage", rawImage);
ImageData *id;
int flash_duration = (int) (waitbeforepicture * 1000);
int flash_duration = (int)(CCstatus.WaitBeforePicture * 1000);
Camera.CaptureToBasisImage(zw, flash_duration);
time(&TimeImageTaken);
localtime(&TimeImageTaken);
id = zw->writeToMemoryAsJPG();
id = zw->writeToMemoryAsJPG();
delete zw;
return id;
return id;
}
time_t ClassFlowTakeImage::getTimeImageTaken()
time_t ClassFlowTakeImage::getTimeImageTaken(void)
{
return TimeImageTaken;
}
@@ -312,4 +597,3 @@ ClassFlowTakeImage::~ClassFlowTakeImage(void)
{
delete rawImage;
}

View File

@@ -9,54 +9,32 @@
#include <string>
class ClassFlowTakeImage :
public ClassFlowImage
class ClassFlowTakeImage : public ClassFlowImage
{
protected:
float waitbeforepicture;
float waitbeforepicture_store;
framesize_t ImageSize;
bool isImageSize;
bool ZoomEnabled = false;
int ZoomMode = 0;
int zoomOffsetX = 0;
int zoomOffsetY = 0;
bool ImageGrayscale;
bool ImageNegative;
bool ImageAec2;
int ImageQuality;
time_t TimeImageTaken;
string namerawimage;
int image_height, image_width;
bool SaveAllFiles;
bool FixedExposure;
void CopyFile(string input, string output);
esp_err_t camera_capture();
esp_err_t camera_capture(void);
void takePictureWithFlash(int flash_duration);
void SetInitialParameter(void);
void SetInitialParameter(void);
public:
CImageBasis *rawImage;
ClassFlowTakeImage(std::vector<ClassFlow*>* lfc);
ClassFlowTakeImage(std::vector<ClassFlow *> *lfc);
bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool ReadParameter(FILE *pfile, string &aktparamgraph);
bool doFlow(string time);
string getHTMLSingleStep(string host);
time_t getTimeImageTaken();
string name(){return "ClassFlowTakeImage";};
time_t getTimeImageTaken(void);
string name() { return "ClassFlowTakeImage"; };
ImageData* SendRawImage();
ImageData *SendRawImage(void);
esp_err_t SendRawJPG(httpd_req_t *req);
~ClassFlowTakeImage(void);
};
#endif //CLASSFFLOWTAKEIMAGE_H
#endif // CLASSFFLOWTAKEIMAGE_H

File diff suppressed because it is too large Load Diff

View File

@@ -10,25 +10,78 @@
#include "CImageBasis.h"
#include "ClassFlowControll.h"
typedef struct
{
framesize_t ImageFrameSize = FRAMESIZE_VGA; // 0 - 10
gainceiling_t ImageGainceiling; // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
int ImageQuality; // 0 - 63
int ImageBrightness; // (-2 to 2) - set brightness
int ImageContrast; //-2 - 2
int ImageSaturation; //-2 - 2
int ImageSharpness; //-2 - 2
bool ImageAutoSharpness;
int ImageSpecialEffect; // 0 - 6
int ImageWbMode; // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
int ImageAwb; // white balance enable (0 or 1)
int ImageAwbGain; // Auto White Balance enable (0 or 1)
int ImageAec; // auto exposure off (1 or 0)
int ImageAec2; // automatic exposure sensor (0 or 1)
int ImageAeLevel; // auto exposure levels (-2 to 2)
int ImageAecValue; // set exposure manually (0-1200)
int ImageAgc; // auto gain off (1 or 0)
int ImageAgcGain; // set gain manually (0 - 30)
int ImageBpc; // black pixel correction
int ImageWpc; // white pixel correction
int ImageRawGma; // (1 or 0)
int ImageLenc; // lens correction (1 or 0)
int ImageHmirror; // (0 or 1) flip horizontally
int ImageVflip; // Invert image (0 or 1)
int ImageDcw; // downsize enable (1 or 0)
int ImageWidth;
int ImageHeight;
int ImageLedIntensity;
bool ImageZoomEnabled;
int ImageZoomMode;
int ImageZoomOffsetX;
int ImageZoomOffsetY;
int ImageZoomSize;
int WaitBeforePicture;
bool isImageSize;
bool CameraInitSuccessful;
bool changedCameraSettings;
bool DemoMode;
bool SaveAllFiles;
} camera_flow_config_temp_t;
extern camera_flow_config_temp_t CFstatus;
extern ClassFlowControll flowctrl;
esp_err_t setCCstatusToCFstatus(void); // CCstatus >>> CFstatus
esp_err_t setCFstatusToCCstatus(void); // CFstatus >>> CCstatus
esp_err_t setCFstatusToCam(void); // CFstatus >>> Kamera
void register_server_main_flow_task_uri(httpd_handle_t server);
void CheckIsPlannedReboot();
bool getIsPlannedReboot();
void CheckIsPlannedReboot(void);
bool getIsPlannedReboot(void);
void InitializeFlowTask();
void DeleteMainFlowTask();
bool isSetupModusActive();
void InitializeFlowTask(void);
void DeleteMainFlowTask(void);
bool isSetupModusActive(void);
int getCountFlowRounds();
int getCountFlowRounds(void);
#ifdef ENABLE_MQTT
esp_err_t MQTTCtrlFlowStart(std::string _topic);
#endif //ENABLE_MQTT
#endif // ENABLE_MQTT
esp_err_t GetRawJPG(httpd_req_t *req);
esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
#endif //MAINFLOWCONTROL_H
#endif // MAINFLOWCONTROL_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,353 +1,309 @@
#include <string>
#include "CRotateImage.h"
#include "psram.h"
static const char *TAG = "C ROTATE IMG";
CRotateImage::CRotateImage(std::string _name, CImageBasis *_org, CImageBasis *_temp, bool _flip) : CImageBasis(_name)
{
rgb_image = _org->rgb_image;
channels = _org->channels;
width = _org->width;
height = _org->height;
bpp = _org->bpp;
externalImage = true;
ImageTMP = _temp;
ImageOrg = _org;
islocked = false;
doflip = _flip;
}
void CRotateImage::Mirror(){
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->RGBImageLock();
}
else
{
odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
}
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
RGBImageLock();
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = width - x;
y_source = y;
p_source = rgb_image + (channels * (y_source * width + x_source));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
free_psram_heap(std::string(TAG) + "->odata", odata);
if (ImageTMP)
ImageTMP->RGBImageRelease();
RGBImageRelease();
}
void CRotateImage::Rotate(float _angle, int _centerx, int _centery)
{
int org_width, org_height;
float m[2][3];
float x_center = _centerx;
float y_center = _centery;
_angle = _angle / 180 * M_PI;
if (doflip)
{
org_width = width;
org_height = height;
height = org_width;
width = org_height;
x_center = x_center - (org_width/2) + (org_height/2);
y_center = y_center + (org_width/2) - (org_height/2);
if (ImageOrg)
{
ImageOrg->height = height;
ImageOrg->width = width;
}
}
else
{
org_width = width;
org_height = height;
}
m[0][0] = cos(_angle);
m[0][1] = sin(_angle);
m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
m[1][0] = -m[0][1];
m[1][1] = m[0][0];
m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
if (doflip)
{
m[0][2] = m[0][2] + (org_width/2) - (org_height/2);
m[1][2] = m[1][2] - (org_width/2) + (org_height/2);
}
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->RGBImageLock();
}
else
{
odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
}
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
RGBImageLock();
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = int(m[0][0] * x + m[0][1] * y);
y_source = int(m[1][0] * x + m[1][1] * y);
x_source += int(m[0][2]);
y_source += int(m[1][2]);
if ((x_source >= 0) && (x_source < org_width) && (y_source >= 0) && (y_source < org_height))
{
p_source = rgb_image + (channels * (y_source * org_width + x_source));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
else
{
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = 255;
}
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
{
free_psram_heap(std::string(TAG) + "->odata", odata);
}
if (ImageTMP)
ImageTMP->RGBImageRelease();
RGBImageRelease();
}
void CRotateImage::RotateAntiAliasing(float _angle, int _centerx, int _centery)
{
int org_width, org_height;
float m[2][3];
float x_center = _centerx;
float y_center = _centery;
_angle = _angle / 180 * M_PI;
if (doflip)
{
org_width = width;
org_height = height;
height = org_width;
width = org_height;
x_center = x_center - (org_width/2) + (org_height/2);
y_center = y_center + (org_width/2) - (org_height/2);
if (ImageOrg)
{
ImageOrg->height = height;
ImageOrg->width = width;
}
}
else
{
org_width = width;
org_height = height;
}
m[0][0] = cos(_angle);
m[0][1] = sin(_angle);
m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
m[1][0] = -m[0][1];
m[1][1] = m[0][0];
m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
if (doflip)
{
m[0][2] = m[0][2] + (org_width/2) - (org_height/2);
m[1][2] = m[1][2] - (org_width/2) + (org_height/2);
}
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->RGBImageLock();
}
else
{
odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
}
int x_source_1, y_source_1, x_source_2, y_source_2;
float x_source, y_source;
float quad_ul, quad_ur, quad_ol, quad_or;
stbi_uc* p_target;
stbi_uc *p_source_ul, *p_source_ur, *p_source_ol, *p_source_or;
RGBImageLock();
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = (m[0][0] * x + m[0][1] * y);
y_source = (m[1][0] * x + m[1][1] * y);
x_source += (m[0][2]);
y_source += (m[1][2]);
x_source_1 = (int)x_source;
x_source_2 = x_source_1 + 1;
y_source_1 = (int)y_source;
y_source_2 = y_source_1 + 1;
quad_ul = (x_source_2 - x_source) * (y_source_2 - y_source);
quad_ur = (1- (x_source_2 - x_source)) * (y_source_2 - y_source);
quad_or = (x_source_2 - x_source) * (1-(y_source_2 - y_source));
quad_ol = (1- (x_source_2 - x_source)) * (1-(y_source_2 - y_source));
if ((x_source_1 >= 0) && (x_source_2 < org_width) && (y_source_1 >= 0) && (y_source_2 < org_height))
{
p_source_ul = rgb_image + (channels * (y_source_1 * org_width + x_source_1));
p_source_ur = rgb_image + (channels * (y_source_1 * org_width + x_source_2));
p_source_or = rgb_image + (channels * (y_source_2 * org_width + x_source_1));
p_source_ol = rgb_image + (channels * (y_source_2 * org_width + x_source_2));
for (int _channels = 0; _channels < channels; ++_channels)
{
p_target[_channels] = (int)((float)p_source_ul[_channels] * quad_ul
+ (float)p_source_ur[_channels] * quad_ur
+ (float)p_source_or[_channels] * quad_or
+ (float)p_source_ol[_channels] * quad_ol);
}
}
else
{
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = 255;
}
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
{
free_psram_heap(std::string(TAG) + "->odata", odata);
}
if (ImageTMP)
ImageTMP->RGBImageRelease();
RGBImageRelease();
}
void CRotateImage::Rotate(float _angle)
{
// ESP_LOGD(TAG, "width %d, height %d", width, height);
Rotate(_angle, width / 2, height / 2);
}
void CRotateImage::RotateAntiAliasing(float _angle)
{
// ESP_LOGD(TAG, "width %d, height %d", width, height);
RotateAntiAliasing(_angle, width / 2, height / 2);
}
void CRotateImage::Translate(int _dx, int _dy)
{
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->RGBImageLock();
}
else
{
odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
}
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
RGBImageLock();
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = x - _dx;
y_source = y - _dy;
if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height))
{
p_source = rgb_image + (channels * (y_source * width + x_source));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
else
{
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = 255;
}
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
{
free_psram_heap(std::string(TAG) + "->odata", odata);
}
if (ImageTMP)
{
ImageTMP->RGBImageRelease();
}
RGBImageRelease();
}
#include <string>
#include "CRotateImage.h"
#include "psram.h"
static const char *TAG = "C ROTATE IMG";
CRotateImage::CRotateImage(std::string _name, CImageBasis *_org, CImageBasis *_temp, bool _flip) : CImageBasis(_name)
{
rgb_image = _org->rgb_image;
channels = _org->channels;
width = _org->width;
height = _org->height;
bpp = _org->bpp;
externalImage = true;
ImageTMP = _temp;
ImageOrg = _org;
islocked = false;
doflip = _flip;
}
void CRotateImage::Rotate(float _angle, int _centerx, int _centery)
{
int org_width, org_height;
float m[2][3];
float x_center = _centerx;
float y_center = _centery;
_angle = _angle / 180 * M_PI;
if (doflip)
{
org_width = width;
org_height = height;
height = org_width;
width = org_height;
x_center = x_center - (org_width/2) + (org_height/2);
y_center = y_center + (org_width/2) - (org_height/2);
if (ImageOrg)
{
ImageOrg->height = height;
ImageOrg->width = width;
}
}
else
{
org_width = width;
org_height = height;
}
m[0][0] = cos(_angle);
m[0][1] = sin(_angle);
m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
m[1][0] = -m[0][1];
m[1][1] = m[0][0];
m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
if (doflip)
{
m[0][2] = m[0][2] + (org_width/2) - (org_height/2);
m[1][2] = m[1][2] - (org_width/2) + (org_height/2);
}
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->RGBImageLock();
}
else
{
odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
}
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
RGBImageLock();
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = int(m[0][0] * x + m[0][1] * y);
y_source = int(m[1][0] * x + m[1][1] * y);
x_source += int(m[0][2]);
y_source += int(m[1][2]);
if ((x_source >= 0) && (x_source < org_width) && (y_source >= 0) && (y_source < org_height))
{
p_source = rgb_image + (channels * (y_source * org_width + x_source));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
else
{
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = 255;
}
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
{
free_psram_heap(std::string(TAG) + "->odata", odata);
}
if (ImageTMP)
ImageTMP->RGBImageRelease();
RGBImageRelease();
}
void CRotateImage::RotateAntiAliasing(float _angle, int _centerx, int _centery)
{
int org_width, org_height;
float m[2][3];
float x_center = _centerx;
float y_center = _centery;
_angle = _angle / 180 * M_PI;
if (doflip)
{
org_width = width;
org_height = height;
height = org_width;
width = org_height;
x_center = x_center - (org_width/2) + (org_height/2);
y_center = y_center + (org_width/2) - (org_height/2);
if (ImageOrg)
{
ImageOrg->height = height;
ImageOrg->width = width;
}
}
else
{
org_width = width;
org_height = height;
}
m[0][0] = cos(_angle);
m[0][1] = sin(_angle);
m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
m[1][0] = -m[0][1];
m[1][1] = m[0][0];
m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
if (doflip)
{
m[0][2] = m[0][2] + (org_width/2) - (org_height/2);
m[1][2] = m[1][2] - (org_width/2) + (org_height/2);
}
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->RGBImageLock();
}
else
{
odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
}
int x_source_1, y_source_1, x_source_2, y_source_2;
float x_source, y_source;
float quad_ul, quad_ur, quad_ol, quad_or;
stbi_uc* p_target;
stbi_uc *p_source_ul, *p_source_ur, *p_source_ol, *p_source_or;
RGBImageLock();
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = (m[0][0] * x + m[0][1] * y);
y_source = (m[1][0] * x + m[1][1] * y);
x_source += (m[0][2]);
y_source += (m[1][2]);
x_source_1 = (int)x_source;
x_source_2 = x_source_1 + 1;
y_source_1 = (int)y_source;
y_source_2 = y_source_1 + 1;
quad_ul = (x_source_2 - x_source) * (y_source_2 - y_source);
quad_ur = (1- (x_source_2 - x_source)) * (y_source_2 - y_source);
quad_or = (x_source_2 - x_source) * (1-(y_source_2 - y_source));
quad_ol = (1- (x_source_2 - x_source)) * (1-(y_source_2 - y_source));
if ((x_source_1 >= 0) && (x_source_2 < org_width) && (y_source_1 >= 0) && (y_source_2 < org_height))
{
p_source_ul = rgb_image + (channels * (y_source_1 * org_width + x_source_1));
p_source_ur = rgb_image + (channels * (y_source_1 * org_width + x_source_2));
p_source_or = rgb_image + (channels * (y_source_2 * org_width + x_source_1));
p_source_ol = rgb_image + (channels * (y_source_2 * org_width + x_source_2));
for (int _channels = 0; _channels < channels; ++_channels)
{
p_target[_channels] = (int)((float)p_source_ul[_channels] * quad_ul
+ (float)p_source_ur[_channels] * quad_ur
+ (float)p_source_or[_channels] * quad_or
+ (float)p_source_ol[_channels] * quad_ol);
}
}
else
{
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = 255;
}
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
{
free_psram_heap(std::string(TAG) + "->odata", odata);
}
if (ImageTMP)
ImageTMP->RGBImageRelease();
RGBImageRelease();
}
void CRotateImage::Rotate(float _angle)
{
// ESP_LOGD(TAG, "width %d, height %d", width, height);
Rotate(_angle, width / 2, height / 2);
}
void CRotateImage::RotateAntiAliasing(float _angle)
{
// ESP_LOGD(TAG, "width %d, height %d", width, height);
RotateAntiAliasing(_angle, width / 2, height / 2);
}
void CRotateImage::Translate(int _dx, int _dy)
{
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->RGBImageLock();
}
else
{
odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM);
}
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
RGBImageLock();
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = x - _dx;
y_source = y - _dy;
if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height))
{
p_source = rgb_image + (channels * (y_source * width + x_source));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
else
{
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = 255;
}
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
{
free_psram_heap(std::string(TAG) + "->odata", odata);
}
if (ImageTMP)
{
ImageTMP->RGBImageRelease();
}
RGBImageRelease();
}

View File

@@ -1,29 +1,28 @@
#pragma once
#ifndef CROTATEIMAGE_H
#define CROTATEIMAGE_H
#include "CImageBasis.h"
class CRotateImage: public CImageBasis
{
public:
CImageBasis *ImageTMP, *ImageOrg;
bool doflip;
CRotateImage(std::string name, std::string _image, bool _flip = false) : CImageBasis(name, _image) {ImageTMP = NULL; ImageOrg = NULL; doflip = _flip;};
CRotateImage(std::string name, uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp, bool _flip = false) : CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL; ImageOrg = NULL; doflip = _flip;};
CRotateImage(std::string name, CImageBasis *_org, CImageBasis *_temp, bool _flip = false);
void Rotate(float _angle);
void RotateAntiAliasing(float _angle);
void Rotate(float _angle, int _centerx, int _centery);
void RotateAntiAliasing(float _angle, int _centerx, int _centery);
void Translate(int _dx, int _dy);
void Mirror();
};
#pragma once
#ifndef CROTATEIMAGE_H
#define CROTATEIMAGE_H
#include "CImageBasis.h"
class CRotateImage: public CImageBasis
{
public:
CImageBasis *ImageTMP, *ImageOrg;
bool doflip;
CRotateImage(std::string name, std::string _image, bool _flip = false) : CImageBasis(name, _image) {ImageTMP = NULL; ImageOrg = NULL; doflip = _flip;};
CRotateImage(std::string name, uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp, bool _flip = false) : CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL; ImageOrg = NULL; doflip = _flip;};
CRotateImage(std::string name, CImageBasis *_org, CImageBasis *_temp, bool _flip = false);
void Rotate(float _angle);
void RotateAntiAliasing(float _angle);
void Rotate(float _angle, int _centerx, int _centery);
void RotateAntiAliasing(float _angle, int _centerx, int _centery);
void Translate(int _dx, int _dy);
};
#endif //CROTATEIMAGE_H

View File

@@ -333,3 +333,17 @@ CTfLiteClass::~CTfLiteClass()
psram_free_shared_tensor_arena_and_model_memory();
}
#ifdef SUPRESS_TFLITE_ERRORS
namespace tflite
{
//tflite::ErrorReporter
// int OwnMicroErrorReporter::Report(const char* format, va_list args)
int OwnMicroErrorReporter::Report(const char* format, va_list args)
{
return 0;
}
}
#endif

View File

@@ -1,3 +1,16 @@
manifest_hash: 63f5c6c9f0bcebc7b9ca12d2aa8b26b2c5f5218d377dc4b2375d9b9ca1df7815
target: esp32
version: 1.0.0
dependencies:
espressif/esp-nn:
component_hash: b32869798bdb40dec6bc99caca48cd65d42f8a9f506b9ab9c598a076f891ede9
source:
pre_release: true
service_url: https://api.components.espressif.com/
type: service
version: 1.0.2
idf:
component_hash: null
source:
type: idf
version: 5.1.2
manifest_hash: a5f7be33336cfab90d6c2eb74757b616296d8c1e61665336749ed18905905567
target: esp32
version: 1.0.0

View File

@@ -191,7 +191,7 @@
#define Digital_Uncertainty 0.2
#define DigitalBand 3
#define Digital_Transition_Range_Predecessor 2
#define Digital_Transition_Area_Predecessor 0.7 // 9.3 - 0.7
#define Digital_Transition_Area_Predecessor 1.0 // 9.0 - 1.0
#define Digital_Transition_Area_Forward 9.7 // Pre-run zero crossing only happens from approx. 9.7 onwards

View File

@@ -46,7 +46,7 @@ void test_analogToDigit_Standard() {
// Default: dig=6.8, ana=8.6 => erg=7
// Transition = no
// Offset = no
TEST_ASSERT_EQUAL_INT(7, undertest->PointerEvalAnalogToDigitNew( 6.8, 8.6, 6, 9.2));
TEST_ASSERT_EQUAL_INT(7, undertest->PointerEvalAnalogToDigitNew( 6.8, 8.6, 8, 9.2));
// https://github.com/jomjol/AI-on-the-edge-device/issues/1143#issuecomment-1274434805
// Also hanging digit () with small pointer after 0 pass.
@@ -101,4 +101,4 @@ void test_analogToDigit_Transition() {
// Special feature: Digit runs with analogue. Therefore 1.8 (vs. 7.8)
TEST_ASSERT_EQUAL_INT(1, undertest->PointerEvalAnalogToDigitNew( 1.8, 7.8, 7, 7.7));
}
}

View File

@@ -108,9 +108,13 @@ void test_ZeigerEvalHybrid() {
// pre = 9.9 (0.0 raw)
// zahl = 1.8
TEST_ASSERT_EQUAL(2, undertest.PointerEvalHybridNew(1.8, 9.0, 9));
// if a digit have an early transition and the pointer is < 9.0
TEST_ASSERT_EQUAL(1, undertest.PointerEvalHybridNew(1.8, 9.0, 9));
// pre = 8.8 (0.0 raw)
// zahl = 1.8
TEST_ASSERT_EQUAL(2, undertest.PointerEvalHybridNew(1.8, 8.9, 8));
// if a digit have an early transition and the pointer is < 9.0
// prev (pointer) = 6.2, but on digital readout = 6.0 (prev is int parameter)
// zahl = 4.6
TEST_ASSERT_EQUAL(4, undertest.PointerEvalHybridNew(4.6, 6.0, 6));
@@ -120,5 +124,4 @@ void test_ZeigerEvalHybrid() {
//TEST_ASSERT_EQUAL(7, undertest.ZeigerEvalHybrid(6.7, -1.0, -1));
}
}

View File

@@ -109,7 +109,7 @@ void testNegative_Issues() {
setAllowNegatives(underTestPost, false);
setPreValue(underTestPost, preValue_extended);
std::string result = process_doFlow(underTestPost);
TEST_ASSERT_EQUAL_STRING("Neg. Rate - Read: - Raw: 22017.98 - Pre: 22018.08 ", underTestPost->getReadoutError().c_str());
TEST_ASSERT_EQUAL_STRING("Neg. Rate - Read: - Raw: 22017.98 - Pre: 22018.09 ", underTestPost->getReadoutError().c_str());
// if negativ no result any more
TEST_ASSERT_EQUAL_STRING("", result.c_str());

View File

@@ -1,7 +1,6 @@
#include "test_flow_postrocess_helper.h"
#include <memory>
/**
* ACHTUNG! Die Test laufen aktuell nur mit ausgeschaltetem Debug in ClassFlowCNNGeneral
@@ -477,12 +476,18 @@ void test_doFlowPP3() {
expected_extended= "126.9231";
// extendResolution=false
result = process_doFlow(analogs, digits, Digital100, false, false, 0);
undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 9.4); // Extreme late transition
result = process_doFlow(undertestPost);
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
delete undertestPost;
// checkConsistency=false und extendResolution=true
result = process_doFlow(analogs, digits, Digital100, false, true, 0);
undertestPost = init_do_flow(analogs, digits, Digital100, false, true, 0);
setAnalogdigitTransistionStart(undertestPost, 9.4); // Extreme late transition
result = process_doFlow(undertestPost);
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
delete undertestPost;
// Fehler V12.0.1
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1282168030
@@ -542,4 +547,266 @@ void test_doFlowPP4() {
}
std::string postProcess(std::vector<float> digits,
std::vector<float> analogs,
float analog2DigitalTransition=0.0,
int decimalShift=0)
{
std::unique_ptr<UnderTestPost> undertestPost(init_do_flow(std::move(analogs),
std::move(digits),
Digital100,
false, false, decimalShift));
setAnalogdigitTransistionStart(undertestPost.get(), analog2DigitalTransition);
return process_doFlow(undertestPost.get());
}
void test_doFlowLateTransition()
{
// in these test cases, the last digit before comma turns 3.6 too late
float a2dt = 3.4; // value when last digit reaches x.8 region
// Questionable? (Meter shows 011.0210 but it already needs to be 012.0210, before transition)
// Slider0007: In my opionion this series starts clearly with 11.x
// As I remember right, this is a real series from rainman110, therefore the following cases
// also needs to be corrected the same way
TEST_ASSERT_EQUAL_STRING("11.0210", postProcess({0.0, 1.0, 1.0}, {0.2, 2.2, 1.0, 0.0}, a2dt).c_str());
// meter shows 011.3210 but it already needs to be 012.3210, just before transition
TEST_ASSERT_EQUAL_STRING("11.3210", postProcess({0.0, 1.0, 1.2}, {3.3, 2.2, 1.0, 0.0}, a2dt).c_str());
// meter shows 012.4210 , this is after transition
TEST_ASSERT_EQUAL_STRING("11.4210", postProcess({0.0, 1.0, 2.0}, {4.3, 2.2, 1.0, 0.0}, a2dt).c_str());
// meter shows 012.987
TEST_ASSERT_EQUAL_STRING("11.9870", postProcess({0.0, 1.0, 2.0}, {9.8, 8.7, 7.0, 0.0}, a2dt).c_str());
// meter shows 0012.003
TEST_ASSERT_EQUAL_STRING("12.003", postProcess({0.0, 0.0, 1.0, 2.0}, {0.1, 0.3, 3.1}, a2dt).c_str());
// meter shows 0012.351
TEST_ASSERT_EQUAL_STRING("12.351", postProcess({0.0, 0.0, 1.0, 2.8}, {3.5, 5.2, 1.1}, a2dt).c_str());
// meter shows 0013.421
TEST_ASSERT_EQUAL_STRING("12.421", postProcess({0.0, 0.0, 1.0, 3.0}, {4.1, 2.2, 1.1}, a2dt).c_str());
}
void test_doFlowEarlyTransition()
{
// in these test cases, the last digit before comma turns at around 7.5
// start transition 7.0 end transition 8.0
float a2dt = 7.8; // value when last digit reaches x.8 region
TEST_ASSERT_EQUAL_STRING("12.6789", postProcess({0.0, 1.0, 2.0}, {6.7, 7.8, 8.9, 9.0}, a2dt).c_str());
TEST_ASSERT_EQUAL_STRING("12.7234", postProcess({0.0, 1.0, 2.4}, {7.2, 2.3, 3.4, 4.0}, a2dt).c_str());
TEST_ASSERT_EQUAL_STRING("12.7789", postProcess({0.0, 1.0, 2.7}, {7.7, 7.8, 8.9, 9.0}, a2dt).c_str());
TEST_ASSERT_EQUAL_STRING("12.8123", postProcess({0.0, 1.0, 3.0}, {8.1, 1.2, 2.3, 3.0}, a2dt).c_str());
TEST_ASSERT_EQUAL_STRING("13.1234", postProcess({0.0, 1.0, 3.0}, {1.2, 2.3, 3.4, 4.0}, a2dt).c_str());
}
void test_doFlowEarlyTransitionEdgeCase()
{
float a2dt = 8.;
// Silder0007: In my opinion this is a unrealistic case {0.0, **0.0**, 9.9, 9,0}, {5.0, 0.0}
// More realistic values: {0.0, 0.9, 9.9, 9,0}, {5.0, 0.0}
TEST_ASSERT_EQUAL_STRING("99.50", postProcess({0.0, 0.0, 9.0, 9.0}, {5.0, 0.0}, a2dt).c_str());
// fails with 99.50
TEST_ASSERT_EQUAL_STRING("199.50", postProcess({0.0, 1.0, 9.0, 9.0}, {5.0, 0.0}, a2dt).c_str());
TEST_ASSERT_EQUAL_STRING("99.95", postProcess({0.0, 1.0, 0.0, 0.0}, {9.5, 5.0}, a2dt).c_str());
}
void test_doFlowIssue2857()
{
// reported by gec75
float a2dt = 9.2;
int decimalShift = 3;
TEST_ASSERT_EQUAL_STRING("252090.0", postProcess({ 2.0, 5.0, 1.9}, { 0.8, 8.8, 9.9, 0.1},
a2dt, decimalShift).c_str());
// reported by Kornelius777
decimalShift = 0;
TEST_ASSERT_EQUAL_STRING("1017.8099", postProcess({ 0.0, 1.0, 0.0, 1.0, 7.0}, { 8.2, 0.9, 9.9, 9.8},
a2dt, decimalShift).c_str());
// with hanging digit
TEST_ASSERT_EQUAL_STRING("1017.8099", postProcess({ 0.0, 1.0, 0.0, 1.0, 6.9}, { 8.2, 0.9, 9.9, 9.8},
a2dt, decimalShift).c_str());
// and deccimal shift
decimalShift = -2;
TEST_ASSERT_EQUAL_STRING("10.178099", postProcess({ 0.0, 1.0, 0.0, 1.0, 6.9}, { 8.2, 0.9, 9.9, 9.8},
a2dt, decimalShift).c_str());
// reported by marcniedersachsen
decimalShift = 0;
TEST_ASSERT_EQUAL_STRING("778.1480", postProcess({ 0.0, 7.0, 7.0, 7.9}, { 1.4, 4.7, 8.0, 0.5},
a2dt, decimalShift).c_str());
decimalShift = 3;
TEST_ASSERT_EQUAL_STRING("778148.0", postProcess({ 0.0, 7.0, 7.0, 7.9}, { 1.4, 4.7, 8.0, 0.5},
a2dt, decimalShift).c_str());
// reported by ohkaja
decimalShift = 0;
TEST_ASSERT_EQUAL_STRING("1052.6669", postProcess({ 0.0, 1.0, 10.0, 4.9, 2.0}, { 6.7, 6.7, 6.9, 9.1},
a2dt, decimalShift).c_str());
// FrankCGN01
decimalShift = -3;
a2dt = 9.7;
TEST_ASSERT_EQUAL_STRING("159.3659", postProcess({ 0.9, 4.8, 8.9, 3.0, 6.0, 5.0}, { 9.6},
a2dt, decimalShift).c_str());
// Second test in https://github.com/jomjol/AI-on-the-edge-device/issues/2857#issuecomment-1937452352
// The last digit seems to be falsely recongnized. It looks like a regular "2" (no transition)
// but it is recognized by the inference as "2.5".
decimalShift = -3;
TEST_ASSERT_EQUAL_STRING("159.5022", postProcess({ 0.9, 4.9, 8.9, 5.0, 0.0, 2.5}, { 2.2},
a2dt, decimalShift).c_str());
// reported by penapena
// Note: this is a strange example, as the last digit (4.4) seems to have very early transition
decimalShift = 0;
TEST_ASSERT_EQUAL_STRING("124.4981", postProcess({ 0.0, 1.0, 2.0, 4.4}, { 5.1, 9.8, 8.3, 1.6},
a2dt, decimalShift).c_str());
// reported by warnmat
decimalShift = 0;
TEST_ASSERT_EQUAL_STRING("51.653", postProcess({ 0.1, 0.1, 5.0, 1.0}, { 6.7, 5.4, 3.1},
a2dt, decimalShift).c_str());
}
void test_doFlowLateTransitionHanging()
{
float a2dt = 3.6;
// haverland: this is the case if the analog pointer is a bit before the digit.
// It's the normal late transition up to 2.0 on analog must the digit transition ends
// After 2.0 on analog it named "hanging digit" by me. It never reach the x.0 until the next
// transition begins.
// BUT. It makes the issue you have later, because all other unter 3.6 are negative values now.
TEST_ASSERT_EQUAL_STRING("12.1210", postProcess({0.0, 1.0, 1.9}, {1.2, 2.2, 1.0, 0.0}, a2dt).c_str());
// Questionable? (meter shows 012.4210 , this is after transition)
// Slider0007: In my opionion this series starts with 11.x with this a2dt value
// As I remember right, this is a real series from rainman110, therefore the following cases
// also needs to be corrected the same way
TEST_ASSERT_EQUAL_STRING("11.4210", postProcess({0.0, 1.0, 1.9}, {4.3, 2.2, 1.0, 0.0}, a2dt).c_str());
TEST_ASSERT_EQUAL_STRING("11.6210", postProcess({0.0, 1.0, 1.9}, {6.3, 2.2, 1.0, 0.0}, a2dt).c_str());
TEST_ASSERT_EQUAL_STRING("12.3610", postProcess({0.0, 1.0, 2.5}, {3.5, 6.2, 1.0, 0.0}, a2dt).c_str());
TEST_ASSERT_EQUAL_STRING("12.4510", postProcess({0.0, 1.0, 3.0}, {4.5, 5.2, 1.0, 0.0}, a2dt).c_str());
TEST_ASSERT_EQUAL_STRING("12.4510", postProcess({0.0, 1.0, 2.9}, {4.5, 5.2, 1.0, 0.0}, a2dt).c_str());
}
void test_doFlowPP_rainman110()
{
// https://github.com/jomjol/AI-on-the-edge-device/issues/2743
// --> Extreme early digit transition. AnanlogDigitTransition needs to set to 3.5 (was limited to 6)
std::vector<float> digits = {4.0, 1.0, 1.8}; // wrong result: 412.3983
std::vector<float> analogs = {3.6, 9.9, 8.1, 3.5};
UnderTestPost* undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 3.5);
TEST_ASSERT_EQUAL_STRING("411.3983", process_doFlow(undertestPost).c_str());
delete undertestPost;
// https://github.com/jomjol/AI-on-the-edge-device/pull/2887
// --> Extreme early digit transition. AnanlogDigitTransition needs to set to 3.5 (was limited to 6)
digits = {4.0, 1.0, 7.9}; // wrong result: 417.2579
analogs = {2.5, 5.8, 7.7, 9.0};
undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 3.5);
TEST_ASSERT_EQUAL_STRING("418.2579", process_doFlow(undertestPost).c_str());
delete undertestPost;
// Edge Case
digits = {9.9, 9.4};
analogs = {5.0, 0.0};
undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 8.0);
TEST_ASSERT_EQUAL_STRING("99.50", process_doFlow(undertestPost).c_str());
delete undertestPost;
// Edge Case
digits = {1.0, 0.0, 0.0};
analogs = {9.5, 5.0};
undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 8.0);
TEST_ASSERT_EQUAL_STRING("99.95", process_doFlow(undertestPost).c_str());
delete undertestPost;
// https://github.com/jomjol/AI-on-the-edge-device/pull/2887
// Discussion 149365.9 vs. 149364.9
digits = {0.9, 4.8, 9.0, 3.0, 6.0, 5.0};
analogs = {9.6};
undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 9.2);
TEST_ASSERT_EQUAL_STRING("149364.9", process_doFlow(undertestPost).c_str());
delete undertestPost;
}
void test_doFlowPP_rainman110_transition()
{
// https://github.com/jomjol/AI-on-the-edge-device/pull/2887
// Edge cases
std::vector<float> digits = {4.0, 1.0, 7.9};
std::vector<float> analogs = {1.4, 5.8, 7.7, 9.0};
UnderTestPost* undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 3.5);
std::string result = process_doFlow(undertestPost);
TEST_ASSERT_EQUAL_STRING("418.1579", result.c_str());
delete undertestPost;
// https://github.com/jomjol/AI-on-the-edge-device/pull/2887
// Edge cases
digits = {4.0, 1.0, 7.9};
analogs = {3.4, 5.8, 7.7, 9.0};
undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 3.5);
result = process_doFlow(undertestPost);
TEST_ASSERT_EQUAL_STRING("418.3579", result.c_str());
delete undertestPost;
// https://github.com/jomjol/AI-on-the-edge-device/pull/2887
// Edge cases
digits = {4.0, 1.0, 8.5};
analogs = {3.7, 5.8, 7.7, 9.0};
undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 3.5);
result = process_doFlow(undertestPost);
TEST_ASSERT_EQUAL_STRING("418.3579", result.c_str());
delete undertestPost;
// https://github.com/jomjol/AI-on-the-edge-device/pull/2887
// Edge cases
digits = {4.0, 1.0, 8.9};
analogs = {4.0, 5.8, 7.7, 9.0};
undertestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
setAnalogdigitTransistionStart(undertestPost, 3.5);
result = process_doFlow(undertestPost);
TEST_ASSERT_EQUAL_STRING("418.4579", result.c_str());
delete undertestPost;
}

View File

@@ -138,6 +138,21 @@ void task_UnityTesting(void *pvParameter)
RUN_TEST(test_doFlowPP3);
printf("---------------------------------------------------------------------------\n");
RUN_TEST(test_doFlowPP4);
printf("---------------------------------------------------------------------------\n");
RUN_TEST(test_doFlowLateTransition);
printf("---------------------------------------------------------------------------\n");
RUN_TEST(test_doFlowEarlyTransition);
printf("---------------------------------------------------------------------------\n");
RUN_TEST(test_doFlowEarlyTransitionEdgeCase);
printf("---------------------------------------------------------------------------\n");
RUN_TEST(test_doFlowIssue2857);
printf("---------------------------------------------------------------------------\n");
RUN_TEST(test_doFlowLateTransitionHanging);
printf("---------------------------------------------------------------------------\n");
RUN_TEST(test_doFlowPP_rainman110);
printf("---------------------------------------------------------------------------\n");
RUN_TEST(test_doFlowPP_rainman110_transition);
UNITY_END();
while(1);
@@ -151,22 +166,9 @@ extern "C" void app_main()
{
initGPIO();
Init_NVS_SDCard();
esp_log_level_set("*", ESP_LOG_DEBUG); // set all components to ERROR level
esp_log_level_set("*", ESP_LOG_ERROR); // set all components to ERROR level
UNITY_BEGIN();
RUN_TEST(testNegative_Issues);
RUN_TEST(testNegative);
/*
RUN_TEST(test_analogToDigit_Standard);
RUN_TEST(test_analogToDigit_Transition);
RUN_TEST(test_doFlowPP);
RUN_TEST(test_doFlowPP1);
RUN_TEST(test_doFlowPP2);
RUN_TEST(test_doFlowPP3);
RUN_TEST(test_doFlowPP4);
// getReadoutRawString test
RUN_TEST(test_getReadoutRawString);
*/
UNITY_END();
// Create dedicated testing task (heap size can be configured - large enough to handle a lot of testing cases)
// ********************************************
xTaskCreate(&task_UnityTesting, "task_UnityTesting", 12 * 1024, NULL, tskIDLE_PRIORITY+2, NULL);
}

View File

@@ -1,8 +1,29 @@
demo
WaitBeforeTakingPicture
ImageQuality
ImageSize
FixedExposure
CamFrameSize
CamGainceiling
CamQuality
CamAutoSharpness
CamSharpness
CamSpecialEffect
CamWbMode
CamAwb
CamAwbGain
CamAec
CamAec2
CamAeLevel
CamAecValue
CamAgc
CamAgcGain
CamBpc
CamWpc
CamRawGma
CamLenc
CamDcw
CamZoom
CamZoomSize
CamZoomOffsetX
CamZoomOffsetY
demo
SearchFieldX
SearchFieldY
AlignmentAlgo

View File

@@ -0,0 +1,15 @@
# Parameter `CamAeLevel`
Default Value: `0`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Auto-Exposure Compensation. Lower values produce darker image.
Range (`-2` .. `2`)

View File

@@ -0,0 +1,13 @@
# Parameter `CamAec`
Default Value: `true`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Auto-Exposure Control Algorithm

View File

@@ -0,0 +1,13 @@
# Parameter `CamAec2`
Default Value: `false`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Switch to "Auto-Exposure Control 2" Algorithm. This may resolve some over-exposure and under-exposure issues.

View File

@@ -0,0 +1,15 @@
# Parameter `CamAecValue`
Default Value: `0`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
set Manuall-Exposure Control Value
Range (`0` .. `1200`)

View File

@@ -0,0 +1,10 @@
# Parameter `CamAgc`
Default Value: `true`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
This sets the Automatic Gain Control, how the camera responds to the overall level of light in the image.

View File

@@ -0,0 +1,13 @@
# Parameter `CamAgcGain`
Default Value: ` `
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
!!! Note
This is visible when AGC is off. Gain is an amplification of the values read from the image sensor.
Range (`0` .. `30`)

View File

@@ -0,0 +1,13 @@
# Parameter `CamAutoSharpness`
Default Value: `false`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
AutoSharpness

View File

@@ -0,0 +1,10 @@
# Parameter `CamAwb`
Default Value: ` `
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Auto White Balance

View File

@@ -0,0 +1,10 @@
# Parameter `CamAwbGain`
Default Value: ` `
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Auto White Balance Gain

View File

@@ -0,0 +1,10 @@
# Parameter `CamBpc`
Default Value: `true`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Black Pixel Correction

View File

@@ -0,0 +1,10 @@
# Parameter `CamBrightness`
Default Value: `0`
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Image Brightness (`-2` .. `2`)

View File

@@ -0,0 +1,5 @@
# Parameter `CamColorbar`
Default Value: `false`
!!! Note
This parameter can also be set on the Reference Image configuration page!

View File

@@ -0,0 +1,11 @@
# Parameter `CamContrast`
Default Value: `0`
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Image Contrast (`-2` .. `2`)

View File

@@ -0,0 +1,13 @@
# Parameter `CamDcw`
Default Value: `true`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
!!! Note
When DCW is on, the image that you receive will be the size that you requested (VGA, QQVGA, etc).
When DCW is off, the image that you receive will be one of UXGA, SVGA, or CIF. In other words, literally the actual image size as read from the sensor without any scaling.
Note that if DCW is off, and you pick a different image size, this implicitly turns DCW back on again (although this isn't reflected in the options).

View File

@@ -0,0 +1,10 @@
# Parameter `CamDenoise`
Default Value: ` `
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Denoise Image (not supported)

View File

@@ -0,0 +1,21 @@
# Parameter `CamGainceiling`
Default Value: `x2`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
!!! Note
This is visible when AGC is on.
Available options:
- `x2`
- `x4`
- `x8`
- `x16`
- `x32`
- `x64`
- `x128`

View File

@@ -0,0 +1,10 @@
# Parameter `CamHmirror`
Default Value: `false`
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Option for initially mirroring the image on the original x-axis.

View File

@@ -0,0 +1,10 @@
# Parameter `CamLenc`
Default Value: `true`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Lens Correction

View File

@@ -0,0 +1,10 @@
# Parameter `CamQuality`
Default Value: `12`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
Quality index for pictures: `8` (highest quality) ... `63` (lowest quality)
!!! Warning
Value below 12 could result in system instabilities!

View File

@@ -0,0 +1,10 @@
# Parameter `CamRawGma`
Default Value: ` `
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
RawGma

View File

@@ -0,0 +1,11 @@
# Parameter `CamSaturation`
Default Value: `0`
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Image Saturation (`-2` .. `2`)

View File

@@ -0,0 +1,13 @@
# Parameter `CamSharpness`
Default Value: `0`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Range (`-2` .. `2`)

View File

@@ -0,0 +1,21 @@
# Parameter `CamSpecialEffect`
Default Value: `no_effect`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Available options:
- `no_effect`
- `negative`
- `grayscale`
- `red`
- `green`
- `blue`
- `retro`

View File

@@ -0,0 +1,10 @@
# Parameter `CamVflip`
Default Value: `false`
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Option for initially flip the image on the original y-axis.

View File

@@ -0,0 +1,18 @@
# Parameter `CamWbMode`
Default Value: `auto`
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
White Balance Mode
Available options:
- `auto`
- `sunny`
- `cloudy`
- `office`
- `home`

View File

@@ -0,0 +1,10 @@
# Parameter `CamWpc`
Default Value: `true`
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
White Pixel Correction

View File

@@ -0,0 +1,13 @@
# Parameter `CamZoom`
Default Value: `false`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
Crop the camera sensor frame to `ImageSize` resolution instead of scaling it down.

View File

@@ -0,0 +1,14 @@
# Parameter `CamZoomOffsetX`
Default Value: `0`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
`ZoomOffsetX` only applies when `Zoom` is enabled.
X coordinate of the crop location within the camera sensor frame.

View File

@@ -0,0 +1,14 @@
# Parameter `CamZoomOffsetY`
Default Value: `0`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
`ZoomOffsetY` only applies when `Zoom` is enabled.
Y coordinate of the crop location within the camera sensor frame.

View File

@@ -0,0 +1,13 @@
# Parameter `CamZoomSize`
Default Value: `0`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
!!! Note
This parameter can also be set on the Reference Image configuration page!
!!! Note
After changing this parameter you need to update your reference image and alignment markers!
`CamZoomSize` only applies when `Zoom` is enabled.

Binary file not shown.

View File

@@ -1,123 +1,136 @@
[TakeImage]
;RawImagesLocation = /log/source
WaitBeforeTakingPicture = 5
;RawImagesRetention = 15
Brightness = 0
Contrast = 0
Saturation = 0
Sharpness = 0
LEDIntensity = 50
ImageQuality = 12
ImageSize = VGA
Zoom = false
ZoomMode = 0
ZoomOffsetX = 0
ZoomOffsetY = 0
Grayscale = false
Negative = false
Aec2 = false
AutoExposureLevel = 0
FixedExposure = false
Demo = false
[Alignment]
InitialRotate = 0.0
InitialMirror = false
SearchFieldX = 20
SearchFieldY = 20
AlignmentAlgo = Default
FlipImageSize = false
/config/ref0.jpg 103 271
/config/ref1.jpg 442 142
[Digits]
Model = /config/dig-cont_0620_s3_q.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/digit
;ROIImagesRetention = 3
main.dig1 294 126 30 54 false
main.dig2 343 126 30 54 false
main.dig3 391 126 30 54 false
[Analog]
Model = /config/ana-cont_1208_s2_q.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/analog
;ROIImagesRetention = 3
main.ana1 432 230 92 92 false
main.ana2 379 332 92 92 false
main.ana3 283 374 92 92 false
main.ana4 155 328 92 92 false
[PostProcessing]
main.DecimalShift = 0
main.AnalogDigitalTransitionStart = 9.2
PreValueUse = true
PreValueAgeStartup = 720
main.AllowNegativeRates = false
main.MaxRateValue = 0.05
;main.MaxRateType = AbsoluteChange
main.ExtendedResolution = false
main.IgnoreLeadingNaN = false
ErrorMessage = true
CheckDigitIncreaseConsistency = false
;[MQTT]
;Uri = mqtt://IP-ADRESS:1883
;MainTopic = watermeter
;ClientID = watermeter
;user = USERNAME
;password = PASSWORD
RetainMessages = false
HomeassistantDiscovery = false
;MeterType = other
;CACert = /config/certs/RootCA.pem
;ClientCert = /config/certs/client.pem.crt
;ClientKey = /config/certs/client.pem.key
;[InfluxDB]
;Uri = undefined
;Database = undefined
;Measurement = undefined
;user = undefined
;password = undefined
;[InfluxDBv2]
;Uri = undefined
;Bucket = undefined
;Measurement = undefined
;Org = undefined
;Token = undefined
;main.Fieldname = undefined
;[GPIO]
;MainTopicMQTT = wasserzaehler/GPIO
;IO0 = input disabled 10 false false
;IO1 = input disabled 10 false false
;IO3 = input disabled 10 false false
;IO4 = built-in-led disabled 10 false false
;IO12 = input-pullup disabled 10 false false
;IO13 = input-pullup disabled 10 false false
LEDType = WS2812
LEDNumbers = 2
LEDColor = 150 150 150
[AutoTimer]
AutoStart = true
Interval = 5
[DataLogging]
DataLogActive = true
DataFilesRetention = 3
[Debug]
LogLevel = 1
LogfilesRetention = 3
[System]
TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
;TimeServer = pool.ntp.org
;Hostname = undefined
RSSIThreshold = -75
CPUFrequency = 160
SetupMode = true
[TakeImage]
;RawImagesLocation = /log/source
;RawImagesRetention = 15
WaitBeforeTakingPicture = 2
CamGainceiling = x4
CamQuality = 8
CamBrightness = 0
CamContrast = 0
CamSaturation = 0
CamSharpness = 1
CamAutoSharpness = false
CamSpecialEffect = no_effect
CamWbMode = auto
CamAwb = true
CamAwbGain = true
CamAec = true
CamAec2 = true
CamAeLevel = 2
CamAecValue = 500
CamAgc = true
CamAgcGain = 0
CamBpc = true
CamWpc = true
CamRawGma = true
CamLenc = true
CamHmirror = false
CamVflip = false
CamDcw = true
CamZoom = false
CamZoomOffsetX = 0
CamZoomOffsetY = 0
CamZoomSize = 0
LEDIntensity = 50
Demo = false
[Alignment]
InitialRotate = 0.0
InitialMirror = false
SearchFieldX = 20
SearchFieldY = 20
AlignmentAlgo = Default
FlipImageSize = false
/config/ref0.jpg 103 271
/config/ref1.jpg 442 142
[Digits]
Model = /config/dig-cont_0700_s3_q.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/digit
;ROIImagesRetention = 3
main.dig1 294 126 30 54 false
main.dig2 343 126 30 54 false
main.dig3 391 126 30 54 false
[Analog]
Model = /config/ana-cont_1300_s2.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/analog
;ROIImagesRetention = 3
main.ana1 432 230 92 92 false
main.ana2 379 332 92 92 false
main.ana3 283 374 92 92 false
main.ana4 155 328 92 92 false
[PostProcessing]
main.DecimalShift = 0
main.AnalogDigitalTransitionStart = 9.2
PreValueUse = true
PreValueAgeStartup = 720
main.AllowNegativeRates = false
main.MaxRateValue = 0.05
;main.MaxRateType = AbsoluteChange
main.ExtendedResolution = false
main.IgnoreLeadingNaN = false
ErrorMessage = true
CheckDigitIncreaseConsistency = false
;[MQTT]
;Uri = mqtt://IP-ADRESS:1883
;MainTopic = watermeter
;ClientID = watermeter
;user = USERNAME
;password = PASSWORD
RetainMessages = false
HomeassistantDiscovery = false
;MeterType = other
;CACert = /config/certs/RootCA.pem
;ClientCert = /config/certs/client.pem.crt
;ClientKey = /config/certs/client.pem.key
;[InfluxDB]
;Uri = undefined
;Database = undefined
;Measurement = undefined
;user = undefined
;password = undefined
;[InfluxDBv2]
;Uri = undefined
;Bucket = undefined
;Measurement = undefined
;Org = undefined
;Token = undefined
;main.Fieldname = undefined
;[GPIO]
;MainTopicMQTT = wasserzaehler/GPIO
;IO0 = input disabled 10 false false
;IO1 = input disabled 10 false false
;IO3 = input disabled 10 false false
;IO4 = built-in-led disabled 10 false false
;IO12 = input-pullup disabled 10 false false
;IO13 = input-pullup disabled 10 false false
LEDType = WS2812
LEDNumbers = 2
LEDColor = 150 150 150
[AutoTimer]
AutoStart = true
Interval = 5
[DataLogging]
DataLogActive = true
DataFilesRetention = 3
[Debug]
LogLevel = 1
LogfilesRetention = 3
[System]
TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
;TimeServer = pool.ntp.org
;Hostname = undefined
RSSIThreshold = -75
CPUFrequency = 160
SetupMode = true

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -113,49 +113,56 @@
<hr />
<table>
<colgroup>
<col span="1" style="width: 33.3%;">
<col span="1" style="width: 33.3%;">
<col span="1" style="width: 33.3%;">
</colgroup>
<tr>
<td>Marker:
<select id="index" name="reference" onchange="ChangeSelection()">
<option value="0" selected>Marker 1</option>
<option value="1" >Marker 2</option>
</select>
</td>
<td colspan="2" style="padding-left: 22px; color: grey;">Filename: <output type="text" name="name" id="name" onchange="namechanged()"></td>
</tr>
<tr>
<td style="padding-top: 10px">x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()"></td>
<td style="padding-top: 10px">dx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchanged()"></td>
<td rowspan="2" style="padding-top: 10px;"><input class="button" type="button" value="Update Marker" onclick="CutOutReference()"></td>
</tr>
<tr>
<td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()"></td>
<td>dy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()"></td>
</tr>
<tr>
<td style="vertical-align: bottom;">Selected Image Area:</td>
<td style="vertical-align: bottom;">Resulting Marker:</td>
<td><input class="button" type="button" id="enhancecontrast" value="Enhance Image Contrast" onclick="EnhanceContrast()"></td>
</tr>
<tr>
<td style="height:70px; vertical-align: top;"><img id="img_ref_org" src = ""></td> <!--/img_tmp/ref_zw_org.jpg-->
<td style="height:70px; vertical-align: top;"><img id="img_ref" src = ""></td> <!--/img_tmp/ref_zw.jpg-->
</tr>
<tr>
<td style="vertical-align:bottom;"><b>Reference Image:</b></td>
<td></td>
<td><input style="font-weight:bold;" class="button" type="submit" name="saveroi" id="savemarker" onclick="SaveToConfig()" value="Save New Marker">
</td>
</tr>
<tr>
<td colspan="3"><canvas id="canvas" crossorigin></canvas></td>
</tr>
</table>
<colgroup>
<col span="1" style="width: 33.3%;">
<col span="1" style="width: 33.3%;">
<col span="1" style="width: 33.3%;">
</colgroup>
<tr>
<td>Marker:
<select id="index" name="reference" onchange="ChangeSelection()">
<option value="0" selected>Marker 1</option>
<option value="1" >Marker 2</option>
</select>
</td>
<td colspan="2" style="padding-left: 22px; color: grey;">Filename: <output type="text" name="name" id="name" onchange="namechanged()"></td>
</tr>
<tr>
<td style="padding-top: 10px">x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()"></td>
<td style="padding-top: 10px">dx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchanged()"></td>
<td rowspan="2" style="padding-top: 10px;"><input class="button" type="button" value="Update Marker" onclick="CutOutReference()"></td>
</tr>
<tr>
<td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()"></td>
<td>dy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()"></td>
</tr>
<tr>
<td style="vertical-align: bottom;">Selected Image Area:</td>
<td style="vertical-align: bottom;">Resulting Marker:</td>
<td><input class="button" type="button" id="enhancecontrast" value="Enhance Image Contrast" onclick="EnhanceContrast()"></td>
</tr>
<tr>
<td style="height:70px; vertical-align: top;"><img id="img_ref_org" src = ""></td> <!--/img_tmp/ref_zw_org.jpg-->
<td style="height:70px; vertical-align: top;"><img id="img_ref" src = ""></td> <!--/img_tmp/ref_zw.jpg-->
</tr>
<tr>
<td style="vertical-align:bottom;"><b>Reference Image:</b></td>
<td></td>
<td>
<input style="font-weight:bold;" class="button" type="submit" name="saveroi" id="savemarker" onclick="SaveToConfig()" value="Save New Marker">
</td>
</tr>
<tr>
<td colspan="3"><canvas id="canvas" crossorigin></canvas></td>
</tr>
</table>
<script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
@@ -173,6 +180,7 @@ var canvas = document.getElementById('canvas'),
domainname = getDomainname(),
neueref1,
neueref2,
cofcat,
param;
function doReboot() {
@@ -290,8 +298,7 @@ function UpdateReference(){
draw();
}
_filenameurl = refInfo[aktindex]["name"].replace("/config/", "/img_tmp/");
var _filenameurl = refInfo[aktindex]["name"].replace("/config/", "/img_tmp/");
var url = domainname + "/fileserver" + _filenameurl + "?" + Date.now();
document.getElementById("img_ref").src = url;
@@ -352,7 +359,7 @@ function openDescription() {
if(window.location.hash) {
var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
if(hash == 'description') {
document.getElementById("desc_details").open = true;
document.getElementById("desc_details").open = false;
}
}
}
@@ -368,7 +375,7 @@ function LoadReference(){
draw();
}
_filenameurl = refInfo[aktindex]["name"];
var _filenameurl = refInfo[aktindex]["name"];
var url = domainname + "/fileserver" + _filenameurl + "?" + Date.now();
document.getElementById("img_ref").src = url;
@@ -387,17 +394,23 @@ function LoadReference(){
function init() {
openDescription();
domainname = getDomainname();
loadConfig(domainname);
if (!loadConfig(domainname)) {
firework.launch('Configuration could not be loaded! Please reload the page!', 'danger', 30000);
return;
}
ParseConfig();
param = getConfigParameters();
cofcat = getConfigCategory();
document.getElementById("savemarker").disabled = true;
document.getElementById("enhancecontrast").disabled = true;
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
loadCanvas(domainname + "/fileserver/config/reference.jpg");
loadCanvas(domainname + "/fileserver/config/reference.jpg");
//CopyReferenceToImgTmp(domainname);
refInfo = GetReferencesInfo();
@@ -405,6 +418,7 @@ function init() {
//UpdateReference();
LoadReference();
drawImage();
draw();
}
function drawImage(){

View File

@@ -125,7 +125,6 @@
<div id="div1">
<table>
<colgroup>
<col span="1" style="width: 22%;">
@@ -133,9 +132,11 @@
<col span="1" style="width: 26%;">
<col span="1" style="width: 26%;">
</colgroup>
<tr>
<td colspan="4" style="padding: 0px"><class id="Numbers_text" style="color:black;">Number Sequence:</class></td>
</tr>
<tr>
<td>
<select id="Numbers_value1" onchange="numberChanged()">
@@ -156,15 +157,18 @@
<col span="1" style="width: 26%;">
<col span="1" style="width: 26%;">
</colgroup>
<tr>
<td style="padding: 0px">ROI:</td>
</tr>
<tr>
<td><select id="index" name="index" onchange="ChangeSelection()" tabindex=1></select></td>
<td><input class="button" type="submit" id="newROI" name="newROI" onclick="newROI()" value="New ROI"></td>
<td><input class="button" type="submit" id="renameROI" name="renameROI" onclick="renameROI()" value="Rename ROI"></td>
<td><input class="button" type="submit" id="deleteROI" name="deleteROI" onclick="deleteROI()" value="Delete ROI"></td>
</tr>
<tr>
<td class="multiplier">Multiplier: <output type="text" id="multiplier" name="multiplier"></output><br>
(only based on order)
@@ -183,14 +187,17 @@
<col span="1" style="width: 18%;">
<col span="1" style="width: 64%;">
</colgroup>
<tr>
<td>x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()" tabindex=2></td>
<td>Δx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchangeddx()" tabindex=4></td>
</tr>
<tr>
<td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()" tabindex=3></td>
<td>Δy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()" tabindex=5></td>
</tr>
<tr>
<td colspan="3"><input type="checkbox" id="CCW" name="CCW" value="0" onclick="changeCCW()" unchecked tabindex=8><label for="CCW">Counter clockwise rotation (CCW)</label></td>
</tr>
@@ -199,10 +206,9 @@
<hr>
The following settings are only used for easier setup, they are <b>not</b> persisted on the device:<br>
<input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=9><label for="showall">Show all ROIs</label><br>
<input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=9><label for="showall"> Show all ROIs</label><br>
<input type="checkbox" id="lockAspectRatio" name="lockAspectRatio" value="1" onclick="changelockAspectRatio()" checked tabindex=6><label for="lockAspectRatio"> Lock aspect ratio </label><br>
<input type="checkbox" id="lockSizes" name="lockSizes" value="1" onclick="changelockSizes()" checked tabindex=7><label for="lockSizes"> Synchronize y, Δx and Δy between ROIs</label><br>
<hr>
<table>
@@ -212,20 +218,23 @@ The following settings are only used for easier setup, they are <b>not</b> persi
<col span="1" style="width: 26%;">
<col span="1" style="width: 26%;">
</colgroup>
<tr>
<td colspan="3" style="vertical-align: bottom;"><b>Reference Image:</b></td>
<!---<td><button class="button" id="reboot" type="button" onclick="doReboot()">Reboot device</button></td>-->
<td><input style="font-weight:bold;" class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save Config" tabindex=10></td>
<td>
<input style="font-weight:bold;" class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save Config" tabindex=10>
</td>
</tr>
<tr>
<td colspan="4"><canvas id="canvas" crossorigin></canvas></td>
</tr>
</table>
<script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="jquery-3.6.0.min.js?v=$COMMIT_HASH"></script>
<script language="JavaScript">
var canvas = document.getElementById('canvas'),
@@ -595,7 +604,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
if(window.location.hash) {
var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
if(hash == 'description') {
document.getElementById("desc_details").open = true;
document.getElementById("desc_details").open = false;
}
}
}
@@ -603,18 +612,26 @@ The following settings are only used for easier setup, they are <b>not</b> persi
function init() {
openDescription();
domainname = getDomainname();
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
loadCanvas(domainname + "/fileserver/config/reference.jpg");
loadConfig(domainname);
if (!loadConfig(domainname)) {
firework.launch('Configuration could not be loaded! Please reload the page!', 'danger', 30000);
return;
}
ParseConfig();
param = getConfigParameters();
cofcat = getConfigCategory();
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
loadCanvas(domainname + "/fileserver/config/reference.jpg");
UpdateNUMBERS();
/* Check if the ROIs have same dy and dx. If so, tick the sync checkbox */
var all_dx_dy_Identical = true;
if (ROIInfo.length > 1) {
for (var i = 1; i < (ROIInfo.length); ++i) { // 2nd .. last ROI
if (parseInt(ROIInfo[i].dx) != parseInt(ROIInfo[0].dx) || parseInt(ROIInfo[i].dy) != parseInt(ROIInfo[0].dy)) {

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@
p {font-size: 1em;}
input[type=number] {
width: 40px;
width: 60px;
margin-right: 10px;
padding: 3px 5px;
display: inline-block;
@@ -123,17 +123,25 @@
<col span="1" style="width: 26%;">
<col span="1" style="width: 26%;">
</colgroup>
<tr>
<td colspan="4" style="padding: 0px"><class id="Numbers_text" style="color:black;">Number Sequence:</class></td>
</tr>
<tr>
<td>
<select id="Numbers_value1" onchange="numberChanged()">
</select>
</td>
<td><input class="button" type="submit" id="newNumber" name="newNumber" onclick="newNumber()" value="New Sequence"></td>
<td><input class="button" type="submit" id="renameNumber" name="renameNumber" onclick="renameNumber()" value="Rename Sequence"></td>
<td><input class="button" type="submit" id="removeNumber" name="removeNumber" onclick="removeNumber()" value="Delete Sequence"></td>
<td>
<input class="button" type="submit" id="newNumber" name="newNumber" onclick="newNumber()" value="New Sequence">
</td>
<td>
<input class="button" type="submit" id="renameNumber" name="renameNumber" onclick="renameNumber()" value="Rename Sequence">
</td>
<td>
<input class="button" type="submit" id="removeNumber" name="removeNumber" onclick="removeNumber()" value="Delete Sequence">
</td>
</tr>
</table>
@@ -146,15 +154,26 @@
<col span="1" style="width: 26%;">
<col span="1" style="width: 26%;">
</colgroup>
<tr>
<td style="padding: 0px">ROI:</td>
</tr>
<tr>
<td><select id="index" name="index" onchange="ChangeSelection()" tabindex=1></select></td>
<td><input class="button" type="submit" id="newROI" name="newROI" onclick="newROI()" value="New ROI"></td>
<td><input class="button" type="submit" id="renameROI" name="renameROI" onclick="renameROI()" value="Rename ROI"></td>
<td><input class="button" type="submit" id="deleteROI" name="deleteROI" onclick="deleteROI()" value="Delete ROI"></td>
<td>
<select id="index" name="index" onchange="ChangeSelection()" tabindex=1></select>
</td>
<td>
<input class="button" type="submit" id="newROI" name="newROI" onclick="newROI()" value="New ROI">
</td>
<td>
<input class="button" type="submit" id="renameROI" name="renameROI" onclick="renameROI()" value="Rename ROI">
</td>
<td>
<input class="button" type="submit" id="deleteROI" name="deleteROI" onclick="deleteROI()" value="Delete ROI">
</td>
</tr>
<tr>
<td class="multiplier">Multiplier: <output type="text" id="multiplier" name="multiplier"></output><br>
(only based on order)
@@ -162,8 +181,12 @@
<td class="multiplier">Multiplier: <output type="text" id="multiplier_decshift" name="multiplier_decshift"></output><br>
(order + decimal shift: <output type="text" id="decimalShift" name="decimalShift"></output>)
</td>
<td><input class="button" type="submit" id="movePrevious" onclick="movePrevious()" value="Move ROI Higher"></td>
<td><input class="button" type="submit" id="moveNext" onclick="moveNext()" value="Move ROI Lower"></td>
<td>
<input class="button" type="submit" id="movePrevious" onclick="movePrevious()" value="Move ROI Higher">
</td>
<td>
<input class="button" type="submit" id="moveNext" onclick="moveNext()" value="Move ROI Lower">
</td>
</tr>
</table>
@@ -173,10 +196,12 @@
<col span="1" style="width: 18%;">
<col span="1" style="width: 64%;">
</colgroup>
<tr>
<td>x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()" tabindex=2></td>
<td>Δx: <input type="number" name="refdx" id="refdx" step=1 onchange="valuemanualchangeddx()" tabindex=4></td>
</tr>
</tr>
<tr>
<td>y: <input type="number" name="refy" id="refy" step=1 onchange="valuemanualchanged()" tabindex=3></td>
<td>Δy: <input type="number" name="refdy" id="refdy" step=1 onchange="valuemanualchanged()" tabindex=5></td>
@@ -186,11 +211,11 @@
<hr>
The following settings are only used for easier setup, they are <b>not</b> persisted on the device:<br>
<input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=10><label for="showall">Show all ROIs</label><br>
<input type="checkbox" id="lockAspectRatio" name="lockAspectRatio" value="1" onclick="changelockAspectRatio()" checked tabindex=6><label for="lockAspectRatio"> Lock aspect ratio </label><br>
<input type="checkbox" id="lockSizes" name="lockSizes" value="1" onclick="changelockSizes()" checked tabindex=7><label for="lockSizes"> Synchronize y, Δx and Δy between ROIs</label><br>
<input type="checkbox" id="lockSpaceEquidistant" name="lockSpaceEquidistant" value="1" onclick="changeLockSpaceEquidistant()" checked tabindex=8>
The following settings are only used for easier setup, they are <b>not</b> persisted on the device:<br>
<input type="checkbox" id="showall" name="showall" value="1" onclick="draw()" checked tabindex=10><label for="showall">Show all ROIs</label><br>
<input type="checkbox" id="lockAspectRatio" name="lockAspectRatio" value="1" onclick="changelockAspectRatio()" checked tabindex=6><label for="lockAspectRatio"> Lock aspect ratio </label><br>
<input type="checkbox" id="lockSizes" name="lockSizes" value="1" onclick="changelockSizes()" checked tabindex=7><label for="lockSizes"> Synchronize y, Δx and Δy between ROIs</label><br>
<input type="checkbox" id="lockSpaceEquidistant" name="lockSpaceEquidistant" value="1" onclick="changeLockSpaceEquidistant()" checked tabindex=8>
<label for="lockSpaceEquidistant">Keep equidistance of <input type="number" name="space" id="space" maxlength="2" max=99 step=1 onchange="valuemanualchangedspace()" tabindex=9> between all ROIs</label><br>
<hr>
@@ -201,10 +226,14 @@ The following settings are only used for easier setup, they are <b>not</b> persi
<col span="1" style="width: 26%;">
<col span="1" style="width: 26%;">
</colgroup>
<tr>
<td colspan="3" style="vertical-align: bottom;"><b>Reference Image:</b></td>
<td><input style="font-weight:bold;" class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save Config" tabindex=11></td>
</tr>
<td>
<input style="font-weight:bold;" class="button" type="submit" id="saveroi" name="saveroi" onclick="SaveToConfig()" value="Save Config" tabindex=11>
</td>
</tr>
<tr>
<td colspan="4"><canvas id="canvas" crossorigin></canvas></td>
</tr>
@@ -491,6 +520,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
}
var _index = document.getElementById("index");
while (_index.length){
_index.remove(0);
}
@@ -582,7 +612,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
if(window.location.hash) {
var hash = window.location.hash.substring(1); //Puts hash in variable, and removes the # character
if(hash == 'description') {
document.getElementById("desc_details").open = true;
document.getElementById("desc_details").open = false;
}
}
}
@@ -590,14 +620,21 @@ The following settings are only used for easier setup, they are <b>not</b> persi
function init() {
openDescription();
domainname = getDomainname();
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
loadCanvas(domainname + "/fileserver/config/reference.jpg");
loadConfig(domainname);
if (!loadConfig(domainname)) {
firework.launch('Configuration could not be loaded! Please reload the page!', 'danger', 30000);
return;
}
ParseConfig();
param = getConfigParameters();
cofcat = getConfigCategory();
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
loadCanvas(domainname + "/fileserver/config/reference.jpg");
UpdateNUMBERS();
/* Check if the ROIs are equidistant. Only if not, untick the checkbox */
@@ -717,6 +754,7 @@ The following settings are only used for easier setup, they are <b>not</b> persi
}
erg = CreateNUMBER(_numbernew);
if (erg != "") {
firework.launch(erg, 'danger', 30000);
}
@@ -844,14 +882,17 @@ The following settings are only used for easier setup, they are <b>not</b> persi
function mouseUp() {
drag = false;
if (rect.w < 0) {
rect.w = -rect.w
rect.startX-=rect.w
}
if (rect.h < 0) {
rect.h = -rect.h
rect.startY-=rect.h
}
document.getElementById("refdx").value = rect.w;
document.getElementById("refdy").value = rect.h;
document.getElementById("refx").value = rect.startX;
@@ -876,10 +917,12 @@ The following settings are only used for easier setup, they are <b>not</b> persi
}
document.getElementById("refdx").value = rect.w;
document.getElementById("refdy").value = rect.h;
draw();
}
else {
draw();
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
@@ -915,10 +958,10 @@ The following settings are only used for easier setup, they are <b>not</b> persi
rect.startX = document.getElementById("refx").value;
rect.startY = document.getElementById("refy").value;
draw();
if (lockSpaceEquidistant) {
makeX_SpaceEquidistant();
}
}
draw();
}
document.getElementById("saveroi").disabled = false;
@@ -990,11 +1033,13 @@ The following settings are only used for easier setup, they are <b>not</b> persi
_roialt= sel.options[sel.selectedIndex].text;
var _roinew = prompt("Please enter a new name for the selected ROI", _roialt);
if (_roinew === null) {
return; //break out of the function early because prompt was aborted
}
erg = RenameROI(_number, "digit", _roialt, _roinew);
if (erg != "") {
firework.launch(erg, 'danger', 30000);
}

File diff suppressed because it is too large Load Diff

View File

@@ -21,21 +21,21 @@
var streamPopup;
var streamFlashlight = false;
var streamWindowFeatures =
'channelmode=no,directories=no,fullscreen=no,' +
'location=no,dependent=yes,menubar=no,resizable=no,scrollbars=no,' +
'status=no,toolbar=no,titlebar=no,' +
'left=10,top=260,width=640px,height=480px';
'channelmode=no,directories=no,fullscreen=no,' +
'location=no,dependent=yes,menubar=no,resizable=no,scrollbars=no,' +
'status=no,toolbar=no,titlebar=no,' +
'left=10,top=260,width=640px,height=480px';
function loadPage(page) {
function loadPage(page) {
console.log("loadPage( " + page + " )");
if (streamPopup) // Ensure that stream popup is closed because it's blocking web interface
if (streamPopup) { // Ensure that stream popup is closed because it's blocking web interface
streamPopup.close();
}
asyncPageLoad(page);
}
async function asyncPageLoad(page ) {
console.log(" loading " + page + " ...");
document.cookie = "page="+page + "; path=/";
@@ -46,7 +46,6 @@
});
}
function resetMenu() {
[].forEach.call(document.querySelectorAll('.submenu'), function (el) {
el.style.visibility = 'visible';
@@ -54,18 +53,20 @@
}
function getCookie(cname) {
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for(let i = 0; i <ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
let name = cname + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(';');
for(let i = 0; i <ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
</script>
@@ -90,7 +91,7 @@
<li><a>Settings <i class="arrow down"></i></a>
<ul class="submenu" style="width: 260px">
<li style="width: 260px"><a href="#" onclick="loadPage('prevalue_set.html?v=$COMMIT_HASH');">Set "Previous Value"</a></li>
<li style="width: 260px"><a>Alignment <i class="arrow right"></i></a>
<li style="width: 260px"><a>References <i class="arrow right"></i></a>
<ul style="width: 350px">
<li style="width: 350px"><a href="#" onclick="loadPage('edit_reference.html?v=$COMMIT_HASH');">Reference Image and Camera Settings</a></li>
<li style="width: 350px"><a href="#" onclick="loadPage('edit_alignment.html?v=$COMMIT_HASH');">Alignment Markers</a></li>
@@ -153,7 +154,7 @@
HA_send_discovery_visibility();
if (getCookie("page") == "" || getCookie("page") == "reboot_page.html?v=$COMMIT_HASH") {
document.cookie = "page=overview.html?v=$COMMIT_HASH" + "; path=/";
document.cookie = "page=overview.html?v=$COMMIT_HASH" + "; path=/";
}
console.log("Loading page: " + getCookie("page"));
document.getElementById('maincontent').src = getCookie("page");
@@ -181,19 +182,18 @@
}
*/
function HA_send_discovery_visibility() {
loadConfig(domainname);
ParseConfig();
category = getConfigCategory();
param = getConfigParameters();
if (category["MQTT"]["enabled"] && param["MQTT"]["HomeassistantDiscovery"]["value1"] == "true") {
if (category["MQTT"]["enabled"] && param["MQTT"]["HomeassistantDiscovery"].value == "true") {
document.getElementById("ManualControl").style.display="";
document.getElementById("HASendDiscovery").style.display="";
}
}
function HA_send_discovery() {
console.log("HA Discovery scheduled");
var url = getDomainname() + '/mqtt_publish_discovery';
@@ -207,15 +207,17 @@
xhttp.send();
}
function start_livestream(streamFlashlight) {
if (streamPopup)
if (streamPopup) {
streamPopup.close();
}
if (streamFlashlight)
if (streamFlashlight) {
streamPopup = window.open(getDomainname() + '/stream?flashlight=true','LivestreamWithlight',streamWindowFeatures);
else
}
else {
streamPopup = window.open(getDomainname() + '/stream','Livestream',streamWindowFeatures);
}
streamPopup.focus();
}

View File

@@ -353,32 +353,6 @@ Copyright &copy; 2020 - 2024 by <a href="https://github.com/jomjol/AI-on-the-edg
xhttp.send();
}
function loadWLANSSID()
{
url = getDomainname() + '/info?type=SSID';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("WLAN-SSID").value = xhttp.response;
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadWLANSSID()
{
url = getDomainname() + '/info?type=SSID';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("wlan-ssid").value = xhttp.response;
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadWLANSSID()
{
url = getDomainname() + '/info?type=SSID';

View File

@@ -5,13 +5,64 @@
<meta charset="UTF-8" />
<style>
.tg {border-collapse:collapse;border-spacing:0;width:100%;min-width:600px;height:100%;color:darkslategray;}
.tg th{min-width:325px;width:325px;height:20px;font-size:18px;text-align:left;font-weight:bold;padding:5px 10px 5px 10px;;overflow:hidden;word-break:normal;background-color:lightgrey;}
.tg td{font-size:15px;padding:5px 10px 5px 10px;overflow:hidden;word-break:normal;}
.tg .tg-1{font-size:15px;vertical-align: top; font-family:Arial, Helvetica, sans-serif !important;}
.tg .tg-2{height:52px;font-size:15px;padding:3px 0px 3px 10px;vertical-align:middle;font-family:Arial, Helvetica, sans-serif !important;}
.tg .tg-3{height:45px;font-size:15px;padding:3px 10px 3px 10px;vertical-align:middle;font-family:Arial, Helvetica, sans-serif !important;}
.tg .tg-4{height:fit-content;font-size:15px;padding:5px 10px 5px 10px;vertical-align:text-top;font-family:Arial, Helvetica, sans-serif !important;}
.tg {
border-collapse:collapse;
border-spacing:0;
width:100%;
min-width:600px;
height:100%;
color:darkslategray;
}
.tg th{
min-width:325px;
width:325px;
height:20px;
font-size:18px;
text-align:left;
font-weight:bold;
padding:5px 10px 5px 10px;
overflow:hidden;
word-break:normal;
background-color:lightgrey;
}
.tg td{
font-size:15px;
padding:5px 10px 5px 10px;
overflow:hidden;
word-break:normal;
}
.tg .tg-1{
font-size:15px;
vertical-align: top;
font-family:Arial, Helvetica, sans-serif !important;
}
.tg .tg-2{
height:52px;
font-size:15px;
padding:3px 0px 3px 10px;
vertical-align:middle;
font-family:Arial, Helvetica, sans-serif !important;
}
.tg .tg-3{
height:45px;
font-size:15px;
padding:3px 10px 3px 10px;
vertical-align:middle;
font-family:Arial, Helvetica, sans-serif !important;
}
.tg .tg-4{
height:fit-content;
font-size:15px;
padding:5px 10px 5px 10px;
vertical-align:text-top;
font-family:Arial, Helvetica, sans-serif !important;
}
</style>
</head>
@@ -78,221 +129,209 @@
</tr>
</table>
<script type="text/javascript" src="jquery-3.6.0.min.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="common.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="readconfigcommon.js?v=$COMMIT_HASH"></script>
<script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script>
<script type="text/javascript">
function addZero(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
function addZero(i) {
if (i < 10) {
i = "0" + i;
}
return i;
}
$(document).ready(function() {
LoadData();
LoadROIImage();
});
function LoadData(){
loadValue("value", "value", "border-collapse: collapse; width: 100%");
loadValue("raw", "raw", "border-collapse: collapse; width: 100%");
loadValue("prevalue", "prevalue", "border-collapse: collapse; width: 100%");
loadValue("error", "error", "border-collapse: collapse; width: 100%");
loadStatus();
loadCPUTemp();
loadRSSI();
loadUptime();
loadRoundCounter();
}
function LoadROIImage(){
var d = new Date();
var timestamp = d.getTime();
var h = addZero(d.getHours());
var m = addZero(d.getMinutes());
var s = addZero(d.getSeconds());
document.getElementById("img").src = getDomainname() + '/img_tmp/alg_roi.jpg?timestamp=' + timestamp;
$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
}
function Refresh() {
setTimeout (function() {
$(document).ready(function() {
LoadData();
LoadROIImage();
Refresh();
}, 300000);
}
});
function loadStatus() {
url = domainname + '/statusflow';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#statusflow').html(_rsp);
}
function LoadData(){
loadValue("value", "value", "border-collapse: collapse; width: 100%");
loadValue("raw", "raw", "border-collapse: collapse; width: 100%");
loadValue("prevalue", "prevalue", "border-collapse: collapse; width: 100%");
loadValue("error", "error", "border-collapse: collapse; width: 100%");
loadStatus();
loadCPUTemp();
loadRSSI();
loadUptime();
loadRoundCounter();
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadCPUTemp() {
url = domainname + '/cpu_temperature';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#cputemp').html("CPU Temperature: " +_rsp + "°C");
}
function LoadROIImage(){
var d = new Date();
var timestamp = d.getTime();
var h = addZero(d.getHours());
var m = addZero(d.getMinutes());
var s = addZero(d.getSeconds());
document.getElementById("img").src = getDomainname() + '/img_tmp/alg_roi.jpg?timestamp=' + timestamp;
$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
}
xhttp.open("GET", url, true);
xhttp.send();
}
function Refresh() {
setTimeout (function() {
LoadData();
LoadROIImage();
Refresh();
}, 300000);
}
function loadRSSI() {
url = domainname + '/rssi';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
function loadStatus() {
url = domainname + '/statusflow';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#statusflow').html(_rsp);
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadCPUTemp() {
url = domainname + '/cpu_temperature';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#cputemp').html("CPU Temperature: " +_rsp + "°C");
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadRSSI() {
url = domainname + '/rssi';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
if (_rsp >= -55) {
$('#rssi').html("WIFI Signal: Excellent (" + _rsp + "dBm)");
}
else if (_rsp < -55 && _rsp >= -67) {
$('#rssi').html("WIFI Signal: Good (" + _rsp + "dBm)");
}
else if (_rsp < -67 && _rsp >= -78) {
$('#rssi').html("WIFI Signal: Fair (" + _rsp + "dBm)");
}
else if (_rsp < -78 && _rsp >= -85) {
$('#rssi').html("WIFI Signal: Weak (" + _rsp + "dBm)");
}
else {
$('#rssi').html("WIFI Signal: Unreliable (" + _rsp + "dBm)");
if (_rsp >= -55) {
$('#rssi').html("WIFI Signal: Excellent (" + _rsp + "dBm)");
}
else if (_rsp < -55 && _rsp >= -67) {
$('#rssi').html("WIFI Signal: Good (" + _rsp + "dBm)");
}
else if (_rsp < -67 && _rsp >= -78) {
$('#rssi').html("WIFI Signal: Fair (" + _rsp + "dBm)");
}
else if (_rsp < -78 && _rsp >= -85) {
$('#rssi').html("WIFI Signal: Weak (" + _rsp + "dBm)");
}
else {
$('#rssi').html("WIFI Signal: Unreliable (" + _rsp + "dBm)");
}
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadUptime() {
url = domainname + '/uptime';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#uptime').html("Uptime: " + _rsp);
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadRoundCounter() {
url = domainname + '/info?type=Round';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#round').html("(Round: " + _rsp + ")");
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadValue(_type, _div, _style) {
url = domainname + '/value?all=true&type=' + _type;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
var _split = _rsp.split("\r");
if (typeof _style == undefined)
out = "<table>";
else
out = "<table style=\"" + _style + "\">";
if (_split.length == 1)
{
var _zer = ZerlegeZeile(_split[0], "\t")
if (_zer.length > 1)
out = _zer[1];
else
out = "";
}
else
{
for (var j = 0; j < _split.length; ++j)
{
var _zer = ZerlegeZeile(_split[j], "\t")
if (_zer.length == 1)
out = out + "<tr><td style=\"width: 22%; padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\">" +
_zer[0] + "</td><td style=\"padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\"> </td></tr>";
else
out = out + "<tr><td style=\"width: 22%; padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\">" +
_zer[0] + "</td><td style=\"padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\" >" + _zer[1] + "</td></tr>";
function loadUptime() {
url = domainname + '/uptime';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#uptime').html("Uptime: " + _rsp);
}
out = out + "</table>"
}
document.getElementById(_div).innerHTML = out;
}
};
xhttp.open("GET", url, true);
xhttp.send();
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadRoundCounter() {
url = domainname + '/info?type=Round';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#round').html("(Round: " + _rsp + ")");
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function setImageMaxWidth()
{
loadConfig(domainname);
ParseConfig();
param = getConfigParameters();
if(param["TakeImage"]["ImageSize"]["value1"] == "QVGA") {
if (param["Alignment"]["FlipImageSize"]["value1"] == "false") {
function loadValue(_type, _div, _style) {
url = domainname + '/value?all=true&type=' + _type;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
var _split = _rsp.split("\r");
if (typeof _style == undefined) {
out = "<table>";
}
else {
out = "<table style=\"" + _style + "\">";
}
if (_split.length == 1) {
var _zer = ZerlegeZeile(_split[0], "\t")
if (_zer.length > 1) {
out = _zer[1];
}
else {
out = "";
}
}
else {
for (var j = 0; j < _split.length; ++j) {
var _zer = ZerlegeZeile(_split[j], "\t")
if (_zer.length == 1) {
out = out + "<tr><td style=\"width: 22%; padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\">" +
_zer[0] + "</td><td style=\"padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\"> </td></tr>";
}
else {
out = out + "<tr><td style=\"width: 22%; padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\">" +
_zer[0] + "</td><td style=\"padding: 3px 5px; text-align: left; vertical-align:middle; border: 1px solid lightgrey\" >" + _zer[1] + "</td></tr>";
}
}
out = out + "</table>"
}
document.getElementById(_div).innerHTML = out;
}
};
xhttp.open("GET", url, true);
xhttp.send();
}
/*
function setImageMaxWidth() {
loadConfig(domainname);
ParseConfig();
param = getConfigParameters();
if(param["TakeImage"]["CamFrameSize"].value == "QVGA") {
document.getElementById("img").style.maxWidth = "320px";
}
else {
document.getElementById("img").style.maxWidth = "240px";
}
}
else {
if (param["Alignment"]["FlipImageSize"]["value1"] == "false") {
document.getElementById("img").style.maxWidth = "640px";
}
else {
document.getElementById("img").style.maxWidth = "480px";
}
}
}
*/
function init(){
domainname = getDomainname();
// setImageMaxWidth(); // CamFrameSize was replaced by zoom - CamFrameSize is no longer needed/used for zoom
Refresh();
}
init();
function init(){
domainname = getDomainname();
setImageMaxWidth();
Refresh();
}
init();
</script>
</script>
</body>
</html>

View File

@@ -1,11 +1,13 @@
function SaveConfigToServer(_domainname){
// leere Zeilen am Ende löschen
var zw = config_split.length - 1;
while (config_split[zw] == "") {
config_split.pop();
}
var config_gesamt = "";
for (var i = 0; i < config_split.length; ++i)
{
config_gesamt = config_gesamt + config_split[i] + "\n";
@@ -26,231 +28,227 @@ function UpdateConfig(zw, _index, _enhance, _domainname){
function createReader(file) {
var image = new Image();
reader.onload = function(evt) {
var image = new Image();
image.onload = function(evt) {
var width = this.width;
var height = this.height;
//alert (width); // will produce something like 198
};
image.src = evt.target.result;
};
reader.readAsDataURL(file);
}
function ZerlegeZeile(input, delimiter = " =\t\r")
{
var Output = Array(0);
function ZerlegeZeile(input, delimiter = " =\t\r") {
var Output = Array(0);
// delimiter = " =,\t";
/* The input can have multiple formats:
* - key = value
* - key = value1 value2 value3 ...
* - key value1 value2 value3 ...
*
* Examples:
* - ImageSize = VGA
* - IO0 = input disabled 10 false false
* - main.dig1 28 144 55 100 false
*
* This causes issues eg. if a password key has a whitespace or equal sign in its value.
* As a workaround and to not break any legacy usage, we enforce to only use the
* equal sign, if the key is "password"
*/
if (input.includes("password") || input.includes("Token")) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence
var pos = input.indexOf("=");
delimiter = " \t\r"
Output.push(trim(input.substr(0, pos), delimiter));
Output.push(trim(input.substr(pos +1, input.length), delimiter));
}
else { // Legacy Mode
input = trim(input, delimiter);
var pos = findDelimiterPos(input, delimiter);
var token;
while (pos > -1) {
token = input.substr(0, pos);
token = trim(token, delimiter);
Output.push(token);
input = input.substr(pos+1, input.length);
input = trim(input, delimiter);
pos = findDelimiterPos(input, delimiter);
}
Output.push(input);
}
/* The input can have multiple formats:
* - key = value
* - key = value1 value2 value3 ...
* - key value1 value2 value3 ...
*
* Examples:
* - ImageSize = VGA
* - IO0 = input disabled 10 false false
* - main.dig1 28 144 55 100 false
*
* This causes issues eg. if a password key has a whitespace or equal sign in its value.
* As a workaround and to not break any legacy usage, we enforce to only use the
* equal sign, if the key is "password"
*/
if (input.includes("password") || input.includes("Token")) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence
var pos = input.indexOf("=");
delimiter = " \t\r"
Output.push(trim(input.substr(0, pos), delimiter));
Output.push(trim(input.substr(pos +1, input.length), delimiter));
}
else { // Legacy Mode
input = trim(input, delimiter);
var pos = findDelimiterPos(input, delimiter);
var token;
while (pos > -1) {
token = input.substr(0, pos);
token = trim(token, delimiter);
Output.push(token);
input = input.substr(pos+1, input.length);
input = trim(input, delimiter);
pos = findDelimiterPos(input, delimiter);
}
Output.push(input);
}
return Output;
}
return Output;
}
function findDelimiterPos(input, delimiter)
{
var pos = -1;
var zw;
var akt_del;
function findDelimiterPos(input, delimiter) {
var pos = -1;
var zw;
var akt_del;
for (var anz = 0; anz < delimiter.length; ++anz)
{
akt_del = delimiter[anz];
zw = input.indexOf(akt_del);
if (zw > -1)
{
if (pos > -1)
{
if (zw < pos)
pos = zw;
}
else
pos = zw;
}
}
return pos;
}
for (var anz = 0; anz < delimiter.length; ++anz) {
akt_del = delimiter[anz];
zw = input.indexOf(akt_del);
if (zw > -1) {
if (pos > -1) {
if (zw < pos) {
pos = zw;
}
}
else {
pos = zw;
}
}
}
return pos;
}
function trim(istring, adddelimiter)
{
while ((istring.length > 0) && (adddelimiter.indexOf(istring[0]) >= 0)){
istring = istring.substr(1, istring.length-1);
}
function trim(istring, adddelimiter) {
while ((istring.length > 0) && (adddelimiter.indexOf(istring[0]) >= 0)) {
istring = istring.substr(1, istring.length-1);
}
while ((istring.length > 0) && (adddelimiter.indexOf(istring[istring.length-1]) >= 0)){
istring = istring.substr(0, istring.length-1);
}
while ((istring.length > 0) && (adddelimiter.indexOf(istring[istring.length-1]) >= 0)) {
istring = istring.substr(0, istring.length-1);
}
return istring;
}
return istring;
}
function getConfig()
{
return config_gesamt;
function getConfig() {
return config_gesamt;
}
function loadConfig(_domainname)
{
var xhttp = new XMLHttpRequest();
try {
url = _domainname + '/fileserver/config/config.ini';
xhttp.open("GET", url, false);
xhttp.send();
config_gesamt = xhttp.responseText;
config_gesamt = config_gesamt.replace("InitalRotate", "InitialRotate"); // Korrigiere Schreibfehler in config.ini !!!!!
}
catch (error)
{
// firework.launch('Deleting Config.ini failed!', 'danger', 30000);
}
return true;
function loadConfig(_domainname) {
var xhttp = new XMLHttpRequest();
try {
url = _domainname + '/fileserver/config/config.ini';
xhttp.open("GET", url, false);
xhttp.send();
config_gesamt = xhttp.responseText;
config_gesamt = config_gesamt.replace("InitalRotate", "InitialRotate"); // Korrigiere Schreibfehler in config.ini !!!!!
} catch (error) {}
return true;
}
function dataURLtoBlob(dataurl)
{
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
while(n--){
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], {type:mime});
}
function FileCopyOnServer(_source, _target, _domainname = ""){
url = _domainname + "/editflow?task=copy&in=" + _source + "&out=" + _target;
var xhttp = new XMLHttpRequest();
try {
xhttp.open("GET", url, false);
xhttp.send(); }
catch (error)
{
// firework.launch('Deleting Config.ini failed!', 'danger', 30000);
}
function FileCopyOnServer(_source, _target, _domainname = "") {
url = _domainname + "/editflow?task=copy&in=" + _source + "&out=" + _target;
var xhttp = new XMLHttpRequest();
try {
xhttp.open("GET", url, false);
xhttp.send();
} catch (error) {}
}
function FileDeleteOnServer(_filename, _domainname = ""){
var xhttp = new XMLHttpRequest();
var okay = false;
function FileDeleteOnServer(_filename, _domainname = "") {
var xhttp = new XMLHttpRequest();
var okay = false;
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
okay = true;
} else if (xhttp.status == 0) {
// firework.launch('Server closed the connection abruptly!', 'danger', 30000);
// location.reload()
} else {
// firework.launch('An error occured: ' + xhttp.responseText, 'danger', 30000);
// location.reload()
}
}
};
try {
var url = _domainname + "/delete" + _filename;
xhttp.open("POST", url, false);
xhttp.send();
}
catch (error)
{
// firework.launch('Deleting Config.ini failed!', 'danger', 30000);
}
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
okay = true;
}
else if (xhttp.status == 0) {
// firework.launch('Server closed the connection abruptly!', 'danger', 30000);
// location.reload()
}
else {
// firework.launch('An error occured: ' + xhttp.responseText, 'danger', 30000);
// location.reload()
}
}
};
try {
var url = _domainname + "/delete" + _filename;
xhttp.open("POST", url, false);
xhttp.send();
} catch (error) {}
return okay;
return okay;
}
function FileSendContent(_content, _filename, _domainname = ""){
var xhttp = new XMLHttpRequest();
var okay = false;
function FileSendContent(_content, _filename, _domainname = "") {
var xhttp = new XMLHttpRequest();
var okay = false;
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
okay = true;
} else if (xhttp.status == 0) {
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4) {
if (xhttp.status == 200) {
okay = true;
}
else if (xhttp.status == 0) {
firework.launch('Server closed the connection abruptly!', 'danger', 30000);
} else {
}
else {
firework.launch('An error occured: ' + xhttp.responseText, 'danger', 30000);
}
}
};
}
}
};
try {
upload_path = _domainname + "/upload" + _filename;
xhttp.open("POST", upload_path, false);
xhttp.send(_content);
}
catch (error)
{
// firework.launch('Deleting Config.ini failed!', 'danger', 30000);
}
try {
upload_path = _domainname + "/upload" + _filename;
xhttp.open("POST", upload_path, false);
xhttp.send(_content);
} catch (error) {}
return okay;
}
function MakeRefImageZW(zw, _enhance, _domainname){
var _filename = zw["name"].replace("/config/", "/img_tmp/");
var _filename = zw["name"].replace("/config/", "/img_tmp/");
var url = _domainname + "/editflow?task=cutref&in=/config/reference.jpg&out=" + _filename + "&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
var url = _domainname + "/editflow?task=cutref&in=/config/reference.jpg&out=" + _filename + "&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
if (_enhance == true){
url = url + "&enhance=true";
}
if (_enhance == true){
url = url + "&enhance=true";
}
var xhttp = new XMLHttpRequest();
var xhttp = new XMLHttpRequest();
try {
xhttp.open("GET", url, false);
xhttp.send();
} catch (error){}
try {
xhttp.open("GET", url, false);
xhttp.send();
} catch (error){}
if (xhttp.responseText == "CutImage Done") {
firework.launch('Image Contrast got enhanced', 'success', 5000);
return true;
}
else {
return false;
}
if (xhttp.responseText == "CutImage Done") {
firework.launch('Image Contrast got enhanced', 'success', 5000);
return true;
}
else {
return false;
}
}

File diff suppressed because it is too large Load Diff