Compare commits

...

61 Commits

Author SHA1 Message Date
CaCO3
0d0b0187f4 Update index.html 2024-02-17 01:13:17 +01:00
CaCO3
4cf9ea6c45 updated changelog 2024-02-17 00:51:10 +01:00
CaCO3
1b76e0f449 restructure menu 2024-02-17 00:50:41 +01:00
CaCO3
d4a0ad20ff Restructure menus (#2921)
* renamed config pages
* restructured menu
2024-02-17 00:40:46 +01:00
CaCO3
df72445e79 show note a bit longer 2024-02-16 22:45:32 +01:00
CaCO3
456cb93809 Update reply-bot.yaml 2024-02-16 22:36:16 +01:00
CaCO3
d968a7adc6 Update reply-bot.yaml 2024-02-16 22:33:38 +01:00
CaCO3
9a52b8b2f3 Update reply-bot.yaml 2024-02-16 22:30:15 +01:00
CaCO3
8caa852bbf Update info.html 2024-02-16 22:27:00 +01:00
michael
4faca4c46c Update edit_reference.html (#2914)
On the ref image page, when a cam setting gets changed, disable the save button to enforce creating a new image first
2024-02-16 22:16:38 +01:00
michael
238fc5fae3 Update edit_config_param_template.html (#2915)
Show Warning when changing camera settings in edit config param
2024-02-16 22:13:09 +01:00
CaCO3
c32ca5a23c the yaml files must have the file extention yaml. If they are called yml, they are threated slightly different in the actions section 2024-02-16 00:03:24 +01:00
CaCO3
827d9d1700 updated param doc: added note that the ref image and alignment marks need to be updated as well (#2916)
param-doc: added note that the ref image and alignment marks need to be updated as well
2024-02-15 23:49:14 +01:00
CaCO3
0ea4b3b3ce Update Changelog.md 2024-02-15 23:28:50 +01:00
CaCO3
3e26c6c743 restructured ROI pages 2024-02-15 22:16:18 +01:00
michael
fa5c99b3cb Button to hide other red Digit Frames (#2907)
Button to hide other red Digit Frames for easier setup, implements #2680
2024-02-15 21:55:01 +01:00
CaCO3
6feae4e239 Use valid default values 2024-02-15 00:12:37 +01:00
CaCO3
ef64be3888 Enhance ref image page (#2910)
Enhanced Reference Image page
2024-02-14 23:49:35 +01:00
CaCO3
cc89d625f2 Enhance ref image page2 (#2908)
minor fixes
2024-02-14 21:02:08 +01:00
CaCO3
08ba754b88 Restructure reference image page (#2905) 2024-02-14 16:54:31 +01:00
michael
6b38e44d7f Loading alignment page faster (#2868)
Da es Probleme mit param_temp gab (mal ging es, mal nicht), habe ich extra Parameter angelegt (_rotate_temp, _mirror_temp, _isize_temp, _grayscale_temp, _negative_temp, _aec2_temp, _FixedExposure_temp, _zoom_temp, _zm_temp, _x_temp, _y_temp, _intensity_temp, _brightness_temp, _contrast_temp, _saturation_temp, _sharpness_temp, _ae_temp).
Bei den bisherigen Tests, hat alles so funktioniert wie es soll.
2024-02-14 16:24:29 +01:00
CaCO3
141aea7fa7 Revert "Implemented late analog / digital transition (#2778)"
This reverts commit b5a4cfed96.
2024-02-12 22:41:56 +01:00
CaCO3
bcd07761b6 . 2024-02-12 22:37:46 +01:00
CaCO3
fe4d861e15 . 2024-02-12 22:37:46 +01:00
CaCO3
71322c9fbe fixed review findings 2024-02-12 22:37:46 +01:00
CaCO3
f8b4881a50 . 2024-02-12 22:37:46 +01:00
CaCO3
438d5696e4 . 2024-02-12 22:37:46 +01:00
CaCO3
0d391c8780 . 2024-02-12 22:37:46 +01:00
CaCO3
59de6319a1 . 2024-02-12 22:37:46 +01:00
CaCO3
3805687219 . 2024-02-12 22:37:46 +01:00
CaCO3
c6a789dc45 . 2024-02-12 22:37:46 +01:00
CaCO3
246f9cfc31 . 2024-02-12 22:37:46 +01:00
CaCO3
b2d8c60bb1 . 2024-02-12 22:37:46 +01:00
CaCO3
1d573cd18a . 2024-02-12 22:37:46 +01:00
CaCO3
b2e5cdd8a3 . 2024-02-12 22:37:46 +01:00
CaCO3
f7fde7c430 . 2024-02-12 22:37:46 +01:00
CaCO3
2c19080a66 . 2024-02-12 22:37:46 +01:00
CaCO3
35663c5fd4 add tooltip css 2024-02-12 22:37:46 +01:00
CaCO3
5b449d5c45 update param doc 2024-02-12 22:37:46 +01:00
CaCO3
3a5f3496d5 fix typo in variable name 2024-02-12 22:37:46 +01:00
CaCO3
00434d01c3 update action 2024-02-12 22:37:46 +01:00
CaCO3
3e0bb81e32 added tooltips to reference image page 2024-02-12 22:37:46 +01:00
CaCO3
4f57f9eafd add spacing 2024-02-12 22:37:46 +01:00
CaCO3
f24ec581e6 Added FixedExposure to reference image page 2024-02-12 22:37:46 +01:00
CaCO3
0d78bb78ea corrected default 2024-02-12 22:37:46 +01:00
CaCO3
47aea007b3 Added param InitialMirror to config page 2024-02-12 22:37:46 +01:00
CaCO3
284b3f428e on reference image page, hide expert params and add checkbox to unhide them 2024-02-12 22:37:46 +01:00
CaCO3
92d45c7971 Moved 6 Reference Impage Parameters from expert to normal level 2024-02-12 22:37:46 +01:00
CaCO3
ff1d9d3b4f prepare table row IDs to be removed as tehy seem unused 2024-02-12 22:37:46 +01:00
CaCO3
2b57dd0853 . 2024-02-12 22:37:46 +01:00
CaCO3
dd8f5eea22 Added parameters to config page 2024-02-12 22:37:46 +01:00
Joo Aun Saw
60c5305378 Fix up Zoom option documentation 2024-02-12 22:37:46 +01:00
Joo Aun Saw
8b1c65a38a add documentation for new TakeImage options 2024-02-12 22:37:46 +01:00
Joo Aun Saw
4f5933c4f2 add default values for new TakeImage options in config.ini 2024-02-12 22:37:46 +01:00
Joo Aun Saw
06c9bfb0de html: fix negative not applied correctly after saving reference 2024-02-12 22:37:46 +01:00
Joo Aun Saw
69f1a99b55 ov2640: support sharpness control 2024-02-12 22:37:46 +01:00
Joo Aun Saw
a8fb88a35d Support negative photo effect and auto exposure control 2 2024-02-12 22:37:46 +01:00
Joo Aun Saw
d418d22155 removed redundant changes 2024-02-12 22:37:46 +01:00
Joo Aun Saw
53e8cf49f9 limit auto exposure values to range -2 to +2 2024-02-12 22:37:46 +01:00
Joo Aun Saw
ac4f823cbf Support crop image on sensor, grayscale, auto exposure level 2024-02-12 22:37:46 +01:00
CaCO3
444dc0fa39 add missing image 2024-02-11 22:14:57 +01:00
61 changed files with 3748 additions and 2708 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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);

View 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;
}

View 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

View File

@@ -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);

View File

@@ -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"));

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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());
}

View File

@@ -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);

View File

@@ -2,16 +2,10 @@ demo
WaitBeforeTakingPicture
ImageQuality
ImageSize
LEDIntensity
Brightness
Contrast
Saturation
FixedExposure
SearchFieldX
SearchFieldY
AlignmentAlgo
InitialMirror
FlipImageSize
CNNGoodThreshold
PreValueAgeStartup
ErrorMessage

View File

@@ -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:
![](img/flipImageSize.png)

View File

@@ -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.

View File

@@ -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`)

View 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.

View 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`)

View File

@@ -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`)

View File

@@ -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`)

View File

@@ -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.

View File

@@ -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.

View 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.

View File

@@ -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`)

View 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.

View File

@@ -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`)

View 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`)

View 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.

View 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.

View 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.

View 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.

View File

@@ -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

View File

@@ -1 +1 @@
edit_config_param.html
edit_config.html

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

View File

@@ -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>

View File

@@ -242,7 +242,7 @@ table {
<h3>Copyright</h3>
Copyright &copy; 2020 - 2023 by <a href="https://github.com/jomjol/AI-on-the-edge-device" target=_blank>Jomjol</a> and others.
Copyright &copy; 2020 - 2024 by <a href="https://github.com/jomjol/AI-on-the-edge-device" target=_blank>Jomjol</a> and others.
</body>
</html>

View File

@@ -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());}
)
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;"

View File

@@ -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...")