mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-06 19:46:54 +03:00
Compare commits
61 Commits
mqtt-logfi
...
v15.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d0b0187f4 | ||
|
|
4cf9ea6c45 | ||
|
|
1b76e0f449 | ||
|
|
d4a0ad20ff | ||
|
|
df72445e79 | ||
|
|
456cb93809 | ||
|
|
d968a7adc6 | ||
|
|
9a52b8b2f3 | ||
|
|
8caa852bbf | ||
|
|
4faca4c46c | ||
|
|
238fc5fae3 | ||
|
|
c32ca5a23c | ||
|
|
827d9d1700 | ||
|
|
0ea4b3b3ce | ||
|
|
3e26c6c743 | ||
|
|
fa5c99b3cb | ||
|
|
6feae4e239 | ||
|
|
ef64be3888 | ||
|
|
cc89d625f2 | ||
|
|
08ba754b88 | ||
|
|
6b38e44d7f | ||
|
|
141aea7fa7 | ||
|
|
bcd07761b6 | ||
|
|
fe4d861e15 | ||
|
|
71322c9fbe | ||
|
|
f8b4881a50 | ||
|
|
438d5696e4 | ||
|
|
0d391c8780 | ||
|
|
59de6319a1 | ||
|
|
3805687219 | ||
|
|
c6a789dc45 | ||
|
|
246f9cfc31 | ||
|
|
b2d8c60bb1 | ||
|
|
1d573cd18a | ||
|
|
b2e5cdd8a3 | ||
|
|
f7fde7c430 | ||
|
|
2c19080a66 | ||
|
|
35663c5fd4 | ||
|
|
5b449d5c45 | ||
|
|
3a5f3496d5 | ||
|
|
00434d01c3 | ||
|
|
3e0bb81e32 | ||
|
|
4f57f9eafd | ||
|
|
f24ec581e6 | ||
|
|
0d78bb78ea | ||
|
|
47aea007b3 | ||
|
|
284b3f428e | ||
|
|
92d45c7971 | ||
|
|
ff1d9d3b4f | ||
|
|
2b57dd0853 | ||
|
|
dd8f5eea22 | ||
|
|
60c5305378 | ||
|
|
8b1c65a38a | ||
|
|
4f5933c4f2 | ||
|
|
06c9bfb0de | ||
|
|
69f1a99b55 | ||
|
|
a8fb88a35d | ||
|
|
d418d22155 | ||
|
|
53e8cf49f9 | ||
|
|
ac4f823cbf | ||
|
|
444dc0fa39 |
@@ -1,5 +1,5 @@
|
||||
# Reply Bot
|
||||
# It uses the configuration in .github/label-commenter-config.yml
|
||||
# It uses the configuration in .github/label-commenter-config.yaml
|
||||
# See https://github.com/peaceiris/actions-label-commenter
|
||||
|
||||
name: Reply-Bot
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
|
||||
####################################################################
|
||||
## Remove labels again (issues only)
|
||||
## Make sure to also add the reply message to .github/label-commenter-config.yml!
|
||||
## Make sure to also add the reply message to .github/label-commenter-config.yaml!
|
||||
## This currently seems no longer to work due to changes on the actions-cool/issues-helper!
|
||||
####################################################################
|
||||
# - name: Remove 'Logfile' label again (issues only)
|
||||
@@ -74,6 +74,7 @@ jobs:
|
||||
## Write the response
|
||||
####################################################################
|
||||
- name: Write Response
|
||||
uses: peaceiris/actions-label-commenter@c2d00660c86f2b9ed0fb35b372c451558eba85b3
|
||||
uses: peaceiris/actions-label-commenter@v1
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
github_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
config_file: .github/label-commenter-config.yaml
|
||||
17
Changelog.md
17
Changelog.md
@@ -1,3 +1,18 @@
|
||||
## [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)
|
||||
|
||||
#### Core Changes
|
||||
- Added new camera settings (See `Settings > Alignment > Reference Image and Camera Settings`). You might need to re-create the reference image and alignment marks. Note worthy:
|
||||
- You can now crop the image
|
||||
- Support to configure sharpness, grayscale, negatoive and exposure
|
||||
- Enhanced various WebUI pages with better explanations and usability
|
||||
- Add Firmware Version to MQTT
|
||||
|
||||
#### Bug Fixes
|
||||
- Reverted "Implemented late analog / digital transition [#2778](https://github.com/jomjol/AI-on-the-edge-device/pull/2778) (introduced in `v15.5`) as is seems to cause issues for many users.
|
||||
|
||||
|
||||
## [15.6.0] - 2024-02-09
|
||||
|
||||
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.5.0...v15.6.0)
|
||||
@@ -42,6 +57,8 @@ For a full list of changes see [Full list of changes](https://github.com/jomjol/
|
||||
- dig-class100-0167_s2_q.tflite
|
||||
- dig-class11_1700_s2.tflite
|
||||
- ana-cont_1208_s2_q.tflite
|
||||
|
||||
- Added config entries for MQTT TLS
|
||||
|
||||
|
||||
#### Fixed
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "driver/ledc.h"
|
||||
#include "MainFlowControl.h"
|
||||
|
||||
#include "ov2640_sharpness.h"
|
||||
|
||||
#if (ESP_IDF_VERSION_MAJOR >= 5)
|
||||
#include "soc/periph_defs.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
@@ -53,6 +55,10 @@ static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary="
|
||||
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
|
||||
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
|
||||
|
||||
// OV2640 Camera SDE Indirect Register Access
|
||||
#define OV2640_IRA_BPADDR 0x7C
|
||||
#define OV2640_IRA_BPDATA 0x7D
|
||||
|
||||
|
||||
static camera_config_t camera_config = {
|
||||
.pin_pwdn = CAM_PIN_PWDN,
|
||||
@@ -166,48 +172,93 @@ static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size
|
||||
}
|
||||
|
||||
|
||||
bool CCamera::SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation)
|
||||
bool CCamera::SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation, int _autoExposureLevel, bool _grayscale, bool _negative, bool _aec2, int _sharpnessLevel)
|
||||
{
|
||||
_brightness = min(2, max(-2, _brightness));
|
||||
_contrast = min(2, max(-2, _contrast));
|
||||
_saturation = min(2, max(-2, _saturation));
|
||||
_autoExposureLevel = min(2, max(-2, _autoExposureLevel));
|
||||
bool _autoSharpness = false;
|
||||
if (_sharpnessLevel <= -4)
|
||||
_autoSharpness = true;
|
||||
_sharpnessLevel = min(3, max(-3, _sharpnessLevel));
|
||||
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
if (s) {
|
||||
// camera gives precedence to negative over grayscale, so it's easier to do negative ourselves.
|
||||
// if (_negative) {
|
||||
// s->set_special_effect(s, 1); // 0 - no effect, 1 - negative, 2 - grayscale, 3 - reddish, 4 - greenish, 5 - blue, 6 - retro
|
||||
// }
|
||||
if (_grayscale) {
|
||||
s->set_special_effect(s, 2); // 0 - no effect, 1 - negative, 2 - grayscale, 3 - reddish, 4 - greenish, 5 - blue, 6 - retro
|
||||
}
|
||||
|
||||
// auto exposure controls
|
||||
s->set_aec2(s, _aec2 ? 1 : 0);
|
||||
s->set_ae_level(s, _autoExposureLevel); // -2 to 2
|
||||
s->set_gainceiling(s, GAINCEILING_2X); // GAINCEILING_2X 4X 8X 16X 32X 64X 128X
|
||||
|
||||
// post processing
|
||||
if (_autoSharpness) {
|
||||
s->set_sharpness(s, 0); // auto-sharpness is not officially supported, default to 0
|
||||
}
|
||||
s->set_saturation(s, _saturation);
|
||||
s->set_contrast(s, _contrast);
|
||||
s->set_brightness(s, _brightness);
|
||||
|
||||
/* Workaround - bug in cam library - enable bits are set without using bitwise OR logic -> only latest enable setting is used */
|
||||
/* Library version: https://github.com/espressif/esp32-camera/commit/5c8349f4cf169c8a61283e0da9b8cff10994d3f3 */
|
||||
/* Reference: https://esp32.com/viewtopic.php?f=19&t=14376#p93178 */
|
||||
/* The memory structure is as follows for
|
||||
byte_0 = enable_bits
|
||||
byte_0->bit0 = enable saturation and hue --> OK
|
||||
byte_0->bit1 = enable saturation --> OK
|
||||
byte_0->bit2 = enable brightness and contrast --> OK
|
||||
byte_0->bit3 = enable green -> blue spitial effect (Antique and blunish and greenish and readdish and b&w) enable
|
||||
byte_0->bit4 = anable gray -> read spitial effect (Antique and blunish and greenish and readdish and b&w) enable
|
||||
byte_0->bit5 = remove (UV) in YUV color system
|
||||
byte_0->bit6 = enable negative
|
||||
byte_0->bit7 = remove (Y) in YUV color system
|
||||
byte_1 = saturation1 0-255 --> ?
|
||||
byte_2 = hue 0-255 --> OK
|
||||
byte_3 = saturation2 0-255 --> OK
|
||||
byte_4 = reenter saturation2 in documents --> ?
|
||||
byte_5 = spital effect green -> blue 0-255 --> ?
|
||||
byte_6 = spital effect gray -> read 0-255 --> ?
|
||||
byte_7 = contrast lower byte 0-255 --> OK
|
||||
byte_8 = contrast higher byte 0-255 --> OK
|
||||
byte_9 = brightness 0-255 --> OK
|
||||
byte_10= if byte_10==4 contrast effective --> ?
|
||||
*/
|
||||
camera_sensor_info_t *sensor_info = esp_camera_sensor_get_info(&(s->id));
|
||||
if (sensor_info != NULL) {
|
||||
if (sensor_info->model == CAMERA_OV2640) {
|
||||
if (_autoSharpness) {
|
||||
ov2640_enable_auto_sharpness(s);
|
||||
} else {
|
||||
ov2640_set_sharpness(s, _sharpnessLevel);
|
||||
}
|
||||
|
||||
//s->set_reg(s, 0x7C, 0xFF, 2); // Optional feature - hue setting: Select byte 2 in register 0x7C to set hue value
|
||||
//s->set_reg(s, 0x7D, 0xFF, 0); // Optional feature - hue setting: Hue value 0 - 255
|
||||
s->set_reg(s, 0xFF, 0x01, 0); // Select DSP bank
|
||||
s->set_reg(s, 0x7C, 0xFF, 0); // Select byte 0 in register 0x7C
|
||||
s->set_reg(s, 0x7D, 7, 7); // Set bit 0, 1, 2 in register 0x7D to enable saturation, contrast, brightness and hue control
|
||||
/* Workaround - bug in cam library - enable bits are set without using bitwise OR logic -> only latest enable setting is used */
|
||||
/* Library version: https://github.com/espressif/esp32-camera/commit/5c8349f4cf169c8a61283e0da9b8cff10994d3f3 */
|
||||
/* Reference: https://esp32.com/viewtopic.php?f=19&t=14376#p93178 */
|
||||
/* The memory structure is as follows for
|
||||
byte_0 = enable_bits
|
||||
byte_0->bit0 = enable saturation and hue --> OK
|
||||
byte_0->bit1 = enable saturation --> OK
|
||||
byte_0->bit2 = enable brightness and contrast --> OK
|
||||
byte_0->bit3 = enable green -> blue spitial effect (Antique and blunish and greenish and readdish and b&w) enable
|
||||
byte_0->bit4 = anable gray -> read spitial effect (Antique and blunish and greenish and readdish and b&w) enable
|
||||
byte_0->bit5 = remove (UV) in YUV color system
|
||||
byte_0->bit6 = enable negative
|
||||
byte_0->bit7 = remove (Y) in YUV color system
|
||||
byte_1 = saturation1 0-255 --> ?
|
||||
byte_2 = hue 0-255 --> OK
|
||||
byte_3 = saturation2 0-255 --> OK
|
||||
byte_4 = reenter saturation2 in documents --> ?
|
||||
byte_5 = spital effect green -> blue 0-255 --> ?
|
||||
byte_6 = spital effect gray -> read 0-255 --> ?
|
||||
byte_7 = contrast lower byte 0-255 --> OK
|
||||
byte_8 = contrast higher byte 0-255 --> OK
|
||||
byte_9 = brightness 0-255 --> OK
|
||||
byte_10= if byte_10==4 contrast effective --> ?
|
||||
*/
|
||||
|
||||
//s->set_reg(s, 0x7C, 0xFF, 2); // Optional feature - hue setting: Select byte 2 in register 0x7C to set hue value
|
||||
//s->set_reg(s, 0x7D, 0xFF, 0); // Optional feature - hue setting: Hue value 0 - 255
|
||||
int indirectReg0 = 0x07; // Set bit 0, 1, 2 to enable saturation, contrast, brightness and hue control
|
||||
if (_grayscale) {
|
||||
indirectReg0 |= 0x18;
|
||||
}
|
||||
// camera gives precedence to negative over grayscale, so it's easier to do negative ourselves.
|
||||
// if (_negative) {
|
||||
// indirectReg0 |= 0x40;
|
||||
// }
|
||||
// Indirect register access
|
||||
s->set_reg(s, 0xFF, 0x01, 0); // Select DSP bank
|
||||
s->set_reg(s, OV2640_IRA_BPADDR, 0xFF, 0x00); // Address 0x00
|
||||
s->set_reg(s, OV2640_IRA_BPDATA, 0xFF, indirectReg0);
|
||||
s->set_reg(s, OV2640_IRA_BPADDR, 0xFF, 0x05); // Address 0x05
|
||||
s->set_reg(s, OV2640_IRA_BPDATA, 0xFF, 0x80);
|
||||
s->set_reg(s, OV2640_IRA_BPDATA, 0xFF, 0x80);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "SetBrightnessContrastSaturation: Failed to get control structure");
|
||||
@@ -219,38 +270,127 @@ bool CCamera::SetBrightnessContrastSaturation(int _brightness, int _contrast, in
|
||||
brightness = _brightness;
|
||||
contrast = _contrast;
|
||||
saturation = _saturation;
|
||||
autoExposureLevel = _autoExposureLevel;
|
||||
imageGrayscale = _grayscale;
|
||||
imageNegative = _negative;
|
||||
imageAec2 = _aec2;
|
||||
imageAutoSharpness = _autoSharpness;
|
||||
imageSharpnessLevel = _sharpnessLevel;
|
||||
|
||||
ESP_LOGD(TAG, "brightness %d, contrast: %d, saturation %d", brightness, contrast, saturation);
|
||||
ESP_LOGD(TAG, "brightness %d, contrast: %d, saturation %d, autoExposureLevel %d, grayscale %d", brightness, contrast, saturation, autoExposureLevel, (int)imageGrayscale);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CCamera::SetQualitySize(int qual, framesize_t resol)
|
||||
/*
|
||||
* resolution = 0 \\ 1600 x 1200
|
||||
* resolution = 1 \\ 800 x 600
|
||||
* resolution = 2 \\ 400 x 296
|
||||
*/
|
||||
void CCamera::SetCamWindow(sensor_t *s, int resolution, int xOffset, int yOffset, int xLength, int yLength)
|
||||
{
|
||||
qual = min(63, max(8, qual)); // Limit quality from 8..63 (values lower than 8 tent to be unstable)
|
||||
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
if (s) {
|
||||
s->set_quality(s, qual);
|
||||
s->set_framesize(s, resol);
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "SetQualitySize: Failed to get control structure");
|
||||
}
|
||||
s->set_res_raw(s, resolution, 0, 0, 0, xOffset, yOffset, xLength, yLength, xLength, yLength, false, false);
|
||||
}
|
||||
|
||||
ActualResolution = resol;
|
||||
ActualQuality = qual;
|
||||
|
||||
void CCamera::SetImageWidthHeightFromResolution(framesize_t resol)
|
||||
{
|
||||
if (resol == FRAMESIZE_QVGA)
|
||||
{
|
||||
image_height = 240;
|
||||
image_width = 320;
|
||||
image_width = 320;
|
||||
}
|
||||
else if (resol == FRAMESIZE_VGA)
|
||||
{
|
||||
image_height = 480;
|
||||
image_width = 640;
|
||||
image_width = 640;
|
||||
}
|
||||
else if (resol == FRAMESIZE_SVGA)
|
||||
{
|
||||
image_height = 600;
|
||||
image_width = 800;
|
||||
}
|
||||
else if (resol == FRAMESIZE_XGA)
|
||||
{
|
||||
image_height = 768;
|
||||
image_width = 1024;
|
||||
}
|
||||
else if (resol == FRAMESIZE_HD)
|
||||
{
|
||||
image_height = 720;
|
||||
image_width = 1280;
|
||||
}
|
||||
else if (resol == FRAMESIZE_SXGA)
|
||||
{
|
||||
image_height = 1024;
|
||||
image_width = 1280;
|
||||
}
|
||||
else if (resol == FRAMESIZE_UXGA)
|
||||
{
|
||||
image_height = 1200;
|
||||
image_width = 1600;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CCamera::SetZoom(bool zoomEnabled, int zoomMode, int zoomOffsetX, int zoomOffsetY)
|
||||
{
|
||||
imageZoomEnabled = zoomEnabled;
|
||||
imageZoomMode = zoomMode;
|
||||
imageZoomOffsetX = zoomOffsetX;
|
||||
imageZoomOffsetY = zoomOffsetY;
|
||||
|
||||
sensor_t *s = esp_camera_sensor_get();
|
||||
if (s) {
|
||||
if (imageZoomEnabled) {
|
||||
int z = imageZoomMode;
|
||||
int x = imageZoomOffsetX;
|
||||
int y = imageZoomOffsetY;
|
||||
if (z > 1)
|
||||
z = 1;
|
||||
if (image_width >= 800 || image_height >= 600) {
|
||||
z = 0;
|
||||
}
|
||||
int maxX = 1600 - image_width;
|
||||
int maxY = 1200 - image_height;
|
||||
if (z == 1) {
|
||||
maxX = 800 - image_width;
|
||||
maxY = 600 - image_height;
|
||||
}
|
||||
if (x > maxX)
|
||||
x = maxX;
|
||||
if (y > maxY)
|
||||
y = maxY;
|
||||
SetCamWindow(s, z, x, y, image_width, image_height);
|
||||
} else {
|
||||
s->set_framesize(s, ActualResolution);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CCamera::SetQualitySize(int qual, framesize_t resol, bool zoomEnabled, int zoomMode, int zoomOffsetX, int zoomOffsetY)
|
||||
{
|
||||
qual = min(63, max(8, qual)); // Limit quality from 8..63 (values lower than 8 tent to be unstable)
|
||||
|
||||
ActualResolution = resol;
|
||||
ActualQuality = qual;
|
||||
|
||||
imageZoomEnabled = zoomEnabled;
|
||||
imageZoomMode = zoomMode;
|
||||
imageZoomOffsetX = zoomOffsetX;
|
||||
imageZoomOffsetY = zoomOffsetY;
|
||||
|
||||
SetImageWidthHeightFromResolution(resol);
|
||||
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
if (s) {
|
||||
s->set_quality(s, qual);
|
||||
SetZoom(zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "SetQualitySize: Failed to get control structure");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,7 +455,7 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
#endif
|
||||
|
||||
camera_fb_t * fb = esp_camera_fb_get();
|
||||
esp_camera_fb_return(fb);
|
||||
esp_camera_fb_return(fb);
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
LEDOnOff(false);
|
||||
@@ -340,24 +480,32 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CaptureToBasisImage: Can't allocate _zwImage");
|
||||
}
|
||||
esp_camera_fb_return(fb);
|
||||
esp_camera_fb_return(fb);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CaptureToBasisImage - After fb_get");
|
||||
#endif
|
||||
|
||||
LEDOnOff(false);
|
||||
LEDOnOff(false);
|
||||
|
||||
if (delay > 0)
|
||||
LightOnOff(false);
|
||||
|
||||
// TickType_t xDelay = 1000 / portTICK_PERIOD_MS;
|
||||
// TickType_t xDelay = 1000 / portTICK_PERIOD_MS;
|
||||
// vTaskDelay( xDelay ); // wait for power to recover
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CaptureToBasisImage - After LoadFromMemory");
|
||||
#endif
|
||||
|
||||
if (_zwImage == NULL) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (imageNegative) {
|
||||
_zwImage->Negative();
|
||||
}
|
||||
|
||||
stbi_uc* p_target;
|
||||
stbi_uc* p_source;
|
||||
int channels = 3;
|
||||
@@ -375,9 +523,9 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
{
|
||||
p_target = _Image->rgb_image + (channels * (y * width + x));
|
||||
p_source = _zwImage->rgb_image + (channels * (y * width + x));
|
||||
p_target[0] = p_source[0];
|
||||
p_target[1] = p_source[1];
|
||||
p_target[2] = p_source[2];
|
||||
for (int c = 0; c < channels; c++) {
|
||||
p_target[c] = p_source[c];
|
||||
}
|
||||
}
|
||||
|
||||
delete _zwImage;
|
||||
@@ -386,7 +534,7 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
LogFile.WriteHeapInfo("CaptureToBasisImage - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -394,7 +542,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
{
|
||||
string ftype;
|
||||
|
||||
LEDOnOff(true); // Switched off to save power !
|
||||
LEDOnOff(true); // Switched off to save power !
|
||||
|
||||
if (delay > 0) {
|
||||
LightOnOff(true);
|
||||
@@ -414,7 +562,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
LEDOnOff(false);
|
||||
LEDOnOff(false);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "w %d, h %d, size %d", fb->width, fb->height, fb->len);
|
||||
@@ -504,8 +652,7 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
LEDOnOff(false);
|
||||
|
||||
LEDOnOff(false);
|
||||
res = httpd_resp_set_type(req, "image/jpeg");
|
||||
if(res == ESP_OK){
|
||||
res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=raw.jpg");
|
||||
@@ -662,49 +809,89 @@ void CCamera::LEDOnOff(bool status)
|
||||
}
|
||||
|
||||
|
||||
void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol)
|
||||
void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol, bool &zoomEnabled, int &zoomMode, int &zoomOffsetX, int &zoomOffsetY)
|
||||
{
|
||||
char _query[100];
|
||||
char _qual[10];
|
||||
char _size[10];
|
||||
char _value[10];
|
||||
|
||||
resol = ActualResolution;
|
||||
qual = ActualQuality;
|
||||
|
||||
zoomEnabled = imageZoomEnabled;
|
||||
zoomMode = imageZoomMode;
|
||||
zoomOffsetX = imageZoomOffsetX;
|
||||
zoomOffsetY = imageZoomOffsetY;
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "size", _size, 10) == ESP_OK)
|
||||
if (httpd_query_key_value(_query, "size", _value, sizeof(_value)) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Size: %s", _size);
|
||||
#endif
|
||||
if (strcmp(_size, "QVGA") == 0)
|
||||
if (strcmp(_value, "QVGA") == 0)
|
||||
resol = FRAMESIZE_QVGA; // 320x240
|
||||
else if (strcmp(_size, "VGA") == 0)
|
||||
else if (strcmp(_value, "VGA") == 0)
|
||||
resol = FRAMESIZE_VGA; // 640x480
|
||||
else if (strcmp(_size, "SVGA") == 0)
|
||||
else if (strcmp(_value, "SVGA") == 0)
|
||||
resol = FRAMESIZE_SVGA; // 800x600
|
||||
else if (strcmp(_size, "XGA") == 0)
|
||||
else if (strcmp(_value, "XGA") == 0)
|
||||
resol = FRAMESIZE_XGA; // 1024x768
|
||||
else if (strcmp(_size, "SXGA") == 0)
|
||||
else if (strcmp(_value, "SXGA") == 0)
|
||||
resol = FRAMESIZE_SXGA; // 1280x1024
|
||||
else if (strcmp(_size, "UXGA") == 0)
|
||||
else if (strcmp(_value, "UXGA") == 0)
|
||||
resol = FRAMESIZE_UXGA; // 1600x1200
|
||||
}
|
||||
if (httpd_query_key_value(_query, "quality", _qual, 10) == ESP_OK)
|
||||
if (httpd_query_key_value(_query, "quality", _value, sizeof(_value)) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Quality: %s", _qual);
|
||||
#endif
|
||||
qual = atoi(_qual);
|
||||
|
||||
qual = atoi(_value);
|
||||
if (qual > 63) // Limit to max. 63
|
||||
qual = 63;
|
||||
else if (qual < 8) // Limit to min. 8
|
||||
qual = 8;
|
||||
}
|
||||
if (httpd_query_key_value(_query, "z", _value, sizeof(_value)) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Zoom: %s", _value);
|
||||
#endif
|
||||
if (atoi(_value) != 0)
|
||||
zoomEnabled = true;
|
||||
else
|
||||
zoomEnabled = false;
|
||||
}
|
||||
if (httpd_query_key_value(_query, "zm", _value, sizeof(_value)) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Zoom mode: %s", _value);
|
||||
#endif
|
||||
zoomMode = atoi(_value);
|
||||
if (zoomMode > 2)
|
||||
zoomMode = 2;
|
||||
else if (zoomMode < 0)
|
||||
zoomMode = 0;
|
||||
}
|
||||
if (httpd_query_key_value(_query, "x", _value, sizeof(_value)) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "X offset: %s", _value);
|
||||
#endif
|
||||
zoomOffsetX = atoi(_value);
|
||||
if (zoomOffsetX < 0)
|
||||
zoomOffsetX = 0;
|
||||
}
|
||||
if (httpd_query_key_value(_query, "y", _value, sizeof(_value)) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Y offset: %s", _value);
|
||||
#endif
|
||||
zoomOffsetY = atoi(_value);
|
||||
if (zoomOffsetY < 0)
|
||||
zoomOffsetY = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class CCamera {
|
||||
protected:
|
||||
int ActualQuality;
|
||||
framesize_t ActualResolution;
|
||||
int brightness, contrast, saturation;
|
||||
int brightness, contrast, saturation, autoExposureLevel;
|
||||
bool isFixedExposure;
|
||||
int waitbeforepicture_org;
|
||||
int led_intensity = 4095;
|
||||
@@ -31,8 +31,24 @@ class CCamera {
|
||||
bool loadNextDemoImage(camera_fb_t *fb);
|
||||
long GetFileSize(std::string filename);
|
||||
|
||||
void SetCamWindow(sensor_t *s, int resolution, int xOffset, int yOffset, int xLength, int yLength);
|
||||
void SetImageWidthHeightFromResolution(framesize_t resol);
|
||||
|
||||
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();
|
||||
@@ -41,9 +57,10 @@ class CCamera {
|
||||
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 SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation);
|
||||
void GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol);
|
||||
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);
|
||||
|
||||
124
code/components/jomjol_controlcamera/ov2640_sharpness.cpp
Normal file
124
code/components/jomjol_controlcamera/ov2640_sharpness.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include <stdint.h>
|
||||
#include "esp_camera.h"
|
||||
#include "ov2640_sharpness.h"
|
||||
|
||||
|
||||
#define OV2640_MAXLEVEL_SHARPNESS 6
|
||||
|
||||
const static uint8_t OV2640_SHARPNESS_AUTO[]=
|
||||
{
|
||||
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,
|
||||
0x93, 0x00, 0x20,
|
||||
0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const static uint8_t OV2640_SHARPNESS_LEVEL0[]=
|
||||
{
|
||||
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,
|
||||
0x00, 0x00, 0x00
|
||||
};
|
||||
const static uint8_t OV2640_SHARPNESS_LEVEL2[]=
|
||||
{
|
||||
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,
|
||||
0x00, 0x00, 0x00
|
||||
};
|
||||
const static uint8_t OV2640_SHARPNESS_LEVEL4[]=
|
||||
{
|
||||
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,
|
||||
0x00, 0x00, 0x00
|
||||
};
|
||||
const static uint8_t OV2640_SHARPNESS_LEVEL6[]=
|
||||
{
|
||||
0xFF, 0x00, 0xff,
|
||||
0x92, 0x01, 0xff,
|
||||
0x93, 0xdf, 0x1f,
|
||||
0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
const static uint8_t *OV2640_SETTING_SHARPNESS[]=
|
||||
{
|
||||
OV2640_SHARPNESS_LEVEL0, // -3 sharpness
|
||||
OV2640_SHARPNESS_LEVEL1,
|
||||
OV2640_SHARPNESS_LEVEL2,
|
||||
OV2640_SHARPNESS_LEVEL3,
|
||||
OV2640_SHARPNESS_LEVEL4,
|
||||
OV2640_SHARPNESS_LEVEL5,
|
||||
OV2640_SHARPNESS_LEVEL6 // +3 sharpness
|
||||
};
|
||||
|
||||
static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
|
||||
{
|
||||
uint8_t address;
|
||||
uint8_t value;
|
||||
uint8_t orgval;
|
||||
uint8_t mask;
|
||||
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;
|
||||
|
||||
table_mask_write(sensor, OV2640_SHARPNESS_MANUAL);
|
||||
table_mask_write(sensor, OV2640_SETTING_SHARPNESS[sharpness + 3]);
|
||||
return 0;
|
||||
}
|
||||
11
code/components/jomjol_controlcamera/ov2640_sharpness.h
Normal file
11
code/components/jomjol_controlcamera/ov2640_sharpness.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef OV2640_SHARPNESS_H
|
||||
#define OV2640_SHARPNESS_H
|
||||
|
||||
#include "esp_camera.h"
|
||||
|
||||
int ov2640_enable_auto_sharpness(sensor_t *sensor);
|
||||
int ov2640_set_sharpness(sensor_t *sensor, int sharpness); // -3 to +3, -4 for auto-sharpness
|
||||
|
||||
#endif
|
||||
@@ -97,14 +97,18 @@ esp_err_t handler_capture(httpd_req_t *req)
|
||||
{
|
||||
int quality;
|
||||
framesize_t res;
|
||||
bool zoomEnabled;
|
||||
int zoomMode;
|
||||
int zoomOffsetX;
|
||||
int zoomOffsetY;
|
||||
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
|
||||
Camera.SetQualitySize(quality, res);
|
||||
Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
|
||||
|
||||
esp_err_t result;
|
||||
result = Camera.CaptureToHTTP(req);
|
||||
@@ -136,6 +140,10 @@ esp_err_t handler_capture_with_light(httpd_req_t *req)
|
||||
|
||||
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)
|
||||
@@ -153,13 +161,13 @@ esp_err_t handler_capture_with_light(httpd_req_t *req)
|
||||
}
|
||||
}
|
||||
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
Camera.GetCameraParameter(req, quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
|
||||
Camera.SetQualitySize(quality, res);
|
||||
Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
|
||||
Camera.LightOnOff(true);
|
||||
const TickType_t xDelay = delay / portTICK_PERIOD_MS;
|
||||
vTaskDelay( xDelay );
|
||||
@@ -200,6 +208,10 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -228,11 +240,11 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
|
||||
else
|
||||
fn.append("noname.jpg");
|
||||
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
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);
|
||||
Camera.SetQualitySize(quality, res, zoomEnabled, zoomMode, zoomOffsetX, zoomOffsetY);
|
||||
|
||||
esp_err_t result;
|
||||
result = Camera.CaptureToFile(fn, delay);
|
||||
|
||||
@@ -19,7 +19,7 @@ static const char *TAG = "ALIGN";
|
||||
|
||||
void ClassFlowAlignment::SetInitialParameter(void)
|
||||
{
|
||||
initalrotate = 0;
|
||||
initialrotate = 0;
|
||||
anz_ref = 0;
|
||||
initialmirror = false;
|
||||
use_antialiasing = false;
|
||||
@@ -31,7 +31,7 @@ void ClassFlowAlignment::SetInitialParameter(void)
|
||||
AlignAndCutImage = NULL;
|
||||
ImageBasis = NULL;
|
||||
ImageTMP = NULL;
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
#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;
|
||||
@@ -91,9 +91,9 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
initialmirror = true;
|
||||
}
|
||||
if (((toUpper(splitted[0]) == "INITALROTATE") || (toUpper(splitted[0]) == "INITIALROTATE")) && (splitted.size() > 1))
|
||||
if (((toUpper(splitted[0]) == "initialrotate") || (toUpper(splitted[0]) == "INITIALROTATE")) && (splitted.size() > 1))
|
||||
{
|
||||
this->initalrotate = std::stod(splitted[1]);
|
||||
this->initialrotate = std::stod(splitted[1]);
|
||||
}
|
||||
if ((toUpper(splitted[0]) == "SEARCHFIELDX") && (splitted.size() > 1))
|
||||
{
|
||||
@@ -229,12 +229,12 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
|
||||
}
|
||||
|
||||
if ((initalrotate != 0) || initialflip)
|
||||
if ((initialrotate != 0) || initialflip)
|
||||
{
|
||||
if (use_antialiasing)
|
||||
rt.RotateAntiAliasing(initalrotate);
|
||||
rt.RotateAntiAliasing(initialrotate);
|
||||
else
|
||||
rt.Rotate(initalrotate);
|
||||
rt.Rotate(initialrotate);
|
||||
|
||||
if (SaveAllFiles)
|
||||
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
|
||||
|
||||
@@ -16,7 +16,7 @@ class ClassFlowAlignment :
|
||||
public ClassFlow
|
||||
{
|
||||
protected:
|
||||
float initalrotate;
|
||||
float initialrotate;
|
||||
bool initialmirror;
|
||||
bool initialflip;
|
||||
bool use_antialiasing;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,6 @@
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -727,130 +726,6 @@ string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){
|
||||
return zw;
|
||||
}
|
||||
|
||||
|
||||
float wrapAround(float val)
|
||||
{
|
||||
return fmod(val, 10.);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks whether val is in the range [min, max]
|
||||
*
|
||||
* Note, this function also handles the wrap around case,
|
||||
* in which min could be larger than max in case of
|
||||
* a circular range
|
||||
*
|
||||
* @param val The value to be checked
|
||||
* @param min Minimal bound of the range
|
||||
* @param max Maximum bound of the range
|
||||
* @return True, if val is in the range
|
||||
*/
|
||||
bool inRange(float val, float min, float max)
|
||||
{
|
||||
assert(min >= 0. && min < 10.0);
|
||||
assert(max >= 0. && max <= 10.0);
|
||||
assert(val >= 0. && val < 10.0);
|
||||
|
||||
if (min <= max)
|
||||
{
|
||||
return min <= val && val <= max;
|
||||
}
|
||||
else
|
||||
{
|
||||
// e.g. between 8 and 2 (of the next round)
|
||||
return (min <= val && val < 10.) || (0. <= val && val <= max);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Synchronizes a potential misalignment between analog and digital part
|
||||
*
|
||||
* @param The current value assembled from digits (pre comma) and analogs (post comma)
|
||||
* @param digitalPrecision The post-comma value of the last digit ([0...9])
|
||||
* @param analogDigitalShift The value of the 0.1 analog, when the digital precision == 5 in [0, 9.9]
|
||||
*
|
||||
* We define 3 phases:
|
||||
* - Pre transition: analog post comma < analogDigitalShift && not in transition
|
||||
* - Transition: Digital Precision in range 1...9
|
||||
* - Post transition: analog post comma > analogDigitalShift && not in transition
|
||||
*
|
||||
* @return The synchronized values as a string
|
||||
*/
|
||||
std::string syncDigitalAnalog(const std::string& value, const std::string& digitalPrecision,
|
||||
double analogDigitalShift)
|
||||
{
|
||||
if (digitalPrecision.empty())
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
const auto pos = value.find('.');
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
// disassemble value into pre and post comma part
|
||||
const auto preComma = value.substr(0, pos);
|
||||
|
||||
// memorize, to be able to assemble right numbers of leading zeros
|
||||
const size_t nPreComma = preComma.size();
|
||||
const auto postComma = value.substr(pos+1);
|
||||
|
||||
const float digitalPostComma = std::atof(digitalPrecision.c_str());
|
||||
int digitalPreComma = std::atoi(preComma.c_str());
|
||||
const float analogPostComma = std::atof(("0." + postComma).c_str());
|
||||
|
||||
// Determine phase
|
||||
const bool inTransition = digitalPostComma > 0. && digitalPostComma < 10.;
|
||||
const bool postTransition = !inTransition && inRange(analogPostComma*10., analogDigitalShift, wrapAround(analogDigitalShift + 5.));
|
||||
const bool preTransition = !inTransition && inRange(analogPostComma*10., 0, analogDigitalShift);
|
||||
|
||||
|
||||
if (inRange(analogDigitalShift, 0.5, 5.))
|
||||
{
|
||||
// late transition, last digit starts transition, when analog is between [0.5, 5)
|
||||
if (inTransition || preTransition)
|
||||
{
|
||||
ESP_LOGD("syncDigitalAnalog", "Late digital transition. Increase digital value by 1.");
|
||||
digitalPreComma += 1;
|
||||
}
|
||||
}
|
||||
else if (inRange(analogDigitalShift, 5., 9.5))
|
||||
{
|
||||
// early transition
|
||||
if (postTransition && analogPostComma*10 > analogDigitalShift)
|
||||
{
|
||||
ESP_LOGD("syncDigitalAnalog", "Early digital transition. Decrease digital value by 1.");
|
||||
digitalPreComma -= 1;
|
||||
}
|
||||
|
||||
// transition has not finished, but we are already at the new cycle
|
||||
// this also should handle hanging digits
|
||||
if (inTransition && analogPostComma < 0.5) {
|
||||
digitalPreComma += 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
// assemble result into string again, pad with zeros
|
||||
auto preCommaNew = std::to_string(digitalPreComma);
|
||||
for (size_t i = preCommaNew.size(); i < nPreComma; ++i)
|
||||
preCommaNew = "0" + preCommaNew;
|
||||
|
||||
const std::string result = preCommaNew + "." + postComma;
|
||||
|
||||
#if debugSync
|
||||
ESP_LOGD("syncDigitalAnalog", "result: %s", result.c_str());
|
||||
#endif
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
{
|
||||
string result = "";
|
||||
@@ -894,8 +769,6 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
|
||||
int previous_value = -1;
|
||||
|
||||
// ------------------- start processing analog values --------------------------//
|
||||
|
||||
if (NUMBERS[j]->analog_roi)
|
||||
{
|
||||
NUMBERS[j]->ReturnRawValue = flowAnalog->getReadout(j, NUMBERS[j]->isExtendedResolution);
|
||||
@@ -909,38 +782,19 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After analog->getReadout: ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
if (NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi)
|
||||
NUMBERS[j]->ReturnRawValue = "." + NUMBERS[j]->ReturnRawValue;
|
||||
|
||||
// ----------------- start processing digital values --------------------------//
|
||||
|
||||
// we need the precision of the digital values to determine transition phase
|
||||
std::string digitalPrecision = {"0"};
|
||||
if (NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi) {
|
||||
// we have nachkommad and vorkomman part!
|
||||
|
||||
std::string analogValues = NUMBERS[j]->ReturnRawValue;
|
||||
std::string digitValues = flowDigit->getReadout(j, true, previous_value, NUMBERS[j]->analog_roi->ROI[0]->result_float, 0.);
|
||||
|
||||
if (flowDigit->getCNNType() != Digital)
|
||||
{
|
||||
// The digital type does not provide an extended resolution, so we cannot extract it
|
||||
digitalPrecision = digitValues.substr(digitValues.size() - 1);
|
||||
digitValues = digitValues.substr(0, digitValues.size() - 1);
|
||||
}
|
||||
|
||||
NUMBERS[j]->ReturnRawValue = digitValues + "." + analogValues;
|
||||
}
|
||||
|
||||
|
||||
if (NUMBERS[j]->digit_roi && !NUMBERS[j]->analog_roi)
|
||||
if (NUMBERS[j]->digit_roi)
|
||||
{
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, NUMBERS[j]->isExtendedResolution, previous_value); // Extended Resolution only if there are no analogue digits
|
||||
if (NUMBERS[j]->analog_roi)
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, false, previous_value, NUMBERS[j]->analog_roi->ROI[0]->result_float, NUMBERS[j]->AnalogDigitalTransitionStart) + NUMBERS[j]->ReturnRawValue;
|
||||
else
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, NUMBERS[j]->isExtendedResolution, previous_value); // Extended Resolution only if there are no analogue digits
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After digital->getReadout: ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
|
||||
// ------------------ start corrections --------------------------//
|
||||
|
||||
NUMBERS[j]->ReturnRawValue = ShiftDecimal(NUMBERS[j]->ReturnRawValue, NUMBERS[j]->DecimalShift);
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
@@ -960,7 +814,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
{
|
||||
if (PreValueUse && NUMBERS[j]->PreValueOkay)
|
||||
{
|
||||
NUMBERS[j]->ReturnValue = ErsetzteN(NUMBERS[j]->ReturnValue, NUMBERS[j]->PreValue);
|
||||
NUMBERS[j]->ReturnValue = ErsetzteN(NUMBERS[j]->ReturnValue, NUMBERS[j]->PreValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -973,13 +827,6 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
continue; // there is no number because there is still an N.
|
||||
}
|
||||
}
|
||||
|
||||
if (NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi)
|
||||
{
|
||||
// Synchronize potential misalignment between analog and digital part
|
||||
NUMBERS[j]->ReturnValue = syncDigitalAnalog(NUMBERS[j]->ReturnValue, digitalPrecision, NUMBERS[j]->AnalogDigitalTransitionStart);
|
||||
}
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After findDelimiterPos: ReturnValue %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
|
||||
@@ -50,6 +50,17 @@ void ClassFlowTakeImage::SetInitialParameter(void)
|
||||
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;
|
||||
@@ -70,9 +81,11 @@ bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
int _brightness = -100;
|
||||
int _contrast = -100;
|
||||
int _saturation = -100;
|
||||
int _brightness = 0;
|
||||
int _contrast = 0;
|
||||
int _saturation = 0;
|
||||
int _sharpness = 0;
|
||||
int _autoExposureLevel = 0;
|
||||
|
||||
if (aktparamgraph.size() == 0)
|
||||
if (!this->GetNextParagraph(pfile, aktparamgraph))
|
||||
@@ -92,6 +105,43 @@ bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
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());
|
||||
@@ -129,6 +179,11 @@ bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
_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")
|
||||
@@ -150,8 +205,8 @@ bool ClassFlowTakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
}
|
||||
}
|
||||
|
||||
Camera.SetBrightnessContrastSaturation(_brightness, _contrast, _saturation);
|
||||
Camera.SetQualitySize(ImageQuality, ImageSize);
|
||||
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;
|
||||
|
||||
@@ -17,6 +17,13 @@ protected:
|
||||
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;
|
||||
|
||||
@@ -48,51 +48,45 @@ bool isPlannedReboot = false;
|
||||
|
||||
static const char *TAG = "MAINCTRL";
|
||||
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
void CheckIsPlannedReboot()
|
||||
{
|
||||
FILE *pfile;
|
||||
void CheckIsPlannedReboot() {
|
||||
FILE *pfile;
|
||||
|
||||
if ((pfile = fopen("/sdcard/reboot.txt", "r")) == NULL) {
|
||||
//LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Initial boot or not a planned reboot");
|
||||
//LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Initial boot or not a planned reboot");
|
||||
isPlannedReboot = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Planned reboot");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Planned reboot");
|
||||
DeleteFile("/sdcard/reboot.txt"); // Prevent Boot Loop!!!
|
||||
isPlannedReboot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool getIsPlannedReboot()
|
||||
{
|
||||
bool getIsPlannedReboot() {
|
||||
return isPlannedReboot;
|
||||
}
|
||||
|
||||
|
||||
int getCountFlowRounds()
|
||||
{
|
||||
int getCountFlowRounds() {
|
||||
return countRounds;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t GetJPG(std::string _filename, httpd_req_t *req)
|
||||
{
|
||||
esp_err_t GetJPG(std::string _filename, httpd_req_t *req) {
|
||||
return flowctrl.GetJPGStream(_filename, req);
|
||||
}
|
||||
|
||||
|
||||
esp_err_t GetRawJPG(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t GetRawJPG(httpd_req_t *req) {
|
||||
return flowctrl.SendRawJPG(req);
|
||||
}
|
||||
|
||||
|
||||
bool isSetupModusActive()
|
||||
{
|
||||
bool isSetupModusActive() {
|
||||
return flowctrl.getStatusSetupModus();
|
||||
}
|
||||
|
||||
@@ -102,19 +96,19 @@ void DeleteMainFlowTask()
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "DeleteMainFlowTask: xHandletask_autodoFlow: %ld", (long) xHandletask_autodoFlow);
|
||||
#endif
|
||||
if( xHandletask_autodoFlow != NULL )
|
||||
{
|
||||
|
||||
if( xHandletask_autodoFlow != NULL ) {
|
||||
vTaskDelete(xHandletask_autodoFlow);
|
||||
xHandletask_autodoFlow = NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Killed: xHandletask_autodoFlow");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void doInit(void)
|
||||
{
|
||||
void doInit() {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Start flowctrl.InitFlow(config);");
|
||||
#endif
|
||||
@@ -132,8 +126,7 @@ void doInit(void)
|
||||
}
|
||||
|
||||
|
||||
bool doflow(void)
|
||||
{
|
||||
bool doflow() {
|
||||
std::string zw_time = getCurrentTimeString(LOGFILE_TIME_FORMAT);
|
||||
ESP_LOGD(TAG, "doflow - start %s", zw_time.c_str());
|
||||
flowisrunning = true;
|
||||
@@ -148,8 +141,7 @@ bool doflow(void)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_get_heap(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_get_heap(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_get_heap - Start");
|
||||
ESP_LOGD(TAG, "handler_get_heap uri: %s", req->uri);
|
||||
@@ -172,12 +164,10 @@ esp_err_t handler_get_heap(httpd_req_t *req)
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (zw.length() > 0)
|
||||
{
|
||||
if (zw.length() > 0) {
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -189,8 +179,7 @@ esp_err_t handler_get_heap(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_init(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_init(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_init - Start");
|
||||
ESP_LOGD(TAG, "handler_doinit uri: %s", req->uri);
|
||||
@@ -213,8 +202,7 @@ esp_err_t handler_init(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_stream(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_stream(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_stream - Start");
|
||||
ESP_LOGD(TAG, "handler_stream uri: %s", req->uri);
|
||||
@@ -224,16 +212,15 @@ esp_err_t handler_stream(httpd_req_t *req)
|
||||
char _value[10];
|
||||
bool flashlightOn = false;
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 50) == ESP_OK)
|
||||
{
|
||||
if (httpd_req_get_url_query_str(req, _query, 50) == ESP_OK) {
|
||||
// ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "flashlight", _value, 10) == ESP_OK)
|
||||
{
|
||||
if (httpd_query_key_value(_query, "flashlight", _value, 10) == ESP_OK) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "flashlight is found%s", _value);
|
||||
#endif
|
||||
if (strlen(_value) > 0)
|
||||
if (strlen(_value) > 0) {
|
||||
flashlightOn = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,20 +266,17 @@ esp_err_t handler_flow_start(httpd_req_t *req) {
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
esp_err_t MQTTCtrlFlowStart(std::string _topic) {
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("MQTTCtrlFlowStart - Start");
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG, "MQTTCtrlFlowStart: topic %s", _topic.c_str());
|
||||
|
||||
if (autostartIsEnabled)
|
||||
{
|
||||
if (autostartIsEnabled) {
|
||||
xTaskAbortDelay(xHandletask_autodoFlow); // Delay will be aborted if task is in blocked (waiting) state. If task is already running, no action
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Flow start triggered by MQTT topic " + _topic);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Flow start triggered by MQTT topic " + _topic + ", but flow is not active!");
|
||||
}
|
||||
|
||||
@@ -305,31 +289,26 @@ esp_err_t MQTTCtrlFlowStart(std::string _topic) {
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
|
||||
esp_err_t handler_json(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_json(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_json - Start");
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG, "handler_JSON uri: %s", req->uri);
|
||||
|
||||
if (bTaskAutoFlowCreated)
|
||||
{
|
||||
if (bTaskAutoFlowCreated) {
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
std::string zw = flowctrl.getJSON();
|
||||
if (zw.length() > 0)
|
||||
{
|
||||
if (zw.length() > 0) {
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Flow not (yet) started: REST API /json not yet available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
@@ -342,14 +321,12 @@ esp_err_t handler_json(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_wasserzaehler(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler water counter - Start");
|
||||
#endif
|
||||
|
||||
if (bTaskAutoFlowCreated)
|
||||
{
|
||||
if (bTaskAutoFlowCreated) {
|
||||
bool _rawValue = false;
|
||||
bool _noerror = false;
|
||||
bool _all = false;
|
||||
@@ -361,34 +338,30 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
char _query[100];
|
||||
char _size[10];
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK) {
|
||||
// ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "all", _size, 10) == ESP_OK)
|
||||
{
|
||||
if (httpd_query_key_value(_query, "all", _size, 10) == ESP_OK) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "all is found%s", _size);
|
||||
#endif
|
||||
_all = true;
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "type", _size, 10) == ESP_OK)
|
||||
{
|
||||
if (httpd_query_key_value(_query, "type", _size, 10) == ESP_OK) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "all is found: %s", _size);
|
||||
#endif
|
||||
_type = std::string(_size);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "rawvalue", _size, 10) == ESP_OK)
|
||||
{
|
||||
if (httpd_query_key_value(_query, "rawvalue", _size, 10) == ESP_OK) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "rawvalue is found: %s", _size);
|
||||
#endif
|
||||
_rawValue = true;
|
||||
}
|
||||
if (httpd_query_key_value(_query, "noerror", _size, 10) == ESP_OK)
|
||||
{
|
||||
|
||||
if (httpd_query_key_value(_query, "noerror", _size, 10) == ESP_OK) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "noerror is found: %s", _size);
|
||||
#endif
|
||||
@@ -398,37 +371,42 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (_all)
|
||||
{
|
||||
if (_all) {
|
||||
httpd_resp_set_type(req, "text/plain");
|
||||
ESP_LOGD(TAG, "TYPE: %s", _type.c_str());
|
||||
int _intype = READOUT_TYPE_VALUE;
|
||||
if (_type == "prevalue")
|
||||
|
||||
if (_type == "prevalue") {
|
||||
_intype = READOUT_TYPE_PREVALUE;
|
||||
if (_type == "raw")
|
||||
}
|
||||
|
||||
if (_type == "raw") {
|
||||
_intype = READOUT_TYPE_RAWVALUE;
|
||||
if (_type == "error")
|
||||
}
|
||||
|
||||
if (_type == "error") {
|
||||
_intype = READOUT_TYPE_ERROR;
|
||||
|
||||
}
|
||||
|
||||
zw = flowctrl.getReadoutAll(_intype);
|
||||
ESP_LOGD(TAG, "ZW: %s", zw.c_str());
|
||||
if (zw.length() > 0)
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
|
||||
if (zw.length() > 0) {
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
std::string *status = flowctrl.getActStatus();
|
||||
string query = std::string(_query);
|
||||
// ESP_LOGD(TAG, "Query: %s, query.c_str());
|
||||
if (query.find("full") != std::string::npos)
|
||||
{
|
||||
if (query.find("full") != std::string::npos) {
|
||||
string txt;
|
||||
txt = "<body style=\"font-family: arial\">";
|
||||
|
||||
if ((countRounds <= 1) && (*status != std::string("Flow finished"))) { // First round not completed yet
|
||||
if ((countRounds <= 1) && (*status != std::string("Flow finished"))) {
|
||||
// First round not completed yet
|
||||
txt += "<h3>Please wait for the first round to complete!</h3><h3>Current state: " + *status + "</h3>\n";
|
||||
}
|
||||
else {
|
||||
@@ -439,15 +417,16 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
}
|
||||
|
||||
zw = flowctrl.getReadout(_rawValue, _noerror, 0);
|
||||
if (zw.length() > 0)
|
||||
|
||||
if (zw.length() > 0) {
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
}
|
||||
|
||||
|
||||
if (query.find("full") != std::string::npos)
|
||||
{
|
||||
if (query.find("full") != std::string::npos) {
|
||||
string txt, zw;
|
||||
|
||||
if ((countRounds <= 1) && (*status != std::string("Flow finished"))) { // First round not completed yet
|
||||
if ((countRounds <= 1) && (*status != std::string("Flow finished"))) {
|
||||
// First round not completed yet
|
||||
// Nothing to do
|
||||
}
|
||||
else {
|
||||
@@ -459,23 +438,26 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
std::vector<HTMLInfo*> htmlinfodig;
|
||||
htmlinfodig = flowctrl.GetAllDigital();
|
||||
|
||||
for (int i = 0; i < htmlinfodig.size(); ++i)
|
||||
{
|
||||
if (flowctrl.GetTypeDigital() == Digital)
|
||||
{
|
||||
if (htmlinfodig[i]->val == 10)
|
||||
for (int i = 0; i < htmlinfodig.size(); ++i) {
|
||||
if (flowctrl.GetTypeDigital() == Digital) {
|
||||
if (htmlinfodig[i]->val >= 10) {
|
||||
zw = "NaN";
|
||||
else
|
||||
}
|
||||
else {
|
||||
zw = to_string((int) htmlinfodig[i]->val);
|
||||
}
|
||||
|
||||
txt += "<td style=\"width: 100px\"><h4>" + zw + "</h4><p><img src=\"/img_tmp/" + htmlinfodig[i]->filename + "\"></p></td>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(1) << htmlinfodig[i]->val;
|
||||
zw = stream.str();
|
||||
|
||||
if (std::stod(zw) >= 10) {
|
||||
zw = "NaN";
|
||||
}
|
||||
|
||||
txt += "<td style=\"width: 100px\"><h4>" + zw + "</h4><p><img src=\"/img_tmp/" + htmlinfodig[i]->filename + "\"></p></td>\n";
|
||||
}
|
||||
delete htmlinfodig[i];
|
||||
@@ -486,31 +468,35 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
txt += "</tr></table>\n";
|
||||
httpd_resp_sendstr_chunk(req, txt.c_str());
|
||||
|
||||
|
||||
/* Analog ROIs */
|
||||
txt = "<hr><h3>Recognized Analog ROIs (previous round)</h3>\n";
|
||||
txt += "<table style=\"border-spacing: 5px\"><tr style=\"text-align: center; vertical-align: top;\">\n";
|
||||
|
||||
std::vector<HTMLInfo*> htmlinfoana;
|
||||
htmlinfoana = flowctrl.GetAllAnalog();
|
||||
for (int i = 0; i < htmlinfoana.size(); ++i)
|
||||
{
|
||||
|
||||
for (int i = 0; i < htmlinfoana.size(); ++i) {
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(1) << htmlinfoana[i]->val;
|
||||
zw = stream.str();
|
||||
|
||||
if (std::stod(zw) >= 10) {
|
||||
zw = "NaN";
|
||||
}
|
||||
|
||||
txt += "<td style=\"width: 150px;\"><h4>" + zw + "</h4><p><img src=\"/img_tmp/" + htmlinfoana[i]->filename + "\"></p></td>\n";
|
||||
delete htmlinfoana[i];
|
||||
delete htmlinfoana[i];
|
||||
}
|
||||
|
||||
htmlinfoana.clear();
|
||||
|
||||
txt += "</tr>\n</table>\n";
|
||||
httpd_resp_sendstr_chunk(req, txt.c_str());
|
||||
|
||||
|
||||
/* Full Image
|
||||
* Only show it after the image got taken and aligned */
|
||||
txt = "<hr><h3>Aligned Image (current round)</h3>\n";
|
||||
|
||||
if ((*status == std::string("Initialization")) ||
|
||||
(*status == std::string("Initialization (delayed)")) ||
|
||||
(*status == std::string("Take Image"))) {
|
||||
@@ -526,8 +512,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Flow not (yet) started: REST API /value not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
@@ -540,8 +525,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_editflow(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_editflow(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_editflow - Start");
|
||||
#endif
|
||||
@@ -552,10 +536,8 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
char _valuechar[30];
|
||||
string _task;
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK)
|
||||
{
|
||||
if (httpd_query_key_value(_query, "task", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK) {
|
||||
if (httpd_query_key_value(_query, "task", _valuechar, 30) == ESP_OK) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "task is found: %s", _valuechar);
|
||||
#endif
|
||||
@@ -563,27 +545,22 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
}
|
||||
}
|
||||
|
||||
if (_task.compare("namenumbers") == 0)
|
||||
{
|
||||
if (_task.compare("namenumbers") == 0) {
|
||||
ESP_LOGD(TAG, "Get NUMBER list");
|
||||
return get_numbers_file_handler(req);
|
||||
}
|
||||
|
||||
if (_task.compare("data") == 0)
|
||||
{
|
||||
if (_task.compare("data") == 0) {
|
||||
ESP_LOGD(TAG, "Get data list");
|
||||
return get_data_file_handler(req);
|
||||
}
|
||||
|
||||
if (_task.compare("tflite") == 0)
|
||||
{
|
||||
if (_task.compare("tflite") == 0) {
|
||||
ESP_LOGD(TAG, "Get tflite list");
|
||||
return get_tflite_file_handler(req);
|
||||
}
|
||||
|
||||
|
||||
if (_task.compare("copy") == 0)
|
||||
{
|
||||
if (_task.compare("copy") == 0) {
|
||||
string in, out, zw;
|
||||
|
||||
httpd_query_key_value(_query, "in", _valuechar, 30);
|
||||
@@ -605,9 +582,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
}
|
||||
|
||||
|
||||
if (_task.compare("cutref") == 0)
|
||||
{
|
||||
if (_task.compare("cutref") == 0) {
|
||||
string in, out, zw;
|
||||
int x, y, dx, dy;
|
||||
bool enhance = false;
|
||||
@@ -643,11 +618,9 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "dy: %s", zw.c_str());
|
||||
#endif
|
||||
|
||||
if (httpd_query_key_value(_query, "enhance", _valuechar, 10) == ESP_OK)
|
||||
{
|
||||
if (httpd_query_key_value(_query, "enhance", _valuechar, 10) == ESP_OK) {
|
||||
zw = string(_valuechar);
|
||||
if (zw.compare("true") == 0)
|
||||
{
|
||||
if (zw.compare("true") == 0) {
|
||||
enhance = true;
|
||||
}
|
||||
}
|
||||
@@ -665,8 +638,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
delete caic;
|
||||
|
||||
CImageBasis *cim = new CImageBasis("cutref", out2);
|
||||
if (enhance)
|
||||
{
|
||||
if (enhance) {
|
||||
cim->Contrast(90);
|
||||
}
|
||||
|
||||
@@ -674,8 +646,6 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
delete cim;
|
||||
|
||||
psram_deinit_shared_memory_for_take_image_step();
|
||||
|
||||
|
||||
zw = "CutImage Done";
|
||||
}
|
||||
else {
|
||||
@@ -686,55 +656,128 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
|
||||
}
|
||||
|
||||
if (_task.compare("test_take") == 0)
|
||||
{
|
||||
if ((_task.compare("test_take") == 0) || (_task.compare("cam_settings") == 0)) {
|
||||
std::string _zw = "";
|
||||
std::string _host = "";
|
||||
std::string _bri = "";
|
||||
std::string _con = "";
|
||||
std::string _sat = "";
|
||||
std::string _int = "";
|
||||
int bri = -100;
|
||||
int sat = -100;
|
||||
int con = -100;
|
||||
int intens = -100;
|
||||
int aelevel = 0;
|
||||
int zoommode = 0;
|
||||
int zoomoffsetx = 0;
|
||||
int zoomoffsety = 0;
|
||||
bool zoom = false;
|
||||
bool negative = false;
|
||||
bool aec2 = false;
|
||||
int sharpnessLevel = 0;
|
||||
#ifdef GRAYSCALE_AS_DEFAULT
|
||||
bool grayscale = true;
|
||||
#else
|
||||
bool grayscale = false;
|
||||
#endif
|
||||
|
||||
if (httpd_query_key_value(_query, "host", _valuechar, 30) == ESP_OK) {
|
||||
_host = std::string(_valuechar);
|
||||
}
|
||||
if (httpd_query_key_value(_query, "int", _valuechar, 30) == ESP_OK) {
|
||||
_int = std::string(_valuechar);
|
||||
std::string _int = std::string(_valuechar);
|
||||
intens = stoi(_int);
|
||||
}
|
||||
if (httpd_query_key_value(_query, "bri", _valuechar, 30) == ESP_OK) {
|
||||
_bri = std::string(_valuechar);
|
||||
std::string _bri = std::string(_valuechar);
|
||||
bri = stoi(_bri);
|
||||
}
|
||||
if (httpd_query_key_value(_query, "con", _valuechar, 30) == ESP_OK) {
|
||||
_con = std::string(_valuechar);
|
||||
std::string _con = std::string(_valuechar);
|
||||
con = stoi(_con);
|
||||
}
|
||||
if (httpd_query_key_value(_query, "sat", _valuechar, 30) == ESP_OK) {
|
||||
_sat = std::string(_valuechar);
|
||||
std::string _sat = std::string(_valuechar);
|
||||
sat = stoi(_sat);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "ae", _valuechar, 30) == ESP_OK) {
|
||||
std::string _ae = std::string(_valuechar);
|
||||
aelevel = stoi(_ae);
|
||||
}
|
||||
if (httpd_query_key_value(_query, "sh", _valuechar, 30) == ESP_OK) {
|
||||
std::string _sh = std::string(_valuechar);
|
||||
sharpnessLevel = stoi(_sh);
|
||||
}
|
||||
if (httpd_query_key_value(_query, "gs", _valuechar, 30) == ESP_OK) {
|
||||
std::string _gr = std::string(_valuechar);
|
||||
if (stoi(_gr) != 0) {
|
||||
grayscale = true;
|
||||
}
|
||||
else {
|
||||
grayscale = false;
|
||||
}
|
||||
}
|
||||
if (httpd_query_key_value(_query, "ne", _valuechar, 30) == ESP_OK) {
|
||||
std::string _ne = std::string(_valuechar);
|
||||
if (stoi(_ne) != 0) {
|
||||
negative = true;
|
||||
}
|
||||
else {
|
||||
negative = false;
|
||||
}
|
||||
}
|
||||
if (httpd_query_key_value(_query, "a2", _valuechar, 30) == ESP_OK) {
|
||||
std::string _a2 = std::string(_valuechar);
|
||||
if (stoi(_a2) != 0) {
|
||||
aec2 = true;
|
||||
}
|
||||
else {
|
||||
aec2 = false;
|
||||
}
|
||||
}
|
||||
if (httpd_query_key_value(_query, "z", _valuechar, 30) == ESP_OK) {
|
||||
std::string _zoom = std::string(_valuechar);
|
||||
if (stoi(_zoom) != 0) {
|
||||
zoom = true;
|
||||
}
|
||||
else {
|
||||
zoom = false;
|
||||
}
|
||||
}
|
||||
if (httpd_query_key_value(_query, "zm", _valuechar, 30) == ESP_OK) {
|
||||
std::string _zm = std::string(_valuechar);
|
||||
zoommode = stoi(_zm);
|
||||
}
|
||||
if (httpd_query_key_value(_query, "x", _valuechar, 30) == ESP_OK) {
|
||||
std::string _x = std::string(_valuechar);
|
||||
zoomoffsetx = stoi(_x);
|
||||
}
|
||||
if (httpd_query_key_value(_query, "y", _valuechar, 30) == ESP_OK) {
|
||||
std::string _y = std::string(_valuechar);
|
||||
zoomoffsety = stoi(_y);
|
||||
}
|
||||
|
||||
// ESP_LOGD(TAG, "Parameter host: %s", _host.c_str());
|
||||
// string zwzw = "Do " + _task + " start\n"; ESP_LOGD(TAG, zwzw.c_str());
|
||||
Camera.SetBrightnessContrastSaturation(bri, con, sat);
|
||||
Camera.SetZoom(zoom, zoommode, zoomoffsetx, zoomoffsety);
|
||||
Camera.SetBrightnessContrastSaturation(bri, con, sat, aelevel, grayscale, negative, aec2, sharpnessLevel);
|
||||
Camera.SetLEDIntensity(intens);
|
||||
ESP_LOGD(TAG, "test_take - vor TakeImage");
|
||||
std::string zw = flowctrl.doSingleStep("[TakeImage]", _host);
|
||||
|
||||
if (_task.compare("cam_settings") == 0)
|
||||
{
|
||||
ESP_LOGD(TAG, "Cam Settings set");
|
||||
_zw = "Cam Settings set";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ESP_LOGD(TAG, "test_take - vor TakeImage");
|
||||
_zw = flowctrl.doSingleStep("[TakeImage]", _host);
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
httpd_resp_send(req, _zw.c_str(), _zw.length());
|
||||
}
|
||||
|
||||
|
||||
if (_task.compare("test_align") == 0)
|
||||
{
|
||||
|
||||
if (_task.compare("test_align") == 0) {
|
||||
std::string _host = "";
|
||||
if (httpd_query_key_value(_query, "host", _valuechar, 30) == ESP_OK) {
|
||||
_host = std::string(_valuechar);
|
||||
@@ -755,8 +798,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_statusflow(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_statusflow(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_statusflow - Start");
|
||||
#endif
|
||||
@@ -764,8 +806,7 @@ esp_err_t handler_statusflow(httpd_req_t *req)
|
||||
const char* resp_str;
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (bTaskAutoFlowCreated)
|
||||
{
|
||||
if (bTaskAutoFlowCreated) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "handler_statusflow: %s", req->uri);
|
||||
#endif
|
||||
@@ -775,8 +816,7 @@ esp_err_t handler_statusflow(httpd_req_t *req)
|
||||
|
||||
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
resp_str = "Flow task not yet created";
|
||||
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
|
||||
}
|
||||
@@ -789,8 +829,7 @@ esp_err_t handler_statusflow(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_cputemp(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_cputemp(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_cputemp - Start");
|
||||
#endif
|
||||
@@ -806,19 +845,16 @@ esp_err_t handler_cputemp(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_rssi(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_rssi(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_rssi - Start");
|
||||
#endif
|
||||
|
||||
if (getWIFIisConnected())
|
||||
{
|
||||
if (getWIFIisConnected()) {
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, std::to_string(get_WIFI_RSSI()).c_str(), HTTPD_RESP_USE_STRLEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "WIFI not (yet) connected: REST API /rssi not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
@@ -831,9 +867,7 @@ esp_err_t handler_rssi(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_uptime(httpd_req_t *req)
|
||||
{
|
||||
|
||||
esp_err_t handler_uptime(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_uptime - Start");
|
||||
#endif
|
||||
@@ -851,8 +885,7 @@ esp_err_t handler_uptime(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_prevalue(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_prevalue(httpd_req_t *req) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_prevalue - Start");
|
||||
ESP_LOGD(TAG, "handler_prevalue: %s", req->uri);
|
||||
@@ -881,7 +914,8 @@ esp_err_t handler_prevalue(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
#endif
|
||||
|
||||
if (httpd_query_key_value(_query, "numbers", _numbersname, 50) != ESP_OK) { // If request is incomplete
|
||||
if (httpd_query_key_value(_query, "numbers", _numbersname, 50) != ESP_OK) {
|
||||
// If request is incomplete
|
||||
sReturnMessage = "E91: Query parameter incomplete or not valid!<br> "
|
||||
"Call /setPreValue to show REST API usage info and/or check documentation";
|
||||
httpd_resp_send(req, sReturnMessage.c_str(), sReturnMessage.length());
|
||||
@@ -894,12 +928,14 @@ esp_err_t handler_prevalue(httpd_req_t *req)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else { // if no parameter is provided, print handler usage
|
||||
else {
|
||||
// if no parameter is provided, print handler usage
|
||||
httpd_resp_send(req, RESTUsageInfo.c_str(), RESTUsageInfo.length());
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (strlen(_value) == 0) { // If no value is povided --> return actual PreValue
|
||||
if (strlen(_value) == 0) {
|
||||
// If no value is povided --> return actual PreValue
|
||||
sReturnMessage = flowctrl.GetPrevalue(std::string(_numbersname));
|
||||
|
||||
if (sReturnMessage.empty()) {
|
||||
@@ -938,14 +974,12 @@ esp_err_t handler_prevalue(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
void task_autodoFlow(void *pvParameter)
|
||||
{
|
||||
void task_autodoFlow(void *pvParameter) {
|
||||
int64_t fr_start, fr_delta_ms;
|
||||
|
||||
bTaskAutoFlowCreated = true;
|
||||
|
||||
if (!isPlannedReboot && (esp_reset_reason() == ESP_RST_PANIC))
|
||||
{
|
||||
if (!isPlannedReboot && (esp_reset_reason() == ESP_RST_PANIC)) {
|
||||
flowctrl.setActStatus("Initialization (delayed)");
|
||||
//#ifdef ENABLE_MQTT
|
||||
//MQTTPublish(mqttServer_getMainTopic() + "/" + "status", "Initialization (delayed)", false); // Right now, not possible -> MQTT Service is going to be started later
|
||||
@@ -959,8 +993,7 @@ void task_autodoFlow(void *pvParameter)
|
||||
flowctrl.setAutoStartInterval(auto_interval);
|
||||
autostartIsEnabled = flowctrl.getIsAutoStart();
|
||||
|
||||
if (isSetupModusActive())
|
||||
{
|
||||
if (isSetupModusActive()) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "We are in Setup Mode -> Not starting Auto Flow!");
|
||||
autostartIsEnabled = false;
|
||||
std::string zw_time = getCurrentTimeString(LOGFILE_TIME_FORMAT);
|
||||
@@ -974,22 +1007,19 @@ void task_autodoFlow(void *pvParameter)
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Autostart is not enabled -> Not starting Flow");
|
||||
}
|
||||
|
||||
while (autostartIsEnabled)
|
||||
{
|
||||
while (autostartIsEnabled) {
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "----------------------------------------------------------------"); // Clear separation between runs
|
||||
std::string _zw = "Round #" + std::to_string(++countRounds) + " started";
|
||||
time_t roundStartTime = getUpTime();
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _zw);
|
||||
fr_start = esp_timer_get_time();
|
||||
|
||||
if (flowisrunning)
|
||||
{
|
||||
if (flowisrunning) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Autoflow: doFlow is already running!");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Autoflow: doFlow is started");
|
||||
#endif
|
||||
@@ -1029,16 +1059,16 @@ void task_autodoFlow(void *pvParameter)
|
||||
#endif
|
||||
|
||||
fr_delta_ms = (esp_timer_get_time() - fr_start) / 1000;
|
||||
if (auto_interval > fr_delta_ms)
|
||||
{
|
||||
|
||||
if (auto_interval > fr_delta_ms) {
|
||||
const TickType_t xDelay = (auto_interval - fr_delta_ms) / portTICK_PERIOD_MS;
|
||||
ESP_LOGD(TAG, "Autoflow: sleep for: %ldms", (long) xDelay);
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
}
|
||||
|
||||
while(1) // Keep flow task running to handle necessary sub tasks like reboot handler, etc..
|
||||
{
|
||||
while(1) {
|
||||
// Keep flow task running to handle necessary sub tasks like reboot handler, etc..
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
@@ -1048,25 +1078,24 @@ void task_autodoFlow(void *pvParameter)
|
||||
}
|
||||
|
||||
|
||||
void InitializeFlowTask()
|
||||
{
|
||||
void InitializeFlowTask() {
|
||||
BaseType_t xReturned;
|
||||
|
||||
ESP_LOGD(TAG, "getESPHeapInfo: %s", getESPHeapInfo().c_str());
|
||||
|
||||
uint32_t stackSize = 16 * 1024;
|
||||
xReturned = xTaskCreatePinnedToCore(&task_autodoFlow, "task_autodoFlow", stackSize, NULL, tskIDLE_PRIORITY+2, &xHandletask_autodoFlow, 0);
|
||||
if( xReturned != pdPASS )
|
||||
{
|
||||
|
||||
if( xReturned != pdPASS ) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Creation task_autodoFlow failed. Requested stack size:" + std::to_string(stackSize));
|
||||
LogFile.WriteHeapInfo("Creation task_autodoFlow failed");
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "getESPHeapInfo: %s", getESPHeapInfo().c_str());
|
||||
}
|
||||
|
||||
|
||||
void register_server_main_flow_task_uri(httpd_handle_t server)
|
||||
{
|
||||
void register_server_main_flow_task_uri(httpd_handle_t server) {
|
||||
ESP_LOGI(TAG, "server_main_flow_task - Registering URI handlers");
|
||||
|
||||
httpd_uri_t camuri = { };
|
||||
@@ -1166,5 +1195,4 @@ void register_server_main_flow_task_uri(httpd_handle_t server)
|
||||
camuri.handler = handler_stream;
|
||||
camuri.user_ctx = (void*) "stream";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
}
|
||||
|
||||
@@ -443,7 +443,7 @@ void CImageBasis::LoadFromMemory(stbi_uc *_buffer, int len)
|
||||
//free_psram_heap(std::string(TAG) + "->rgb_image (LoadFromMemory)", rgb_image);
|
||||
}
|
||||
|
||||
rgb_image = stbi_load_from_memory(_buffer, len, &width, &height, &channels, 3);
|
||||
rgb_image = stbi_load_from_memory(_buffer, len, &width, &height, &channels, STBI_rgb);
|
||||
bpp = channels;
|
||||
ESP_LOGD(TAG, "Image loaded from memory: %d, %d, %d", width, height, channels);
|
||||
|
||||
@@ -459,6 +459,44 @@ void CImageBasis::LoadFromMemory(stbi_uc *_buffer, int len)
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::crop_image(unsigned short cropLeft, unsigned short cropRight, unsigned short cropTop, unsigned short cropBottom)
|
||||
{
|
||||
unsigned int maxTopIndex = cropTop * width * channels;
|
||||
unsigned int minBottomIndex = ((width*height) - (cropBottom * width)) * channels;
|
||||
unsigned short maxX = width - cropRight; // In pixels
|
||||
unsigned short newWidth = width - cropLeft - cropRight;
|
||||
unsigned short newHeight = height - cropTop - cropBottom;
|
||||
|
||||
unsigned int writeIndex = 0;
|
||||
// Loop over all bytes
|
||||
for (int i = 0; i < width * height * channels; i += channels) {
|
||||
// Calculate current X, Y pixel position
|
||||
int x = (i/channels) % width;
|
||||
|
||||
// Crop from the top
|
||||
if (i < maxTopIndex) { continue; }
|
||||
|
||||
// Crop from the bottom
|
||||
if (i > minBottomIndex) { continue; }
|
||||
|
||||
// Crop from the left
|
||||
if (x <= cropLeft) { continue; }
|
||||
|
||||
// Crop from the right
|
||||
if (x > maxX) { continue; }
|
||||
|
||||
// If we get here, keep the pixels
|
||||
for (int c = 0; c < channels; c++) {
|
||||
rgb_image[writeIndex++] = rgb_image[i+c];
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new dimensions of the framebuffer for further use.
|
||||
width = newWidth;
|
||||
height = newHeight;
|
||||
}
|
||||
|
||||
|
||||
CImageBasis::CImageBasis(string _name, CImageBasis *_copyfrom)
|
||||
{
|
||||
name = _name;
|
||||
@@ -598,6 +636,20 @@ CImageBasis::CImageBasis(string _name, uint8_t* _rgb_image, int _channels, int _
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::Negative(void)
|
||||
{
|
||||
RGBImageLock();
|
||||
|
||||
for (int i = 0; i < width * height * channels; i += channels) {
|
||||
for (int c = 0; c < channels; c++) {
|
||||
rgb_image[i+c] = 255 - rgb_image[i+c];
|
||||
}
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::Contrast(float _contrast) //input range [-100..100]
|
||||
{
|
||||
stbi_uc* p_source;
|
||||
|
||||
@@ -56,6 +56,7 @@ class CImageBasis
|
||||
void drawEllipse(int x1, int y1, int radx, int rady, int r, int g, int b, int thickness = 1);
|
||||
|
||||
void setPixelColor(int x, int y, int r, int g, int b);
|
||||
void Negative(void);
|
||||
void Contrast(float _contrast);
|
||||
bool ImageOkay();
|
||||
bool CopyFromMemory(uint8_t* _source, int _size);
|
||||
@@ -74,6 +75,7 @@ class CImageBasis
|
||||
|
||||
void Resize(int _new_dx, int _new_dy);
|
||||
void Resize(int _new_dx, int _new_dy, CImageBasis *_target);
|
||||
void crop_image(unsigned short cropLeft, unsigned short cropRight, unsigned short cropTop, unsigned short cropBottom);
|
||||
|
||||
void LoadFromMemory(stbi_uc *_buffer, int len);
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#define FLASH_GPIO GPIO_NUM_4 // PIN for flashlight LED
|
||||
#define USE_PWM_LEDFLASH // if __LEDGLOBAL is defined, a global variable is used for LED control, otherwise locally and each time a new
|
||||
#define CAM_LIVESTREAM_REFRESHRATE 500 // Camera livestream feature: Waiting time in milliseconds to refresh image
|
||||
// #define GRAYSCALE_AS_DEFAULT
|
||||
|
||||
|
||||
//ClassControllCamera + ClassFlowTakeImage
|
||||
|
||||
@@ -109,11 +109,6 @@ CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
|
||||
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=16
|
||||
<<<<<<< Updated upstream
|
||||
=======
|
||||
CONFIG_HTTPD_WS_SUPPORT=y
|
||||
CONFIG_LWIP_MAX_SOCKETS=12
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16
|
||||
CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=16
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "test_flow_postrocess_helper.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ACHTUNG! Die Test laufen aktuell nur mit ausgeschaltetem Debug in ClassFlowCNNGeneral
|
||||
@@ -541,64 +542,4 @@ void test_doFlowPP4() {
|
||||
|
||||
}
|
||||
|
||||
std::string postProcess(std::vector<float> digits,
|
||||
std::vector<float> analogs,
|
||||
float analog2DigitalTransition=0.0)
|
||||
{
|
||||
std::unique_ptr<UnderTestPost> undertestPost(init_do_flow(std::move(analogs),
|
||||
std::move(digits),
|
||||
Digital100,
|
||||
false, false));
|
||||
|
||||
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.6;
|
||||
|
||||
// meter shows 011.0210 but it already needs to be 012.0210, before transition
|
||||
TEST_ASSERT_EQUAL_STRING("12.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("12.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("12.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("12.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("13.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("13.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("13.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.5;
|
||||
|
||||
// meter shows 011.0210 but it already needs to be 012.0210, before transition
|
||||
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());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -164,8 +164,6 @@ extern "C" void app_main()
|
||||
RUN_TEST(test_doFlowPP2);
|
||||
RUN_TEST(test_doFlowPP3);
|
||||
RUN_TEST(test_doFlowPP4);
|
||||
RUN_TEST(test_doFlowLateTransition);
|
||||
RUN_TEST(test_doFlowEarlyTransition);
|
||||
|
||||
// getReadoutRawString test
|
||||
RUN_TEST(test_getReadoutRawString);
|
||||
|
||||
@@ -2,16 +2,10 @@ demo
|
||||
WaitBeforeTakingPicture
|
||||
ImageQuality
|
||||
ImageSize
|
||||
LEDIntensity
|
||||
Brightness
|
||||
Contrast
|
||||
Saturation
|
||||
FixedExposure
|
||||
SearchFieldX
|
||||
SearchFieldY
|
||||
AlignmentAlgo
|
||||
InitialMirror
|
||||
FlipImageSize
|
||||
CNNGoodThreshold
|
||||
PreValueAgeStartup
|
||||
ErrorMessage
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Parameter `FlipImageSize`
|
||||
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.
|
||||
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!
|
||||
|
||||
This parameter can be used to rotate the viewport together with the alignment rotation:
|
||||

|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Parameter `InitialMirror`
|
||||
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.
|
||||
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.
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# Parameter `InitialRotate`
|
||||
Default Value: `179`
|
||||
Default Value: `0`
|
||||
|
||||
Unit: Degrees
|
||||
|
||||
Initial rotation of image before alignment in degree (0 .. 359)
|
||||
!!! Note
|
||||
This parameter can also be set on the Reference Image configuration page!
|
||||
|
||||
!!! Note
|
||||
This parameter is accessible on the Reference Image Page but not on the Config page!
|
||||
After changing this parameter you need to update your reference image and alignment markers!
|
||||
|
||||
Initial rotation of image before alignment in degree (`-360` .. `+360`)
|
||||
|
||||
13
param-docs/parameter-pages/TakeImage/Aec2.md
Normal file
13
param-docs/parameter-pages/TakeImage/Aec2.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Parameter `Aec2`
|
||||
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.
|
||||
15
param-docs/parameter-pages/TakeImage/AutoExposureLevel.md
Normal file
15
param-docs/parameter-pages/TakeImage/AutoExposureLevel.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Parameter `AutoExposureLevel`
|
||||
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!
|
||||
|
||||
Exposure compensation. Lower values produce darker image.
|
||||
|
||||
Range (`-2` .. `2`)
|
||||
@@ -1,10 +1,10 @@
|
||||
# Parameter `Brightness`
|
||||
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.
|
||||
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`)
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Parameter `Contrast`
|
||||
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
|
||||
This parameter can also be set on the Reference Image configuration.
|
||||
After changing this parameter you need to update your reference image and alignment markers!
|
||||
|
||||
Image Contrast (`-2` .. `2`)
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Parameter `Demo`
|
||||
Default Value: `false`
|
||||
|
||||
!!! Warning
|
||||
This is an **Expert Parameter**! Only change it if you understand what it does!
|
||||
|
||||
Enable to use demo images instead of the real camera images.
|
||||
Make sure to have a `/demo` folder on your SD-Card and make sure it contains the expected files!
|
||||
Check [here](../Demo-Mode) for details.
|
||||
|
||||
@@ -4,4 +4,10 @@ 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!
|
||||
|
||||
Fixes the illumination setting of camera at the startup and uses this later -> Individual round is faster.
|
||||
|
||||
13
param-docs/parameter-pages/TakeImage/Grayscale.md
Normal file
13
param-docs/parameter-pages/TakeImage/Grayscale.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Parameter `Grayscale`
|
||||
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!
|
||||
|
||||
Produces black and white image.
|
||||
@@ -1,8 +1,10 @@
|
||||
# Parameter `LEDIntensity`
|
||||
Default Value: `50`
|
||||
|
||||
!!! Warning
|
||||
This is an **Expert Parameter**! Only change it if you understand what it does!
|
||||
This parameter can also be set on the Reference Image configuration.
|
||||
!!! 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 the Flash LED Intensity: (`0` .. `100`)
|
||||
|
||||
13
param-docs/parameter-pages/TakeImage/Negative.md
Normal file
13
param-docs/parameter-pages/TakeImage/Negative.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Parameter `Negative`
|
||||
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!
|
||||
|
||||
Inverts the colors.
|
||||
@@ -1,11 +1,11 @@
|
||||
# Parameter `Saturation`
|
||||
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
|
||||
This parameter can also be set on the Reference Image configuration.
|
||||
After changing this parameter you need to update your reference image and alignment markers!
|
||||
|
||||
Image Saturation (`-2` .. `2`)
|
||||
|
||||
|
||||
15
param-docs/parameter-pages/TakeImage/Sharpness.md
Normal file
15
param-docs/parameter-pages/TakeImage/Sharpness.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Parameter `Sharpness`
|
||||
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!
|
||||
|
||||
Changes the sharpness of the image. Set to `-4` for auto-sharpness.
|
||||
|
||||
Range (`-4` .. `3`)
|
||||
13
param-docs/parameter-pages/TakeImage/Zoom.md
Normal file
13
param-docs/parameter-pages/TakeImage/Zoom.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Parameter `Zoom`
|
||||
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.
|
||||
15
param-docs/parameter-pages/TakeImage/ZoomMode.md
Normal file
15
param-docs/parameter-pages/TakeImage/ZoomMode.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Parameter `ZoomMode`
|
||||
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!
|
||||
|
||||
`ZoomMode` only applies when `Zoom` is enabled.
|
||||
Value 0: Crop the camera sensor frame to `ImageSize` resolution.
|
||||
Value 1: Scale the camera sensor frame to 800 x 600 pixels then crop it to `ImageSize` resolution.
|
||||
14
param-docs/parameter-pages/TakeImage/ZoomOffsetX.md
Normal file
14
param-docs/parameter-pages/TakeImage/ZoomOffsetX.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Parameter `ZoomOffsetX`
|
||||
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.
|
||||
14
param-docs/parameter-pages/TakeImage/ZoomOffsetY.md
Normal file
14
param-docs/parameter-pages/TakeImage/ZoomOffsetY.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Parameter `ZoomOffsetY`
|
||||
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.
|
||||
@@ -5,9 +5,18 @@ WaitBeforeTakingPicture = 5
|
||||
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
|
||||
|
||||
|
||||
2
sd-card/html/.gitignore
vendored
2
sd-card/html/.gitignore
vendored
@@ -1 +1 @@
|
||||
edit_config_param.html
|
||||
edit_config.html
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xml:lang="en">
|
||||
<head>
|
||||
<title>Alignment marker</title>
|
||||
<title>Alignment markers</title>
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
<style>
|
||||
@@ -86,16 +86,16 @@
|
||||
|
||||
<body style="font-family: arial; padding: 0px 10px;">
|
||||
<div id="overlay">
|
||||
<div id="overlaytext">Device is busy with digitalization round. Waiting until it completes...</div>
|
||||
<div id="overlaytext"></div>
|
||||
</div>
|
||||
|
||||
<h2>Alignment Marker</h2>
|
||||
<h2>Alignment Markers</h2>
|
||||
<details id="desc_details" style="font-size:16px">
|
||||
<summary><b>CLICK HERE</b> for usage description. More infos in documentation:
|
||||
<a href=https://jomjol.github.io/AI-on-the-edge-device-docs/Alignment/ target=_blank>Alignment</a>
|
||||
</summary>
|
||||
<p>
|
||||
Two alignment marker with clear contour and proper contrast are needed to identify unique "fix points" on the image.
|
||||
Two alignment markers with clear contour and proper contrast are needed to identify unique "fix points" on the image.
|
||||
The marker area should be not be part of the variable area of ROI evaluation. Please find more information in documenation:
|
||||
<a href=https://jomjol.github.io/AI-on-the-edge-device-docs/Alignment/ target=_blank>Alignment</a>
|
||||
</p>
|
||||
@@ -162,37 +162,63 @@
|
||||
<script type="text/javascript" src="readconfigparam.js?v=$COMMIT_HASH"></script>
|
||||
|
||||
<script language="JavaScript">
|
||||
var canvas = document.getElementById('canvas'),
|
||||
ctx = canvas.getContext('2d'),
|
||||
imageObj = new Image(),
|
||||
rect = {},
|
||||
drag = false,
|
||||
aktindex = 0,
|
||||
refInfo,
|
||||
enhanceCon = false,
|
||||
param;
|
||||
domainname = getDomainname();
|
||||
param;
|
||||
var canvas = document.getElementById('canvas'),
|
||||
ctx = canvas.getContext('2d'),
|
||||
imageObj = new Image(),
|
||||
rect = {},
|
||||
drag = false,
|
||||
aktindex = 0,
|
||||
refInfo,
|
||||
enhanceCon = false,
|
||||
domainname = getDomainname(),
|
||||
neueref1,
|
||||
neueref2,
|
||||
param;
|
||||
|
||||
function doReboot() {
|
||||
if (confirm("Are you sure you want to reboot? Did you save your changes?")) {
|
||||
var stringota = getDomainname() + "/reboot";
|
||||
window.location = stringota;
|
||||
window.location.href = stringota;
|
||||
window.location.assign(stringota);
|
||||
window.location.replace(stringota);
|
||||
if (confirm("Are you sure you want to reboot? Did you save your changes?")) {
|
||||
var stringota = getDomainname() + "/reboot";
|
||||
window.location = stringota;
|
||||
window.location.href = stringota;
|
||||
window.location.assign(stringota);
|
||||
window.location.replace(stringota);
|
||||
}
|
||||
}
|
||||
|
||||
function ChangeSelection(){
|
||||
aktindex = parseInt(document.getElementById("index").value);
|
||||
UpdateReference();
|
||||
|
||||
if (aktindex == 0 && neueref1 == 1) {
|
||||
UpdateReference();
|
||||
}
|
||||
else if (aktindex == 1 && neueref2 == 1) {
|
||||
UpdateReference();
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadReference();
|
||||
}
|
||||
}
|
||||
|
||||
function SaveToConfig(){
|
||||
if (confirm("Are you sure you want to save the new alignment marker configuration?")) {
|
||||
WriteConfigININew();
|
||||
UpdateConfigReference(domainname)
|
||||
|
||||
if (neueref1 == 1 && neueref2 == 1) {
|
||||
UpdateConfigReferences(domainname);
|
||||
}
|
||||
|
||||
else if (neueref1 == 1) {
|
||||
var anzneueref = 1;
|
||||
UpdateConfigReference(anzneueref, domainname);
|
||||
}
|
||||
|
||||
else if (neueref2 == 1) {
|
||||
var anzneueref = 2;
|
||||
UpdateConfigReference(anzneueref, domainname);
|
||||
}
|
||||
|
||||
//UpdateConfigReference(domainname)
|
||||
SaveConfigToServer(domainname);
|
||||
document.getElementById("savemarker").disabled = true;
|
||||
document.getElementById("enhancecontrast").disabled = true;
|
||||
@@ -208,7 +234,7 @@ function EnhanceContrast(){
|
||||
refInfo[aktindex]["dx"] = document.getElementById("refdx").value;
|
||||
refInfo[aktindex]["dy"] = document.getElementById("refdy").value;
|
||||
|
||||
enhanceCon = true;
|
||||
var enhanceCon = true;
|
||||
|
||||
document.getElementById("overlay").style.display = "block";
|
||||
document.getElementById("overlaytext").innerHTML = "Enhancing Image Contrast...";
|
||||
@@ -219,11 +245,17 @@ function EnhanceContrast(){
|
||||
|
||||
async function task() {
|
||||
while (true) {
|
||||
var ret = MakeContrastImageZW(refInfo[aktindex], enhanceCon, domainname);
|
||||
if (ret) {
|
||||
var ret = MakeRefImageZW(refInfo[aktindex], enhanceCon, domainname);
|
||||
if (ret) {
|
||||
UpdateReference();
|
||||
//document.getElementById("enhancecontrast").disabled = true;
|
||||
document.getElementById("overlay").style.display = "none";
|
||||
if (aktindex == 0) {
|
||||
neueref1 = 1;
|
||||
}
|
||||
else if (aktindex == 1) {
|
||||
neueref2 = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
@@ -276,260 +308,284 @@ function UpdateReference(){
|
||||
}
|
||||
|
||||
function dataURLtoBlob(dataurl) {
|
||||
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
|
||||
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
|
||||
var arr = dataurl.split(',');
|
||||
var mime = arr[0].match(/:(.*?);/)[1];
|
||||
var bstr = atob(arr[1]);
|
||||
var n = bstr.length;
|
||||
var u8arr = new Uint8Array(n);
|
||||
|
||||
while(n--){
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
|
||||
return new Blob([u8arr], {type:mime});
|
||||
}
|
||||
|
||||
function loadCanvas(dataURL) {
|
||||
var canvas = document.getElementById('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
function loadCanvas(dataURL) {
|
||||
var canvas = document.getElementById('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
imageObj.onload = function() {
|
||||
canvas.width = this.width;
|
||||
canvas.height = this.height;
|
||||
drawImage();
|
||||
};
|
||||
|
||||
imageObj.onload = function() {
|
||||
canvas.width = this.width;
|
||||
canvas.height = this.height;
|
||||
drawImage();
|
||||
};
|
||||
imageObj.src = dataURL;
|
||||
}
|
||||
|
||||
imageObj.src = dataURL;
|
||||
}
|
||||
|
||||
|
||||
function getCoords(elem) { // crossbrowser version
|
||||
var box = elem.getBoundingClientRect();
|
||||
var body = document.body;
|
||||
var docEl = document.documentElement;
|
||||
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
|
||||
var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
|
||||
var clientTop = docEl.clientTop || body.clientTop || 0;
|
||||
var clientLeft = docEl.clientLeft || body.clientLeft || 0;
|
||||
var top = box.top + scrollTop - clientTop;
|
||||
var left = box.left + scrollLeft - clientLeft;
|
||||
return { top: Math.round(top), left: Math.round(left) };
|
||||
}
|
||||
|
||||
|
||||
/* hash #description open the details part of the page */
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
openDescription();
|
||||
domainname = getDomainname();
|
||||
loadConfig(domainname);
|
||||
ParseConfig();
|
||||
param = getConfigParameters();
|
||||
|
||||
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");
|
||||
|
||||
CopyReferenceToImgTmp(domainname);
|
||||
refInfo = GetReferencesInfo();
|
||||
|
||||
UpdateReference();
|
||||
|
||||
drawImage();
|
||||
}
|
||||
|
||||
|
||||
function drawImage(){
|
||||
var canvas = document.getElementById('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
context.clearRect(0,0,imageObj.width,imageObj.height);
|
||||
context.save();
|
||||
context.drawImage(imageObj, 0, 0);
|
||||
// context.restore();
|
||||
}
|
||||
|
||||
|
||||
function CutOutReference(){
|
||||
refInfo[aktindex]["x"] = document.getElementById("refx").value;
|
||||
refInfo[aktindex]["y"] = document.getElementById("refy").value;
|
||||
refInfo[aktindex]["dx"] = document.getElementById("refdx").value;
|
||||
refInfo[aktindex]["dy"] = document.getElementById("refdy").value;
|
||||
|
||||
document.getElementById("overlay").style.display = "block";
|
||||
document.getElementById("overlaytext").innerHTML = "Updating marker...";
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function task() {
|
||||
while (true) {
|
||||
var ret = MakeRefZW(refInfo[aktindex], domainname);
|
||||
if (ret) {
|
||||
UpdateReference();
|
||||
document.getElementById("enhancecontrast").disabled = false;
|
||||
document.getElementById("savemarker").disabled = false;
|
||||
document.getElementById("overlay").style.display = "none";
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// Get status
|
||||
var xhttp = new XMLHttpRequest();
|
||||
try {
|
||||
xhttp.open("GET", domainname + "/statusflow", false);
|
||||
xhttp.send();
|
||||
}
|
||||
catch (error){}
|
||||
|
||||
document.getElementById("overlaytext").innerHTML = "Device is busy, waiting until the Digitalization Round got completed (this can take several minutes)...<br><br>Current step: " + xhttp.responseText;
|
||||
console.log("Device is busy, waiting 5s then checking again...");
|
||||
await sleep(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(function() { // Delay so the overlay gets shown
|
||||
task();
|
||||
}, 1);
|
||||
}
|
||||
|
||||
function drawGrid(){
|
||||
var canvas = document.getElementById('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
w = canvas.width;
|
||||
h = canvas.height;
|
||||
ctx.save();
|
||||
ctx.strokeStyle = '#00FF00';
|
||||
|
||||
for (i = h/2; i < h; i += 100)
|
||||
{
|
||||
ctx.moveTo(0, i);
|
||||
ctx.lineTo(w, i);
|
||||
ctx.stroke();
|
||||
ctx.moveTo(0, h-i);
|
||||
ctx.lineTo(w, h-i);
|
||||
ctx.stroke();
|
||||
}
|
||||
for (i = w/2; i < w; i += 100)
|
||||
{
|
||||
ctx.moveTo(i, 0);
|
||||
ctx.lineTo(i, h);
|
||||
ctx.stroke();
|
||||
ctx.moveTo(w-i, 0);
|
||||
ctx.lineTo(w-i, h);
|
||||
ctx.stroke(); }
|
||||
// ctx.restore();
|
||||
}
|
||||
|
||||
|
||||
function draw() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
context.drawImage(imageObj, 0, 0);
|
||||
lw = 4
|
||||
context.lineWidth = lw;
|
||||
context.strokeStyle = "#FF0000";
|
||||
var x0 = parseInt(rect.startX) - parseInt(lw/2);
|
||||
var y0 = parseInt(rect.startY) - parseInt(lw/2);
|
||||
var dx = parseInt(rect.w) + parseInt(lw);
|
||||
var dy = parseInt(rect.h) + parseInt(lw);
|
||||
context.strokeRect(x0, y0, dx, dy);
|
||||
}
|
||||
|
||||
function getCoords(elem) { // crossbrowser version
|
||||
var box = elem.getBoundingClientRect();
|
||||
var body = document.body;
|
||||
var docEl = document.documentElement;
|
||||
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
|
||||
var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
|
||||
var clientTop = docEl.clientTop || body.clientTop || 0;
|
||||
var clientLeft = docEl.clientLeft || body.clientLeft || 0;
|
||||
var top = box.top + scrollTop - clientTop;
|
||||
var left = box.left + scrollLeft - clientLeft;
|
||||
function getCoords(elem) { // crossbrowser version
|
||||
var box = elem.getBoundingClientRect();
|
||||
var body = document.body;
|
||||
var docEl = document.documentElement;
|
||||
var scrollTop = window.pageYOffset || docEl.scrollTop || body.scrollTop;
|
||||
var scrollLeft = window.pageXOffset || docEl.scrollLeft || body.scrollLeft;
|
||||
var clientTop = docEl.clientTop || body.clientTop || 0;
|
||||
var clientLeft = docEl.clientLeft || body.clientLeft || 0;
|
||||
var top = box.top + scrollTop - clientTop;
|
||||
var left = box.left + scrollLeft - clientLeft;
|
||||
return { top: Math.round(top), left: Math.round(left) };
|
||||
}
|
||||
|
||||
/* hash #description open the details part of the page */
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mouseDown(e) {
|
||||
zw = getCoords(this)
|
||||
rect.startX = e.pageX - zw.left;
|
||||
rect.startY = e.pageY - zw.top;
|
||||
document.getElementById("refx").value = rect.startX;
|
||||
document.getElementById("refy").value = rect.startY;
|
||||
drag = true;
|
||||
function LoadReference(){
|
||||
document.getElementById("img_ref").onload = function () {
|
||||
document.getElementById("refdx").value = this.width;
|
||||
document.getElementById("refdy").value = this.height;
|
||||
refInfo[aktindex]["dx"] = this.width;
|
||||
refInfo[aktindex]["dy"] = this.height;
|
||||
rect.w = document.getElementById("refdx").value;
|
||||
rect.h = document.getElementById("refdy").value;
|
||||
draw();
|
||||
}
|
||||
|
||||
function mouseUp() {
|
||||
drag = false;
|
||||
if (rect.w < 0) {
|
||||
rect.w = -rect.w
|
||||
rect.startX-=rect.w
|
||||
_filenameurl = refInfo[aktindex]["name"];
|
||||
var url = domainname + "/fileserver" + _filenameurl + "?" + Date.now();
|
||||
document.getElementById("img_ref").src = url;
|
||||
|
||||
_filenameurl = _filenameurl.replace(".jpg", "_org.jpg");
|
||||
var url = domainname + "/fileserver" + _filenameurl + "?" + Date.now();
|
||||
document.getElementById("img_ref_org").src = url;
|
||||
|
||||
document.getElementById("name").value = refInfo[aktindex]["name"];
|
||||
document.getElementById("refx").value = refInfo[aktindex]["x"];
|
||||
document.getElementById("refy").value = refInfo[aktindex]["y"];
|
||||
rect.startX = document.getElementById("refx").value;
|
||||
rect.startY = document.getElementById("refy").value;
|
||||
draw();
|
||||
}
|
||||
|
||||
function init() {
|
||||
openDescription();
|
||||
domainname = getDomainname();
|
||||
loadConfig(domainname);
|
||||
ParseConfig();
|
||||
param = getConfigParameters();
|
||||
|
||||
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");
|
||||
|
||||
//CopyReferenceToImgTmp(domainname);
|
||||
refInfo = GetReferencesInfo();
|
||||
|
||||
//UpdateReference();
|
||||
LoadReference();
|
||||
drawImage();
|
||||
}
|
||||
|
||||
function drawImage(){
|
||||
var canvas = document.getElementById('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
context.clearRect(0,0,imageObj.width,imageObj.height);
|
||||
context.save();
|
||||
context.drawImage(imageObj, 0, 0);
|
||||
// context.restore();
|
||||
}
|
||||
|
||||
function CutOutReference(){
|
||||
refInfo[aktindex]["x"] = document.getElementById("refx").value;
|
||||
refInfo[aktindex]["y"] = document.getElementById("refy").value;
|
||||
refInfo[aktindex]["dx"] = document.getElementById("refdx").value;
|
||||
refInfo[aktindex]["dy"] = document.getElementById("refdy").value;
|
||||
|
||||
var enhanceCon = false;
|
||||
|
||||
document.getElementById("overlay").style.display = "block";
|
||||
document.getElementById("overlaytext").innerHTML = "Updating marker...";
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function task() {
|
||||
while (true) {
|
||||
var ret = MakeRefImageZW(refInfo[aktindex], enhanceCon, domainname);
|
||||
|
||||
if (ret) {
|
||||
UpdateReference();
|
||||
document.getElementById("enhancecontrast").disabled = false;
|
||||
document.getElementById("savemarker").disabled = false;
|
||||
document.getElementById("overlay").style.display = "none";
|
||||
|
||||
if (aktindex == 0) {
|
||||
neueref1 = 1;
|
||||
}
|
||||
else if (aktindex == 1) {
|
||||
neueref2 = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (rect.h < 0) {
|
||||
rect.h = -rect.h
|
||||
rect.startY-=rect.h
|
||||
else {
|
||||
// Get status
|
||||
var xhttp = new XMLHttpRequest();
|
||||
try {
|
||||
xhttp.open("GET", domainname + "/statusflow", false);
|
||||
xhttp.send();
|
||||
}
|
||||
catch (error){}
|
||||
|
||||
document.getElementById("overlaytext").innerHTML = "Device is busy, waiting until the Digitalization Round got completed (this can take several minutes)...<br><br>Current step: " + xhttp.responseText;
|
||||
console.log("Device is busy, waiting 5s then checking again...");
|
||||
await sleep(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(function() { // Delay so the overlay gets shown
|
||||
task();
|
||||
}, 1);
|
||||
}
|
||||
|
||||
function drawGrid(){
|
||||
var canvas = document.getElementById('canvas');
|
||||
var ctx = canvas.getContext('2d');
|
||||
var w = canvas.width;
|
||||
var h = canvas.height;
|
||||
ctx.save();
|
||||
ctx.strokeStyle = '#00FF00';
|
||||
|
||||
for (i = h/2; i < h; i += 100) {
|
||||
ctx.moveTo(0, i);
|
||||
ctx.lineTo(w, i);
|
||||
ctx.stroke();
|
||||
ctx.moveTo(0, h-i);
|
||||
ctx.lineTo(w, h-i);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
for (i = w/2; i < w; i += 100) {
|
||||
ctx.moveTo(i, 0);
|
||||
ctx.lineTo(i, h);
|
||||
ctx.stroke();
|
||||
ctx.moveTo(w-i, 0);
|
||||
ctx.lineTo(w-i, h);
|
||||
ctx.stroke();
|
||||
}
|
||||
// ctx.restore();
|
||||
}
|
||||
|
||||
function draw() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
context.drawImage(imageObj, 0, 0);
|
||||
var lw = 4
|
||||
context.lineWidth = lw;
|
||||
context.strokeStyle = "#FF0000";
|
||||
var x0 = parseInt(rect.startX) - parseInt(lw/2);
|
||||
var y0 = parseInt(rect.startY) - parseInt(lw/2);
|
||||
var dx = parseInt(rect.w) + parseInt(lw);
|
||||
var dy = parseInt(rect.h) + parseInt(lw);
|
||||
context.strokeRect(x0, y0, dx, dy);
|
||||
}
|
||||
|
||||
function mouseDown(e) {
|
||||
var zw = getCoords(this)
|
||||
rect.startX = e.pageX - zw.left;
|
||||
rect.startY = e.pageY - zw.top;
|
||||
document.getElementById("refx").value = rect.startX;
|
||||
document.getElementById("refy").value = rect.startY;
|
||||
drag = true;
|
||||
}
|
||||
|
||||
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;
|
||||
document.getElementById("refy").value = rect.startY;
|
||||
}
|
||||
|
||||
function mouseMove(e) {
|
||||
if (drag) {
|
||||
var zw = getCoords(this)
|
||||
rect.w = (e.pageX - zw.left) - rect.startX;
|
||||
rect.h = (e.pageY - zw.top) - rect.startY ;
|
||||
document.getElementById("refdx").value = rect.w;
|
||||
document.getElementById("refdy").value = rect.h;
|
||||
document.getElementById("refx").value = rect.startX;
|
||||
document.getElementById("refy").value = rect.startY;
|
||||
draw();
|
||||
}
|
||||
else {
|
||||
draw();
|
||||
var canvas = document.getElementById('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
|
||||
function mouseMove(e) {
|
||||
if (drag) {
|
||||
zw = getCoords(this)
|
||||
rect.w = (e.pageX - zw.left) - rect.startX;
|
||||
rect.h = (e.pageY - zw.top) - rect.startY ;
|
||||
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');
|
||||
|
||||
zw = getCoords(this);
|
||||
x = e.pageX - zw.left;
|
||||
y = e.pageY - zw.top;
|
||||
var zw = getCoords(this);
|
||||
var x = e.pageX - zw.left;
|
||||
var y = e.pageY - zw.top;
|
||||
|
||||
context.lineWidth = 2;
|
||||
context.strokeStyle = "#00FF00";
|
||||
context.beginPath();
|
||||
context.moveTo(0,y);
|
||||
context.lineTo(canvas.width, y);
|
||||
context.moveTo(x, 0);
|
||||
context.lineTo(x, canvas.height);
|
||||
context.stroke();
|
||||
}
|
||||
context.lineWidth = 2;
|
||||
context.strokeStyle = "#00FF00";
|
||||
context.beginPath();
|
||||
context.moveTo(0,y);
|
||||
context.lineTo(canvas.width, y);
|
||||
context.moveTo(x, 0);
|
||||
context.lineTo(x, canvas.height);
|
||||
context.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
function namechanged()
|
||||
{
|
||||
_name = document.getElementById("name").value;
|
||||
refInfo[aktindex]["name"] = _name;
|
||||
function namechanged() {
|
||||
_name = document.getElementById("name").value;
|
||||
refInfo[aktindex]["name"] = _name;
|
||||
}
|
||||
|
||||
function valuemanualchanged(){
|
||||
if (!drag) {
|
||||
rect.w = document.getElementById("refdx").value;
|
||||
rect.h = document.getElementById("refdy").value;
|
||||
rect.startX = document.getElementById("refx").value;
|
||||
rect.startY = document.getElementById("refy").value;
|
||||
draw();
|
||||
}
|
||||
|
||||
function valuemanualchanged(){
|
||||
if (!drag) {
|
||||
rect.w = document.getElementById("refdx").value;
|
||||
rect.h = document.getElementById("refdy").value;
|
||||
rect.startX = document.getElementById("refx").value;
|
||||
rect.startY = document.getElementById("refy").value;
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
init();
|
||||
init();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
BIN
sd-card/html/img/flipImageSize.png
Normal file
BIN
sd-card/html/img/flipImageSize.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 167 KiB |
@@ -24,7 +24,7 @@
|
||||
'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=250,width=640px,height=480px';
|
||||
'left=10,top=260,width=640px,height=480px';
|
||||
|
||||
function loadPage(page) {
|
||||
console.log("loadPage( " + page + " )");
|
||||
@@ -88,21 +88,21 @@
|
||||
<ul>
|
||||
<li><a href="#" onclick="loadPage('overview.html?v=$COMMIT_HASH');">Overview</a></li>
|
||||
<li><a>Settings <i class="arrow down"></i></a>
|
||||
<ul class="submenu">
|
||||
<li><a href="#" onclick="loadPage('prevalue_set.html?v=$COMMIT_HASH');">Set "Previous Value"</a></li>
|
||||
<li><a href="#" onclick="loadPage('edit_config_param.html?v=$COMMIT_HASH');">Configuration</a></li>
|
||||
<li><a>Alignment <i class="arrow right"></i></a>
|
||||
<ul>
|
||||
<li><a href="#" onclick="loadPage('edit_reference.html?v=$COMMIT_HASH');">Reference Image</a></li>
|
||||
<li><a href="#" onclick="loadPage('edit_alignment.html?v=$COMMIT_HASH');">Alignment Marker</a></li>
|
||||
<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>
|
||||
<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>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a><strong>R</strong>egions <strong>O</strong>f <strong>I</strong>nterest <i class="arrow right"></i></a>
|
||||
<li style="width: 260px"><a>Regions of Interest (ROIs)<i class="arrow right"></i></a>
|
||||
<ul>
|
||||
<li><a href="#" onclick="loadPage('edit_digits.html?v=$COMMIT_HASH');">Digit ROI</a></li>
|
||||
<li><a href="#" onclick="loadPage('edit_analog.html?v=$COMMIT_HASH');">Analog ROI</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li style="width: 260px"><a href="#" onclick="loadPage('edit_config.html?v=$COMMIT_HASH');">Configuration</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ table {
|
||||
|
||||
|
||||
<h3>Copyright</h3>
|
||||
Copyright © 2020 - 2023 by <a href="https://github.com/jomjol/AI-on-the-edge-device" target=_blank>Jomjol</a> and others.
|
||||
Copyright © 2020 - 2024 by <a href="https://github.com/jomjol/AI-on-the-edge-device" target=_blank>Jomjol</a> and others.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
if (action_runtime > 10) { // After 10 seconds, start to check if we are up again
|
||||
/* Check if the device is up again and forward to index page if so */
|
||||
fetch('reboot_page.html?v=$COMMIT_HASH&' + Math.random(), {mode: 'no-cors'}).then(
|
||||
r=>{parent.location.href=('index.html?v=$COMMIT_HASH');}
|
||||
r=>{parent.location.href=('index.html?v=' + Math.random());}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -39,13 +39,11 @@ function createReader(file) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
function ZerlegeZeile(input, delimiter = " =\t\r")
|
||||
{
|
||||
var Output = Array(0);
|
||||
// delimiter = " =,\t";
|
||||
|
||||
|
||||
/* The input can have multiple formats:
|
||||
* - key = value
|
||||
* - key = value1 value2 value3 ...
|
||||
@@ -82,7 +80,6 @@ function ZerlegeZeile(input, delimiter = " =\t\r")
|
||||
}
|
||||
|
||||
return Output;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +107,6 @@ function findDelimiterPos(input, delimiter)
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function trim(istring, adddelimiter)
|
||||
{
|
||||
@@ -234,32 +230,21 @@ function FileSendContent(_content, _filename, _domainname = ""){
|
||||
}
|
||||
|
||||
|
||||
function SaveCanvasToImage(_canvas, _filename, _delete = true, _domainname = ""){
|
||||
var JPEG_QUALITY=0.8;
|
||||
var dataUrl = _canvas.toDataURL('image/jpeg', JPEG_QUALITY);
|
||||
var rtn = dataURLtoBlob(dataUrl);
|
||||
|
||||
if (_delete) {
|
||||
FileDeleteOnServer(_filename, _domainname);
|
||||
}
|
||||
|
||||
FileSendContent(rtn, _filename, _domainname);
|
||||
}
|
||||
|
||||
|
||||
function MakeContrastImageZW(zw, _enhance, _domainname){
|
||||
_filename = zw["name"].replace("/config/", "/img_tmp/");
|
||||
url = _domainname + "/editflow?task=cutref&in=/config/reference.jpg&out=" + _filename + "&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
|
||||
function MakeRefImageZW(zw, _enhance, _domainname){
|
||||
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"];
|
||||
|
||||
if (_enhance == true){
|
||||
url = url + "&enhance=true";
|
||||
}
|
||||
|
||||
var xhttp = new XMLHttpRequest();
|
||||
|
||||
try {
|
||||
xhttp.open("GET", url, false);
|
||||
xhttp.send();
|
||||
}
|
||||
catch (error){}
|
||||
} catch (error){}
|
||||
|
||||
if (xhttp.responseText == "CutImage Done") {
|
||||
firework.launch('Image Contrast got enhanced', 'success', 5000);
|
||||
@@ -269,28 +254,3 @@ function MakeContrastImageZW(zw, _enhance, _domainname){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function MakeRefZW(zw, _domainname){
|
||||
_filetarget = zw["name"].replace("/config/", "/img_tmp/");
|
||||
_filetarget = _filetarget.replace(".jpg", "_org.jpg");
|
||||
url = _domainname + "/editflow?task=cutref&in=/config/reference.jpg&out="+_filetarget+"&x=" + zw["x"] + "&y=" + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
|
||||
var xhttp = new XMLHttpRequest();
|
||||
try {
|
||||
xhttp.open("GET", url, false);
|
||||
xhttp.send();
|
||||
}
|
||||
catch (error){}
|
||||
|
||||
if (xhttp.responseText == "CutImage Done") {
|
||||
_filetarget2 = zw["name"].replace("/config/", "/img_tmp/");
|
||||
// _filetarget2 = _filetarget2.replace(".jpg", "_org.jpg");
|
||||
FileCopyOnServer(_filetarget, _filetarget2, _domainname);
|
||||
firework.launch('Marker got updated', 'success', 5000);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -117,10 +117,19 @@ function ParseConfig() {
|
||||
ParamAddValue(param, catname, "Brightness");
|
||||
ParamAddValue(param, catname, "Contrast");
|
||||
ParamAddValue(param, catname, "Saturation");
|
||||
ParamAddValue(param, catname, "Sharpness");
|
||||
ParamAddValue(param, catname, "LEDIntensity");
|
||||
ParamAddValue(param, catname, "ImageQuality");
|
||||
ParamAddValue(param, catname, "ImageSize");
|
||||
ParamAddValue(param, catname, "FixedExposure");
|
||||
ParamAddValue(param, catname, "ImageSize");
|
||||
ParamAddValue(param, catname, "Zoom");
|
||||
ParamAddValue(param, catname, "ZoomMode");
|
||||
ParamAddValue(param, catname, "ZoomOffsetX");
|
||||
ParamAddValue(param, catname, "ZoomOffsetY");
|
||||
ParamAddValue(param, catname, "Grayscale");
|
||||
ParamAddValue(param, catname, "Negative");
|
||||
ParamAddValue(param, catname, "Aec2");
|
||||
ParamAddValue(param, catname, "AutoExposureLevel");
|
||||
ParamAddValue(param, catname, "FixedExposure");
|
||||
|
||||
var catname = "Alignment";
|
||||
category[catname] = new Object();
|
||||
@@ -458,8 +467,6 @@ function WriteConfigININew()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
config_split = new Array(0);
|
||||
|
||||
for (var cat in param) {
|
||||
@@ -556,7 +563,6 @@ function WriteConfigININew()
|
||||
}
|
||||
|
||||
|
||||
|
||||
function isCommented(input)
|
||||
{
|
||||
let isComment = false;
|
||||
@@ -593,7 +599,6 @@ function getConfigCategory() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
function ExtractROIs(_aktline, _type){
|
||||
var linesplit = ZerlegeZeile(_aktline);
|
||||
abc = getNUMBERS(linesplit[0], _type);
|
||||
@@ -669,7 +674,6 @@ function getNUMBERS(_name, _type, _create = true)
|
||||
}
|
||||
|
||||
|
||||
|
||||
function CopyReferenceToImgTmp(_domainname)
|
||||
{
|
||||
for (index = 0; index < 2; ++index)
|
||||
@@ -691,7 +695,7 @@ function GetReferencesInfo(){
|
||||
}
|
||||
|
||||
|
||||
function UpdateConfigReference(_domainname){
|
||||
function UpdateConfigReferences(_domainname){
|
||||
for (var index = 0; index < 2; ++index)
|
||||
{
|
||||
_filenamenach = REFERENCES[index]["name"];
|
||||
@@ -703,11 +707,35 @@ function UpdateConfigReference(_domainname){
|
||||
_filenamevon = _filenamevon.replace(".jpg", "_org.jpg");
|
||||
FileDeleteOnServer(_filenamenach, _domainname);
|
||||
FileCopyOnServer(_filenamevon, _filenamenach, _domainname);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function UpdateConfigReference(_anzneueref, _domainname){
|
||||
var index = 0;
|
||||
|
||||
if (_anzneueref == 1) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
else if (_anzneueref == 2) {
|
||||
index = 1;
|
||||
}
|
||||
|
||||
_filenamenach = REFERENCES[index]["name"];
|
||||
_filenamevon = _filenamenach.replace("/config/", "/img_tmp/");
|
||||
|
||||
FileDeleteOnServer(_filenamenach, _domainname);
|
||||
FileCopyOnServer(_filenamevon, _filenamenach, _domainname);
|
||||
|
||||
_filenamenach = _filenamenach.replace(".jpg", "_org.jpg");
|
||||
_filenamevon = _filenamevon.replace(".jpg", "_org.jpg");
|
||||
|
||||
FileDeleteOnServer(_filenamenach, _domainname);
|
||||
FileCopyOnServer(_filenamevon, _filenamenach, _domainname);
|
||||
}
|
||||
|
||||
|
||||
function getNUMBERInfo(){
|
||||
return NUMBERS;
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ body, html {
|
||||
break;
|
||||
|
||||
case 6: // Config page
|
||||
document.getElementById('maincontent').src = 'edit_config_param.html?v=$COMMIT_HASH#description';
|
||||
document.getElementById('maincontent').src = 'edit_config.html?v=$COMMIT_HASH#description';
|
||||
|
||||
document.getElementById('h_iframe_explain').style.display = "";
|
||||
document.getElementById('h_iframe_explain').style="height:100px;"
|
||||
|
||||
@@ -8,8 +8,9 @@ import markdown
|
||||
|
||||
parameterDocsFolder = "../../param-docs/parameter-pages"
|
||||
docsMainFolder = "../../sd-card/html"
|
||||
configPageTemplate = "edit_config_param_template.html"
|
||||
configPage = "edit_config_param.html"
|
||||
configPageTemplate = "edit_config_template.html"
|
||||
configPage = "edit_config.html"
|
||||
refImagePage = "edit_reference.html"
|
||||
|
||||
htmlTooltipPrefix = """
|
||||
<div class="rst-content"><div class="tooltip"><img src="help.png" width="32px"><span class="tooltiptext">
|
||||
@@ -54,13 +55,16 @@ def generateHtmlTooltip(section, parameter, markdownFile):
|
||||
# Add the tooltip to the config page
|
||||
with open(docsMainFolder + "/" + configPage, 'r') as configPageHandle:
|
||||
configPageContent = configPageHandle.read()
|
||||
|
||||
# print("replacing $TOOLTIP_" + section + "_" + parameter + " with the tooltip content...")
|
||||
configPageContent = configPageContent.replace("<td>$TOOLTIP_" + section + "_" + parameter + "</td>", "<td>" + htmlTooltip + "</td>")
|
||||
|
||||
with open(docsMainFolder + "/" + configPage, 'w') as configPageHandle:
|
||||
configPageHandle.write(configPageContent)
|
||||
|
||||
# Add the tooltip to the reference image page
|
||||
with open(docsMainFolder + "/" + refImagePage, 'r') as refImagePageHandle:
|
||||
refImagePageContent = refImagePageHandle.read()
|
||||
refImagePageContent = refImagePageContent.replace("<td>$TOOLTIP_" + section + "_" + parameter + "</td>", "<td>" + htmlTooltip + "</td>")
|
||||
with open(docsMainFolder + "/" + refImagePage, 'w') as refImagePageHandle:
|
||||
refImagePageHandle.write(refImagePageContent)
|
||||
|
||||
print("Generating Tooltips...")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user