Merge pull request #75 from jomjol/rolling-reduce-sd-use

Update with reduced SD card usage
This commit is contained in:
jomjol
2020-12-28 16:27:29 +01:00
committed by GitHub
60 changed files with 2014 additions and 1081 deletions

View File

@@ -19,13 +19,30 @@ A 3d-printable housing can be found here: https://www.thingiverse.com/thing:4571
### Known Issues ### Known Issues
* Reboot on extensive web access due to the limits of the internal web server * Spontaneous reboots, most probably due to weak power supply during power intensive operations (taking / calculating pictures)
------ ------
**General remark:** Beside the `firmware.bin`, typically also the content of `/html` needs to be updated! **General remark:** Beside the `firmware.bin`, typically also the content of `/html` needs to be updated!
##### Rolling - (2020-12-07) ##### Rolling - (2020-12-27)
* Major change: no need of SD card for image processing anymore (all in memory)
* 95% less SD card writing
* SD use: mainly reading of data (config, html, tflite parameters), only log files and prevalue write on SD card anymore
* Need to limit camera resolution to VGA (due to memory limits)
* New Feature: setting of time server in `config.ini`
```
[System]
TimeServer = fritz.box
```
* Bug fix: corrected handling of out commented analog pointer ROIs
2020-12-07
* Improvement: internal file handling * Improvement: internal file handling

View File

@@ -270,37 +270,6 @@ void LoadWlanFromFile(std::string fn, std::string &_ssid, std::string &_passphra
} }
} }
/*
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "IP")){
_ip = zerlegt[1];
if ((_ip[0] == '"') && (_ip[_ip.length()-1] == '"')){
_ip = _ip.substr(1, _ip.length()-2);
}
}
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "GATEWAY")){
_gw = zerlegt[1];
if ((_gw[0] == '"') && (_gw[_gw.length()-1] == '"')){
_gw = _gw.substr(1, _gw.length()-2);
}
}
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "NETMASK")){
_netmask = zerlegt[1];
if ((_netmask[0] == '"') && (_netmask[_netmask.length()-1] == '"')){
_netmask = _netmask.substr(1, _netmask.length()-2);
}
}
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "DNS")){
_dns = zerlegt[1];
if ((_dns[0] == '"') && (_dns[_dns.length()-1] == '"')){
_dns = _dns.substr(1, _dns.length()-2);
}
}
*/
if (fgets(zw, 1024, pFile) == NULL) if (fgets(zw, 1024, pFile) == NULL)
{ {
line = ""; line = "";

View File

@@ -1,4 +1,5 @@
#include "ClassControllCamera.h" #include "ClassControllCamera.h"
#include "ClassLogFile.h"
#include <stdio.h> #include <stdio.h>
#include "driver/gpio.h" #include "driver/gpio.h"
@@ -6,34 +7,11 @@
#include "esp_log.h" #include "esp_log.h"
#include "Helper.h" #include "Helper.h"
#include "CFindTemplate.h" #include "CImageBasis.h"
// #include "camera_define.h"
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
#define BOARD_ESP32CAM_AITHINKER #define BOARD_ESP32CAM_AITHINKER
/**
* 2. Kconfig setup
*
* If you have a Kconfig file, copy the content from
* https://github.com/espressif/esp32-camera/blob/master/Kconfig into it.
* In case you haven't, copy and paste this Kconfig file inside the src directory.
* This Kconfig file has definitions that allows more control over the camera and
* how it will be initialized.
*/
/**
* 3. Enable PSRAM on sdkconfig:
*
* CONFIG_ESP32_SPIRAM_SUPPORT=y
*
* More info on
* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support
*/
// ================================ CODE ======================================
#include <esp_event_loop.h> #include <esp_event_loop.h>
#include <esp_log.h> #include <esp_log.h>
@@ -47,31 +25,8 @@
#include "esp_camera.h" #include "esp_camera.h"
// WROVER-KIT PIN Map
#ifdef BOARD_WROVER_KIT
#define CAM_PIN_PWDN -1 //power down is not used
#define CAM_PIN_RESET -1 //software reset will be performed
#define CAM_PIN_XCLK 21
#define CAM_PIN_SIOD 26
#define CAM_PIN_SIOC 27
#define CAM_PIN_D7 35
#define CAM_PIN_D6 34
#define CAM_PIN_D5 39
#define CAM_PIN_D4 36
#define CAM_PIN_D3 19
#define CAM_PIN_D2 18
#define CAM_PIN_D1 5
#define CAM_PIN_D0 4
#define CAM_PIN_VSYNC 25
#define CAM_PIN_HREF 23
#define CAM_PIN_PCLK 22
#endif
// ESP32Cam (AiThinker) PIN Map // ESP32Cam (AiThinker) PIN Map
#ifdef BOARD_ESP32CAM_AITHINKER
#define CAM_PIN_PWDN (gpio_num_t) 32 #define CAM_PIN_PWDN (gpio_num_t) 32
#define CAM_PIN_RESET -1 //software reset will be performed #define CAM_PIN_RESET -1 //software reset will be performed
@@ -91,8 +46,6 @@
#define CAM_PIN_HREF 23 #define CAM_PIN_HREF 23
#define CAM_PIN_PCLK 22 #define CAM_PIN_PCLK 22
#endif
static const char *TAG = "example:take_picture"; static const char *TAG = "example:take_picture";
static camera_config_t camera_config = { static camera_config_t camera_config = {
@@ -120,7 +73,8 @@ static camera_config_t camera_config = {
.ledc_channel = LEDC_CHANNEL_0, .ledc_channel = LEDC_CHANNEL_0,
.pixel_format = PIXFORMAT_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG .pixel_format = PIXFORMAT_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG
.frame_size = FRAMESIZE_UXGA, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG .frame_size = FRAMESIZE_VGA, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
// .frame_size = FRAMESIZE_UXGA, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
@@ -128,14 +82,11 @@ static camera_config_t camera_config = {
.fb_count = 1 //if more than one, i2s runs in continuous mode. Use only with JPEG .fb_count = 1 //if more than one, i2s runs in continuous mode. Use only with JPEG
}; };
/////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////
#include "driver/ledc.h" #include "driver/ledc.h"
CCamera Camera; CCamera Camera;
#define FLASH_GPIO GPIO_NUM_4 #define FLASH_GPIO GPIO_NUM_4
#define BLINK_GPIO GPIO_NUM_33 #define BLINK_GPIO GPIO_NUM_33
@@ -145,8 +96,6 @@ typedef struct {
} jpg_chunking_t; } jpg_chunking_t;
///////////////////////////////////////////////////////////////////////////////////////////////////////
#define LEDC_LS_CH2_GPIO (4) #define LEDC_LS_CH2_GPIO (4)
#define LEDC_LS_CH2_CHANNEL LEDC_CHANNEL_2 #define LEDC_LS_CH2_CHANNEL LEDC_CHANNEL_2
#define LEDC_LS_TIMER LEDC_TIMER_1 #define LEDC_LS_TIMER LEDC_TIMER_1
@@ -172,14 +121,6 @@ void test(){
////////////////////////////////////////////////////////////////////////////////////////////////////////
static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){ static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){
jpg_chunking_t *j = (jpg_chunking_t *)arg; jpg_chunking_t *j = (jpg_chunking_t *)arg;
if(!index){ if(!index){
@@ -200,12 +141,157 @@ void CCamera::SetQualitySize(int qual, framesize_t resol)
s->set_framesize(s, resol); s->set_framesize(s, resol);
ActualResolution = resol; ActualResolution = resol;
ActualQuality = qual; ActualQuality = qual;
if (resol == FRAMESIZE_QVGA)
{
image_height = 240;
image_width = 320;
}
if (resol == FRAMESIZE_VGA)
{
image_height = 480;
image_width = 640;
}
// No higher Mode than VGA, damit der Kameraspeicher ausreicht.
/*
if (resol == FRAMESIZE_SVGA)
{
image_height = 600;
image_width = 800;
}
if (resol == FRAMESIZE_XGA)
{
image_height = 768;
image_width = 1024;
}
if (resol == FRAMESIZE_SXGA)
{
image_height = 1024;
image_width = 1280;
}
if (resol == FRAMESIZE_UXGA)
{
image_height = 1200;
image_width = 1600;
}
*/
}
esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
{
string ftype;
static const int BMP_HEADER_LEN = 54; // von to_bmp.c !!!!!!!!!!!!!!!
LEDOnOff(true);
// if (debug_detail_heap) LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Start");
if (delay > 0)
{
LightOnOff(true);
const TickType_t xDelay = delay / portTICK_PERIOD_MS;
vTaskDelay( xDelay );
}
// if (debug_detail_heap) LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LightOn");
camera_fb_t * fb = esp_camera_fb_get();
if (!fb) {
ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed");
LEDOnOff(false);
return ESP_FAIL;
}
// if (debug_detail_heap) LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After fb_get");
LEDOnOff(false);
if (delay > 0)
{
LightOnOff(false);
}
TickType_t xDelay = 1000 / portTICK_PERIOD_MS;
vTaskDelay( xDelay ); // wait for power to recover
uint8_t * buf = NULL;
size_t buf_len = 0;
int _anz = 0;
xDelay = 3000 / portTICK_PERIOD_MS;
while (!frame2bmp(fb, &buf, &buf_len) && _anz < 5)
{
std::string _zw1 = "CCamera::CaptureToBasisImage failed #" + std::to_string(++_anz);
LogFile.WriteToFile(_zw1);
esp_camera_fb_return(fb);
_zw1 = "CCamera::CaptureToBasisImage failed #" + std::to_string(_anz) + " - after esp_camera_fb_return";
LogFile.WriteToFile(_zw1);
free(buf);
_zw1 = "CCamera::CaptureToBasisImage failed #" + std::to_string(_anz) + " - after free";
LogFile.WriteToFile(_zw1);
InitCam();
_zw1 = "CCamera::CaptureToBasisImage failed #" + std::to_string(_anz) + " - after InitCam";
LogFile.WriteToFile(_zw1);
vTaskDelay( xDelay );
fb = esp_camera_fb_get();
_zw1 = "CCamera::CaptureToBasisImage failed #" + std::to_string(_anz) + " - after esp_camera_fb_get";
LogFile.WriteToFile(_zw1);
}
esp_camera_fb_return(fb);
if (debug_detail_heap) LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After frame2bmp");
int _len_zw = buf_len - BMP_HEADER_LEN;
uint8_t *_buf_zeiger = buf + BMP_HEADER_LEN;
stbi_uc* p_target;
stbi_uc* p_source;
int channels = 3;
int width = image_width;
int height = image_height;
std::string _zw = "Targetimage: " + std::to_string((int) _Image->rgb_image) + " Size: " + std::to_string(_Image->width) + ", " + std::to_string(_Image->height);
_zw = _zw + " Buf: " + std::to_string((int) buf);
if (debug_detail_heap) LogFile.WriteToFile(_zw);
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = _Image->rgb_image + (channels * (y * width + x));
p_source = _buf_zeiger + (channels * (y * width + x));
p_target[0] = p_source[2];
p_target[1] = p_source[1];
p_target[2] = p_source[0];
}
if (debug_detail_heap) LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After Copy To Target");
// _Image->CopyFromMemory(_buf_zeiger, _len_zw);
free(buf);
if (debug_detail_heap) LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Done");
return ESP_OK;
} }
esp_err_t CCamera::CaptureToFile(std::string nm, int delay) esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
{ {
// nm = "/sdcard/josef_zw.bmp";
string ftype; string ftype;
LEDOnOff(true); LEDOnOff(true);
@@ -286,15 +372,29 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
size_t fb_len = 0; size_t fb_len = 0;
int64_t fr_start = esp_timer_get_time(); int64_t fr_start = esp_timer_get_time();
LEDOnOff(true);
if (delay > 0)
{
LightOnOff(true);
const TickType_t xDelay = delay / portTICK_PERIOD_MS;
vTaskDelay( xDelay );
}
fb = esp_camera_fb_get(); fb = esp_camera_fb_get();
if (!fb) { if (!fb) {
ESP_LOGE(TAGCAMERACLASS, "Camera capture failed"); ESP_LOGE(TAGCAMERACLASS, "Camera capture failed");
httpd_resp_send_500(req); httpd_resp_send_500(req);
return ESP_FAIL; return ESP_FAIL;
} }
LEDOnOff(false);
res = httpd_resp_set_type(req, "image/jpeg"); res = httpd_resp_set_type(req, "image/jpeg");
if(res == ESP_OK){ if(res == ESP_OK){
res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg"); res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=raw.jpg");
} }
if(res == ESP_OK){ if(res == ESP_OK){
@@ -312,6 +412,12 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
int64_t fr_end = esp_timer_get_time(); int64_t fr_end = esp_timer_get_time();
ESP_LOGI(TAGCAMERACLASS, "JPG: %uKB %ums", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000)); ESP_LOGI(TAGCAMERACLASS, "JPG: %uKB %ums", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000));
if (delay > 0)
{
LightOnOff(false);
}
return res; return res;
} }
@@ -369,7 +475,7 @@ void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol
if (strcmp(_size, "SXGA") == 0) if (strcmp(_size, "SXGA") == 0)
resol = FRAMESIZE_SXGA; // 1280x1024 resol = FRAMESIZE_SXGA; // 1280x1024
if (strcmp(_size, "UXGA") == 0) if (strcmp(_size, "UXGA") == 0)
resol = FRAMESIZE_UXGA; // 1600x1200 resol = FRAMESIZE_UXGA; // 1600x1200
} }
if (httpd_query_key_value(_query, "quality", _qual, 10) == ESP_OK) if (httpd_query_key_value(_query, "quality", _qual, 10) == ESP_OK)
{ {
@@ -409,8 +515,6 @@ CCamera::CCamera()
esp_err_t CCamera::InitCam() esp_err_t CCamera::InitCam()
{ {
printf("Init Flash\n");
//power up the camera if PWDN pin is defined
if(CAM_PIN_PWDN != -1){ if(CAM_PIN_PWDN != -1){
// Init the GPIO // Init the GPIO
gpio_pad_select_gpio(CAM_PIN_PWDN); gpio_pad_select_gpio(CAM_PIN_PWDN);

View File

@@ -10,12 +10,13 @@
#include "esp_camera.h" #include "esp_camera.h"
#include <string> #include <string>
#include <esp_http_server.h> #include <esp_http_server.h>
#include "CImageBasis.h"
#define CAMERA_MODEL_AI_THINKER #define CAMERA_MODEL_AI_THINKER
static const char *TAGCAMERACLASS = "server_part_camera"; static const char *TAGCAMERACLASS = "server_part_camera";
class CCamera { class CCamera {
@@ -24,6 +25,8 @@ class CCamera {
framesize_t ActualResolution; framesize_t ActualResolution;
public: public:
int image_height, image_width;
CCamera(); CCamera();
esp_err_t InitCam(); esp_err_t InitCam();
@@ -35,13 +38,13 @@ class CCamera {
framesize_t TextToFramesize(const char * text); framesize_t TextToFramesize(const char * text);
esp_err_t CaptureToFile(std::string nm, int delay = 0); esp_err_t CaptureToFile(std::string nm, int delay = 0);
esp_err_t CaptureToBasisImage(CImageBasis *_Image, int delay = 0);
}; };
extern CCamera Camera; extern CCamera Camera;
extern bool debug_detail_heap;
#endif #endif

View File

@@ -29,26 +29,38 @@ void PowerResetCamera(){
esp_err_t handler_lightOn(httpd_req_t *req) esp_err_t handler_lightOn(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_lightOn - Start");
LogFile.WriteToFile("handler_lightOn"); LogFile.WriteToFile("handler_lightOn");
printf("handler_lightOn uri:\n"); printf(req->uri); printf("\n"); printf("handler_lightOn uri:\n"); printf(req->uri); printf("\n");
Camera.LightOnOff(true); Camera.LightOnOff(true);
const char* resp_str = (const char*) req->user_ctx; const char* resp_str = (const char*) req->user_ctx;
httpd_resp_send(req, resp_str, strlen(resp_str)); httpd_resp_send(req, resp_str, strlen(resp_str));
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_lightOn - Done");
return ESP_OK; return ESP_OK;
}; };
esp_err_t handler_lightOff(httpd_req_t *req) esp_err_t handler_lightOff(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_lightOff - Start");
LogFile.WriteToFile("handler_lightOff"); LogFile.WriteToFile("handler_lightOff");
printf("handler_lightOff uri:\n"); printf(req->uri); printf("\n"); printf("handler_lightOff uri:\n"); printf(req->uri); printf("\n");
Camera.LightOnOff(false); Camera.LightOnOff(false);
const char* resp_str = (const char*) req->user_ctx; const char* resp_str = (const char*) req->user_ctx;
httpd_resp_send(req, resp_str, strlen(resp_str)); httpd_resp_send(req, resp_str, strlen(resp_str));
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_lightOff - Done");
return ESP_OK; return ESP_OK;
}; };
esp_err_t handler_capture(httpd_req_t *req) esp_err_t handler_capture(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_capture - Start");
LogFile.WriteToFile("handler_capture"); LogFile.WriteToFile("handler_capture");
int quality; int quality;
framesize_t res; framesize_t res;
@@ -59,12 +71,17 @@ esp_err_t handler_capture(httpd_req_t *req)
esp_err_t ressult; esp_err_t ressult;
ressult = Camera.CaptureToHTTP(req); ressult = Camera.CaptureToHTTP(req);
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_capture - Done");
return ressult; return ressult;
}; };
esp_err_t handler_capture_with_ligth(httpd_req_t *req) esp_err_t handler_capture_with_ligth(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_capture_with_ligth - Start");
LogFile.WriteToFile("handler_capture_with_ligth"); LogFile.WriteToFile("handler_capture_with_ligth");
char _query[100]; char _query[100];
char _delay[10]; char _delay[10];
@@ -98,6 +115,8 @@ esp_err_t handler_capture_with_ligth(httpd_req_t *req)
ressult = Camera.CaptureToHTTP(req); ressult = Camera.CaptureToHTTP(req);
Camera.LightOnOff(false); Camera.LightOnOff(false);
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_capture_with_ligth - Done");
return ressult; return ressult;
}; };
@@ -106,6 +125,8 @@ esp_err_t handler_capture_with_ligth(httpd_req_t *req)
esp_err_t handler_capture_save_to_file(httpd_req_t *req) esp_err_t handler_capture_save_to_file(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_capture_save_to_file - Start");
LogFile.WriteToFile("handler_capture_save_to_file"); LogFile.WriteToFile("handler_capture_save_to_file");
char _query[100]; char _query[100];
char _delay[10]; char _delay[10];
@@ -151,6 +172,8 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
const char* resp_str = (const char*) fn.c_str(); const char* resp_str = (const char*) fn.c_str();
httpd_resp_send(req, resp_str, strlen(resp_str)); httpd_resp_send(req, resp_str, strlen(resp_str));
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_capture_save_to_file - Done");
return ressult; return ressult;
}; };

View File

@@ -13,4 +13,7 @@ void register_server_camera_uri(httpd_handle_t server);
void PowerResetCamera(); void PowerResetCamera();
extern bool debug_detail_heap;
#endif #endif

View File

@@ -25,7 +25,7 @@ char scratch[SCRATCH_BUFSIZE];
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0) (strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
esp_err_t send_file(httpd_req_t *req, std::string filename, struct stat * file_stat) esp_err_t send_file(httpd_req_t *req, std::string filename)
{ {
FILE *fd = OpenFileAndWait(filename.c_str(), "r"); FILE *fd = OpenFileAndWait(filename.c_str(), "r");
if (!fd) { if (!fd) {
@@ -35,7 +35,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename, struct stat * file_
return ESP_FAIL; return ESP_FAIL;
} }
ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", filename.c_str(), file_stat->st_size); ESP_LOGI(TAG, "Sending file : %s ...", filename.c_str());
set_content_type_from_file(req, filename.c_str()); set_content_type_from_file(req, filename.c_str());
/* Retrieve the pointer to scratch buffer for temporary storage */ /* Retrieve the pointer to scratch buffer for temporary storage */
@@ -67,6 +67,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename, struct stat * file_
/* Copies the full path into destination buffer and returns /* Copies the full path into destination buffer and returns
* pointer to path (skipping the preceding base path) */ * pointer to path (skipping the preceding base path) */
const char* get_path_from_uri(char *dest, const char *base_path, const char *uri, size_t destsize) const char* get_path_from_uri(char *dest, const char *base_path, const char *uri, size_t destsize)

View File

@@ -5,6 +5,6 @@
const char* get_path_from_uri(char *dest, const char *base_path, const char *uri, size_t destsize); const char* get_path_from_uri(char *dest, const char *base_path, const char *uri, size_t destsize);
esp_err_t send_file(httpd_req_t *req, std::string filename, struct stat * file_stat); esp_err_t send_file(httpd_req_t *req, std::string filename);
esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename); esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename);

View File

@@ -303,6 +303,8 @@ void CheckOTAUpdate(void)
esp_err_t handler_ota_update(httpd_req_t *req) esp_err_t handler_ota_update(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_ota_update - Start");
LogFile.WriteToFile("handler_ota_update"); LogFile.WriteToFile("handler_ota_update");
char _query[200]; char _query[200];
char _filename[30]; char _filename[30];
@@ -378,7 +380,9 @@ esp_err_t handler_ota_update(httpd_req_t *req)
} }
httpd_resp_send(req, resp_str, strlen(resp_str)); httpd_resp_send(req, resp_str, strlen(resp_str));
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_ota_update - Done");
return ESP_OK; return ESP_OK;
}; };
@@ -414,6 +418,8 @@ void doReboot(){
esp_err_t handler_reboot(httpd_req_t *req) esp_err_t handler_reboot(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_reboot - Start");
LogFile.WriteToFile("handler_reboot"); LogFile.WriteToFile("handler_reboot");
ESP_LOGI(TAGPARTOTA, "!!! System will restart within 5 sec!!!"); ESP_LOGI(TAGPARTOTA, "!!! System will restart within 5 sec!!!");
const char* resp_str = "!!! System will restart within 5 sec!!!"; const char* resp_str = "!!! System will restart within 5 sec!!!";
@@ -421,6 +427,7 @@ esp_err_t handler_reboot(httpd_req_t *req)
doReboot(); doReboot();
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_reboot - Done");
return ESP_OK; return ESP_OK;
} }

View File

@@ -8,4 +8,6 @@ static const char *TAGPARTOTA = "server_ota";
void register_server_ota_sdcard_uri(httpd_handle_t server); void register_server_ota_sdcard_uri(httpd_handle_t server);
void CheckOTAUpdate(); void CheckOTAUpdate();
void doReboot(); void doReboot();
extern bool debug_detail_heap;

View File

@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
idf_component_register(SRCS ${app_sources} idf_component_register(SRCS ${app_sources}
INCLUDE_DIRS "." INCLUDE_DIRS "."
REQUIRES jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_fileserver_ota) REQUIRES jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_fileserver_ota jomjol_image_proc)

View File

@@ -9,9 +9,11 @@
void ClassFlow::SetInitialParameter(void) void ClassFlow::SetInitialParameter(void)
{ {
ListFlowControll = NULL; ListFlowControll = NULL;
previousElement = NULL;
} }
//std::vector<string> ClassFlow::ZerlegeZeile(std::string input, std::string delimiter);
std::vector<string> ClassFlow::ZerlegeZeile(std::string input, std::string delimiter) std::vector<string> ClassFlow::ZerlegeZeile(std::string input, std::string delimiter)
{ {
@@ -55,7 +57,6 @@ bool ClassFlow::GetNextParagraph(FILE* pfile, string& aktparamgraph)
ClassFlow::ClassFlow(void) ClassFlow::ClassFlow(void)
{ {
SetInitialParameter(); SetInitialParameter();
ListFlowControll = NULL;
} }
ClassFlow::ClassFlow(std::vector<ClassFlow*> * lfc) ClassFlow::ClassFlow(std::vector<ClassFlow*> * lfc)
@@ -64,6 +65,13 @@ ClassFlow::ClassFlow(std::vector<ClassFlow*> * lfc)
ListFlowControll = lfc; ListFlowControll = lfc;
} }
ClassFlow::ClassFlow(std::vector<ClassFlow*> * lfc, ClassFlow *_prev)
{
SetInitialParameter();
ListFlowControll = lfc;
previousElement = _prev;
}
bool ClassFlow::ReadParameter(FILE* pfile, string &aktparamgraph) bool ClassFlow::ReadParameter(FILE* pfile, string &aktparamgraph)
{ {
return false; return false;
@@ -100,7 +108,7 @@ bool ClassFlow::getNextLine(FILE* pfile, string *rt)
} }
*rt = zw; *rt = zw;
*rt = trim(*rt); *rt = trim(*rt);
while (zw[0] == '#' || (rt->size() == 0)) // Kommentarzeilen und Leerzeilen überspringen while (zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) // Kommentarzeilen (; oder #) und Leerzeilen überspringen
{ {
fgets(zw, 1024, pfile); fgets(zw, 1024, pfile);
printf("%s", zw); printf("%s", zw);

View File

@@ -5,7 +5,7 @@
#include <vector> #include <vector>
#include "Helper.h" #include "Helper.h"
#include "CFindTemplate.h" #include "CImageBasis.h"
using namespace std; using namespace std;
@@ -16,7 +16,10 @@ using namespace std;
struct HTMLInfo struct HTMLInfo
{ {
float val; float val;
CImageBasis *image = NULL;
CImageBasis *image_org = NULL;
std::string filename; std::string filename;
std::string filename_org;
}; };
@@ -30,12 +33,15 @@ protected:
bool getNextLine(FILE* pfile, string* rt); bool getNextLine(FILE* pfile, string* rt);
std::vector<ClassFlow*>* ListFlowControll; std::vector<ClassFlow*>* ListFlowControll;
ClassFlow *previousElement;
virtual void SetInitialParameter(void); virtual void SetInitialParameter(void);
public: public:
ClassFlow(void); ClassFlow(void);
ClassFlow(std::vector<ClassFlow*> * lfc); ClassFlow(std::vector<ClassFlow*> * lfc);
ClassFlow(std::vector<ClassFlow*> * lfc, ClassFlow *_prev);
virtual bool ReadParameter(FILE* pfile, string &aktparamgraph); virtual bool ReadParameter(FILE* pfile, string &aktparamgraph);
virtual bool doFlow(string time); virtual bool doFlow(string time);
virtual string getHTMLSingleStep(string host); virtual string getHTMLSingleStep(string host);

View File

@@ -1,29 +1,55 @@
#include "ClassFlowAlignment.h" #include "ClassFlowAlignment.h"
#include "ClassFlowMakeImage.h"
#include "ClassFlow.h"
#include "CRotateImage.h"
#include "ClassLogFile.h" #include "ClassLogFile.h"
ClassFlowAlignment::ClassFlowAlignment()
bool AlignmentExtendedDebugging = true;
void ClassFlowAlignment::SetInitialParameter(void)
{ {
initalrotate = 0; initalrotate = 0;
anz_ref = 0; anz_ref = 0;
suchex = 40; suchex = 40;
suchey = 40; suchey = 40;
initialmirror = false; initialmirror = false;
SaveAllFiles = false;
namerawimage = "/sdcard/img_tmp/raw.jpg"; namerawimage = "/sdcard/img_tmp/raw.jpg";
ListFlowControll = NULL; ListFlowControll = NULL;
AlignAndCutImage = NULL;
ImageBasis = NULL;
ImageTMP = NULL;
previousElement = NULL;
ref_dx[0] = 0; ref_dx[1] = 0;
ref_dy[0] = 0; ref_dy[1] = 0;
} }
ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc) ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
{ {
initalrotate = 0; SetInitialParameter();
anz_ref = 0;
suchex = 40;
suchey = 40;
initialmirror = false;
namerawimage = "/sdcard/img_tmp/raw.jpg";
ListFlowControll = lfc; ListFlowControll = lfc;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowMakeImage") == 0)
{
ImageBasis = ((ClassFlowMakeImage*) (*ListFlowControll)[i])->rawImage;
}
}
if (!ImageBasis) // die Funktion Bilder aufnehmen existiert nicht --> muss erst erzeugt werden NUR ZU TESTZWECKEN
{
if (AlignmentExtendedDebugging) printf("CImageBasis musste erzeugt werden\n");
ImageBasis = new CImageBasis(namerawimage);
}
} }
bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph) bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
{ {
std::vector<string> zerlegt; std::vector<string> zerlegt;
@@ -59,11 +85,18 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
} }
if ((zerlegt.size() == 3) && (anz_ref < 2)) if ((zerlegt.size() == 3) && (anz_ref < 2))
{ {
this->reffilename[anz_ref] = FormatFileName("/sdcard" + zerlegt[0]); reffilename[anz_ref] = FormatFileName("/sdcard" + zerlegt[0]);
this->ref_x[anz_ref] = std::stod(zerlegt[1]); ref_x[anz_ref] = std::stod(zerlegt[1]);
this->ref_y[anz_ref] = std::stod(zerlegt[2]); ref_y[anz_ref] = std::stod(zerlegt[2]);
anz_ref++; anz_ref++;
} }
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
SaveAllFiles = true;
}
} }
return true; return true;
@@ -80,72 +113,52 @@ string ClassFlowAlignment::getHTMLSingleStep(string host)
} }
bool ClassFlowAlignment::doFlow(string time) bool ClassFlowAlignment::doFlow(string time)
{ {
string input = namerawimage; if (!ImageTMP)
string output = "/sdcard/img_tmp/rot.jpg"; ImageTMP = new CImageBasis(ImageBasis, 5);
string output3 = "/sdcard/img_tmp/rot_roi.jpg";
string output2 = "/sdcard/img_tmp/alg.jpg";
string output4 = "/sdcard/img_tmp/alg_roi.jpg";
string output1 = "/sdcard/img_tmp/mirror.jpg";
input = FormatFileName(input); if (AlignAndCutImage)
output = FormatFileName(output); delete AlignAndCutImage;
output2 = FormatFileName(output2); AlignAndCutImage = new CAlignAndCutImage(ImageBasis, ImageTMP);
CRotateImage rt(AlignAndCutImage, ImageTMP);
if (initialmirror){ if (initialmirror){
CRotate *rt;
rt = new CRotate(input);
if (!rt->ImageOkay()){
LogFile.WriteToFile("ClassFlowAlignment::doFlow CRotate Inital Mirror raw.jpg not okay!");
delete rt;
return false;
}
printf("do mirror\n"); printf("do mirror\n");
rt->Mirror(); rt.Mirror();
rt->SaveToFile(output1); if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
input = output1;
delete rt;
} }
if (initalrotate != 0) if (initalrotate != 0)
{ {
CRotate *rt = NULL; rt.Rotate(initalrotate);
printf("Load rotationfile: %s\n", input.c_str()); if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
rt = new CRotate(input);
if (!rt->ImageOkay()){
LogFile.WriteToFile("ClassFlowAlignment::doFlow CRotate raw.jpg not okay!");
delete rt;
return false;
}
rt->Rotate(this->initalrotate);
rt->SaveToFile(output);
delete rt;
} }
else
AlignAndCutImage->Align(reffilename[0], ref_x[0], ref_y[0], reffilename[1], ref_x[1], ref_y[1], suchex, suchey, "");
AlignAndCutImage->GetRefSize(ref_dx, ref_dy);
if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
if (SaveAllFiles)
{ {
CopyFile(input, output); DrawRef(ImageTMP);
ImageTMP->SaveToFile(FormatFileName("/sdcard/img_tmp/alg_roi.jpg"));
} }
CAlignAndCutImage *caic; if (ImageTMP) // nuss gelöscht werden, um Speicherplatz für das Laden von tflite zu haben
caic = new CAlignAndCutImage(output);
caic->Align(this->reffilename[0], this->ref_x[0], this->ref_y[0], this->reffilename[1], this->ref_x[1], this->ref_y[1], suchex, suchey, output3);
caic->SaveToFile(output2);
printf("Startwriting Output4:%s\n", output4.c_str());
if (output4.length() > 0)
{ {
caic->drawRect(ref_x[0], ref_y[0], caic->t0_dx, caic->t0_dy, 255, 0, 0, 2); delete ImageTMP;
caic->drawRect(ref_x[1], ref_y[1], caic->t1_dx, caic->t1_dy, 255, 0, 0, 2); ImageTMP = NULL;
caic->SaveToFile(output4); }
printf("Write output4: %s\n", output4.c_str());
}
delete caic;
// Align mit Templates
return true; return true;
} }
void ClassFlowAlignment::DrawRef(CImageBasis *_zw)
{
_zw->drawRect(ref_x[0], ref_y[0], ref_dx[0], ref_dy[0], 255, 0, 0, 2);
_zw->drawRect(ref_x[1], ref_y[1], ref_dx[1], ref_dy[1], 255, 0, 0, 2);
}

View File

@@ -2,6 +2,7 @@
#include "ClassFlow.h" #include "ClassFlow.h"
#include "Helper.h" #include "Helper.h"
#include "CAlignAndCutImage.h"
#include <string> #include <string>
@@ -15,13 +16,24 @@ protected:
bool initialmirror; bool initialmirror;
string reffilename[2]; string reffilename[2];
int ref_x[2], ref_y[2]; int ref_x[2], ref_y[2];
int ref_dx[2], ref_dy[2];
int anz_ref; int anz_ref;
int suchex, suchey; int suchex, suchey;
string namerawimage; string namerawimage;
bool SaveAllFiles;
CAlignAndCutImage *AlignAndCutImage;
void SetInitialParameter(void);
public: public:
ClassFlowAlignment(); CImageBasis *ImageBasis, *ImageTMP;
ClassFlowAlignment(std::vector<ClassFlow*>* lfc); ClassFlowAlignment(std::vector<ClassFlow*>* lfc);
CAlignAndCutImage* GetAlignAndCutImage(){return AlignAndCutImage;};
void DrawRef(CImageBasis *_zw);
bool ReadParameter(FILE* pfile, string& aktparamgraph); bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time); bool doFlow(string time);
string getHTMLSingleStep(string host); string getHTMLSingleStep(string host);

View File

@@ -16,21 +16,30 @@ static const char* TAG = "flow_analog";
bool debugdetailanalog = false; bool debugdetailanalog = false;
ClassFlowAnalog::ClassFlowAnalog() : ClassFlowImage(TAG) void ClassFlowAnalog::SetInitialParameter(void)
{ {
string cnnmodelfile = ""; string cnnmodelfile = "";
modelxsize = 1; modelxsize = 1;
modelysize = 1; modelysize = 1;
ListFlowControll = NULL; ListFlowControll = NULL;
} previousElement = NULL;
SaveAllFiles = false;
}
ClassFlowAnalog::ClassFlowAnalog(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG) ClassFlowAnalog::ClassFlowAnalog(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
{ {
string cnnmodelfile = ""; SetInitialParameter();
modelxsize = 1; ListFlowControll = lfc;
modelysize = 1;
}
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0)
{
flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i];
}
}
}
string ClassFlowAnalog::getReadout() string ClassFlowAnalog::getReadout()
@@ -113,9 +122,24 @@ bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph)
neuroi->deltax = std::stoi(zerlegt[3]); neuroi->deltax = std::stoi(zerlegt[3]);
neuroi->deltay = std::stoi(zerlegt[4]); neuroi->deltay = std::stoi(zerlegt[4]);
neuroi->result = -1; neuroi->result = -1;
neuroi->image = NULL;
neuroi->image_org = NULL;
ROI.push_back(neuroi); ROI.push_back(neuroi);
} }
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
SaveAllFiles = true;
}
} }
for (int i = 0; i < ROI.size(); ++i)
{
ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3);
ROI[i]->image_org = new CImageBasis(ROI[i]->deltax, ROI[i]->deltay, 3);
}
return true; return true;
} }
@@ -162,79 +186,37 @@ bool ClassFlowAnalog::doFlow(string time)
bool ClassFlowAnalog::doAlignAndCut(string time) bool ClassFlowAnalog::doAlignAndCut(string time)
{ {
string input = "/sdcard/img_tmp/alg.jpg"; CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage();
string input_roi = "/sdcard/img_tmp/alg_roi.jpg";
string ioresize = "/sdcard/img_tmp/resize.bmp";
string output;
string nm;
input = FormatFileName(input);
input_roi = FormatFileName(input_roi);
CResizeImage *rs;
CImageBasis *img_roi = NULL;
CAlignAndCutImage *caic = new CAlignAndCutImage(input);
if (!caic->ImageOkay()){
if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut not okay!");
delete caic;
return false;
}
if (input_roi.length() > 0){
img_roi = new CImageBasis(input_roi);
if (!img_roi->ImageOkay()){
if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut ImageRoi not okay!");
delete caic;
delete img_roi;
return false;
}
}
for (int i = 0; i < ROI.size(); ++i) for (int i = 0; i < ROI.size(); ++i)
{ {
printf("Analog %d - Align&Cut\n", i); printf("Analog %d - Align&Cut\n", i);
output = "/sdcard/img_tmp/" + ROI[i]->name + ".jpg";
output = FormatFileName(output); caic->CutAndSave(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, ROI[i]->image_org);
caic->CutAndSave(output, ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay); if (SaveAllFiles) ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".jpg"));
rs = new CResizeImage(output); ROI[i]->image_org->Resize(modelxsize, modelysize, ROI[i]->image);
if (!rs->ImageOkay()){ if (SaveAllFiles) ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp"));
if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut CResizeImage(output);!");
delete caic;
delete rs;
return false;
}
rs->Resize(modelxsize, modelysize);
ioresize = "/sdcard/img_tmp/ra" + std::to_string(i) + ".bmp";
ioresize = FormatFileName(ioresize);
rs->SaveToFile(ioresize);
delete rs;
if (img_roi)
{
int r = 0;
int g = 255;
int b = 0;
img_roi->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, r, g, b, 1);
img_roi->drawCircle((int) (ROI[i]->posx + ROI[i]->deltax/2), (int) (ROI[i]->posy + ROI[i]->deltay/2), (int) (ROI[i]->deltax/2), r, g, b, 2);
img_roi->drawLine((int) (ROI[i]->posx + ROI[i]->deltax/2), (int) ROI[i]->posy, (int) (ROI[i]->posx + ROI[i]->deltax/2), (int) (ROI[i]->posy + ROI[i]->deltay), r, g, b, 2);
img_roi->drawLine((int) ROI[i]->posx, (int) (ROI[i]->posy + ROI[i]->deltay/2), (int) ROI[i]->posx + ROI[i]->deltax, (int) (ROI[i]->posy + ROI[i]->deltay/2), r, g, b, 2);
}
} }
delete caic;
if (img_roi)
{
img_roi->SaveToFile(input_roi);
delete img_roi;
}
return true; return true;
} }
void ClassFlowAnalog::DrawROI(CImageBasis *_zw)
{
int r = 0;
int g = 255;
int b = 0;
for (int i = 0; i < ROI.size(); ++i)
{
_zw->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, r, g, b, 1);
_zw->drawCircle((int) (ROI[i]->posx + ROI[i]->deltax/2), (int) (ROI[i]->posy + ROI[i]->deltay/2), (int) (ROI[i]->deltax/2), r, g, b, 2);
_zw->drawLine((int) (ROI[i]->posx + ROI[i]->deltax/2), (int) ROI[i]->posy, (int) (ROI[i]->posx + ROI[i]->deltax/2), (int) (ROI[i]->posy + ROI[i]->deltay), r, g, b, 2);
_zw->drawLine((int) ROI[i]->posx, (int) (ROI[i]->posy + ROI[i]->deltay/2), (int) ROI[i]->posx + ROI[i]->deltax, (int) (ROI[i]->posy + ROI[i]->deltay/2), r, g, b, 2);
}
}
bool ClassFlowAnalog::doNeuralNetwork(string time) bool ClassFlowAnalog::doNeuralNetwork(string time)
{ {
string logPath = CreateLogFolder(time); string logPath = CreateLogFolder(time);
@@ -265,7 +247,8 @@ bool ClassFlowAnalog::doNeuralNetwork(string time)
#ifndef OHNETFLITE #ifndef OHNETFLITE
// LogFile.WriteToFile("ClassFlowAnalog::doNeuralNetwork vor CNN tflite->LoadInputImage(ioresize)"); // LogFile.WriteToFile("ClassFlowAnalog::doNeuralNetwork vor CNN tflite->LoadInputImage(ioresize)");
tflite->LoadInputImage(ioresize); // tflite->LoadInputImage(ioresize);
tflite->LoadInputImageBasis(ROI[i]->image);
tflite->Invoke(); tflite->Invoke();
if (debugdetailanalog) LogFile.WriteToFile("Nach Invoke"); if (debugdetailanalog) LogFile.WriteToFile("Nach Invoke");
@@ -278,9 +261,12 @@ bool ClassFlowAnalog::doNeuralNetwork(string time)
// printf("Result sin, cos, ziffer: %f, %f, %f\n", f1, f2, result); // printf("Result sin, cos, ziffer: %f, %f, %f\n", f1, f2, result);
ROI[i]->result = result * 10; ROI[i]->result = result * 10;
printf("Result Analog%i: %f\n", i, ROI[i]->result); printf("Result Analog%i: %f\n", i, ROI[i]->result);
LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time); if (isLogImage)
{
LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time, ROI[i]->image_org);
}
} }
#ifndef OHNETFLITE #ifndef OHNETFLITE
delete tflite; delete tflite;

View File

@@ -1,10 +1,12 @@
#pragma once #pragma once
#include "ClassFlowImage.h" #include "ClassFlowImage.h"
#include "ClassFlowAlignment.h"
// #include "CTfLiteClass.h" // #include "CTfLiteClass.h"
struct roianalog { struct roianalog {
int posx, posy, deltax, deltay; int posx, posy, deltax, deltay;
float result; float result;
CImageBasis *image, *image_org;
string name; string name;
}; };
@@ -17,14 +19,21 @@ protected:
string cnnmodelfile; string cnnmodelfile;
int modelxsize, modelysize; int modelxsize, modelysize;
int ZeigerEval(float zahl, int ziffer_vorgaenger); int ZeigerEval(float zahl, int ziffer_vorgaenger);
bool SaveAllFiles;
ClassFlowAlignment* flowpostalignment;
void SetInitialParameter(void);
public: public:
ClassFlowAnalog();
ClassFlowAnalog(std::vector<ClassFlow*>* lfc); ClassFlowAnalog(std::vector<ClassFlow*>* lfc);
bool ReadParameter(FILE* pfile, string& aktparamgraph); bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time); bool doFlow(string time);
string getHTMLSingleStep(string host); string getHTMLSingleStep(string host);
string getReadout(); string getReadout();
void DrawROI(CImageBasis *_zw);
bool doNeuralNetwork(string time); bool doNeuralNetwork(string time);
bool doAlignAndCut(string time); bool doAlignAndCut(string time);

View File

@@ -9,8 +9,11 @@
#include "Helper.h" #include "Helper.h"
#include "server_ota.h" #include "server_ota.h"
#include "server_help.h"
static const char* TAG = "flow_controll"; static const char* TAG = "flow_controll";
std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _host){ std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _host){
std::string _classname = ""; std::string _classname = "";
std::string result = ""; std::string result = "";
@@ -68,6 +71,9 @@ void ClassFlowControll::SetInitialParameter(void)
AutoStart = false; AutoStart = false;
SetupModeActive = false; SetupModeActive = false;
AutoIntervall = 10; AutoIntervall = 10;
flowdigit = NULL;
flowanalog = NULL;
flowpostprocessing = NULL;
} }
bool ClassFlowControll::isAutoStart(long &_intervall) bool ClassFlowControll::isAutoStart(long &_intervall)
@@ -83,13 +89,25 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
_type = trim(_type); _type = trim(_type);
if (toUpper(_type).compare("[MAKEIMAGE]") == 0) if (toUpper(_type).compare("[MAKEIMAGE]") == 0)
{
cfc = new ClassFlowMakeImage(&FlowControll); cfc = new ClassFlowMakeImage(&FlowControll);
flowmakeimage = (ClassFlowMakeImage*) cfc;
}
if (toUpper(_type).compare("[ALIGNMENT]") == 0) if (toUpper(_type).compare("[ALIGNMENT]") == 0)
{
cfc = new ClassFlowAlignment(&FlowControll); cfc = new ClassFlowAlignment(&FlowControll);
flowalignment = (ClassFlowAlignment*) cfc;
}
if (toUpper(_type).compare("[ANALOG]") == 0) if (toUpper(_type).compare("[ANALOG]") == 0)
{
cfc = new ClassFlowAnalog(&FlowControll); cfc = new ClassFlowAnalog(&FlowControll);
flowanalog = (ClassFlowAnalog*) cfc;
}
if (toUpper(_type).compare("[DIGITS]") == 0) if (toUpper(_type).compare("[DIGITS]") == 0)
{
cfc = new ClassFlowDigit(&FlowControll); cfc = new ClassFlowDigit(&FlowControll);
flowdigit = (ClassFlowDigit*) cfc;
}
if (toUpper(_type).compare("[MQTT]") == 0) if (toUpper(_type).compare("[MQTT]") == 0)
cfc = new ClassFlowMQTT(&FlowControll); cfc = new ClassFlowMQTT(&FlowControll);
if (toUpper(_type).compare("[POSTPROCESSING]") == 0) if (toUpper(_type).compare("[POSTPROCESSING]") == 0)
@@ -139,6 +157,7 @@ void ClassFlowControll::InitFlow(std::string config)
cfc = CreateClassFlow(line); cfc = CreateClassFlow(line);
if (cfc) if (cfc)
{ {
printf("Start ReadParameter\n");
cfc->ReadParameter(pFile, line); cfc->ReadParameter(pFile, line);
} }
else else
@@ -158,9 +177,7 @@ std::string ClassFlowControll::getActStatus(){
} }
void ClassFlowControll::doFlowMakeImageOnly(string time){ void ClassFlowControll::doFlowMakeImageOnly(string time){
bool result = true;
std::string zw_time; std::string zw_time;
int repeat = 0;
for (int i = 0; i < FlowControll.size(); ++i) for (int i = 0; i < FlowControll.size(); ++i)
{ {
@@ -181,12 +198,18 @@ bool ClassFlowControll::doFlow(string time)
std::string zw_time; std::string zw_time;
int repeat = 0; int repeat = 0;
/////////////////////////////////////////////////////
if (debug_detail_heap) LogFile.WriteHeapInfo("ClassFlowAnalog::doFlow - Start");
/////////////////////////////////////////////////////////
for (int i = 0; i < FlowControll.size(); ++i) for (int i = 0; i < FlowControll.size(); ++i)
{ {
zw_time = gettimestring("%Y%m%d-%H%M%S"); zw_time = gettimestring("%Y%m%d-%H%M%S");
aktstatus = zw_time + ": " + FlowControll[i]->name(); aktstatus = zw_time + ": " + FlowControll[i]->name();
string zw = "FlowControll.doFlow - " + FlowControll[i]->name(); string zw = "FlowControll.doFlow - " + FlowControll[i]->name();
LogFile.WriteToFile(zw); if (debug_detail_heap) LogFile.WriteHeapInfo(zw);
// LogFile.WriteToFile(zw);
if (!FlowControll[i]->doFlow(time)){ if (!FlowControll[i]->doFlow(time)){
repeat++; repeat++;
LogFile.WriteToFile("Fehler im vorheriger Schritt - wird zum " + to_string(repeat) + ". Mal wiederholt"); LogFile.WriteToFile("Fehler im vorheriger Schritt - wird zum " + to_string(repeat) + ". Mal wiederholt");
@@ -202,6 +225,8 @@ bool ClassFlowControll::doFlow(string time)
{ {
result = true; result = true;
} }
if (debug_detail_heap) LogFile.WriteHeapInfo("ClassFlowAnalog::doFlow");
} }
zw_time = gettimestring("%Y%m%d-%H%M%S"); zw_time = gettimestring("%Y%m%d-%H%M%S");
aktstatus = zw_time + ": Flow is done"; aktstatus = zw_time + ": Flow is done";
@@ -320,6 +345,14 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
setTimeZone(zerlegt[1]); setTimeZone(zerlegt[1]);
} }
if ((toUpper(zerlegt[0]) == "TIMESERVER") && (zerlegt.size() > 1))
{
string zw = "Set TimeZone: " + zerlegt[1];
reset_servername(zerlegt[1]);
}
if ((toUpper(zerlegt[0]) == "SETUPMODE") && (zerlegt.size() > 1)) if ((toUpper(zerlegt[0]) == "SETUPMODE") && (zerlegt.size() > 1))
{ {
if (toUpper(zerlegt[1]) == "TRUE") if (toUpper(zerlegt[1]) == "TRUE")
@@ -362,4 +395,85 @@ int ClassFlowControll::CleanTempFolder() {
ESP_LOGI(TAG, "%d files deleted", deleted); ESP_LOGI(TAG, "%d files deleted", deleted);
return 0; return 0;
}
esp_err_t ClassFlowControll::SendRawJPG(httpd_req_t *req)
{
return flowmakeimage->SendRawJPG(req);
}
esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
{
printf("ClassFlowControll::GetJPGStream %s\n", _fn.c_str());
CImageBasis *_send = NULL;
esp_err_t result = ESP_FAIL;
bool Dodelete = false;
if (_fn == "alg.jpg")
{
_send = flowalignment->ImageBasis;
}
if (_fn == "alg_roi.jpg")
{
CImageBasis* _imgzw = new CImageBasis(flowalignment->ImageBasis);
flowalignment->DrawRef(_imgzw);
if (flowdigit) flowdigit->DrawROI(_imgzw);
if (flowanalog) flowanalog->DrawROI(_imgzw);
_send = _imgzw;
Dodelete = true;
}
std::vector<HTMLInfo*> htmlinfo;
htmlinfo = GetAllDigital();
for (int i = 0; i < htmlinfo.size(); ++i)
{
if (_fn == htmlinfo[i]->filename)
{
if (htmlinfo[i]->image)
_send = htmlinfo[i]->image;
}
if (_fn == htmlinfo[i]->filename_org)
{
if (htmlinfo[i]->image_org)
_send = htmlinfo[i]->image_org;
}
}
htmlinfo = GetAllAnalog();
for (int i = 0; i < htmlinfo.size(); ++i)
{
if (_fn == htmlinfo[i]->filename)
{
if (htmlinfo[i]->image)
_send = htmlinfo[i]->image;
}
if (_fn == htmlinfo[i]->filename_org)
{
if (htmlinfo[i]->image_org)
_send = htmlinfo[i]->image_org;
}
}
if (_send)
{
ESP_LOGI(TAG, "Sending file : %s ...", _fn.c_str());
set_content_type_from_file(req, _fn.c_str());
result = _send->SendJPGtoHTTP(req);
ESP_LOGI(TAG, "File sending complete");
/* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0);
}
if (Dodelete)
{
delete _send;
}
return result;
} }

View File

@@ -17,6 +17,10 @@ class ClassFlowControll :
protected: protected:
std::vector<ClassFlow*> FlowControll; std::vector<ClassFlow*> FlowControll;
ClassFlowPostProcessing* flowpostprocessing; ClassFlowPostProcessing* flowpostprocessing;
ClassFlowAlignment* flowalignment;
ClassFlowAnalog* flowanalog;
ClassFlowDigit* flowdigit;
ClassFlowMakeImage* flowmakeimage;
ClassFlow* CreateClassFlow(std::string _type); ClassFlow* CreateClassFlow(std::string _type);
bool AutoStart; bool AutoStart;
@@ -35,6 +39,9 @@ public:
string GetPrevalue(); string GetPrevalue();
bool ReadParameter(FILE* pfile, string& aktparamgraph); bool ReadParameter(FILE* pfile, string& aktparamgraph);
esp_err_t GetJPGStream(std::string _fn, httpd_req_t *req);
esp_err_t SendRawJPG(httpd_req_t *req);
std::string doSingleStep(std::string _stepname, std::string _host); std::string doSingleStep(std::string _stepname, std::string _host);
bool isAutoStart(long &_intervall); bool isAutoStart(long &_intervall);
@@ -49,3 +56,5 @@ public:
string name(){return "ClassFlowControll";}; string name(){return "ClassFlowControll";};
}; };
extern bool debug_detail_heap;

View File

@@ -1,5 +1,6 @@
#include "ClassFlowDigit.h" #include "ClassFlowDigit.h"
//#include "CFindTemplate.h" //#include "CFindTemplate.h"
//#include "CTfLiteClass.h" //#include "CTfLiteClass.h"
@@ -15,19 +16,49 @@
static const char* TAG = "flow_digital"; static const char* TAG = "flow_digital";
ClassFlowDigit::ClassFlowDigit() : ClassFlowImage(TAG)
void ClassFlowDigit::SetInitialParameter(void)
{ {
string cnnmodelfile = ""; string cnnmodelfile = "";
modelxsize = 1; modelxsize = 1;
modelysize = 1; modelysize = 1;
ListFlowControll = NULL; ListFlowControll = NULL;
previousElement = NULL;
SaveAllFiles = false;
}
ClassFlowDigit::ClassFlowDigit() : ClassFlowImage(TAG)
{
SetInitialParameter();
} }
ClassFlowDigit::ClassFlowDigit(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG) ClassFlowDigit::ClassFlowDigit(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
{ {
string cnnmodelfile = ""; SetInitialParameter();
modelxsize = 1; ListFlowControll = lfc;
modelysize = 1;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0)
{
flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i];
}
}
}
ClassFlowDigit::ClassFlowDigit(std::vector<ClassFlow*>* lfc, ClassFlow *_prev) : ClassFlowImage(lfc, _prev, TAG)
{
SetInitialParameter();
ListFlowControll = lfc;
previousElement = _prev;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0)
{
flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i];
}
}
} }
string ClassFlowDigit::getReadout() string ClassFlowDigit::getReadout()
@@ -85,9 +116,25 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph)
neuroi->deltax = std::stoi(zerlegt[3]); neuroi->deltax = std::stoi(zerlegt[3]);
neuroi->deltay = std::stoi(zerlegt[4]); neuroi->deltay = std::stoi(zerlegt[4]);
neuroi->resultklasse = -1; neuroi->resultklasse = -1;
neuroi->image = NULL;
neuroi->image_org = NULL;
ROI.push_back(neuroi); ROI.push_back(neuroi);
} }
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
SaveAllFiles = true;
}
} }
for (int i = 0; i < ROI.size(); ++i)
{
ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3);
ROI[i]->image_org = new CImageBasis(ROI[i]->deltax, ROI[i]->deltay, 3);
}
return true; return true;
} }
@@ -133,60 +180,17 @@ bool ClassFlowDigit::doFlow(string time)
bool ClassFlowDigit::doAlignAndCut(string time) bool ClassFlowDigit::doAlignAndCut(string time)
{ {
string input = "/sdcard/img_tmp/alg.jpg"; CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage();
string input_roi = "/sdcard/img_tmp/alg_roi.jpg";
string ioresize = "/sdcard/img_tmp/resize.bmp";
string output;
string nm;
input = FormatFileName(input);
input_roi = FormatFileName(input_roi);
CResizeImage *rs;
CImageBasis *img_roi = NULL;
CAlignAndCutImage *caic = new CAlignAndCutImage(input);
if (!caic->ImageOkay()){
LogFile.WriteToFile("ClassFlowDigit::doAlignAndCut not okay!");
delete caic;
return false;
}
if (input_roi.length() > 0){
img_roi = new CImageBasis(input_roi);
if (!img_roi->ImageOkay()){
LogFile.WriteToFile("ClassFlowDigit::doAlignAndCut ImageRoi not okay!");
delete caic;
delete img_roi;
return false;
}
}
for (int i = 0; i < ROI.size(); ++i) for (int i = 0; i < ROI.size(); ++i)
{ {
printf("DigitalDigit %d - Align&Cut\n", i); printf("DigitalDigit %d - Align&Cut\n", i);
output = "/sdcard/img_tmp/" + ROI[i]->name + ".jpg";
output = FormatFileName(output); caic->CutAndSave(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, ROI[i]->image_org);
caic->CutAndSave(output, ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay); if (SaveAllFiles) ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".jpg"));
rs = new CResizeImage(output); ROI[i]->image_org->Resize(modelxsize, modelysize, ROI[i]->image);
rs->Resize(modelxsize, modelysize); if (SaveAllFiles) ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp"));
ioresize = "/sdcard/img_tmp/rd" + std::to_string(i) + ".bmp";
ioresize = FormatFileName(ioresize);
rs->SaveToFile(ioresize);
delete rs;
if (img_roi)
{
img_roi->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, 0, 0, 255, 2);
}
}
delete caic;
if (img_roi)
{
img_roi->SaveToFile(input_roi);
delete img_roi;
} }
return true; return true;
@@ -196,17 +200,9 @@ bool ClassFlowDigit::doNeuralNetwork(string time)
{ {
string logPath = CreateLogFolder(time); string logPath = CreateLogFolder(time);
string input = "/sdcard/img_tmp/alg.jpg";
string ioresize = "/sdcard/img_tmp/resize.bmp";
string output;
string nm;
input = FormatFileName(input);
#ifndef OHNETFLITE #ifndef OHNETFLITE
CTfLiteClass *tflite = new CTfLiteClass; CTfLiteClass *tflite = new CTfLiteClass;
string zwcnn = "/sdcard" + cnnmodelfile; string zwcnn = FormatFileName("/sdcard" + cnnmodelfile);
zwcnn = FormatFileName(zwcnn);
printf(zwcnn.c_str());printf("\n"); printf(zwcnn.c_str());printf("\n");
tflite->LoadModel(zwcnn); tflite->LoadModel(zwcnn);
tflite->MakeAllocate(); tflite->MakeAllocate();
@@ -215,17 +211,18 @@ bool ClassFlowDigit::doNeuralNetwork(string time)
for (int i = 0; i < ROI.size(); ++i) for (int i = 0; i < ROI.size(); ++i)
{ {
printf("DigitalDigit %d - TfLite\n", i); printf("DigitalDigit %d - TfLite\n", i);
ioresize = "/sdcard/img_tmp/rd" + std::to_string(i) + ".bmp";
ioresize = FormatFileName(ioresize);
// printf("output: %s, ioresize: %s\n", output.c_str(), ioresize.c_str());
ROI[i]->resultklasse = 0; ROI[i]->resultklasse = 0;
#ifndef OHNETFLITE #ifndef OHNETFLITE
ROI[i]->resultklasse = tflite->GetClassFromImage(ioresize); ROI[i]->resultklasse = tflite->GetClassFromImageBasis(ROI[i]->image);
#endif #endif
printf("Result Digit%i: %d\n", i, ROI[i]->resultklasse); printf("Result Digit%i: %d\n", i, ROI[i]->resultklasse);
LogImage(logPath, ROI[i]->name, NULL, &ROI[i]->resultklasse, time); if (isLogImage)
{
LogImage(logPath, ROI[i]->name, NULL, &ROI[i]->resultklasse, time, ROI[i]->image_org);
}
} }
#ifndef OHNETFLITE #ifndef OHNETFLITE
delete tflite; delete tflite;
@@ -233,6 +230,11 @@ bool ClassFlowDigit::doNeuralNetwork(string time)
return true; return true;
} }
void ClassFlowDigit::DrawROI(CImageBasis *_zw)
{
for (int i = 0; i < ROI.size(); ++i)
_zw->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, 0, 0, 255, 2);
}
std::vector<HTMLInfo*> ClassFlowDigit::GetHTMLInfo() std::vector<HTMLInfo*> ClassFlowDigit::GetHTMLInfo()
{ {
@@ -241,10 +243,14 @@ std::vector<HTMLInfo*> ClassFlowDigit::GetHTMLInfo()
for (int i = 0; i < ROI.size(); ++i) for (int i = 0; i < ROI.size(); ++i)
{ {
HTMLInfo *zw = new HTMLInfo; HTMLInfo *zw = new HTMLInfo;
zw->filename = ROI[i]->name + ".jpg"; zw->filename = ROI[i]->name + ".bmp";
zw->filename_org = ROI[i]->name + ".jpg";
zw->val = ROI[i]->resultklasse; zw->val = ROI[i]->resultklasse;
zw->image = ROI[i]->image;
zw->image_org = ROI[i]->image_org;
result.push_back(zw); result.push_back(zw);
} }
return result; return result;
} }

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "ClassFlowImage.h" #include "ClassFlowImage.h"
#include "ClassFlowAlignment.h"
#include "Helper.h" #include "Helper.h"
#include <string> #include <string>
@@ -8,6 +9,7 @@ struct roi {
int posx, posy, deltax, deltay; int posx, posy, deltax, deltay;
int resultklasse; int resultklasse;
string name; string name;
CImageBasis *image, *image_org;
roi* next; roi* next;
}; };
@@ -18,19 +20,27 @@ protected:
std::vector<roi*> ROI; std::vector<roi*> ROI;
string cnnmodelfile; string cnnmodelfile;
int modelxsize, modelysize; int modelxsize, modelysize;
bool SaveAllFiles;
ClassFlowAlignment* flowpostalignment;
bool doNeuralNetwork(string time); bool doNeuralNetwork(string time);
bool doAlignAndCut(string time); bool doAlignAndCut(string time);
void SetInitialParameter(void);
public: public:
ClassFlowDigit(); ClassFlowDigit();
ClassFlowDigit(std::vector<ClassFlow*>* lfc); ClassFlowDigit(std::vector<ClassFlow*>* lfc);
ClassFlowDigit(std::vector<ClassFlow*>* lfc, ClassFlow *_prev);
bool ReadParameter(FILE* pfile, string& aktparamgraph); bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time); bool doFlow(string time);
string getHTMLSingleStep(string host); string getHTMLSingleStep(string host);
string getReadout(); string getReadout();
std::vector<HTMLInfo*> GetHTMLInfo(); std::vector<HTMLInfo*> GetHTMLInfo();
void DrawROI(CImageBasis *_zw);
string name(){return "ClassFlowDigit";}; string name(){return "ClassFlowDigit";};
}; };

View File

@@ -5,6 +5,7 @@
#include <dirent.h> #include <dirent.h>
#include "time_sntp.h" #include "time_sntp.h"
#include "ClassLogFile.h" #include "ClassLogFile.h"
#include "CImageBasis.h"
ClassFlowImage::ClassFlowImage(const char* logTag) ClassFlowImage::ClassFlowImage(const char* logTag)
{ {
@@ -12,12 +13,19 @@ ClassFlowImage::ClassFlowImage(const char* logTag)
isLogImage = false; isLogImage = false;
} }
ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag) : ClassFlow((std::vector<ClassFlow*>*)lfc) ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag) : ClassFlow(lfc)
{ {
this->logTag = logTag; this->logTag = logTag;
isLogImage = false; isLogImage = false;
} }
ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, ClassFlow *_prev, const char* logTag) : ClassFlow(lfc, _prev)
{
this->logTag = logTag;
isLogImage = false;
}
string ClassFlowImage::CreateLogFolder(string time) { string ClassFlowImage::CreateLogFolder(string time) {
if (!isLogImage) if (!isLogImage)
return ""; return "";
@@ -32,7 +40,7 @@ string ClassFlowImage::CreateLogFolder(string time) {
return logPath; return logPath;
} }
void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time) { void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time, CImageBasis *_img) {
if (!isLogImage) if (!isLogImage)
return; return;
@@ -50,7 +58,8 @@ void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, i
string output = "/sdcard/img_tmp/" + name + ".jpg"; string output = "/sdcard/img_tmp/" + name + ".jpg";
output = FormatFileName(output); output = FormatFileName(output);
printf("save to file: %s\n", nm.c_str()); printf("save to file: %s\n", nm.c_str());
CopyFile(output, nm); _img->SaveToFile(nm);
// CopyFile(output, nm);
} }
void ClassFlowImage::RemoveOldLogs() void ClassFlowImage::RemoveOldLogs()

View File

@@ -12,11 +12,13 @@ protected:
const char* logTag; const char* logTag;
string CreateLogFolder(string time); string CreateLogFolder(string time);
void LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time); void LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time, CImageBasis *_img);
public: public:
ClassFlowImage(const char* logTag); ClassFlowImage(const char* logTag);
ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag); ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag);
ClassFlowImage(std::vector<ClassFlow*> * lfc, ClassFlow *_prev, const char* logTag);
void RemoveOldLogs(); void RemoveOldLogs();
}; };

View File

@@ -6,7 +6,7 @@
#include <time.h> #include <time.h>
ClassFlowMQTT::ClassFlowMQTT() void ClassFlowMQTT::SetInitialParameter(void)
{ {
uri = ""; uri = "";
topic = ""; topic = "";
@@ -15,20 +15,35 @@ ClassFlowMQTT::ClassFlowMQTT()
OldValue = ""; OldValue = "";
flowpostprocessing = NULL; flowpostprocessing = NULL;
user = ""; user = "";
password = ""; password = "";
previousElement = NULL;
ListFlowControll = NULL;
}
ClassFlowMQTT::ClassFlowMQTT()
{
SetInitialParameter();
} }
ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc) ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc)
{ {
uri = ""; SetInitialParameter();
topic = "";
topicError = "";
clientname = "watermeter";
OldValue = "";
flowpostprocessing = NULL;
user = "";
password = "";
ListFlowControll = lfc;
for (int i = 0; i < ListFlowControll->size(); ++i)
{
if (((*ListFlowControll)[i])->name().compare("ClassFlowPostProcessing") == 0)
{
flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i];
}
}
}
ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc, ClassFlow *_prev)
{
SetInitialParameter();
previousElement = _prev;
ListFlowControll = lfc; ListFlowControll = lfc;
for (int i = 0; i < ListFlowControll->size(); ++i) for (int i = 0; i < ListFlowControll->size(); ++i)
@@ -38,9 +53,9 @@ ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc)
flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i]; flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i];
} }
} }
} }
bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
{ {
std::vector<string> zerlegt; std::vector<string> zerlegt;

View File

@@ -13,11 +13,13 @@ protected:
std::string OldValue; std::string OldValue;
ClassFlowPostProcessing* flowpostprocessing; ClassFlowPostProcessing* flowpostprocessing;
std::string user, password; std::string user, password;
void SetInitialParameter(void);
public: public:
ClassFlowMQTT(); ClassFlowMQTT();
ClassFlowMQTT(std::vector<ClassFlow*>* lfc); ClassFlowMQTT(std::vector<ClassFlow*>* lfc);
ClassFlowMQTT(std::vector<ClassFlow*>* lfc, ClassFlow *_prev);
bool ReadParameter(FILE* pfile, string& aktparamgraph); bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time); bool doFlow(string time);
string name(){return "ClassFlowMQTT";}; string name(){return "ClassFlowMQTT";};

View File

@@ -1,7 +1,8 @@
#include "ClassFlowMakeImage.h" #include "ClassFlowMakeImage.h"
#include "Helper.h" #include "Helper.h"
#include "ClassLogFile.h"
#include "CFindTemplate.h" #include "CImageBasis.h"
#include "ClassControllCamera.h" #include "ClassControllCamera.h"
#include <time.h> #include <time.h>
@@ -16,30 +17,27 @@ esp_err_t ClassFlowMakeImage::camera_capture(){
void ClassFlowMakeImage::takePictureWithFlash(int flashdauer) void ClassFlowMakeImage::takePictureWithFlash(int flashdauer)
{ {
string nm = namerawimage; Camera.CaptureToBasisImage(rawImage, flashdauer);
if (isImageSize && (ImageQuality > 0)) if (SaveAllFiles) rawImage->SaveToFile(namerawimage);
Camera.SetQualitySize(ImageQuality, ImageSize);
printf("Start CaptureFile\n");
Camera.CaptureToFile(nm, flashdauer);
} }
void ClassFlowMakeImage::SetInitialParameter(void)
ClassFlowMakeImage::ClassFlowMakeImage() : ClassFlowImage(TAG)
{ {
waitbeforepicture = 5; waitbeforepicture = 5;
isImageSize = false; isImageSize = false;
ImageQuality = -1; ImageQuality = -1;
TimeImageTaken = 0; TimeImageTaken = 0;
ImageQuality = 5;
rawImage = NULL;
ImageSize = FRAMESIZE_VGA;
SaveAllFiles = false;
namerawimage = "/sdcard/img_tmp/raw.jpg"; namerawimage = "/sdcard/img_tmp/raw.jpg";
} }
ClassFlowMakeImage::ClassFlowMakeImage(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG) ClassFlowMakeImage::ClassFlowMakeImage(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
{ {
waitbeforepicture = 5; SetInitialParameter();
isImageSize = false;
ImageQuality = -1;
TimeImageTaken = 0;
namerawimage = "/sdcard/img_tmp/raw.jpg";
} }
bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph) bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
@@ -64,14 +62,28 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
isLogImage = true; isLogImage = true;
} }
if ((zerlegt[0] == "ImageQuality") && (zerlegt.size() > 1)) if ((zerlegt[0] == "ImageQuality") && (zerlegt.size() > 1))
this->ImageQuality = std::stod(zerlegt[1]); ImageQuality = std::stod(zerlegt[1]);
if ((zerlegt[0] == "ImageSize") && (zerlegt.size() > 1)) if ((zerlegt[0] == "ImageSize") && (zerlegt.size() > 1))
{ {
ImageSize = Camera.TextToFramesize(zerlegt[1].c_str()); ImageSize = Camera.TextToFramesize(zerlegt[1].c_str());
isImageSize = true; isImageSize = true;
} }
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
{
if (toUpper(zerlegt[1]) == "TRUE")
SaveAllFiles = true;
}
} }
Camera.SetQualitySize(ImageQuality, ImageSize);
image_width = Camera.image_width;
image_height = Camera.image_height;
rawImage = new CImageBasis();
rawImage->CreateEmptyImage(image_width, image_height, 3);
return true; return true;
} }
@@ -84,27 +96,49 @@ string ClassFlowMakeImage::getHTMLSingleStep(string host)
bool ClassFlowMakeImage::doFlow(string zwtime) bool ClassFlowMakeImage::doFlow(string zwtime)
{ {
////////////////////////////////////////////////////////////////////
// TakeImage and Store into /image_tmp/raw.jpg TO BE DONE
////////////////////////////////////////////////////////////////////
string logPath = CreateLogFolder(zwtime); string logPath = CreateLogFolder(zwtime);
int flashdauer = (int) waitbeforepicture * 1000; int flashdauer = (int) waitbeforepicture * 1000;
if (debug_detail_heap) LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - Before takePictureWithFlash");
takePictureWithFlash(flashdauer); takePictureWithFlash(flashdauer);
time(&TimeImageTaken);
localtime(&TimeImageTaken);
LogImage(logPath, "raw", NULL, NULL, zwtime); if (debug_detail_heap) LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After takePictureWithFlash");
LogImage(logPath, "raw", NULL, NULL, zwtime, rawImage);
RemoveOldLogs(); RemoveOldLogs();
if (debug_detail_heap) LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After RemoveOldLogs");
return true; return true;
} }
esp_err_t ClassFlowMakeImage::SendRawJPG(httpd_req_t *req)
{
int flashdauer = (int) waitbeforepicture * 1000;
return Camera.CaptureToHTTP(req, flashdauer);
}
ImageData* ClassFlowMakeImage::SendRawImage()
{
CImageBasis *zw = new CImageBasis(rawImage);
ImageData *id;
int flashdauer = (int) waitbeforepicture * 1000;
Camera.CaptureToBasisImage(zw, flashdauer);
id = zw->writeToMemoryAsJPG();
delete zw;
return id;
}
time_t ClassFlowMakeImage::getTimeImageTaken() time_t ClassFlowMakeImage::getTimeImageTaken()
{ {
return TimeImageTaken; return TimeImageTaken;
} }
ClassFlowMakeImage::~ClassFlowMakeImage(void)
{
delete rawImage;
}

View File

@@ -20,19 +20,34 @@ protected:
int ImageQuality; int ImageQuality;
time_t TimeImageTaken; time_t TimeImageTaken;
string namerawimage; string namerawimage;
int image_height, image_width;
bool SaveAllFiles;
void CopyFile(string input, string output); void CopyFile(string input, string output);
esp_err_t camera_capture(); esp_err_t camera_capture();
void takePictureWithFlash(int flashdauer); void takePictureWithFlash(int flashdauer);
void SetInitialParameter(void);
public: public:
ClassFlowMakeImage(); CImageBasis *rawImage;
ClassFlowMakeImage(std::vector<ClassFlow*>* lfc); ClassFlowMakeImage(std::vector<ClassFlow*>* lfc);
bool ReadParameter(FILE* pfile, string& aktparamgraph); bool ReadParameter(FILE* pfile, string& aktparamgraph);
bool doFlow(string time); bool doFlow(string time);
string getHTMLSingleStep(string host); string getHTMLSingleStep(string host);
time_t getTimeImageTaken(); time_t getTimeImageTaken();
string name(){return "ClassFlowMakeImage";}; string name(){return "ClassFlowMakeImage";};
ImageData* SendRawImage();
esp_err_t SendRawJPG(httpd_req_t *req);
~ClassFlowMakeImage(void);
}; };
extern bool debug_detail_heap;

View File

@@ -18,6 +18,64 @@
using namespace std; using namespace std;
/////////////////////////////////////////////////////////////////////////////////////////////
string getESPHeapInfo(){
string espInfoResultStr = "";
char aMsgBuf[80];
multi_heap_info_t aMultiHead_info ;
heap_caps_get_info (&aMultiHead_info,MALLOC_CAP_8BIT);
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t aMinFreeHeadSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
sprintf(aMsgBuf," Free Heap Size: %ld", (long) aFreeHeapSize);
size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_SPIRAM);
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
sprintf(aMsgBuf," Heap: %ld", (long) aFreeHeapSize);
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf," Min Free: %ld", (long) aMinFreeHeapSize);
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf," larg. Block: %ld", (long) aHeapLargestFreeBlockSize);
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf," SPI Heap: %ld", (long) aFreeSPIHeapSize);
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf," Min Free Heap Size: %ld", (long) aMinFreeHeadSize);
sprintf(aMsgBuf," NOT_SPI Heap: %ld", (long) (aFreeHeapSize - aFreeSPIHeapSize));
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf," largest Block Size: %ld", (long) aHeapLargestFreeBlockSize);
sprintf(aMsgBuf," Internal Heap: %ld", (long) (aFreeInternalHeapSize));
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf," Internal Min Heap free: %ld", (long) (aMinFreeInternalHeapSize));
espInfoResultStr += string(aMsgBuf);
return espInfoResultStr;
}
size_t getESPHeapSize(){
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
return aFreeHeapSize;
}
size_t getInternalESPHeapSize() {
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
return aFreeInternalHeapSize;
}
///////////////////////////////////////////////////////////////////////////////////////////////
void memCopyGen(uint8_t* _source, uint8_t* _target, int _size)
{
for (int i = 0; i < _size; ++i)
*(_target + i) = *(_source + i);
}
FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec) FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec)
{ {

View File

@@ -10,7 +10,7 @@ void FindReplace(std::string& line, std::string& oldString, std::string& newStri
void CopyFile(string input, string output); void CopyFile(string input, string output);
FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec = 10); FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec = 1);
size_t findDelimiterPos(string input, string delimiter); size_t findDelimiterPos(string input, string delimiter);
//string trim(string istring); //string trim(string istring);
@@ -27,3 +27,12 @@ string toUpper(string in);
float temperatureRead(); float temperatureRead();
time_t addDays(time_t startTime, int days); time_t addDays(time_t startTime, int days);
void memCopyGen(uint8_t* _source, uint8_t* _target, int _size);
///////////////////////////
size_t getInternalESPHeapSize();
size_t getESPHeapSize();
string getESPHeapInfo();
/////////////////////////////

View File

@@ -0,0 +1,192 @@
#include "CAlignAndCutImage.h"
#include "CRotateImage.h"
#include "CFindTemplate.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include <algorithm>
//#define GET_MEMORY malloc
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
CAlignAndCutImage::CAlignAndCutImage(CImageBasis *_org, CImageBasis *_temp)
{
rgb_image = _org->rgb_image;
channels = _org->channels;
width = _org->width;
height = _org->height;
bpp = _org->bpp;
externalImage = true;
ImageTMP = _temp;
}
void CAlignAndCutImage::GetRefSize(int *ref_dx, int *ref_dy)
{
ref_dx[0] = t0_dx;
ref_dy[0] = t0_dy;
ref_dx[1] = t1_dx;
ref_dy[1] = t1_dy;
}
void CAlignAndCutImage::Align(std::string _template0, int ref0_x, int ref0_y, std::string _template1, int ref1_x, int ref1_y, int deltax, int deltay, std::string imageROI)
{
int dx, dy;
int r0_x, r0_y, r1_x, r1_y;
// CFindTemplate* ft = new CFindTemplate(filename);
CFindTemplate* ft = new CFindTemplate(rgb_image, channels, width, height, bpp);
r0_x = ref0_x;
r0_y = ref0_y;
ft->FindTemplate(_template0, &r0_x, &r0_y, deltax, deltay);
t0_dx = ft->tpl_width;
t0_dy = ft->tpl_height;
r1_x = ref1_x;
r1_y = ref1_y;
ft->FindTemplate(_template1, &r1_x, &r1_y, deltax, deltay);
t1_dx = ft->tpl_width;
t1_dy = ft->tpl_height;
delete ft;
dx = ref0_x - r0_x;
dy = ref0_y - r0_y;
r0_x += dx;
r0_y += dy;
r1_x += dx;
r1_y += dy;
float w_org, w_ist, d_winkel;
w_org = atan2(ref1_y - ref0_y, ref1_x - ref0_x);
w_ist = atan2(r1_y - r0_y, r1_x - r0_x);
d_winkel = (w_org - w_ist) * 180 / M_PI;
if (imageROI.length() > 0)
{
CImageBasis* imgzw = new CImageBasis(this);
imgzw->drawRect(r0_x, r0_y, t0_dx, t0_dy, 255, 0, 0, 2);
imgzw->drawRect(r1_x, r1_y, t1_dx, t1_dy, 255, 0, 0, 2);
imgzw->SaveToFile(imageROI);
printf("Alignment: alignment ROI created: %s\n", imageROI.c_str());
delete imgzw;
}
std::string zw = "\tdx:\t" + std::to_string(dx) + "\tdy:\t" + std::to_string(dy) + "\td_winkel:\t" + std::to_string(d_winkel);
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
CRotateImage rt(this, ImageTMP);
rt.Translate(dx, dy);
rt.Rotate(d_winkel, ref0_x, ref0_y);
printf("Alignment: dx %d - dy %d - rot %f\n", dx, dy, d_winkel);
}
void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int dx, int dy)
{
int x2, y2;
x2 = x1 + dx;
y2 = y1 + dy;
x2 = std::min(x2, width - 1);
y2 = std::min(y2, height - 1);
dx = x2 - x1;
dy = y2 - y1;
int memsize = dx * dy * channels;
uint8_t* odata = (unsigned char*) GET_MEMORY(memsize);
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = x1; x < x2; ++x)
for (int y = y1; y < y2; ++y)
{
p_target = odata + (channels * ((y - y1) * dx + (x - x1)));
p_source = rgb_image + (channels * (y * width + x));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
// stbi_write_jpg(_template1.c_str(), dx, dy, channels, odata, 0);
stbi_write_bmp(_template1.c_str(), dx, dy, channels, odata);
stbi_image_free(odata);
}
void CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy, CImageBasis *_target)
{
int x2, y2;
x2 = x1 + dx;
y2 = y1 + dy;
x2 = std::min(x2, width - 1);
y2 = std::min(y2, height - 1);
dx = x2 - x1;
dy = y2 - y1;
if ((_target->height != dy) || (_target->width != dx) || (_target->channels != channels))
{
printf("CAlignAndCutImage::CutAndSave - Bildgröße passt nicht !!!!!!!!!");
return;
}
uint8_t* odata = _target->rgb_image;
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = x1; x < x2; ++x)
for (int y = y1; y < y2; ++y)
{
p_target = odata + (channels * ((y - y1) * dx + (x - x1)));
p_source = rgb_image + (channels * (y * width + x));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
}
CImageBasis* CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy)
{
int x2, y2;
x2 = x1 + dx;
y2 = y1 + dy;
x2 = std::min(x2, width - 1);
y2 = std::min(y2, height - 1);
dx = x2 - x1;
dy = y2 - y1;
int memsize = dx * dy * channels;
uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = x1; x < x2; ++x)
for (int y = y1; y < y2; ++y)
{
p_target = odata + (channels * ((y - y1) * dx + (x - x1)));
p_source = rgb_image + (channels * (y * width + x));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
CImageBasis* rs = new CImageBasis(odata, channels, dx, dy, bpp);
rs->SetIndepended();
return rs;
}

View File

@@ -0,0 +1,18 @@
#include "CImageBasis.h"
class CAlignAndCutImage : public CImageBasis
{
public:
int t0_dx, t0_dy, t1_dx, t1_dy;
CImageBasis *ImageTMP;
CAlignAndCutImage(std::string _image) : CImageBasis(_image) {ImageTMP = NULL;};
CAlignAndCutImage(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL;};
CAlignAndCutImage(CImageBasis *_org, CImageBasis *_temp);
void Align(std::string _template1, int x1, int y1, std::string _template2, int x2, int y2, int deltax = 40, int deltay = 40, std::string imageROI = "");
void CutAndSave(std::string _template1, int x1, int y1, int dx, int dy);
CImageBasis* CutAndSave(int x1, int y1, int dx, int dy);
void CutAndSave(int x1, int y1, int dx, int dy, CImageBasis *_target);
void GetRefSize(int *ref_dx, int *ref_dy);
};

View File

@@ -1,197 +1,26 @@
#include "CFindTemplate.h" #include "CFindTemplate.h"
#include "Helper.h"
#include "ClassLogFile.h"
#include "esp_system.h"
#define _USE_MATH_DEFINES
#include <math.h>
#include <algorithm>
#define _ESP32_PSRAM
using namespace std;
#define GET_MEMORY malloc
/*
CResizeImage::CResizeImage(std::string _image, int _new_dx, int _new_dy)
{
CImageBasis::CImageBasis(_image);
}
*/
uint8_t CImageBasis::GetPixelColor(int x, int y, int ch)
{
stbi_uc* p_source;
p_source = this->rgb_image + (this->channels * (y * this->width + x));
return p_source[ch];
}
void CResizeImage::Resize(int _new_dx, int _new_dy)
{
int memsize = _new_dx * _new_dy * this->channels;
uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
stbir_resize_uint8(this->rgb_image, this->width, this->height, 0, odata, _new_dx, _new_dy, 0, this->channels);
stbi_image_free(this->rgb_image);
this->rgb_image = (unsigned char*)GET_MEMORY(memsize);
this->memCopy(odata, this->rgb_image, memsize);
this->width = _new_dx;
this->height = _new_dy;
stbi_image_free(odata);
}
void CRotate::Mirror(){
int memsize = this->width * this->height * this->channels;
uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = 0; x < this->width; ++x)
for (int y = 0; y < this->height; ++y)
{
p_target = odata + (this->channels * (y * this->width + x));
x_source = this->width - x;
y_source = y;
p_source = this->rgb_image + (this->channels * (y_source * this->width + x_source));
for (int channels = 0; channels < this->channels; ++channels)
p_target[channels] = p_source[channels];
}
// memcpy(this->rgb_image, odata, memsize);
this->memCopy(odata, this->rgb_image, memsize);
stbi_image_free(odata);
}
void CRotate::Rotate(float _angle, int _centerx, int _centery)
{
float m[2][3];
float x_center = _centerx;
float y_center = _centery;
_angle = _angle / 180 * M_PI;
m[0][0] = cos(_angle);
m[0][1] = sin(_angle);
m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
m[1][0] = -m[0][1];
m[1][1] = m[0][0];
m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
int memsize = this->width * this->height * this->channels;
uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = 0; x < this->width; ++x)
for (int y = 0; y < this->height; ++y)
{
p_target = odata + (this->channels * (y * this->width + x));
x_source = int(m[0][0] * x + m[0][1] * y);
y_source = int(m[1][0] * x + m[1][1] * y);
x_source += int(m[0][2]);
y_source += int(m[1][2]);
if ((x_source >= 0) && (x_source < this->width) && (y_source >= 0) && (y_source < this->height))
{
p_source = this->rgb_image + (this->channels * (y_source * this->width + x_source));
for (int channels = 0; channels < this->channels; ++channels)
p_target[channels] = p_source[channels];
}
else
{
for (int channels = 0; channels < this->channels; ++channels)
p_target[channels] = 255;
}
}
// memcpy(this->rgb_image, odata, memsize);
this->memCopy(odata, this->rgb_image, memsize);
stbi_image_free(odata);
}
void CRotate::Rotate(float _angle)
{
this->Rotate(_angle, this->width / 2, this->height / 2);
}
void CRotate::Translate(int _dx, int _dy)
{
int memsize = this->width * this->height * this->channels;
uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = 0; x < this->width; ++x)
for (int y = 0; y < this->height; ++y)
{
p_target = odata + (this->channels * (y * this->width + x));
x_source = x - _dx;
y_source = y - _dy;
if ((x_source >= 0) && (x_source < this->width) && (y_source >= 0) && (y_source < this->height))
{
p_source = this->rgb_image + (this->channels * (y_source * this->width + x_source));
for (int channels = 0; channels < this->channels; ++channels)
p_target[channels] = p_source[channels];
}
else
{
for (int channels = 0; channels < this->channels; ++channels)
p_target[channels] = 255;
}
}
// memcpy(this->rgb_image, odata, memsize);
this->memCopy(odata, this->rgb_image, memsize);
stbi_image_free(odata);
}
CFindTemplate::CFindTemplate(std::string _image)
{
this->channels = 1;
this->rgb_image = stbi_load(_image.c_str(), &(this->width), &(this->height), &(this->bpp), this->channels);
}
void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y) void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y)
{ {
this->FindTemplate(_template, found_x, found_y, 0, 0); FindTemplate(_template, found_x, found_y, 0, 0);
} }
void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy) void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy)
{ {
uint8_t* rgb_template = stbi_load(_template.c_str(), &tpl_width, &tpl_height, &tpl_bpp, this->channels); uint8_t* rgb_template = stbi_load(_template.c_str(), &tpl_width, &tpl_height, &tpl_bpp, channels);
int ow, ow_start, ow_stop; int ow, ow_start, ow_stop;
int oh, oh_start, oh_stop; int oh, oh_start, oh_stop;
if (_dx == 0) if (_dx == 0)
{ {
_dx = this->width; _dx = width;
*found_x = 0; *found_x = 0;
} }
if (_dy == 0) if (_dy == 0)
{ {
_dy = this->height; _dy = height;
*found_y = 0; *found_y = 0;
} }
@@ -199,18 +28,18 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found
ow_start = *found_x - _dx; ow_start = *found_x - _dx;
ow_start = std::max(ow_start, 0); ow_start = std::max(ow_start, 0);
ow_stop = *found_x + _dx; ow_stop = *found_x + _dx;
if ((ow_stop + tpl_width) > this->width) if ((ow_stop + tpl_width) > width)
ow_stop = this->width - tpl_width; ow_stop = width - tpl_width;
ow = ow_stop - ow_start + 1; ow = ow_stop - ow_start + 1;
oh_start = *found_y - _dy; oh_start = *found_y - _dy;
oh_start = std::max(oh_start, 0); oh_start = std::max(oh_start, 0);
oh_stop = *found_y + _dy; oh_stop = *found_y + _dy;
if ((oh_stop + tpl_height) > this->height) if ((oh_stop + tpl_height) > height)
oh_stop = this->height - tpl_height; oh_stop = height - tpl_height;
oh = oh_stop - oh_start + 1; oh = oh_stop - oh_start + 1;
uint8_t* odata = (unsigned char*)GET_MEMORY(ow * oh * this->channels); uint8_t* odata = (unsigned char*)GET_MEMORY(ow * oh * channels);
double aktSAD; double aktSAD;
double minSAD = pow(tpl_width * tpl_height * 255, 2); double minSAD = pow(tpl_width * tpl_height * 255, 2);
@@ -222,11 +51,11 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found
for (int tpl_x = 0; tpl_x < tpl_width; tpl_x++) for (int tpl_x = 0; tpl_x < tpl_width; tpl_x++)
for (int tpl_y = 0; tpl_y < tpl_height; tpl_y++) for (int tpl_y = 0; tpl_y < tpl_height; tpl_y++)
{ {
stbi_uc* p_org = this->rgb_image + (this->channels * ((youter + tpl_y) * this->width + (xouter + tpl_x))); stbi_uc* p_org = rgb_image + (channels * ((youter + tpl_y) * width + (xouter + tpl_x)));
stbi_uc* p_tpl = rgb_template + (this->channels * (tpl_y * tpl_width + tpl_x)); stbi_uc* p_tpl = rgb_template + (channels * (tpl_y * tpl_width + tpl_x));
aktSAD += pow(p_tpl[0] - p_org[0], 2); aktSAD += pow(p_tpl[0] - p_org[0], 2);
} }
stbi_uc* p_out = odata + (this->channels * ((youter - oh_start) * ow + (xouter - ow_start))); stbi_uc* p_out = odata + (channels * ((youter - oh_start) * ow + (xouter - ow_start)));
p_out[0] = int(sqrt(aktSAD / (tpl_width * tpl_height))); p_out[0] = int(sqrt(aktSAD / (tpl_width * tpl_height)));
if (aktSAD < minSAD) if (aktSAD < minSAD)
@@ -237,7 +66,7 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found
} }
} }
stbi_write_bmp("sdcard\\find.bmp", ow, oh, this->channels, odata); stbi_write_bmp("sdcard\\find.bmp", ow, oh, channels, odata);
stbi_image_free(odata); stbi_image_free(odata);
stbi_image_free(rgb_template); stbi_image_free(rgb_template);
@@ -245,303 +74,14 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found
void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, std::string _imageout) void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, std::string _imageout)
{ {
this->FindTemplate(_template, found_x, found_y); FindTemplate(_template, found_x, found_y);
this->SaveToFile(_imageout); SaveToFile(_imageout);
} }
void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy, std::string _imageout) void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy, std::string _imageout)
{ {
this->FindTemplate(_template, found_x, found_y, _dx, _dy); FindTemplate(_template, found_x, found_y, _dx, _dy);
this->SaveToFile(_imageout); SaveToFile(_imageout);
} }
void CImageBasis::memCopy(uint8_t* _source, uint8_t* _target, int _size)
{
#ifdef _ESP32_PSRAM
for (int i = 0; i < _size; ++i)
*(_target + i) = *(_source + i);
#else
memcpy(_target, _source, _size);
#endif
}
bool CImageBasis::isInImage(int x, int y)
{
if ((x < 0) || (x > this->width - 1))
return false;
if ((y < 0) || (y > this->height- 1))
return false;
return true;
}
void CImageBasis::setPixelColor(int x, int y, int r, int g, int b)
{
stbi_uc* p_source;
p_source = this->rgb_image + (this->channels * (y * this->width + x));
p_source[0] = r;
if (this-> channels > 2)
{
p_source[1] = g;
p_source[2] = b;
}
}
void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, int thickness)
{
int zwx1, zwx2, zwy1, zwy2;
int _x, _y, _thick;
zwx1 = x - thickness + 1;
zwx2 = x + dx + thickness - 1;
zwy1 = y;
zwy2 = y;
for (_thick = 0; _thick < thickness; _thick++)
for (_x = zwx1; _x <= zwx2; ++_x)
for (_y = zwy1; _y <= zwy2; _y++)
if (isInImage(_x, _y))
setPixelColor(_x, _y - _thick, r, g, b);
zwx1 = x - thickness + 1;
zwx2 = x + dx + thickness - 1;
zwy1 = y + dy;
zwy2 = y + dy;
for (_thick = 0; _thick < thickness; _thick++)
for (_x = zwx1; _x <= zwx2; ++_x)
for (_y = zwy1; _y <= zwy2; _y++)
if (isInImage(_x, _y))
setPixelColor(_x, _y + _thick, r, g, b);
zwx1 = x;
zwx2 = x;
zwy1 = y;
zwy2 = y + dy;
for (_thick = 0; _thick < thickness; _thick++)
for (_x = zwx1; _x <= zwx2; ++_x)
for (_y = zwy1; _y <= zwy2; _y++)
if (isInImage(_x, _y))
setPixelColor(_x - _thick, _y, r, g, b);
zwx1 = x + dx;
zwx2 = x + dx;
zwy1 = y;
zwy2 = y + dy;
for (_thick = 0; _thick < thickness; _thick++)
for (_x = zwx1; _x <= zwx2; ++_x)
for (_y = zwy1; _y <= zwy2; _y++)
if (isInImage(_x, _y))
setPixelColor(_x + _thick, _y, r, g, b);
}
void CImageBasis::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness)
{
int _x, _y, _thick;
int _zwy1, _zwy2;
thickness = (thickness-1) / 2;
for (_thick = 0; _thick <= thickness; ++_thick)
for (_x = x1 - _thick; _x <= x2 + _thick; ++_x)
{
if (x2 == x1)
{
_zwy1 = y1;
_zwy2 = y2;
}
else
{
_zwy1 = (y2 - y1) * (float)(_x - x1) / (float)(x2 - x1) + y1;
_zwy2 = (y2 - y1) * (float)(_x + 1 - x1) / (float)(x2 - x1) + y1;
}
for (_y = _zwy1 - _thick; _y <= _zwy2 + _thick; _y++)
if (isInImage(_x, _y))
setPixelColor(_x, _y, r, g, b);
}
}
void CImageBasis::drawCircle(int x1, int y1, int rad, int r, int g, int b, int thickness)
{
float deltarad, aktrad;
int _thick, _x, _y;
deltarad = 1 / (4 * M_PI * (rad + thickness - 1));
for (aktrad = 0; aktrad <= (2 * M_PI); aktrad += deltarad)
for (_thick = 0; _thick < thickness; ++_thick)
{
_x = sin(aktrad) * (rad + _thick) + x1;
_y = cos(aktrad) * (rad + _thick) + y1;
if (isInImage(_x, _y))
setPixelColor(_x, _y, r, g, b);
}
}
CImageBasis::CImageBasis()
{
this->externalImage = false;
}
CImageBasis::CImageBasis(std::string _image)
{
channels = 3;
externalImage = false;
filename = _image;
// long freebefore = esp_get_free_heap_size();
rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels);
// if (rgb_image == NULL)
// LogFile.WriteToFile("Image Load failed:" + _image + " FreeHeapSize before: " + to_string(freebefore) + " after: " + to_string(esp_get_free_heap_size()));
// printf("CImageBasis after load\n");
// printf("w %d, h %d, b %d, c %d", this->width, this->height, this->bpp, this->channels);
}
bool CImageBasis::ImageOkay(){
return rgb_image != NULL;
}
CImageBasis::CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp)
{
this->rgb_image = _rgb_image;
this->channels = _channels;
this->width = _width;
this->height = _height;
this->bpp = _bpp;
this->externalImage = true;
}
void CImageBasis::Contrast(float _contrast) //input range [-100..100]
{
stbi_uc* p_source;
float contrast = (_contrast/100) + 1; //convert to decimal & shift range: [0..2]
float intercept = 128 * (1 - contrast);
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_source = this->rgb_image + (this->channels * (y * this->width + x));
for (int channels = 0; channels < this->channels; ++channels)
p_source[channels] = (uint8_t) std::min(255, std::max(0, (int) (p_source[channels] * contrast + intercept)));
}
}
CImageBasis::~CImageBasis()
{
if (!this->externalImage)
stbi_image_free(this->rgb_image);
}
void CImageBasis::SaveToFile(std::string _imageout)
{
string typ = getFileType(_imageout);
if ((typ == "jpg") || (typ == "JPG")) // ACHTUNG PROBLEMATISCH IM ESP32
{
stbi_write_jpg(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image, 0);
}
if ((typ == "bmp") || (typ == "BMP"))
{
stbi_write_bmp(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image);
}
// stbi_write_jpg(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image, 0);
// stbi_write_bmp(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image);
}
void CAlignAndCutImage::Align(std::string _template0, int ref0_x, int ref0_y, std::string _template1, int ref1_x, int ref1_y, int deltax, int deltay, std::string imageROI)
{
int dx, dy;
int r0_x, r0_y, r1_x, r1_y;
CFindTemplate* ft = new CFindTemplate(this->filename);
r0_x = ref0_x;
r0_y = ref0_y;
ft->FindTemplate(_template0, &r0_x, &r0_y, deltax, deltay);
t0_dx = ft->tpl_width;
t0_dy = ft->tpl_height;
r1_x = ref1_x;
r1_y = ref1_y;
ft->FindTemplate(_template1, &r1_x, &r1_y, deltax, deltay);
t1_dx = ft->tpl_width;
t1_dy = ft->tpl_height;
delete ft;
dx = ref0_x - r0_x;
dy = ref0_y - r0_y;
r0_x += dx;
r0_y += dy;
r1_x += dx;
r1_y += dy;
float w_org, w_ist, d_winkel;
w_org = atan2(ref1_y - ref0_y, ref1_x - ref0_x);
w_ist = atan2(r1_y - r0_y, r1_x - r0_x);
d_winkel = (w_org - w_ist) * 180 / M_PI;
if (imageROI.length() > 0)
{
CImageBasis* imgzw = new CImageBasis(this->filename);
imgzw->drawRect(r0_x, r0_y, t0_dx, t0_dy, 255, 0, 0, 2);
imgzw->drawRect(r1_x, r1_y, t1_dx, t1_dy, 255, 0, 0, 2);
imgzw->SaveToFile(imageROI);
printf("Alignment: alignment ROI created: %s\n", imageROI.c_str());
delete imgzw;
}
string zw = "\tdx:\t" + to_string(dx) + "\tdy:\t" + to_string(dy) + "\td_winkel:\t" + to_string(d_winkel);
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
CRotate rt(this->rgb_image, this->channels, this->width, this->height, this->bpp);
rt.Translate(dx, dy);
rt.Rotate(d_winkel, ref0_x, ref0_y);
printf("Alignment: dx %d - dy %d - rot %f\n", dx, dy, d_winkel);
}
void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int dx, int dy)
{
int x2, y2;
x2 = x1 + dx;
y2 = y1 + dy;
x2 = min(x2, this->width - 1);
y2 = min(y2, this->height - 1);
dx = x2 - x1;
dy = y2 - y1;
int memsize = dx * dy * this->channels;
uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = x1; x < x2; ++x)
for (int y = y1; y < y2; ++y)
{
p_target = odata + (this->channels * ((y - y1) * dx + (x - x1)));
p_source = this->rgb_image + (this->channels * (y * this->width + x));
for (int channels = 0; channels < this->channels; ++channels)
p_target[channels] = p_source[channels];
}
// stbi_write_jpg(_template1.c_str(), dx, dy, this->channels, odata, 0);
stbi_write_bmp(_template1.c_str(), dx, dy, this->channels, odata);
stbi_image_free(odata);
}

View File

@@ -1,98 +1,16 @@
#pragma once #include "CImageBasis.h"
#ifndef __CFINDTEMPLATE
#define __CFINGTEMPLATE
#include <stdint.h>
#include <string>
#define _USE_MATH_DEFINES
#include <math.h>
#include "stb_image.h"
#include "stb_image_write.h"
#include "stb_image_resize.h"
class CImageBasis
{
protected:
uint8_t* rgb_image;
int channels;
int width, height, bpp;
bool externalImage;
std::string filename;
void memCopy(uint8_t* _source, uint8_t* _target, int _size);
bool isInImage(int x, int y);
public:
int getWidth(){return this->width;};
int getHeight(){return this->height;};
int getChannels(){return this->channels;};
void drawRect(int x, int y, int dx, int dy, int r = 255, int g = 255, int b = 255, int thickness = 1);
void drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness = 1);
void drawCircle(int x1, int y1, int rad, int r, int g, int b, int thickness = 1);
void setPixelColor(int x, int y, int r, int g, int b);
void Contrast(float _contrast);
bool ImageOkay();
CImageBasis();
CImageBasis(std::string _image);
CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp);
uint8_t GetPixelColor(int x, int y, int ch);
~CImageBasis();
void SaveToFile(std::string _imageout);
};
class CFindTemplate : public CImageBasis class CFindTemplate : public CImageBasis
{ {
public: public:
int tpl_width, tpl_height, tpl_bpp; int tpl_width, tpl_height, tpl_bpp;
CFindTemplate(std::string _image); // CFindTemplate(std::string _image);
CFindTemplate(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {};
void FindTemplate(std::string _template, int* found_x, int* found_y, std::string _imageout); void FindTemplate(std::string _template, int* found_x, int* found_y, std::string _imageout);
void FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy, std::string _imageout); void FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy, std::string _imageout);
void FindTemplate(std::string _template, int* found_x, int* found_y); void FindTemplate(std::string _template, int* found_x, int* found_y);
void FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy); void FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy);
}; };
class CRotate: public CImageBasis
{
public:
CRotate(std::string _image) : CImageBasis(_image) {};
CRotate(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {};
void Rotate(float _angle);
void Rotate(float _angle, int _centerx, int _centery);
void Translate(int _dx, int _dy);
void Mirror();
};
class CAlignAndCutImage : public CImageBasis
{
public:
int t0_dx, t0_dy, t1_dx, t1_dy;
CAlignAndCutImage(std::string _image) : CImageBasis(_image) {};
void Align(std::string _template1, int x1, int y1, std::string _template2, int x2, int y2, int deltax = 40, int deltay = 40, std::string imageROI = "");
void CutAndSave(std::string _template1, int x1, int y1, int dx, int dy);
};
class CResizeImage : public CImageBasis
{
public:
CResizeImage(std::string _image) : CImageBasis(_image) {};
// CResizeImage(std::string _image, int _new_dx, int _new_dy);
void Resize(int _new_dx, int _new_dy);
};
#endif

View File

@@ -0,0 +1,436 @@
#include "CImageBasis.h"
#include "Helper.h"
#include "ClassLogFile.h"
#include <esp_log.h>
#include "esp_system.h"
#include <cstring>
#define _USE_MATH_DEFINES
#include <math.h>
#include <algorithm>
#define _ESP32_PSRAM
using namespace std;
static const char *TAG = "CImageBasis";
void writejpghelp(void *context, void *data, int size)
{
// printf("Size all: %d, size %d\n", ((ImageData*)context)->size, size);
ImageData* _zw = (ImageData*) context;
uint8_t *voidstart = _zw->data;
uint8_t *datastart = (uint8_t*) data;
voidstart += _zw->size;
for (int i = 0; i < size; ++i)
*(voidstart + i) = *(datastart + i);
_zw->size += size;
}
ImageData* CImageBasis::writeToMemoryAsJPG(const int quality)
{
ImageData* ii = new ImageData;
stbi_write_jpg_to_func(writejpghelp, ii, width, height, channels, rgb_image, quality);
return ii;
}
#define HTTP_BUFFER_SENT 1024
struct SendJPGHTTP
{
httpd_req_t *req;
esp_err_t res;
char buf[HTTP_BUFFER_SENT];
int size = 0;
};
inline void writejpgtohttphelp(void *context, void *data, int size)
{
SendJPGHTTP* _send = (SendJPGHTTP*) context;
if ((_send->size + size) >= HTTP_BUFFER_SENT) // data passt nich mehr in buffer
{
httpd_req_t *_req = _send->req;
if (httpd_resp_send_chunk(_req, _send->buf, _send->size) != ESP_OK)
{
ESP_LOGE(TAG, "File sending failed!");
_send->res = ESP_FAIL;
}
_send->size = 0;
}
std::memcpy((void*) (&(_send->buf[0]) + _send->size), data, size);
_send->size+= size;
}
esp_err_t CImageBasis::SendJPGtoHTTP(httpd_req_t *_req, const int quality)
{
SendJPGHTTP ii;
ii.req = _req;
ii.res = ESP_OK;
ii.size = 0;
stbi_write_jpg_to_func(writejpgtohttphelp, &ii, width, height, channels, rgb_image, quality);
if (ii.size > 0)
{
if (httpd_resp_send_chunk(_req, (char*) ii.buf, ii.size) != ESP_OK) // verschicke noch den Rest
{
ESP_LOGE(TAG, "File sending failed!");
ii.res = ESP_FAIL;
}
}
return ii.res;
}
bool CImageBasis::CopyFromMemory(uint8_t* _source, int _size)
{
int gr = height * width * channels;
if (gr != _size) // Größe passt nicht
{
printf("Kann Bild nicht von Speicher kopierte - Größen passen nicht zusammen: soll %d, ist %d\n", _size, gr);
return false;
}
memCopy(_source, rgb_image, _size);
return true;
}
uint8_t CImageBasis::GetPixelColor(int x, int y, int ch)
{
stbi_uc* p_source;
p_source = rgb_image + (channels * (y * width + x));
return p_source[ch];
}
void CImageBasis::memCopy(uint8_t* _source, uint8_t* _target, int _size)
{
#ifdef _ESP32_PSRAM
for (int i = 0; i < _size; ++i)
*(_target + i) = *(_source + i);
#else
memcpy(_target, _source, _size);
#endif
}
bool CImageBasis::isInImage(int x, int y)
{
if ((x < 0) || (x > width - 1))
return false;
if ((y < 0) || (y > height- 1))
return false;
return true;
}
void CImageBasis::setPixelColor(int x, int y, int r, int g, int b)
{
stbi_uc* p_source;
p_source = rgb_image + (channels * (y * width + x));
p_source[0] = r;
if ( channels > 2)
{
p_source[1] = g;
p_source[2] = b;
}
}
void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, int thickness)
{
int zwx1, zwx2, zwy1, zwy2;
int _x, _y, _thick;
zwx1 = x - thickness + 1;
zwx2 = x + dx + thickness - 1;
zwy1 = y;
zwy2 = y;
for (_thick = 0; _thick < thickness; _thick++)
for (_x = zwx1; _x <= zwx2; ++_x)
for (_y = zwy1; _y <= zwy2; _y++)
if (isInImage(_x, _y))
setPixelColor(_x, _y - _thick, r, g, b);
zwx1 = x - thickness + 1;
zwx2 = x + dx + thickness - 1;
zwy1 = y + dy;
zwy2 = y + dy;
for (_thick = 0; _thick < thickness; _thick++)
for (_x = zwx1; _x <= zwx2; ++_x)
for (_y = zwy1; _y <= zwy2; _y++)
if (isInImage(_x, _y))
setPixelColor(_x, _y + _thick, r, g, b);
zwx1 = x;
zwx2 = x;
zwy1 = y;
zwy2 = y + dy;
for (_thick = 0; _thick < thickness; _thick++)
for (_x = zwx1; _x <= zwx2; ++_x)
for (_y = zwy1; _y <= zwy2; _y++)
if (isInImage(_x, _y))
setPixelColor(_x - _thick, _y, r, g, b);
zwx1 = x + dx;
zwx2 = x + dx;
zwy1 = y;
zwy2 = y + dy;
for (_thick = 0; _thick < thickness; _thick++)
for (_x = zwx1; _x <= zwx2; ++_x)
for (_y = zwy1; _y <= zwy2; _y++)
if (isInImage(_x, _y))
setPixelColor(_x + _thick, _y, r, g, b);
}
void CImageBasis::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness)
{
int _x, _y, _thick;
int _zwy1, _zwy2;
thickness = (thickness-1) / 2;
for (_thick = 0; _thick <= thickness; ++_thick)
for (_x = x1 - _thick; _x <= x2 + _thick; ++_x)
{
if (x2 == x1)
{
_zwy1 = y1;
_zwy2 = y2;
}
else
{
_zwy1 = (y2 - y1) * (float)(_x - x1) / (float)(x2 - x1) + y1;
_zwy2 = (y2 - y1) * (float)(_x + 1 - x1) / (float)(x2 - x1) + y1;
}
for (_y = _zwy1 - _thick; _y <= _zwy2 + _thick; _y++)
if (isInImage(_x, _y))
setPixelColor(_x, _y, r, g, b);
}
}
void CImageBasis::drawCircle(int x1, int y1, int rad, int r, int g, int b, int thickness)
{
float deltarad, aktrad;
int _thick, _x, _y;
deltarad = 1 / (4 * M_PI * (rad + thickness - 1));
for (aktrad = 0; aktrad <= (2 * M_PI); aktrad += deltarad)
for (_thick = 0; _thick < thickness; ++_thick)
{
_x = sin(aktrad) * (rad + _thick) + x1;
_y = cos(aktrad) * (rad + _thick) + y1;
if (isInImage(_x, _y))
setPixelColor(_x, _y, r, g, b);
}
}
CImageBasis::CImageBasis()
{
externalImage = false;
}
void CImageBasis::CreateEmptyImage(int _width, int _height, int _channels)
{
bpp = _channels;
width = _width;
height = _height;
channels = _channels;
int memsize = width * height * channels;
rgb_image = (unsigned char*)GET_MEMORY(memsize);
stbi_uc* p_source;
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_source = rgb_image + (channels * (y * width + x));
for (int _channels = 0; _channels < channels; ++_channels)
p_source[_channels] = (uint8_t) 0;
}
}
void CImageBasis::LoadFromMemory(stbi_uc *_buffer, int len)
{
// if (rgb_image)
// free(rgb_image);
rgb_image = stbi_load_from_memory(_buffer, len, &width, &height, &channels, 3);
bpp = channels;
// STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);
}
CImageBasis::CImageBasis(CImageBasis *_copyfrom, int _anzrepeat)
{
externalImage = false;
channels = _copyfrom->channels;
width = _copyfrom->width;
height = _copyfrom->height;
bpp = _copyfrom->bpp;
int memsize = width * height * channels;
rgb_image = (unsigned char*)GET_MEMORY(memsize);
int anz = 1;
TickType_t xDelay;
while (!rgb_image && (anz < _anzrepeat))
{
printf("Create Image from Copy - Speicher ist voll - Versuche es erneut: %d.\n", anz);
xDelay = 1000 / portTICK_PERIOD_MS;
rgb_image = (unsigned char*) malloc(memsize);
anz++;
}
if (!rgb_image)
{
printf(getESPHeapInfo().c_str());
printf("\nKein freier Speicher mehr!!!! Benötigt: %d %d %d %d\n", width, height, channels, memsize);
return;
}
memCopy(_copyfrom->rgb_image, rgb_image, memsize);
}
CImageBasis::CImageBasis(int _width, int _height, int _channels)
{
externalImage = false;
channels = _channels;
width = _width;
height = _height;
bpp = _channels;
int memsize = width * height * channels;
rgb_image = (unsigned char*)GET_MEMORY(memsize);
if (!rgb_image)
{
printf(getESPHeapInfo().c_str());
printf("\nKein freier Speicher mehr!!!! Benötigt: %d %d %d %d\n", width, height, channels, memsize);
return;
}
}
CImageBasis::CImageBasis(std::string _image)
{
channels = 3;
externalImage = false;
filename = _image;
long zwld = esp_get_free_heap_size();
printf("freeheapsize before: %ld\n", zwld);
rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels);
zwld = esp_get_free_heap_size();
printf("freeheapsize after : %ld\n", zwld);
std::string zw = "Image Load failed:" + _image + "\n";
if (rgb_image == NULL)
printf(zw.c_str());
zw = "CImageBasis after load " + _image + "\n";
printf(zw.c_str());
printf("w %d, h %d, b %d, c %d\n", width, height, bpp, channels);
}
bool CImageBasis::ImageOkay(){
return rgb_image != NULL;
}
CImageBasis::CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp)
{
rgb_image = _rgb_image;
channels = _channels;
width = _width;
height = _height;
bpp = _bpp;
externalImage = true;
}
void CImageBasis::Contrast(float _contrast) //input range [-100..100]
{
stbi_uc* p_source;
float contrast = (_contrast/100) + 1; //convert to decimal & shift range: [0..2]
float intercept = 128 * (1 - contrast);
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_source = rgb_image + (channels * (y * width + x));
for (int _channels = 0; _channels < channels; ++_channels)
p_source[_channels] = (uint8_t) std::min(255, std::max(0, (int) (p_source[_channels] * contrast + intercept)));
}
}
CImageBasis::~CImageBasis()
{
if (!externalImage)
stbi_image_free(rgb_image);
}
void CImageBasis::SaveToFile(std::string _imageout)
{
string typ = getFileType(_imageout);
if ((typ == "jpg") || (typ == "JPG")) // ACHTUNG PROBLEMATISCH IM ESP32
{
stbi_write_jpg(_imageout.c_str(), width, height, channels, rgb_image, 0);
}
if ((typ == "bmp") || (typ == "BMP"))
{
stbi_write_bmp(_imageout.c_str(), width, height, channels, rgb_image);
}
}
void CImageBasis::Resize(int _new_dx, int _new_dy)
{
int memsize = _new_dx * _new_dy * channels;
uint8_t* odata = (unsigned char*)GET_MEMORY(memsize);
stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels);
stbi_image_free(rgb_image);
rgb_image = (unsigned char*)GET_MEMORY(memsize);
memCopy(odata, rgb_image, memsize);
width = _new_dx;
height = _new_dy;
stbi_image_free(odata);
}
void CImageBasis::Resize(int _new_dx, int _new_dy, CImageBasis *_target)
{
if ((_target->height != _new_dy) || (_target->width != _new_dx) || (_target->channels != channels))
{
printf("CImageBasis::Resize - Targetbildgröße passt nicht !!!!!!!!!");
return;
}
uint8_t* odata = _target->rgb_image;
stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels);
}

View File

@@ -0,0 +1,88 @@
#pragma once
#ifndef __CIMAGEBASIS
#define __CIMAGEBASIS
#include <stdint.h>
#include <string>
#include <esp_http_server.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "stb_image.h"
#include "stb_image_write.h"
#include "stb_image_resize.h"
#include "esp_heap_caps.h"
//#define GET_MEMORY malloc
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
#define MAX_JPG_SIZE 128000
struct ImageData
{
uint8_t data[MAX_JPG_SIZE];
size_t size = 0;
};
class CImageBasis
{
protected:
bool externalImage;
std::string filename;
void memCopy(uint8_t* _source, uint8_t* _target, int _size);
bool isInImage(int x, int y);
public:
uint8_t* rgb_image;
int channels;
int width, height, bpp;
int getWidth(){return this->width;};
int getHeight(){return this->height;};
int getChannels(){return this->channels;};
void drawRect(int x, int y, int dx, int dy, int r = 255, int g = 255, int b = 255, int thickness = 1);
void drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness = 1);
void drawCircle(int x1, int y1, int rad, int r, int g, int b, int thickness = 1);
void setPixelColor(int x, int y, int r, int g, int b);
void Contrast(float _contrast);
bool ImageOkay();
bool CopyFromMemory(uint8_t* _source, int _size);
void SetIndepended(){externalImage = false;};
void CreateEmptyImage(int _width, int _height, int _channels);
CImageBasis();
CImageBasis(std::string _image);
CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp);
CImageBasis(int _width, int _height, int _channels);
CImageBasis(CImageBasis *_copyfrom, int _anzrepeat = 0);
void Resize(int _new_dx, int _new_dy);
void Resize(int _new_dx, int _new_dy, CImageBasis *_target);
void LoadFromMemory(stbi_uc *_buffer, int len);
ImageData* writeToMemoryAsJPG(const int quality = 90);
esp_err_t SendJPGtoHTTP(httpd_req_t *req, const int quality = 90);
uint8_t GetPixelColor(int x, int y, int ch);
~CImageBasis();
void SaveToFile(std::string _imageout);
};
#endif

View File

@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
idf_component_register(SRCS ${app_sources} idf_component_register(SRCS ${app_sources}
INCLUDE_DIRS "." INCLUDE_DIRS "."
REQUIRES jomjol_helper jomjol_logfile) REQUIRES jomjol_helper jomjol_logfile esp_http_server)

View File

@@ -0,0 +1,171 @@
#include "CRotateImage.h"
CRotateImage::CRotateImage(CImageBasis *_org, CImageBasis *_temp)
{
rgb_image = _org->rgb_image;
channels = _org->channels;
width = _org->width;
height = _org->height;
bpp = _org->bpp;
externalImage = true;
ImageTMP = _temp;
}
void CRotateImage::Mirror(){
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->rgb_image;
}
else
{
odata = (unsigned char*)GET_MEMORY(memsize);
}
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = width - x;
y_source = y;
p_source = rgb_image + (channels * (y_source * width + x_source));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
{
stbi_image_free(odata);
}
}
void CRotateImage::Rotate(float _angle, int _centerx, int _centery)
{
float m[2][3];
float x_center = _centerx;
float y_center = _centery;
_angle = _angle / 180 * M_PI;
m[0][0] = cos(_angle);
m[0][1] = sin(_angle);
m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center;
m[1][0] = -m[0][1];
m[1][1] = m[0][0];
m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center;
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->rgb_image;
}
else
{
odata = (unsigned char*)GET_MEMORY(memsize);
}
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = int(m[0][0] * x + m[0][1] * y);
y_source = int(m[1][0] * x + m[1][1] * y);
x_source += int(m[0][2]);
y_source += int(m[1][2]);
if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height))
{
p_source = rgb_image + (channels * (y_source * width + x_source));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
else
{
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = 255;
}
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
{
stbi_image_free(odata);
}
}
void CRotateImage::Rotate(float _angle)
{
// printf("width %d, height %d\n", width, height);
Rotate(_angle, width / 2, height / 2);
}
void CRotateImage::Translate(int _dx, int _dy)
{
int memsize = width * height * channels;
uint8_t* odata;
if (ImageTMP)
{
odata = ImageTMP->rgb_image;
}
else
{
odata = (unsigned char*)GET_MEMORY(memsize);
}
int x_source, y_source;
stbi_uc* p_target;
stbi_uc* p_source;
for (int x = 0; x < width; ++x)
for (int y = 0; y < height; ++y)
{
p_target = odata + (channels * (y * width + x));
x_source = x - _dx;
y_source = y - _dy;
if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height))
{
p_source = rgb_image + (channels * (y_source * width + x_source));
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = p_source[_channels];
}
else
{
for (int _channels = 0; _channels < channels; ++_channels)
p_target[_channels] = 255;
}
}
// memcpy(rgb_image, odata, memsize);
memCopy(odata, rgb_image, memsize);
if (!ImageTMP)
{
stbi_image_free(odata);
}
}

View File

@@ -0,0 +1,16 @@
#include "CImageBasis.h"
class CRotateImage: public CImageBasis
{
public:
CImageBasis *ImageTMP;
CRotateImage(std::string _image) : CImageBasis(_image) {ImageTMP = NULL;};
CRotateImage(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL;};
CRotateImage(CImageBasis *_org, CImageBasis *_temp);
void Rotate(float _angle);
void Rotate(float _angle, int _centerx, int _centery);
void Translate(int _dx, int _dy);
void Mirror();
};

View File

@@ -10,6 +10,48 @@ static const char *TAG = "log";
ClassLogFile LogFile("/sdcard/log/message", "log_%Y-%m-%d.txt"); ClassLogFile LogFile("/sdcard/log/message", "log_%Y-%m-%d.txt");
void ClassLogFile::WriteHeapInfo(std::string _id)
{
std::string _zw;
_zw = "\t" + _id + "\t" + getESPHeapInfo();
WriteToFile(_zw);
}
std::string ClassLogFile::getESPHeapInfo(){
string espInfoResultStr = "";
char aMsgBuf[80];
multi_heap_info_t aMultiHead_info ;
heap_caps_get_info (&aMultiHead_info,MALLOC_CAP_8BIT);
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t aMinFreeHeadSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
sprintf(aMsgBuf,"Free Heap Size: \t%ld", (long) aFreeHeapSize);
size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_SPIRAM);
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
sprintf(aMsgBuf,"\tHeap:\t%ld", (long) aFreeHeapSize);
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf,"\tMin Free:\t%ld", (long) aMinFreeHeapSize);
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf,"\tlarg. Block: \t%ld", (long) aHeapLargestFreeBlockSize);
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf,"\tSPI Heap:\t%ld", (long) aFreeSPIHeapSize);
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf,"\tMin Free Heap Size:\t%ld", (long) aMinFreeHeadSize);
sprintf(aMsgBuf,"\tNOT_SPI Heap:\t%ld", (long) (aFreeHeapSize - aFreeSPIHeapSize));
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf,"\tlargest Block Size: \t%ld", (long) aHeapLargestFreeBlockSize);
sprintf(aMsgBuf,"\tInternal Heap:\t%ld", (long) (aFreeInternalHeapSize));
espInfoResultStr += string(aMsgBuf);
sprintf(aMsgBuf,"\tInternal Min Heap free:\t%ld", (long) (aMinFreeInternalHeapSize));
espInfoResultStr += string(aMsgBuf);
return espInfoResultStr;
}
void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool _time) void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool _time)
{ {
FILE* pFile; FILE* pFile;
@@ -19,7 +61,9 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool
return; return;
} }
pFile = OpenFileAndWait(_fn.c_str(), "a+"); // pFile = OpenFileAndWait(_fn.c_str(), "a");
pFile = fopen(_fn.c_str(), "a+");
printf("Logfile opened: %s\n", _fn.c_str());
if (pFile!=NULL) { if (pFile!=NULL) {
if (_time) if (_time)
@@ -55,6 +99,7 @@ void ClassLogFile::SetRetention(unsigned short _retentionInDays){
void ClassLogFile::WriteToFile(std::string info, bool _time) void ClassLogFile::WriteToFile(std::string info, bool _time)
{ {
/*
struct stat path_stat; struct stat path_stat;
if (stat(logroot.c_str(), &path_stat) != 0) { if (stat(logroot.c_str(), &path_stat) != 0) {
ESP_LOGI(TAG, "Create log folder: %s", logroot.c_str()); ESP_LOGI(TAG, "Create log folder: %s", logroot.c_str());
@@ -62,7 +107,7 @@ void ClassLogFile::WriteToFile(std::string info, bool _time)
ESP_LOGI(TAG, "Can't create log foolder"); ESP_LOGI(TAG, "Can't create log foolder");
} }
} }
*/
time_t rawtime; time_t rawtime;
struct tm* timeinfo; struct tm* timeinfo;
char buffer[30]; char buffer[30];
@@ -80,12 +125,12 @@ std::string ClassLogFile::GetCurrentFileName()
{ {
time_t rawtime; time_t rawtime;
struct tm* timeinfo; struct tm* timeinfo;
char buffer[30]; char buffer[60];
time(&rawtime); time(&rawtime);
timeinfo = localtime(&rawtime); timeinfo = localtime(&rawtime);
strftime(buffer, 30, logfile.c_str(), timeinfo); strftime(buffer, 60, logfile.c_str(), timeinfo);
std::string logpath = logroot + "/" + buffer; std::string logpath = logroot + "/" + buffer;
return logpath; return logpath;

View File

@@ -12,6 +12,10 @@ private:
public: public:
ClassLogFile(std::string _logpath, std::string _logfile); ClassLogFile(std::string _logpath, std::string _logfile);
std::string getESPHeapInfo();
void WriteHeapInfo(std::string _id);
void SwitchOnOff(bool _doLogFile); void SwitchOnOff(bool _doLogFile);
void SetRetention(unsigned short _retentionInDays); void SetRetention(unsigned short _retentionInDays);

View File

@@ -1,9 +1,8 @@
#include "CTfLiteClass.h" #include "CTfLiteClass.h"
#include "bitmap_image.hpp" // #include "bitmap_image.hpp"
#include "ClassLogFile.h" #include "ClassLogFile.h"
#include "Helper.h" #include "Helper.h"
#include <sys/stat.h> #include <sys/stat.h>
@@ -21,19 +20,16 @@ float CTfLiteClass::GetOutputValue(int nr)
return output2->data.f[nr]; return output2->data.f[nr];
} }
int CTfLiteClass::GetClassFromImageBasis(CImageBasis *rs)
int CTfLiteClass::GetClassFromImage(std::string _fn)
{ {
// printf("Before Load image %s\n", _fn.c_str()); // printf("Before Load image %s\n", _fn.c_str());
if (!LoadInputImage(_fn)) if (!LoadInputImageBasis(rs))
return -1000; return -1000;
// printf("After Load image %s\n", _fn.c_str());
Invoke(); Invoke();
printf("After Invoke %s\n", _fn.c_str()); printf("After Invoke \n");
return GetOutClassification(); return GetOutClassification();
// return 0;
} }
int CTfLiteClass::GetOutClassification() int CTfLiteClass::GetOutClassification()
@@ -113,17 +109,14 @@ void CTfLiteClass::Invoke()
} }
bool CTfLiteClass::LoadInputImage(std::string _fn)
bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs)
{ {
std::string zw = "ClassFlowAnalog::doNeuralNetwork nach Load Image: " + _fn; std::string zw = "ClassFlowAnalog::doNeuralNetwork nach LoadInputResizeImage: ";
// LogFile.WriteToFile(zw);
bitmap_image image(_fn);
if (debugdetailtflite) LogFile.WriteToFile(zw);
unsigned int w = image.width(); unsigned int w = rs->width;
unsigned int h = image.height(); unsigned int h = rs->height;
unsigned char red, green, blue; unsigned char red, green, blue;
// printf("Image: %s size: %d x %d\n", _fn.c_str(), w, h); // printf("Image: %s size: %d x %d\n", _fn.c_str(), w, h);
input_i = 0; input_i = 0;
@@ -132,18 +125,15 @@ bool CTfLiteClass::LoadInputImage(std::string _fn)
for (int y = 0; y < h; ++y) for (int y = 0; y < h; ++y)
for (int x = 0; x < w; ++x) for (int x = 0; x < w; ++x)
{ {
red = image.red_channel(x, y); red = rs->GetPixelColor(x, y, 0);
green = image.green_channel(x, y); green = rs->GetPixelColor(x, y, 1);
blue = image.blue_channel(x, y); blue = rs->GetPixelColor(x, y, 2);
*(input_data_ptr) = (float) red; *(input_data_ptr) = (float) red;
input_data_ptr++; input_data_ptr++;
*(input_data_ptr) = (float) green; *(input_data_ptr) = (float) green;
input_data_ptr++; input_data_ptr++;
*(input_data_ptr) = (float) blue; *(input_data_ptr) = (float) blue;
input_data_ptr++; input_data_ptr++;
// printf("BMP: %f %f %f\n", (float) red, (float) green, (float) blue);
} }
if (debugdetailtflite) LogFile.WriteToFile("Nach dem Laden in input"); if (debugdetailtflite) LogFile.WriteToFile("Nach dem Laden in input");
@@ -154,7 +144,6 @@ bool CTfLiteClass::LoadInputImage(std::string _fn)
void CTfLiteClass::MakeAllocate() void CTfLiteClass::MakeAllocate()
{ {
// static tflite::ops::micro::AllOpsResolver resolver;
static tflite::AllOpsResolver resolver; static tflite::AllOpsResolver resolver;
this->interpreter = new tflite::MicroInterpreter(this->model, resolver, this->tensor_arena, this->kTensorArenaSize, this->error_reporter); this->interpreter = new tflite::MicroInterpreter(this->model, resolver, this->tensor_arena, this->kTensorArenaSize, this->error_reporter);
@@ -164,7 +153,6 @@ void CTfLiteClass::MakeAllocate()
this->GetInputDimension(); this->GetInputDimension();
return; return;
} }
// printf("Allocate Done.\n"); // printf("Allocate Done.\n");
} }
@@ -172,8 +160,6 @@ void CTfLiteClass::GetInputTensorSize(){
float *zw = this->input; float *zw = this->input;
int test = sizeof(zw); int test = sizeof(zw);
printf("Input Tensor Dimension: %d\n", test); printf("Input Tensor Dimension: %d\n", test);
printf("Input Tensor Dimension: %d\n", test);
} }
long CTfLiteClass::GetFileSize(std::string filename) long CTfLiteClass::GetFileSize(std::string filename)
@@ -188,7 +174,7 @@ unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn)
{ {
long size; long size;
size = this->GetFileSize(_fn); size = GetFileSize(_fn);
if (size == -1) if (size == -1)
{ {
@@ -196,16 +182,25 @@ unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn)
return NULL; return NULL;
} }
unsigned char *result = (unsigned char*) malloc(size); unsigned char *result = (unsigned char*) malloc(size);
int anz = 1;
TickType_t xDelay;
while (!result && (anz < 6)) // maximal 5x versuchen (= 5s)
{
printf("Speicher ist voll - Versuche es erneut: %d.\n", anz);
xDelay = 1000 / portTICK_PERIOD_MS;
result = (unsigned char*) malloc(size);
anz++;
}
if(result != NULL) { if(result != NULL) {
// printf("\nSpeicher ist reserviert\n"); // printf("\nSpeicher ist reserviert\n");
FILE* f = OpenFileAndWait(_fn.c_str(), "rb"); // vorher nur "r" FILE* f = OpenFileAndWait(_fn.c_str(), "rb"); // vorher nur "r"
fread(result, 1, size, f); fread(result, 1, size, f);
fclose(f); fclose(f);
}else { }else {
printf("\nKein freier Speicher vorhanden.\n"); printf("\nKein freier Speicher vorhanden.\n");
} }
@@ -221,14 +216,11 @@ void CTfLiteClass::LoadModel(std::string _fn){
#endif #endif
unsigned char *rd; unsigned char *rd;
rd = this->ReadFileToCharArray(_fn.c_str()); rd = ReadFileToCharArray(_fn.c_str());
// printf("loadedfile: %d", (int) rd);
this->model = tflite::GetModel(rd); this->model = tflite::GetModel(rd);
free(rd); free(rd);
TFLITE_MINIMAL_CHECK(model != nullptr); TFLITE_MINIMAL_CHECK(model != nullptr);
// printf("tfile Loaded.\n");
} }
@@ -239,7 +231,7 @@ CTfLiteClass::CTfLiteClass()
this->interpreter = nullptr; this->interpreter = nullptr;
this->input = nullptr; this->input = nullptr;
this->output = nullptr; this->output = nullptr;
this->kTensorArenaSize = 600 * 1024; this->kTensorArenaSize = 150 * 1024; /// laut testfile: 108000 - bisher 600
this->tensor_arena = new uint8_t[kTensorArenaSize]; this->tensor_arena = new uint8_t[kTensorArenaSize];
} }
@@ -257,6 +249,6 @@ namespace tflite {
return 0; return 0;
} }
} // namespace tflite }

View File

@@ -14,6 +14,8 @@
#include "esp_err.h" #include "esp_err.h"
#include "esp_log.h" #include "esp_log.h"
#include "CImageBasis.h"
#define SUPRESS_TFLITE_ERRORS // use, to avoid error messages from TFLITE #define SUPRESS_TFLITE_ERRORS // use, to avoid error messages from TFLITE
@@ -39,7 +41,6 @@ class CTfLiteClass
const tflite::Model* model; const tflite::Model* model;
tflite::MicroInterpreter* interpreter; tflite::MicroInterpreter* interpreter;
TfLiteTensor* output = nullptr; TfLiteTensor* output = nullptr;
// static tflite::ops::micro::AllOpsResolver *resolver;
static tflite::AllOpsResolver resolver; static tflite::AllOpsResolver resolver;
int kTensorArenaSize; int kTensorArenaSize;
@@ -58,11 +59,11 @@ class CTfLiteClass
void LoadModel(std::string _fn); void LoadModel(std::string _fn);
void MakeAllocate(); void MakeAllocate();
void GetInputTensorSize(); void GetInputTensorSize();
bool LoadInputImage(std::string _fn); bool LoadInputImageBasis(CImageBasis *rs);
void Invoke(); void Invoke();
void GetOutPut(); void GetOutPut();
int GetOutClassification(); int GetOutClassification();
int GetClassFromImage(std::string _fn); int GetClassFromImageBasis(CImageBasis *rs);
float GetOutputValue(int nr); float GetOutputValue(int nr);
void GetInputDimension(bool silent); void GetInputDimension(bool silent);

View File

@@ -24,11 +24,32 @@ TaskHandle_t xHandleblink_task_doFlow = NULL;
TaskHandle_t xHandletask_autodoFlow = NULL; TaskHandle_t xHandletask_autodoFlow = NULL;
bool flowisrunning = false; bool flowisrunning = false;
long auto_intervall = 0; long auto_intervall = 0;
bool auto_isrunning = false; bool auto_isrunning = false;
int countRounds = 0;
int getCountFlowRounds() {
return countRounds;
}
esp_err_t GetJPG(std::string _filename, httpd_req_t *req)
{
return tfliteflow.GetJPGStream(_filename, req);
}
esp_err_t GetRawJPG(httpd_req_t *req)
{
return tfliteflow.SendRawJPG(req);
}
bool isSetupModusActive() { bool isSetupModusActive() {
return tfliteflow.getStatusSetupModus(); return tfliteflow.getStatusSetupModus();
return false; return false;
@@ -91,6 +112,8 @@ void blink_task_doFlow(void *pvParameter)
esp_err_t handler_init(httpd_req_t *req) esp_err_t handler_init(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_init - Start");
LogFile.WriteToFile("handler_init"); LogFile.WriteToFile("handler_init");
printf("handler_doinit uri:\n"); printf(req->uri); printf("\n"); printf("handler_doinit uri:\n"); printf(req->uri); printf("\n");
@@ -104,11 +127,15 @@ esp_err_t handler_init(httpd_req_t *req)
/* Respond with an empty chunk to signal HTTP response completion */ /* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0); httpd_resp_send_chunk(req, NULL, 0);
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_init - Done");
return ESP_OK; return ESP_OK;
}; };
esp_err_t handler_doflow(httpd_req_t *req) esp_err_t handler_doflow(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_doflow - Start");
LogFile.WriteToFile("handler_doflow"); LogFile.WriteToFile("handler_doflow");
char* resp_str; char* resp_str;
@@ -127,7 +154,9 @@ esp_err_t handler_doflow(httpd_req_t *req)
resp_str = "doFlow gestartet - dauert ca. 60 Sekunden"; resp_str = "doFlow gestartet - dauert ca. 60 Sekunden";
httpd_resp_send(req, resp_str, strlen(resp_str)); httpd_resp_send(req, resp_str, strlen(resp_str));
/* Respond with an empty chunk to signal HTTP response completion */ /* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0); httpd_resp_send_chunk(req, NULL, 0);
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_doflow - Done");
return ESP_OK; return ESP_OK;
}; };
@@ -136,6 +165,8 @@ esp_err_t handler_doflow(httpd_req_t *req)
esp_err_t handler_wasserzaehler(httpd_req_t *req) esp_err_t handler_wasserzaehler(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_wasserzaehler - Start");
LogFile.WriteToFile("handler_wasserzaehler"); LogFile.WriteToFile("handler_wasserzaehler");
bool _rawValue = false; bool _rawValue = false;
bool _noerror = false; bool _noerror = false;
@@ -171,7 +202,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
{ {
string txt, zw; string txt, zw;
txt = "<p>Aligned Image: <p><img src=\"/img_tmp/alg.jpg\"> <p>\n"; txt = "<p>Aligned Image: <p><img src=\"/img_tmp/alg_roi.jpg\"> <p>\n";
txt = txt + "Digital Counter: <p> "; txt = txt + "Digital Counter: <p> ";
httpd_resp_sendstr_chunk(req, txt.c_str()); httpd_resp_sendstr_chunk(req, txt.c_str());
@@ -205,7 +236,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
httpd_resp_sendstr_chunk(req, txt.c_str()); httpd_resp_sendstr_chunk(req, txt.c_str());
delete htmlinfo[i]; delete htmlinfo[i];
} }
htmlinfo.clear(); htmlinfo.clear();
} }
@@ -217,12 +248,15 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
/* Respond with an empty chunk to signal HTTP response completion */ /* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_sendstr_chunk(req, NULL); httpd_resp_sendstr_chunk(req, NULL);
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_wasserzaehler - Done");
return ESP_OK; return ESP_OK;
}; };
esp_err_t handler_editflow(httpd_req_t *req) esp_err_t handler_editflow(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_editflow - Start");
LogFile.WriteToFile("handler_editflow"); LogFile.WriteToFile("handler_editflow");
printf("handler_editflow uri: "); printf(req->uri); printf("\n"); printf("handler_editflow uri: "); printf(req->uri); printf("\n");
@@ -324,6 +358,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
zw = "CutImage Done"; zw = "CutImage Done";
httpd_resp_sendstr_chunk(req, zw.c_str()); httpd_resp_sendstr_chunk(req, zw.c_str());
} }
if (_task.compare("test_take") == 0) if (_task.compare("test_take") == 0)
@@ -378,6 +413,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
/* Respond with an empty chunk to signal HTTP response completion */ /* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_sendstr_chunk(req, NULL); httpd_resp_sendstr_chunk(req, NULL);
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_editflow - Done");
return ESP_OK; return ESP_OK;
}; };
@@ -385,6 +421,8 @@ esp_err_t handler_editflow(httpd_req_t *req)
esp_err_t handler_prevalue(httpd_req_t *req) esp_err_t handler_prevalue(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_prevalue - Start");
LogFile.WriteToFile("handler_prevalue"); LogFile.WriteToFile("handler_prevalue");
const char* resp_str; const char* resp_str;
string zw; string zw;
@@ -414,6 +452,8 @@ esp_err_t handler_prevalue(httpd_req_t *req)
/* Respond with an empty chunk to signal HTTP response completion */ /* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0); httpd_resp_send_chunk(req, NULL, 0);
if (debug_detail_heap) LogFile.WriteHeapInfo("handler_prevalue - Start");
return ESP_OK; return ESP_OK;
}; };
@@ -434,7 +474,8 @@ void task_autodoFlow(void *pvParameter)
while (auto_isrunning) while (auto_isrunning)
{ {
LogFile.WriteToFile("task_autodoFlow - next round"); std::string _zw = "task_autodoFlow - next round - Round #" + std::to_string(++countRounds);
LogFile.WriteToFile(_zw);
printf("Autoflow: start\n"); printf("Autoflow: start\n");
fr_start = esp_timer_get_time(); fr_start = esp_timer_get_time();

View File

@@ -1,6 +1,7 @@
#include <esp_log.h> #include <esp_log.h>
#include <esp_http_server.h> #include <esp_http_server.h>
#include "CImageBasis.h"
//#include "ClassControllCamera.h" //#include "ClassControllCamera.h"
@@ -12,4 +13,10 @@ void KillTFliteTasks();
void TFliteDoAutoStart(); void TFliteDoAutoStart();
bool isSetupModusActive(); bool isSetupModusActive();
esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
esp_err_t GetRawJPG(httpd_req_t *req);
extern bool debug_detail_heap;

View File

@@ -1,11 +1,5 @@
#include "time_sntp.h" #include "time_sntp.h"
/* LwIP SNTP example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string> #include <string>
#include <time.h> #include <time.h>
#include <sys/time.h> #include <sys/time.h>
@@ -17,25 +11,19 @@
#include "esp_log.h" #include "esp_log.h"
#include "esp_attr.h" #include "esp_attr.h"
#include "esp_sleep.h" #include "esp_sleep.h"
// #include "nvs_flash.h"
// #include "protocol_examples_common.h"
#include "esp_sntp.h" #include "esp_sntp.h"
#include "ClassLogFile.h" #include "ClassLogFile.h"
static const char *TAG = "sntp"; static const char *TAG = "sntp";
RTC_DATA_ATTR int boot_count = 0;
bool setTimeAlwaysOnReboot = true; bool setTimeAlwaysOnReboot = true;
static void obtain_time(void); static void obtain_time(void);
static void initialize_sntp(void); static void initialize_sntp(void);
void time_sync_notification_cb(struct timeval *tv) void time_sync_notification_cb(struct timeval *tv)
{ {
// LogFile.WriteToFile("Notification of a time synchronization event");
ESP_LOGI(TAG, "Notification of a time synchronization event"); ESP_LOGI(TAG, "Notification of a time synchronization event");
} }
@@ -54,9 +42,6 @@ std::string gettimestring(const char * frm)
void setup_time() void setup_time()
{ {
++boot_count;
ESP_LOGI(TAG, "Boot count: %d", boot_count);
time_t now; time_t now;
struct tm timeinfo; struct tm timeinfo;
time(&now); time(&now);
@@ -72,8 +57,6 @@ void setup_time()
char strftime_buf[64]; char strftime_buf[64];
setTimeZone("CET-1CEST,M3.5.0,M10.5.0/3"); setTimeZone("CET-1CEST,M3.5.0,M10.5.0/3");
// setTimeZone("Europe/Berlin");
// setTimeZone("Asia/Tokyo");
localtime_r(&now, &timeinfo); localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
@@ -97,9 +80,6 @@ void setTimeZone(std::string _tzstring)
static void obtain_time(void) static void obtain_time(void)
{ {
// initialize_sntp();
// wait for time to be set
time_t now = 0; time_t now = 0;
struct tm timeinfo = {}; struct tm timeinfo = {};
int retry = 0; int retry = 0;
@@ -110,18 +90,23 @@ static void obtain_time(void)
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count); ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
vTaskDelay(2000 / portTICK_PERIOD_MS); vTaskDelay(2000 / portTICK_PERIOD_MS);
} }
if (retry == retry_count) {
// LogFile.WriteToFile("Time Synchzronisation nicht erfolgreich ...");
}
else
{
// LogFile.WriteToFile("Time erfolgreich ...");
}
time(&now); time(&now);
localtime_r(&now, &timeinfo); localtime_r(&now, &timeinfo);
} }
void reset_servername(std::string _servername)
{
printf("Set SNTP-Server: %s\n", _servername.c_str());
sntp_stop();
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, _servername.c_str());
sntp_init();
obtain_time();
std::string zw = gettimestring("%Y%m%d-%H%M%S");
printf("Time ist %s\n", zw.c_str());
}
static void initialize_sntp(void) static void initialize_sntp(void)
{ {
ESP_LOGI(TAG, "Initializing SNTP"); ESP_LOGI(TAG, "Initializing SNTP");

View File

@@ -15,4 +15,5 @@
void setup_time(void); void setup_time(void);
std::string gettimestring(const char * frm); std::string gettimestring(const char * frm);
void setTimeZone(std::string _tzstring); void setTimeZone(std::string _tzstring);
void reset_servername(std::string _servername);

View File

@@ -28,6 +28,9 @@
static const char *TAGMAIN = "connect_wlan_main"; static const char *TAGMAIN = "connect_wlan_main";
bool debug_detail_heap = false;
#define FLASH_GPIO GPIO_NUM_4 #define FLASH_GPIO GPIO_NUM_4
void Init_NVS_SDCard() void Init_NVS_SDCard()
@@ -44,10 +47,15 @@ void Init_NVS_SDCard()
// sdmmc_host_t host = SDMMC_HOST_SLOT_1(); // sdmmc_host_t host = SDMMC_HOST_SLOT_1();
// host.flags = SDMMC_HOST_FLAG_1BIT; // host.flags = SDMMC_HOST_FLAG_1BIT;
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
slot_config.width = 1; // 1 line SD mode
esp_vfs_fat_sdmmc_mount_config_t mount_config = { }; esp_vfs_fat_sdmmc_mount_config_t mount_config = { };
mount_config.format_if_mount_failed = false; mount_config.format_if_mount_failed = false;
mount_config.max_files = 5; mount_config.max_files = 5;
gpio_set_pull_mode((gpio_num_t) 15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes
gpio_set_pull_mode((gpio_num_t) 2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes
sdmmc_card_t* card; sdmmc_card_t* card;
ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) { if (ret != ESP_OK) {
@@ -116,7 +124,9 @@ extern "C" void app_main(void)
vTaskDelay( xDelay ); vTaskDelay( xDelay );
// LogFile.WriteToFile("Startsequence 07"); // LogFile.WriteToFile("Startsequence 07");
setup_time(); setup_time();
LogFile.WriteToFile("============================== Main Started ======================================="); LogFile.WriteToFile("=============================================================================================");
LogFile.WriteToFile("=================================== Main Started ============================================");
LogFile.WriteToFile("=============================================================================================");
LogFile.SwitchOnOff(false); LogFile.SwitchOnOff(false);
std::string zw = gettimestring("%Y%m%d-%H%M%S"); std::string zw = gettimestring("%Y%m%d-%H%M%S");

View File

@@ -18,13 +18,14 @@
httpd_handle_t server = NULL; httpd_handle_t server = NULL;
std::string starttime = ""; std::string starttime = "";
/* An HTTP GET handler */ /* An HTTP GET handler */
esp_err_t info_get_handler(httpd_req_t *req) esp_err_t info_get_handler(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("info_get_handler - Start");
LogFile.WriteToFile("info_get_handler"); LogFile.WriteToFile("info_get_handler");
char _query[200]; char _query[200];
char _valuechar[30]; char _valuechar[30];
@@ -125,25 +126,31 @@ esp_err_t info_get_handler(httpd_req_t *req)
return ESP_OK; return ESP_OK;
} }
if (debug_detail_heap) LogFile.WriteHeapInfo("info_get_handler - Done");
return ESP_OK; return ESP_OK;
} }
esp_err_t starttime_get_handler(httpd_req_t *req) esp_err_t starttime_get_handler(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("starttime_get_handler - Start");
httpd_resp_send(req, starttime.c_str(), strlen(starttime.c_str())); httpd_resp_send(req, starttime.c_str(), strlen(starttime.c_str()));
/* Respond with an empty chunk to signal HTTP response completion */ /* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0); httpd_resp_send_chunk(req, NULL, 0);
if (debug_detail_heap) LogFile.WriteHeapInfo("starttime_get_handler - Done");
return ESP_OK; return ESP_OK;
} }
esp_err_t hello_main_handler(httpd_req_t *req) esp_err_t hello_main_handler(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("hello_main_handler - Start");
char filepath[50]; char filepath[50];
struct stat file_stat;
printf("uri: %s\n", req->uri); printf("uri: %s\n", req->uri);
int _pos; int _pos;
esp_err_t res;
char *base_path = (char*) req->user_ctx; char *base_path = (char*) req->user_ctx;
std::string filetosend(base_path); std::string filetosend(base_path);
@@ -182,60 +189,35 @@ esp_err_t hello_main_handler(httpd_req_t *req)
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long"); httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
return ESP_FAIL; return ESP_FAIL;
} }
if (stat(filetosend.c_str(), &file_stat) == -1) {
/* If file not present on SPIFFS check if URI
* corresponds to one of the hardcoded paths */
ESP_LOGE(TAG, "Failed to stat file : %s", filetosend.c_str());
/* Respond with 404 Not Found */
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
return ESP_FAIL;
}
esp_err_t res;
res = httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
if (res != ESP_OK)
return res;
res = send_file(req, filetosend, &file_stat); res = send_file(req, filetosend);
if (res != ESP_OK) if (res != ESP_OK)
return res; return res;
/* Respond with an empty chunk to signal HTTP response completion */ /* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0); httpd_resp_send_chunk(req, NULL, 0);
if (debug_detail_heap) LogFile.WriteHeapInfo("hello_main_handler - Stop");
return ESP_OK; return ESP_OK;
} }
esp_err_t img_tmp_handler(httpd_req_t *req) esp_err_t img_tmp_handler(httpd_req_t *req)
{ {
char filepath[50]; char filepath[50];
struct stat file_stat;
printf("uri: %s\n", req->uri); printf("uri: %s\n", req->uri);
char *base_path = (char*) req->user_ctx; char *base_path = (char*) req->user_ctx;
std::string filetosend(base_path); std::string filetosend(base_path);
const char *filename = get_path_from_uri(filepath, base_path, const char *filename = get_path_from_uri(filepath, base_path,
req->uri + sizeof("/img_tmp") - 1, sizeof(filepath)); req->uri + sizeof("/img_tmp/") - 1, sizeof(filepath));
printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath); printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
filetosend = filetosend + "/img_tmp/" + std::string(filename); filetosend = filetosend + "/img_tmp/" + std::string(filename);
printf("File to upload: %s\n", filetosend.c_str()); printf("File to upload: %s\n", filetosend.c_str());
if (!filename) { esp_err_t res = send_file(req, filetosend);
ESP_LOGE(TAG, "Filename is too long");
/* Respond with 500 Internal Server Error */
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
return ESP_FAIL;
}
if (stat(filetosend.c_str(), &file_stat) == -1) {
/* If file not present on SPIFFS check if URI
* corresponds to one of the hardcoded paths */
ESP_LOGE(TAG, "Failed to stat file : %s", filetosend.c_str());
/* Respond with 404 Not Found */
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
return ESP_FAIL;
}
esp_err_t res = send_file(req, filetosend, &file_stat);
if (res != ESP_OK) if (res != ESP_OK)
return res; return res;
@@ -244,8 +226,47 @@ esp_err_t img_tmp_handler(httpd_req_t *req)
return ESP_OK; return ESP_OK;
} }
esp_err_t img_tmp_virtual_handler(httpd_req_t *req)
{
if (debug_detail_heap) LogFile.WriteHeapInfo("img_tmp_virtual_handler - Start");
char filepath[50];
printf("uri: %s\n", req->uri);
char *base_path = (char*) req->user_ctx;
std::string filetosend(base_path);
const char *filename = get_path_from_uri(filepath, base_path,
req->uri + sizeof("/img_tmp/") - 1, sizeof(filepath));
printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
filetosend = std::string(filename);
printf("File to upload: %s\n", filetosend.c_str());
if (filetosend == "raw.jpg")
{
return GetRawJPG(req);
}
esp_err_t zw = GetJPG(filetosend, req);
if (zw == ESP_OK)
return ESP_OK;
// File wird nicht intern bereit gestellt --> klassischer weg:
if (debug_detail_heap) LogFile.WriteHeapInfo("img_tmp_virtual_handler - Done");
return img_tmp_handler(req);
}
esp_err_t sysinfo_handler(httpd_req_t *req) esp_err_t sysinfo_handler(httpd_req_t *req)
{ {
if (debug_detail_heap) LogFile.WriteHeapInfo("sysinfo_handler - Start");
const char* resp_str; const char* resp_str;
std::string zw; std::string zw;
std::string cputemp = std::to_string(temperatureRead()); std::string cputemp = std::to_string(temperatureRead());
@@ -279,7 +300,9 @@ esp_err_t sysinfo_handler(httpd_req_t *req)
httpd_resp_set_type(req, "application/json"); httpd_resp_set_type(req, "application/json");
httpd_resp_send(req, resp_str, strlen(resp_str)); httpd_resp_send(req, resp_str, strlen(resp_str));
/* Respond with an empty chunk to signal HTTP response completion */ /* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_send_chunk(req, NULL, 0); httpd_resp_send_chunk(req, NULL, 0);
if (debug_detail_heap) LogFile.WriteHeapInfo("sysinfo_handler - Done");
return ESP_OK; return ESP_OK;
} }
@@ -314,7 +337,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t img_tmp_handle = { httpd_uri_t img_tmp_handle = {
.uri = "/img_tmp/*", // Match all URIs of type /path/to/file .uri = "/img_tmp/*", // Match all URIs of type /path/to/file
.method = HTTP_GET, .method = HTTP_GET,
.handler = img_tmp_handler, .handler = img_tmp_virtual_handler,
.user_ctx = (void*) base_path // Pass server data as context .user_ctx = (void*) base_path // Pass server data as context
}; };
httpd_register_uri_handler(server, &img_tmp_handle); httpd_register_uri_handler(server, &img_tmp_handle);

View File

@@ -22,9 +22,7 @@ httpd_handle_t start_webserver(void);
void register_server_main_uri(httpd_handle_t server, const char *base_path); void register_server_main_uri(httpd_handle_t server, const char *base_path);
extern bool debug_detail_heap;
//void disconnect_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
//void connect_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data);
#endif #endif

View File

@@ -1,4 +1,4 @@
const char* GIT_REV="793f928"; const char* GIT_REV="6e521f0";
const char* GIT_TAG=""; const char* GIT_TAG="";
const char* GIT_BRANCH="rolling"; const char* GIT_BRANCH="rolling-reduce-sd-use";
const char* BUILD_TIME="2020-12-07 20:40"; const char* BUILD_TIME="2020-12-28 15:38";

View File

@@ -537,8 +537,8 @@ CONFIG_FATFS_MAX_LFN=255
CONFIG_FATFS_API_ENCODING_ANSI_OEM=y CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
# CONFIG_FATFS_API_ENCODING_UTF_16 is not set # CONFIG_FATFS_API_ENCODING_UTF_16 is not set
# CONFIG_FATFS_API_ENCODING_UTF_8 is not set # CONFIG_FATFS_API_ENCODING_UTF_8 is not set
CONFIG_FATFS_FS_LOCK=5 CONFIG_FATFS_FS_LOCK=10
CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_TIMEOUT_MS=5000
CONFIG_FATFS_PER_FILE_CACHE=y CONFIG_FATFS_PER_FILE_CACHE=y
CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y
# end of FAT Filesystem support # end of FAT Filesystem support
@@ -965,7 +965,7 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
# #
# Virtual file system # Virtual file system
# #
CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y # CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT is not set
CONFIG_VFS_SUPPORT_TERMIOS=y CONFIG_VFS_SUPPORT_TERMIOS=y
# #
@@ -1166,6 +1166,6 @@ CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y
# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set
# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set
CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y # CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT is not set
CONFIG_SUPPORT_TERMIOS=y CONFIG_SUPPORT_TERMIOS=y
# End of deprecated options # End of deprecated options

View File

@@ -83,11 +83,11 @@ CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
CONFIG_ESPTOOLPY_FLASHFREQ="40m" CONFIG_ESPTOOLPY_FLASHFREQ="40m"
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y # CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE="2MB" CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_BEFORE_RESET=y CONFIG_ESPTOOLPY_BEFORE_RESET=y
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
@@ -315,8 +315,8 @@ CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y
CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4
# CONFIG_ESP32_ULP_COPROC_ENABLED is not set # CONFIG_ESP32_ULP_COPROC_ENABLED is not set
CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0
# CONFIG_ESP32_PANIC_PRINT_HALT is not set CONFIG_ESP32_PANIC_PRINT_HALT=y
CONFIG_ESP32_PANIC_PRINT_REBOOT=y # CONFIG_ESP32_PANIC_PRINT_REBOOT is not set
# CONFIG_ESP32_PANIC_SILENT_REBOOT is not set # CONFIG_ESP32_PANIC_SILENT_REBOOT is not set
# CONFIG_ESP32_PANIC_GDBSTUB is not set # CONFIG_ESP32_PANIC_GDBSTUB is not set
CONFIG_ESP32_DEBUG_OCDAWARE=y CONFIG_ESP32_DEBUG_OCDAWARE=y
@@ -537,8 +537,8 @@ CONFIG_FATFS_MAX_LFN=255
CONFIG_FATFS_API_ENCODING_ANSI_OEM=y CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
# CONFIG_FATFS_API_ENCODING_UTF_16 is not set # CONFIG_FATFS_API_ENCODING_UTF_16 is not set
# CONFIG_FATFS_API_ENCODING_UTF_8 is not set # CONFIG_FATFS_API_ENCODING_UTF_8 is not set
CONFIG_FATFS_FS_LOCK=5 CONFIG_FATFS_FS_LOCK=10
CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_TIMEOUT_MS=5000
CONFIG_FATFS_PER_FILE_CACHE=y CONFIG_FATFS_PER_FILE_CACHE=y
CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y
# end of FAT Filesystem support # end of FAT Filesystem support
@@ -965,7 +965,7 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
# #
# Virtual file system # Virtual file system
# #
CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y # CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT is not set
CONFIG_VFS_SUPPORT_TERMIOS=y CONFIG_VFS_SUPPORT_TERMIOS=y
# #
@@ -1166,6 +1166,6 @@ CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread"
CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y
# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set
# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set
CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y # CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT is not set
CONFIG_SUPPORT_TERMIOS=y CONFIG_SUPPORT_TERMIOS=y
# End of deprecated options # End of deprecated options

View File

@@ -1,4 +1,4 @@
const char* GIT_REV="793f928"; const char* GIT_REV="6e521f0";
const char* GIT_TAG=""; const char* GIT_TAG="";
const char* GIT_BRANCH="rolling"; const char* GIT_BRANCH="rolling-reduce-sd-use";
const char* BUILD_TIME="2020-12-07 20:40"; const char* BUILD_TIME="2020-12-28 15:38";

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -123,7 +123,7 @@ textarea {
<td> <td>
<select id="MakeImage_ImageSize_value1"> <select id="MakeImage_ImageSize_value1">
<option value="0" selected>VGA</option> <option value="0" selected>VGA</option>
<option value="1" >SVGA</option> <option value="1" >QVGA</option>
</select> </select>
</td> </td>
<td style="font-size: 80%;"> <td style="font-size: 80%;">
@@ -570,16 +570,16 @@ textarea {
</tr> </tr>
<tr class="expert" id="ex16"> <tr class="expert" id="ex16">
<td width="20px" style="padding-left: 40px;"> <td width="20px" style="padding-left: 40px;">
<input type="checkbox" id="System_TimeUpdateIntervall_enabled" value="1" onclick = 'document.getElementById("System_TimeUpdateIntervall_value1").disabled = !document.getElementById("System_TimeUpdateIntervall_value1").disabled' unchecked > <td"><input type="checkbox" id="System_TimeServer_enabled" value="1" onclick = 'document.getElementById("System_TimeServer_value1").disabled = !document.getElementById("System_TimeServer_value1").disabled' unchecked ></td>
</td>
<td width="200px">
<class id="System_TimeUpdateIntervall_text" style="color:black;">TimeUpdateIntervall</class>
</td> </td>
<td> <td>
<input type="number" id="System_TimeUpdateIntervall_value1" size="13" min="0" step="1"> <class id="System_TimeServer_text" style="color:black;">TimeServer</class>
</td>
<td>
<input type="text" id="System_TimeServer_value1">
</td> </td>
<td style="font-size: 80%;"> <td style="font-size: 80%;">
Intervall for synchronizing the time with the time server (in hours) Time server to synchronize system time (default: "pool.ntp.org" - used if nothing is specified)
</td> </td>
</tr> </tr>
</table> </table>
@@ -717,7 +717,7 @@ function UpdateInput() {
WriteParameter(param, "Debug", "LogfileRetentionInDays", true); WriteParameter(param, "Debug", "LogfileRetentionInDays", true);
WriteParameter(param, "System", "TimeZone", true); WriteParameter(param, "System", "TimeZone", true);
WriteParameter(param, "System", "TimeUpdateIntervall", true); WriteParameter(param, "System", "TimeServer", true);
} }
function WriteConfig(){ function WriteConfig(){
@@ -762,7 +762,7 @@ function WriteConfig(){
ReadParameter(param, "Debug", "LogfileRetentionInDays", true); ReadParameter(param, "Debug", "LogfileRetentionInDays", true);
ReadParameter(param, "System", "TimeZone", true); ReadParameter(param, "System", "TimeZone", true);
ReadParameter(param, "System", "TimeUpdateIntervall", true); ReadParameter(param, "System", "TimeServer", true);
FormatDecimalValue(param, "PostProcessing", "MaxRateValue"); FormatDecimalValue(param, "PostProcessing", "MaxRateValue");

View File

@@ -87,7 +87,7 @@ table {
} }
function loadRawImage(){ function loadRawImage(){
url = basepath + "/fileserver/img_tmp/raw.jpg" + "?session=" + Math.floor((Math.random() * 1000000) + 1); url = basepath + "/img_tmp/raw.jpg" + "?session=" + Math.floor((Math.random() * 1000000) + 1);
document.getElementById("finerotate").value = 0; document.getElementById("finerotate").value = 0;
document.getElementById("prerotateangle").value = getPreRotate(); document.getElementById("prerotateangle").value = getPreRotate();
document.getElementById("mirror").checked = getMirror(); document.getElementById("mirror").checked = getMirror();

View File

@@ -72,9 +72,9 @@ function ParseConfig() {
var catname = "System"; var catname = "System";
param[catname] = new Object(); param[catname] = new Object();
ParamAddValue(param, catname, "TimeZone"); ParamAddValue(param, catname, "TimeZone");
ParamAddValue(param, catname, "TimeServer");
ParamAddValue(param, catname, "AutoAdjustSummertime"); ParamAddValue(param, catname, "AutoAdjustSummertime");
ParamAddValue(param, catname, "TimeUpdateIntervall"); ParamAddValue(param, catname, "SetupMode");
ParamAddValue(param, catname, "SetupMode");
while (aktline < config_split.length){ while (aktline < config_split.length){
if (config_split[aktline].trim().toUpperCase() == "[MAKEIMAGE]") { if (config_split[aktline].trim().toUpperCase() == "[MAKEIMAGE]") {
@@ -149,6 +149,7 @@ function ParseConfigParamSystem(_aktline){
var linesplit = ZerlegeZeile(input, " ="); var linesplit = ZerlegeZeile(input, " =");
ParamExtractValue(param, linesplit, catname, "TimeZone", _aktline, isCom); ParamExtractValue(param, linesplit, catname, "TimeZone", _aktline, isCom);
ParamExtractValue(param, linesplit, catname, "TimeServer", _aktline, isCom);
ParamExtractValue(param, linesplit, catname, "AutoAdjustSummertime", _aktline, isCom); ParamExtractValue(param, linesplit, catname, "AutoAdjustSummertime", _aktline, isCom);
ParamExtractValue(param, linesplit, catname, "TimeUpdateIntervall", _aktline, isCom); ParamExtractValue(param, linesplit, catname, "TimeUpdateIntervall", _aktline, isCom);
ParamExtractValue(param, linesplit, catname, "SetupMode", _aktline, isCom); ParamExtractValue(param, linesplit, catname, "SetupMode", _aktline, isCom);

View File

@@ -1 +1 @@
3.0.0 4.0.0