Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Replace with your desired hostname
- const char* hostnamee = "esp32";
- const char* ssid = "Project"; //your network SSID
- const char* password = "12345678"; //your network password
- const char* apssid = "ESP32-CAM";
- const char* appassword = "12345678";
- #include <ESPmDNS.h>
- #include <WiFi.h>
- #include <esp32-hal-ledc.h>
- #include "soc/soc.h"
- #include "soc/rtc_cntl_reg.h"
- #include "esp_camera.h"
- #include "esp_http_server.h"
- #include "img_converters.h"
- String Feedback = "";
- String Command = "";
- String cmd = "";
- String P1 = "";
- String P2 = "";
- String P3 = "";
- String P4 = "";
- String P5 = "";
- String P6 = "";
- String P7 = "";
- String P8 = "";
- String P9 = "";
- byte ReceiveState = 0;
- byte cmdState = 1;
- byte strState = 1;
- byte questionstate = 0;
- byte equalstate = 0;
- byte semicolonstate = 0;
- typedef struct {
- httpd_req_t *req;
- size_t len;
- } jpg_chunking_t;
- #define PART_BOUNDARY "123456789000000000000987654321"
- static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
- static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
- static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
- httpd_handle_t stream_httpd = NULL;
- httpd_handle_t camera_httpd = NULL;
- #define PWDN_GPIO_NUM 32
- #define RESET_GPIO_NUM -1
- #define XCLK_GPIO_NUM 0
- #define SIOD_GPIO_NUM 26
- #define SIOC_GPIO_NUM 27
- #define Y9_GPIO_NUM 35
- #define Y8_GPIO_NUM 34
- #define Y7_GPIO_NUM 39
- #define Y6_GPIO_NUM 36
- #define Y5_GPIO_NUM 21
- #define Y4_GPIO_NUM 19
- #define Y3_GPIO_NUM 18
- #define Y2_GPIO_NUM 5
- #define VSYNC_GPIO_NUM 25
- #define HREF_GPIO_NUM 23
- #define PCLK_GPIO_NUM 22
- void setup() {
- WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
- Serial.begin(115200);
- Serial.setDebugOutput(true);
- Serial.println();
- camera_config_t config;
- config.ledc_channel = LEDC_CHANNEL_0;
- config.ledc_timer = LEDC_TIMER_0;
- config.pin_d0 = Y2_GPIO_NUM;
- config.pin_d1 = Y3_GPIO_NUM;
- config.pin_d2 = Y4_GPIO_NUM;
- config.pin_d3 = Y5_GPIO_NUM;
- config.pin_d4 = Y6_GPIO_NUM;
- config.pin_d5 = Y7_GPIO_NUM;
- config.pin_d6 = Y8_GPIO_NUM;
- config.pin_d7 = Y9_GPIO_NUM;
- config.pin_xclk = XCLK_GPIO_NUM;
- config.pin_pclk = PCLK_GPIO_NUM;
- config.pin_vsync = VSYNC_GPIO_NUM;
- config.pin_href = HREF_GPIO_NUM;
- config.pin_sscb_sda = SIOD_GPIO_NUM;
- config.pin_sscb_scl = SIOC_GPIO_NUM;
- config.pin_pwdn = PWDN_GPIO_NUM;
- config.pin_reset = RESET_GPIO_NUM;
- config.xclk_freq_hz = 20000000;
- config.pixel_format = PIXFORMAT_JPEG;
- if (psramFound()) {
- config.frame_size = FRAMESIZE_UXGA;
- config.jpeg_quality = 10;
- config.fb_count = 2;
- } else {
- config.frame_size = FRAMESIZE_SVGA;
- config.jpeg_quality = 12;
- config.fb_count = 1;
- }
- esp_err_t err = esp_camera_init(&config);
- if (err != ESP_OK) {
- Serial.printf("Camera init failed with error 0x%x", err);
- ESP.restart();
- }
- sensor_t * s = esp_camera_sensor_get();
- // initial sensors are flipped vertically and colors are a bit saturated
- if (s->id.PID == OV3660_PID) {
- s->set_vflip(s, 1); // flip it back
- s->set_brightness(s, 1); // up the brightness just a bit
- s->set_saturation(s, -2); // lower the saturation
- }
- // drop down frame size for higher initial frame rate
- s->set_framesize(s, FRAMESIZE_QVGA);
- ledcAttachPin(4, 4);
- ledcSetup(4, 5000, 8);
- WiFi.mode(WIFI_AP_STA);
- for (int i = 0; i < 2; i++) {
- WiFi.begin(ssid, password);
- delay(1000);
- Serial.println("");
- Serial.print("Connecting to ");
- Serial.println(ssid);
- long int StartTime = millis();
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- if ((StartTime + 5000) < millis()) break;
- }
- if (WiFi.status() == WL_CONNECTED) {
- WiFi.softAP((WiFi.localIP().toString() + "_" + (String)apssid).c_str(), appassword);
- Serial.println("");
- Serial.println("STAIP address: ");
- Serial.println(WiFi.localIP());
- Serial.println("");
- for (int i = 0; i < 5; i++) {
- ledcWrite(4, 10);
- delay(200);
- ledcWrite(4, 0);
- delay(200);
- }
- break;
- }
- }
- if (WiFi.status() != WL_CONNECTED) {
- WiFi.softAP((WiFi.softAPIP().toString() + "_" + (String)apssid).c_str(), appassword);
- for (int i = 0; i < 2; i++) {
- ledcWrite(4, 10);
- delay(1000);
- ledcWrite(4, 0);
- delay(1000);
- }
- }
- Serial.println("");
- Serial.println("APIP address: ");
- Serial.println(WiFi.softAPIP());
- Serial.println("");
- //***********************************************************************SA
- // Start mDNS service
- if (!MDNS.begin(hostnamee)) {
- Serial.println("Error setting up MDNS responder!");
- while (1) {
- delay(1000);
- }
- }
- Serial.println("mDNS responder started");
- //***********************************************************************SA
- startCameraServer();
- //***********************************************************************SA
- // Add service to MDNS
- MDNS.addService("http", "tcp", 80);
- Serial.print("Camera Ready! Use 'http://");
- Serial.print(hostnamee);
- Serial.println(".local' to connect");
- //***********************************************************************SA
- pinMode(4, OUTPUT);
- digitalWrite(4, LOW);
- }
- void loop() {
- }
- 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;
- if (!index) {
- j->len = 0;
- }
- if (httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK) {
- return 0;
- }
- j->len += len;
- return len;
- }
- static esp_err_t capture_handler(httpd_req_t *req) {
- camera_fb_t * fb = NULL;
- esp_err_t res = ESP_OK;
- fb = esp_camera_fb_get();
- if (!fb) {
- Serial.println("Camera capture failed");
- httpd_resp_send_500(req);
- return ESP_FAIL;
- }
- httpd_resp_set_type(req, "image/jpeg");
- httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- size_t fb_len = 0;
- if (fb->format == PIXFORMAT_JPEG) {
- fb_len = fb->len;
- res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
- } else {
- jpg_chunking_t jchunk = {req, 0};
- res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk) ? ESP_OK : ESP_FAIL;
- httpd_resp_send_chunk(req, NULL, 0);
- fb_len = jchunk.len;
- }
- esp_camera_fb_return(fb);
- return res;
- }
- static esp_err_t stream_handler(httpd_req_t *req) {
- camera_fb_t * fb = NULL;
- esp_err_t res = ESP_OK;
- size_t _jpg_buf_len = 0;
- uint8_t * _jpg_buf = NULL;
- char * part_buf[64];
- res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
- if (res != ESP_OK) {
- return res;
- }
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- while (true) {
- fb = esp_camera_fb_get();
- if (!fb) {
- Serial.println("Camera capture failed");
- res = ESP_FAIL;
- } else {
- if (fb->format != PIXFORMAT_JPEG) {
- bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
- esp_camera_fb_return(fb);
- fb = NULL;
- if (!jpeg_converted) {
- Serial.println("JPEG compression failed");
- res = ESP_FAIL;
- }
- } else {
- _jpg_buf_len = fb->len;
- _jpg_buf = fb->buf;
- }
- }
- if (res == ESP_OK) {
- res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
- }
- if (res == ESP_OK) {
- res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
- }
- if (res == ESP_OK) {
- size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
- res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
- }
- if (fb) {
- esp_camera_fb_return(fb);
- fb = NULL;
- _jpg_buf = NULL;
- } else if (_jpg_buf) {
- free(_jpg_buf);
- _jpg_buf = NULL;
- }
- if (res != ESP_OK) {
- break;
- }
- }
- return res;
- }
- static esp_err_t cmd_handler(httpd_req_t *req) {
- char* buf;
- size_t buf_len;
- char variable[128] = {0,};
- char value[128] = {0,};
- String myCmd = "";
- buf_len = httpd_req_get_url_query_len(req) + 1;
- if (buf_len > 1) {
- buf = (char*)malloc(buf_len);
- if (!buf) {
- httpd_resp_send_500(req);
- return ESP_FAIL;
- }
- if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
- if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK &&
- httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) {
- }
- else {
- myCmd = String(buf);
- }
- }
- free(buf);
- } else {
- httpd_resp_send_404(req);
- return ESP_FAIL;
- }
- Feedback = ""; Command = ""; cmd = ""; P1 = ""; P2 = ""; P3 = ""; P4 = ""; P5 = ""; P6 = ""; P7 = ""; P8 = ""; P9 = "";
- ReceiveState = 0, cmdState = 1, strState = 1, questionstate = 0, equalstate = 0, semicolonstate = 0;
- if (myCmd.length() > 0) {
- myCmd = "?" + myCmd;
- for (int i = 0; i < myCmd.length(); i++) {
- getCommand(char(myCmd.charAt(i)));
- }
- }
- if (cmd.length() > 0) {
- Serial.println("");
- Serial.println("cmd= " + cmd + " ,P1= " + P1 + " ,P2= " + P2 + " ,P3= " + P3 + " ,P4= " + P4 + " ,P5= " + P5 + " ,P6= " + P6 + " ,P7= " + P7 + " ,P8= " + P8 + " ,P9= " + P9);
- Serial.println("");
- if (cmd == "your cmd") {
- }
- else if (cmd == "ip") {
- Feedback = "AP IP: " + WiFi.softAPIP().toString();
- Feedback += "<br>";
- Feedback += "STA IP: " + WiFi.localIP().toString();
- }
- else if (cmd == "mac") {
- Feedback = "STA MAC: " + WiFi.macAddress();
- }
- else if (cmd == "restart") {
- ESP.restart();
- }
- else if (cmd == "digitalwrite") {
- ledcDetachPin(P1.toInt());
- pinMode(P1.toInt(), OUTPUT);
- digitalWrite(P1.toInt(), P2.toInt());
- }
- else if (cmd == "digitalread") {
- Feedback = String(digitalRead(P1.toInt()));
- }
- else if (cmd == "analogwrite") {
- if (P1 == "4") {
- ledcAttachPin(4, 4);
- ledcSetup(4, 5000, 8);
- ledcWrite(4, P2.toInt());
- }
- else {
- ledcAttachPin(P1.toInt(), 9);
- ledcSetup(9, 5000, 8);
- ledcWrite(9, P2.toInt());
- }
- }
- else if (cmd == "analogread") {
- Feedback = String(analogRead(P1.toInt()));
- }
- else if (cmd == "touchread") {
- Feedback = String(touchRead(P1.toInt()));
- }
- else if (cmd == "resetwifi") {
- for (int i = 0; i < 2; i++) {
- WiFi.begin(P1.c_str(), P2.c_str());
- Serial.print("Connecting to ");
- Serial.println(P1);
- long int StartTime = millis();
- while (WiFi.status() != WL_CONNECTED) {
- delay(500);
- if ((StartTime + 5000) < millis()) break;
- }
- Serial.println("");
- Serial.println("STAIP: " + WiFi.localIP().toString());
- Feedback = "STAIP: " + WiFi.localIP().toString();
- if (WiFi.status() == WL_CONNECTED) {
- WiFi.softAP((WiFi.localIP().toString() + "_" + P1).c_str(), P2.c_str());
- for (int i = 0; i < 2; i++) {
- ledcWrite(4, 10);
- delay(300);
- ledcWrite(4, 0);
- delay(300);
- }
- break;
- }
- }
- }
- else if (cmd == "flash") {
- ledcAttachPin(4, 4);
- ledcSetup(4, 5000, 8);
- int val = P1.toInt();
- ledcWrite(4, val);
- }
- else if (cmd == "serial") {
- if (P1 != ""&P1 != "stop") Serial.println(P1);
- if (P2 != ""&P2 != "stop") Serial.println(P2);
- Serial.println();
- }
- else {
- Feedback = "Command is not defined";
- }
- if (Feedback == "") Feedback = Command;
- const char *resp = Feedback.c_str();
- httpd_resp_set_type(req, "text/html");
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- return httpd_resp_send(req, resp, strlen(resp));
- }
- else {
- int val = atoi(value);
- sensor_t * s = esp_camera_sensor_get();
- int res = 0;
- if (!strcmp(variable, "framesize")) {
- if (s->pixformat == PIXFORMAT_JPEG)
- res = s->set_framesize(s, (framesize_t)val);
- }
- else if (!strcmp(variable, "quality")) res = s->set_quality(s, val);
- else if (!strcmp(variable, "contrast")) res = s->set_contrast(s, val);
- else if (!strcmp(variable, "brightness")) res = s->set_brightness(s, val);
- else if (!strcmp(variable, "hmirror")) res = s->set_hmirror(s, val);
- else if (!strcmp(variable, "vflip")) res = s->set_vflip(s, val);
- else if (!strcmp(variable, "flash")) {
- ledcAttachPin(4, 4);
- ledcSetup(4, 5000, 8);
- ledcWrite(4, val);
- }
- else {
- res = -1;
- }
- if (res) {
- return httpd_resp_send_500(req);
- }
- if (buf) {
- Feedback = String(buf);
- const char *resp = Feedback.c_str();
- httpd_resp_set_type(req, "text/html");
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- return httpd_resp_send(req, resp, strlen(resp));
- }
- else {
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- return httpd_resp_send(req, NULL, 0);
- }
- }
- }
- static esp_err_t status_handler(httpd_req_t *req) {
- static char json_response[1024];
- sensor_t * s = esp_camera_sensor_get();
- char * p = json_response;
- *p++ = '{';
- p += sprintf(p, "\"flash\":%d,", 0);
- p += sprintf(p, "\"framesize\":%u,", s->status.framesize);
- p += sprintf(p, "\"quality\":%u,", s->status.quality);
- p += sprintf(p, "\"brightness\":%d,", s->status.brightness);
- p += sprintf(p, "\"contrast\":%d,", s->status.contrast);
- p += sprintf(p, "\"hmirror\":%u,", s->status.hmirror);
- p += sprintf(p, "\"vflip\":%u", s->status.vflip);
- *p++ = '}';
- *p++ = 0;
- httpd_resp_set_type(req, "application/json");
- httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
- return httpd_resp_send(req, json_response, strlen(json_response));
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- static const char PROGMEM INDEX_HTML[] = R"rawliteral(
- <!doctype html>
- <html>
- <head>
- <meta charset="utf-8">
- <meta name="viewport" content="width=device-width,initial-scale=1">
- <meta http-equiv="Access-Control-Allow-Headers" content="Origin, X-Requested-With, Content-Type, Accept">
- <meta http-equiv="Access-Control-Allow-Methods" content="GET,POST,PUT,DELETE,OPTIONS">
- <meta http-equiv="Access-Control-Allow-Origin" content="*">
- <title>Detect Objects</title>
- <style>
- body{font-family:Arial,Helvetica,sans-serif;background:#181818;color:#EFEFEF;font-size:16px}h2{font-size:18px}section.main{display:flex}#menu,section.main{flex-direction:column}#menu{display:flex;flex-wrap:nowrap;min-width:340px;background:#363636;padding:8px;border-radius:4px;margin-top:-10px;margin-right:10px}#content{display:flex;flex-wrap:wrap;align-items:stretch}figure{padding:0;margin:0;-webkit-margin-before:0;margin-block-start:0;-webkit-margin-after:0;margin-block-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;margin-inline-end:0}figure img{display:block;width:100%;height:auto;border-radius:4px;margin-top:8px}@media (min-width: 800px) and (orientation:landscape){#content{display:flex;flex-wrap:nowrap;align-items:stretch}figure img{display:block;max-width:100%;max-height:calc(100vh - 40px);width:auto;height:auto}figure{padding:0;margin:0;-webkit-margin-before:0;margin-block-start:0;-webkit-margin-after:0;margin-block-end:0;-webkit-margin-start:0;margin-inline-start:0;-webkit-margin-end:0;margin-inline-end:0}}section#buttons{display:flex;flex-wrap:nowrap;justify-content:space-between}#nav-toggle{cursor:pointer;display:block}#nav-toggle-cb{outline:0;opacity:0;width:0;height:0}#nav-toggle-cb:checked+#menu{display:none}.input-group{display:flex;flex-wrap:nowrap;line-height:22px;margin:5px 0}.input-group>label{display:inline-block;padding-right:10px;min-width:47%}.input-group input,.input-group select{flex-grow:1}.range-max,.range-min{display:inline-block;padding:0 5px}button{display:block;margin:5px;padding:0 12px;border:0;line-height:28px;cursor:pointer;color:#fff;background:#ff3034;border-radius:5px;font-size:16px;outline:0}button:hover{background:#ff494d}button:active{background:#f21c21}button.disabled{cursor:default;background:#a0a0a0}input[type=range]{-webkit-appearance:none;width:100%;height:22px;background:#363636;cursor:pointer;margin:0}input[type=range]:focus{outline:0}input[type=range]::-webkit-slider-runnable-track{width:100%;height:2px;cursor:pointer;background:#EFEFEF;border-radius:0;border:0 solid #EFEFEF}input[type=range]::-webkit-slider-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursor:pointer;-webkit-appearance:none;margin-top:-11.5px}input[type=range]:focus::-webkit-slider-runnable-track{background:#EFEFEF}input[type=range]::-moz-range-track{width:100%;height:2px;cursor:pointer;background:#EFEFEF;border-radius:0;border:0 solid #EFEFEF}input[type=range]::-moz-range-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursor:pointer}input[type=range]::-ms-track{width:100%;height:2px;cursor:pointer;background:0 0;border-color:transparent;color:transparent}input[type=range]::-ms-fill-lower{background:#EFEFEF;border:0 solid #EFEFEF;border-radius:0}input[type=range]::-ms-fill-upper{background:#EFEFEF;border:0 solid #EFEFEF;border-radius:0}input[type=range]::-ms-thumb{border:1px solid rgba(0,0,30,0);height:22px;width:22px;border-radius:50px;background:#ff3034;cursor:pointer;height:2px}input[type=range]:focus::-ms-fill-lower{background:#EFEFEF}input[type=range]:focus::-ms-fill-upper{background:#363636}.switch{display:block;position:relative;line-height:22px;font-size:16px;height:22px}.switch input{outline:0;opacity:0;width:0;height:0}.slider{width:50px;height:22px;border-radius:22px;cursor:pointer;background-color:grey}.slider,.slider:before{display:inline-block;transition:.4s}.slider:before{position:relative;content:"";border-radius:50%;height:16px;width:16px;left:4px;top:3px;background-color:#fff}input:checked+.slider{background-color:#ff3034}input:checked+.slider:before{-webkit-transform:translateX(26px);transform:translateX(26px)}select{border:1px solid #363636;font-size:14px;height:22px;outline:0;border-radius:5px}.image-container{position:relative;min-width:160px}.close{position:absolute;right:5px;top:5px;background:#ff3034;width:16px;height:16px;border-radius:100px;color:#fff;text-align:center;line-height:18px;cursor:pointer}.hidden{display:none}
- /* Enhanced CSS for result display */
- #result {
- background: #2c2c2c;
- padding: 15px;
- border-radius: 8px;
- margin-top: 20px;
- font-size: 14px;
- line-height: 1.6;
- }
- .result-item {
- margin-bottom: 10px;
- }
- .result-label {
- display: block;
- margin-bottom: 5px;
- font-weight: bold;
- color: #ff3034;
- }
- .progress-bar {
- width: 100%;
- height: 20px;
- background: #444;
- border-radius: 10px;
- overflow: hidden;
- position: relative;
- }
- .progress-bar-fill {
- height: 100%;
- background: #ff3034;
- border-radius: 10px;
- transition: width 0.3s ease;
- }
- .progress-bar-text {
- position: absolute;
- top: 50%;
- left: 10px;
- transform: translateY(-50%);
- color: #fff;
- font-size: 12px;
- }
- .result-final {
- margin-top: 15px;
- padding: 10px;
- background: #1e1e1e;
- border-radius: 5px;
- text-align: center;
- font-size: 16px;
- }
- .result-final-content {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- gap: 10px;
- }
- .result-final-icon {
- font-size: 40px; /* Larger icon */
- }
- .result-final-percentage {
- font-size: 24px; /* Larger percentage */
- font-weight: bold;
- color: #ff3034;
- }
- /* Icons for trash types */
- .icon-empty::before {
- content: "ποΈ"; /* Empty trash icon */
- }
- .icon-paper::before {
- content: "π"; /* Paper trash icon */
- }
- .icon-bottle::before {
- content: "πΆ"; /* Bottle trash icon */
- }
- </style>
- <script src="https:\/\/ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
- <script src="https:\/\/cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf.min.js"></script>
- <script src="https:\/\/cdn.jsdelivr.net/npm/@teachablemachine/[email protected]/dist/teachablemachine-image.min.js"></script>
- <script src="https:\/\/cdn.jsdelivr.net/npm/@teachablemachine/[email protected]/dist/teachablemachine-pose.min.js"></script>
- </head>
- <body>
- <section class="main">
- <figure>
- <div id="stream-container" class="image-container hidden">
- <div class="close" id="close-stream" style="display:none">Γ</div>
- <img id="stream" src="" style="display:none" crossorigin="anonymous">
- <canvas id="canvas" width="0" height="0"></canvas>
- </div>
- </figure>
- <section id="buttons">
- <table>
- <tr><td><button id="restart" onclick="try{fetch(document.location.origin+'/control?restart');}catch(e){}">Restart</button></td><td><button id="get-still" style="display:none">Get Still</button></td><td><button id="toggle-stream" style="display:none"></td></tr>
- </table>
- </section>
- <div id="logo">
- <label for="nav-toggle-cb" id="nav-toggle">☰ Toggle settings</label>
- </div>
- <div id="content">
- <div id="sidebar">
- <input type="checkbox" id="nav-toggle-cb">
- <nav id="menu">
- <div class="input-group">
- <label for="kind">Kind</label>
- <select id="kind">
- <option value="image">image</option>
- <option value="pose">pose</option>
- </select>
- </div>
- <div class="input-group">
- <label style="visibility: hidden;" for="modelPath">Model Path</label>
- <input type="text" style="visibility: hidden;" id="modelPath" value="https:\/\/teachablemachine.withgoogle.com/models/hCGSo2WQw/">
- </div>
- <div class="input-group">
- <label for="btnModel"></label>
- <button type="button" id="btnModel" onclick="LoadModel();">Start Recognition</button>
- </div>
- <div class="input-group" id="flash-group">
- <label for="flash">Flash</label>
- <div class="range-min">0</div>
- <input type="range" id="flash" min="0" max="255" value="0" class="default-action">
- <div class="range-max">255</div>
- </div>
- <div class="input-group" id="framesize-group">
- <label for="framesize">Resolution</label>
- <select id="framesize" class="default-action">
- <option value="10">UXGA(1600x1200)</option>
- <option value="9">SXGA(1280x1024)</option>
- <option value="8">XGA(1024x768)</option>
- <option value="7">SVGA(800x600)</option>
- <option value="6">VGA(640x480)</option>
- <option value="5" selected="selected">CIF(400x296)</option>
- <option value="4">QVGA(320x240)</option>
- <option value="3">HQVGA(240x176)</option>
- <option value="0">QQVGA(160x120)</option>
- </select>
- </div>
- <div class="input-group" id="quality-group">
- <label for="quality">Quality</label>
- <div class="range-min">10</div>
- <input type="range" id="quality" min="10" max="63" value="10" class="default-action">
- <div class="range-max">63</div>
- </div>
- <div class="input-group" id="brightness-group">
- <label for="brightness">Brightness</label>
- <div class="range-min">-2</div>
- <input type="range" id="brightness" min="-2" max="2" value="0" class="default-action">
- <div class="range-max">2</div>
- </div>
- <div class="input-group" id="contrast-group">
- <label for="contrast">Contrast</label>
- <div class="range-min">-2</div>
- <input type="range" id="contrast" min="-2" max="2" value="0" class="default-action">
- <div class="range-max">2</div>
- </div>
- <div class="input-group" id="hmirror-group">
- <label for="hmirror">H-Mirror</label>
- <div class="switch">
- <input id="hmirror" type="checkbox" class="default-action" checked="checked">
- <label class="slider" for="hmirror"></label>
- </div>
- </div>
- <div class="input-group" id="vflip-group">
- <label for="vflip">V-Flip</label>
- <div class="switch">
- <input id="vflip" type="checkbox" class="default-action" checked="checked">
- <label class="slider" for="vflip"></label>
- </div>
- </div>
- </nav>
- </div>
- </div>
- </section>
- <br>
- <div id="result"><div>
- <script>
- document.addEventListener('DOMContentLoaded', function (event) {
- var baseHost = document.location.origin
- var streamUrl = baseHost + ':81'
- const hide = el => {
- el.classList.add('hidden')
- }
- const show = el => {
- el.classList.remove('hidden')
- }
- const disable = el => {
- el.classList.add('disabled')
- el.disabled = true
- }
- const enable = el => {
- el.classList.remove('disabled')
- el.disabled = false
- }
- const updateValue = (el, value, updateRemote) => {
- updateRemote = updateRemote == null ? true : updateRemote
- let initialValue
- if (el.type === 'checkbox') {
- initialValue = el.checked
- value = !!value
- el.checked = value
- } else {
- initialValue = el.value
- el.value = value
- }
- if (updateRemote && initialValue !== value) {
- updateConfig(el);
- }
- }
- function updateConfig (el) {
- let value
- switch (el.type) {
- case 'checkbox':
- value = el.checked ? 1 : 0
- break
- case 'range':
- case 'select-one':
- value = el.value
- break
- case 'button':
- case 'submit':
- value = '1'
- break
- default:
- return
- }
- const query = `${baseHost}/control?var=${el.id}&val=${value}`
- fetch(query)
- .then(response => {
- console.log(`request to ${query} finished, status: ${response.status}`)
- })
- }
- document
- .querySelectorAll('.close')
- .forEach(el => {
- el.onclick = () => {
- hide(el.parentNode)
- }
- })
- // read initial values
- fetch(`${baseHost}/status`)
- .then(function (response) {
- return response.json()
- })
- .then(function (state) {
- document
- .querySelectorAll('.default-action')
- .forEach(el => {
- updateValue(el, state[el.id], false)
- })
- })
- const view = document.getElementById('stream')
- const viewContainer = document.getElementById('stream-container')
- const stillButton = document.getElementById('get-still')
- const streamButton = document.getElementById('toggle-stream')
- const closeButton = document.getElementById('close-stream')
- const stopStream = () => {
- //window.stop();
- view.src="";
- streamButton.innerHTML = 'Start Stream'
- }
- const startStream = () => {
- view.src = `${streamUrl}/stream`
- show(viewContainer)
- streamButton.innerHTML = 'Stop Stream'
- }
- // Attach actions to buttons
- stillButton.onclick = () => {
- stopStream()
- try{
- view.src = `${baseHost}/capture?_cb=${Date.now()}`
- }
- catch(e) {
- view.src = `${baseHost}/capture?_cb=${Date.now()}`
- }
- show(viewContainer)
- }
- closeButton.onclick = () => {
- stopStream()
- hide(viewContainer)
- }
- streamButton.onclick = () => {
- const streamEnabled = streamButton.innerHTML === 'Stop Stream'
- if (streamEnabled) {
- stopStream()
- } else {
- startStream()
- }
- }
- // Attach default on change action
- document
- .querySelectorAll('.default-action')
- .forEach(el => {
- el.onchange = () => updateConfig(el)
- })
- })
- </script>
- <script>
- var getStill = document.getElementById('get-still');
- var ShowImage = document.getElementById('stream');
- var canvas = document.getElementById("canvas");
- var context = canvas.getContext("2d");
- var modelPath = document.getElementById('modelPath');
- var result = document.getElementById('result');
- var kind = document.getElementById('kind');
- let Model;
- async function LoadModel() {
- if (modelPath.value=="") {
- result.innerHTML = "Please input model path.";
- return;
- }
- result.innerHTML = "Please wait for loading model.";
- const URL = modelPath.value;
- const modelURL = URL + "model.json";
- const metadataURL = URL + "metadata.json";
- if (kind.value=="image") {
- Model = await tmImage.load(modelURL, metadataURL);
- }
- else if (kind.value=="pose") {
- Model = await tmPose.load(modelURL, metadataURL);
- }
- maxPredictions = Model.getTotalClasses();
- result.innerHTML = "";
- getStill.style.display = "block";
- getStill.click();
- }
- async function predict() {
- var data = "";
- var maxClassName = "";
- var maxProbability = "";
- canvas.setAttribute("width", ShowImage.width);
- canvas.setAttribute("height", ShowImage.height);
- context.drawImage(ShowImage, 0, 0, ShowImage.width, ShowImage.height);
- if (kind.value=="image")
- var prediction = await Model.predict(canvas);
- else if (kind.value=="pose") {
- var { pose, posenetOutput } = await Model.estimatePose(canvas);
- var prediction = await Model.predict(posenetOutput);
- }
- if (maxPredictions>0) {
- for (let i = 0; i < maxPredictions; i++) {
- const className = prediction[i].className;
- const probability = prediction[i].probability.toFixed(2);
- const percentage = (prediction[i].probability * 100).toFixed(2);
- data += `
- <div class="result-item">
- <div class="result-label">${className}</div>
- <div class="progress-bar">
- <div class="progress-bar-fill" style="width: ${percentage}%"></div>
- <div class="progress-bar-text">${percentage}%</div>
- </div>
- </div>
- `;
- if (i == 0 || prediction[i].probability > maxProbability) {
- maxClassName = className;
- maxProbability = probability;
- }
- }
- // Determine the icon based on the maxClassName
- let iconClass = "icon-empty"; // Default icon
- if (maxClassName.toLowerCase().includes("paper")) {
- iconClass = "icon-paper";
- } else if (maxClassName.toLowerCase().includes("bottle")) {
- iconClass = "icon-bottle";
- }
- result.innerHTML = data;
- result.innerHTML += `
- <div class="result-final">
- <div class="result-final-content">
- <div class="result-final-icon ${iconClass}"></div>
- <div class="result-final-percentage">${(maxProbability * 100).toFixed(2)}%</div>
- </div>
- </div>
- `;
- $.ajax({url: document.location.origin+'/control?serial='+maxClassName+";"+maxProbability+';stop', async: false});
- }
- else
- result.innerHTML = "Unrecognizable";
- getStill.click();
- }
- ShowImage.onload = function (event) {
- if (Model) {
- try {
- document.createEvent("TouchEvent");
- setTimeout(function(){predict();},250);
- }
- catch(e) {
- predict();
- }
- }
- }
- </script>
- </body>
- </html>)rawliteral";
- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- static esp_err_t index_handler(httpd_req_t *req) {
- httpd_resp_set_type(req, "text/html");
- return httpd_resp_send(req, (const char *)INDEX_HTML, strlen(INDEX_HTML));
- }
- void startCameraServer() {
- httpd_config_t config = HTTPD_DEFAULT_CONFIG();
- httpd_uri_t index_uri = {
- .uri = "/",
- .method = HTTP_GET,
- .handler = index_handler,
- .user_ctx = NULL
- };
- httpd_uri_t status_uri = {
- .uri = "/status",
- .method = HTTP_GET,
- .handler = status_handler,
- .user_ctx = NULL
- };
- httpd_uri_t cmd_uri = {
- .uri = "/control",
- .method = HTTP_GET,
- .handler = cmd_handler,
- .user_ctx = NULL
- };
- httpd_uri_t capture_uri = {
- .uri = "/capture",
- .method = HTTP_GET,
- .handler = capture_handler,
- .user_ctx = NULL
- };
- httpd_uri_t stream_uri = {
- .uri = "/stream",
- .method = HTTP_GET,
- .handler = stream_handler,
- .user_ctx = NULL
- };
- Serial.printf("Starting web server on port: '%d'\n", config.server_port); //Server Port
- if (httpd_start(&camera_httpd, &config) == ESP_OK) {
- httpd_register_uri_handler(camera_httpd, &index_uri);
- httpd_register_uri_handler(camera_httpd, &cmd_uri);
- httpd_register_uri_handler(camera_httpd, &status_uri);
- httpd_register_uri_handler(camera_httpd, &capture_uri);
- }
- config.server_port += 1; //Stream Port
- config.ctrl_port += 1; //UDP Port
- Serial.printf("Starting stream server on port: '%d'\n", config.server_port);
- if (httpd_start(&stream_httpd, &config) == ESP_OK) {
- httpd_register_uri_handler(stream_httpd, &stream_uri);
- }
- }
- void getCommand(char c)
- {
- if (c == '?') ReceiveState = 1;
- if ((c == ' ') || (c == '\r') || (c == '\n')) ReceiveState = 0;
- if (ReceiveState == 1)
- {
- Command = Command + String(c);
- if (c == '=') cmdState = 0;
- if (c == ';') strState++;
- if ((cmdState == 1) && ((c != '?') || (questionstate == 1))) cmd = cmd + String(c);
- if ((cmdState == 0) && (strState == 1) && ((c != '=') || (equalstate == 1))) P1 = P1 + String(c);
- if ((cmdState == 0) && (strState == 2) && (c != ';')) P2 = P2 + String(c);
- if ((cmdState == 0) && (strState == 3) && (c != ';')) P3 = P3 + String(c);
- if ((cmdState == 0) && (strState == 4) && (c != ';')) P4 = P4 + String(c);
- if ((cmdState == 0) && (strState == 5) && (c != ';')) P5 = P5 + String(c);
- if ((cmdState == 0) && (strState == 6) && (c != ';')) P6 = P6 + String(c);
- if ((cmdState == 0) && (strState == 7) && (c != ';')) P7 = P7 + String(c);
- if ((cmdState == 0) && (strState == 8) && (c != ';')) P8 = P8 + String(c);
- if ((cmdState == 0) && (strState >= 9) && ((c != ';') || (semicolonstate == 1))) P9 = P9 + String(c);
- if (c == '?') questionstate = 1;
- if (c == '=') equalstate = 1;
- if ((strState >= 9) && (c == ';')) semicolonstate = 1;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment