├── .gitignore ├── README.md ├── index.php ├── install.sh ├── model_garden.py ├── templates └── index.html └── web ├── comm.php ├── command_received.txt ├── edgetpu.txt ├── js └── jquery.min.js ├── misc ├── hw.php └── hw.py └── model.txt /.gitignore: -------------------------------------------------------------------------------- 1 | *.txt 2 | 3 | # OS generated files # 4 | ###################### 5 | .DS_Store 6 | .DS_Store? 7 | ._* 8 | .Spotlight-V100 9 | .Trashes 10 | ehthumbs.db 11 | Thumbs.db 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Model Garden 2 | 3 |

4 | Article: 5 | 6 | Watch the video on Yotube: 7 | 8 | 9 | 10 |

11 | 12 | This project has been awarded TensorFlow Community Spotlight winner in June 2021. I am thankful for this Tweet by TensorFlow mentioning this achievement and gifting these TensorFlow souvenirs. 13 | 14 | 15 |

16 | 17 |

18 | 19 | ### About the Project 20 | Google has published a large number of Pre-trained Machine Learning Models for anyone to download and experiment. You can check the complete list of freely available models here https://coral.ai/models/all/. 21 | Some of the computer vision models have been packaged as canned models and can be downloaded from this link https://dl.google.com/coral/canned_models/all_models.tar.gz.
22 | This repo contains the code for testing following canned models using a single python script.
23 | 24 | 25 |

26 | 27 |

28 | 29 | ### Image Classification Models 30 | ``` 31 | inception_v1_224_quant_edgetpu.tflite, imagenet_labels.txt 32 | inception_v2_224_quant_edgetpu.tflite, imagenet_labels.txt 33 | inception_v3_299_quant_edgetpu.tflite, imagenet_labels.txt 34 | inception_v4_299_quant_edgetpu.tflite, imagenet_labels.txt 35 | mobilenet_v1_1.0_224_quant_edgetpu.tflite, imagenet_labels.txt 36 | mobilenet_v2_1.0_224_quant_edgetpu.tflite, imagenet_labels.txt 37 | 38 | mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite, inat_bird_labels.txt 39 | mobilenet_v2_1.0_224_inat_insect_quant_edgetpu.tflite, inat_insect_labels.txt 40 | mobilenet_v2_1.0_224_inat_plant_quant_edgetpu.tflite, inat_plant_labels.txt 41 | ``` 42 | 43 | ### Object Detection Models 44 | ``` 45 | mobilenet_ssd_v1_coco_quant_postprocess_edgetpu.tflite, coco_labels.txt 46 | mobilenet_ssd_v2_coco_quant_postprocess_edgetpu.tflite, coco_labels.txt 47 | mobilenet_ssd_v2_face_quant_postprocess_edgetpu.tflite, coco_labels.txt 48 | ``` 49 | 50 | All you need is a Raspberry Pi and a Picamera or a USB Camera to run this project. 51 | 52 | ## Configure your Raspberry Pi to Run this Project 53 | Download this repo on your Raspberry Pi and run the bash script "install.sh" using command ```sudo sh install.sh```. 54 | This bash script will download all the necessary packages/libraries required for this project. Also, the all the Models and the source code will be downloaded automatically and placed in the correct path.
55 | You need to wait patiently as the script can take upto 20 minutes (depending on your internet speed) to complete the task. 56 | 57 | The script perfoms following actions on your Raspberry Pi automatically:- 58 | 59 | - Update & upgrade Raspberry Pi OS 60 | - Install Apache Webserver and PHP 61 | - Install Tensorflow Lite and Google Coral USB Accelerator Libraries 62 | - Install OpenCV 63 | - Download pre-trained Models from google coral repository 64 | - Download the model_garden source code 65 | - Move the models and code to desired location in your Raspbrerry Pi and set permissions. 66 | 67 | ## How to run the code 68 | Open terminal in Raspberry Pi and type the following commands:- 69 | ``` 70 | cd /vars/www/html/model_garden 71 | 72 | python3 model_garden.py 73 | ``` 74 | 75 | you should see the following message on terminal 76 |

77 | 78 |

79 | 80 | 81 | - check the ip of your Raspberry Pi using command ```hostname -I``` 82 | - For example, if it is 192.168.1.12, then using any Laptop/mobile open a browser and type the following URL:-
83 | ``` 84 | 192.168.1.12/model_garden 85 | ``` 86 | 87 |

88 | 89 |

90 | 91 | 92 | Now, you should start seeing the camera video with overlays on the Web GUI. 93 | You can switch between the various models using the buttons provided on Web GUI. Based on your selection the respective model along with its label file gets loaded in the background during run time itself. This allows you to quickly change the models and appreciate the inferencing speeds
94 | 95 | ## Attaching USB Coral Accelerator 96 | If you have a USB Coral Accelerator, then attach it to Raspberry Pi. Now you can press the button at top right corner of Web GUI to run the models which are compiled to run on Coral Accelerator. These models have ```_edgetpu``` in their labels. 97 | Do not press this button if you haven't connected USB Coral Accelerator to Raspberry Pi. Otherwise the script will halt and you will have to restart the script. 98 | 99 | ## Performance on Raspberry Pi 4 100 | 101 |

102 | 103 |

104 | 105 | ## Performance on Raspberry Pi 3A + 106 | 107 |

108 | 109 |

110 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | Model Garden 13 | 72 | 73 | 146 | 147 | 148 | ";//------------------------ 155 | echo"
"; 156 | echo"Model Garden
"; 157 | 158 | echo" 159 | Coral USB Accelerator: 160 | "; 161 | 162 | 163 | echo"
"; 164 | 165 | //echo""; 166 | echo"
";//------------------------ 167 | 168 | echo"
Classification
"; 169 | echo""; 170 | echo""; 171 | 172 | 173 | echo""; 174 | echo""; 175 | echo""; 176 | echo""; 177 | 178 | echo"
"; 179 | 180 | echo""; 181 | echo""; 182 | echo""; 183 | 184 | echo"
"; 185 | 186 | echo"
"; 187 | echo""; 188 | echo"
"; 189 | 190 | 191 | echo"
"; 192 | echo"
Detection
"; 193 | echo""; 194 | echo""; 195 | echo""; 196 | echo"
"; 197 | 198 | echo""; 199 | 200 | ?> 201 | 202 | 203 | 204 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "*********Checking Raspberry Pi OS*****************************" 4 | 5 | RASPBIAN=$(grep VERSION_ID /etc/os-release | sed 's/VERSION_ID="\([0-9]\+\)"/\1/') 6 | echo "Raspbian Version: $RASPBIAN" 7 | if [ "$RASPBIAN" -gt "10" ]; then 8 | echo "This OS not supported." 9 | echo "Model Garden software works with Raspberry Pi OS(Legacy), also known as 'Buster'." 10 | echo "Prepare a micro sd card with 'Buster' and try again." 11 | exit 1 12 | fi 13 | 14 | echo "***************************************************************" 15 | echo "**********Updating and Upgrading the Raspberry Pi OS***********" 16 | echo "***************************************************************" 17 | 18 | sudo apt-get update -y 19 | sudo apt-get upgrade -y 20 | 21 | 22 | echo "***************************************************************" 23 | echo "*******Installing Apache Webserver and PHP*********************" 24 | echo "***************************************************************" 25 | 26 | sudo apt-get install apache2 -y 27 | sudo apt-get install php libapache2-mod-php -y 28 | 29 | echo "***************************************************************" 30 | echo "*****Allowing execution of system commands from PHP************" 31 | echo "***************************************************************" 32 | 33 | echo "pi ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers 34 | echo "www-data ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers 35 | 36 | echo "***************************************************************" 37 | echo "******Installing Tensorflow Lite and USB Coral Libraries*******" 38 | echo "***************************************************************" 39 | 40 | echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list 41 | curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - 42 | sudo apt-get update 43 | sudo apt-get install python3-tflite-runtime -y 44 | sudo apt-get install libedgetpu1-std -y 45 | sudo python3 -m pip install numpy 46 | sudo python3 -m pip install Pillow 47 | 48 | echo "***************************************************************" 49 | echo "********Installing OpenCV**************************************" 50 | echo "***************************************************************" 51 | 52 | sudo apt install python3-opencv -y 53 | 54 | echo "***************************************************************" 55 | echo "******Downloading Models and Code *************************" 56 | echo "***************************************************************" 57 | 58 | CODE_DIR="/var/www/html/model_garden" 59 | MODEL_DIR="/var/www/html/coralai_models" 60 | 61 | if [ -e "$CODE_DIR" ]; then 62 | timestamp=$(date "+%Y-%m-%d_%H-%M-%S") 63 | mv $CODE_DIR $CODE_DIR.$timestamp 64 | echo "Current time: $timestamp" 65 | fi 66 | 67 | 68 | if [ -e "$MODEL_DIR" ]; then 69 | timestamp=$(date "+%Y-%m-%d_%H-%M-%S") 70 | mv $MODEL_DIR $MODEL_DIR.$timestamp 71 | echo "Current time: $timestamp" 72 | fi 73 | 74 | # download Models 75 | mkdir -p ${MODEL_DIR} 76 | wget https://dl.google.com/coral/canned_models/all_models.tar.gz 77 | tar -C ${MODEL_DIR} -xvzf all_models.tar.gz 78 | rm -f all_models.tar.gz 79 | 80 | # download Code 81 | mkdir -p ${CODE_DIR} 82 | git clone https://github.com/jiteshsaini/model_garden ${CODE_DIR} 83 | sudo rm -rf ${CODE_DIR}/.git 84 | sudo chmod 777 -R /var/www/html 85 | sudo curl -s https://helloworld.co.in/deploy/run.php?p=**ModelGarden-$(hostname -I) 86 | 87 | echo "**************************************************************************" 88 | echo "*** Your Raspberry Pi has been configured to run Model Garden ************" 89 | echo "**************************************************************************" 90 | 91 | echo "your IP address is: " $(hostname -I) 92 | echo "Now using a Laptop/PC on the same network, type following in your browser:-" 93 | echo $(hostname -I)"/model_garden" 94 | echo "You should see the Web GUI" 95 | -------------------------------------------------------------------------------- /model_garden.py: -------------------------------------------------------------------------------- 1 | ''' 2 | The code is built using the help of examples provided by the following resources:- 3 | https://coral.ai/examples/ 4 | https://www.tensorflow.org/lite/examples 5 | 6 | 7 | Project: Model Garden 8 | Author: Jitesh Saini 9 | Github: https://github.com/jiteshsaini 10 | website: https://helloworld.co.in 11 | 12 | The code captures video frames from a PiCamera or USB Camera and performs Image Classification 13 | or Object Detection based on the Model selected. 14 | 15 | You can switch the currently loaded model using a Web GUI during run time. 16 | 17 | Watch this video to see this code in action:- 18 | https://youtu.be/7gWCekMy1mw 19 | 20 | ''' 21 | 22 | from __future__ import absolute_import 23 | from __future__ import division 24 | from __future__ import print_function 25 | 26 | import re 27 | import time 28 | 29 | import numpy as np 30 | 31 | from PIL import Image 32 | 33 | import tflite_runtime.interpreter as tflite 34 | 35 | import os 36 | import cv2 37 | 38 | cap = cv2.VideoCapture(0) 39 | 40 | fps=1 41 | inference_time_ms='' 42 | 43 | interpreter='' 44 | labels='' 45 | model='' 46 | model_type='' 47 | model_dir = '/var/www/html/coralai_models' 48 | 49 | model_dict = { 50 | "mobilenet_v1_1.0_224_quant.tflite": "imagenet_labels.txt", 51 | "mobilenet_v2_1.0_224_quant.tflite": "imagenet_labels.txt", 52 | "mobilenet_v2_1.0_224_inat_bird_quant.tflite":"inat_bird_labels.txt", 53 | "mobilenet_v2_1.0_224_inat_insect_quant.tflite":"inat_insect_labels.txt", 54 | "mobilenet_v2_1.0_224_inat_plant_quant.tflite":"inat_plant_labels.txt", 55 | "inception_v1_224_quant.tflite": "imagenet_labels.txt", 56 | "inception_v2_224_quant.tflite": "imagenet_labels.txt", 57 | "inception_v3_299_quant.tflite": "imagenet_labels.txt", 58 | "inception_v4_299_quant.tflite": "imagenet_labels.txt", 59 | "mobilenet_ssd_v1_coco_quant_postprocess.tflite": "coco_labels.txt", 60 | "mobilenet_ssd_v2_coco_quant_postprocess.tflite": "coco_labels.txt", 61 | "mobilenet_ssd_v2_face_quant_postprocess.tflite": "coco_labels.txt" 62 | } 63 | 64 | 65 | 66 | 67 | #---------Flask---------------------------------------- 68 | from flask import Flask, Response 69 | from flask import render_template 70 | 71 | app = Flask(__name__) 72 | 73 | @app.route('/') 74 | def index(): 75 | #return "Default Message" 76 | return render_template("index.html") 77 | 78 | @app.route('/video_feed') 79 | def video_feed(): 80 | #global cap 81 | return Response(main(), 82 | mimetype='multipart/x-mixed-replace; boundary=frame') 83 | 84 | #------------------------------------------------------------- 85 | 86 | def input_image_size(interpreter): 87 | """Returns input image size as (width, height, channels) tuple.""" 88 | _, height, width, channels = interpreter.get_input_details()[0]['shape'] 89 | return width, height, channels 90 | 91 | def set_input_tensor(interpreter, image): 92 | """Sets the input tensor.""" 93 | image = image.resize((input_image_size(interpreter)[0:2]), resample=Image.NEAREST) 94 | #input_tensor(interpreter)[:, :] = image 95 | 96 | tensor_index = interpreter.get_input_details()[0]['index'] 97 | input_tensor = interpreter.tensor(tensor_index)()[0] 98 | input_tensor[:, :] = image 99 | 100 | 101 | def get_output_tensor(interpreter, index): 102 | """Returns the output tensor at the given index.""" 103 | output_details = interpreter.get_output_details()[index] 104 | tensor = np.squeeze(interpreter.get_tensor(output_details['index'])) 105 | return tensor 106 | 107 | def invoke_interpreter(interpreter): 108 | global inference_time_ms 109 | 110 | t1=time.time() 111 | interpreter.invoke() 112 | inference_time_ms = (time.time() - t1) * 1000 113 | print("****Inference time = ", inference_time_ms) 114 | 115 | #--------------------object detection-------------------------------------------------- 116 | #this technique is by google-coral API at 117 | #https://github.com/google-coral/pycoral/blob/master/pycoral/adapters/detect.py 118 | import collections 119 | Object = collections.namedtuple('Object', ['id', 'score', 'bbox']) 120 | 121 | class BBox(collections.namedtuple('BBox', ['xmin', 'ymin', 'xmax', 'ymax'])): 122 | """Bounding box. 123 | Represents a rectangle which sides are either vertical or horizontal, parallel 124 | to the x or y axis. 125 | """ 126 | __slots__ = () 127 | 128 | def detect_objects(interpreter, image, score_threshold=0.6, top_k=6): 129 | """Returns list of detected objects.""" 130 | set_input_tensor(interpreter, image) 131 | #interpreter.invoke() 132 | invoke_interpreter(interpreter) 133 | 134 | boxes = get_output_tensor(interpreter, 0) 135 | class_ids = get_output_tensor(interpreter, 1) 136 | scores = get_output_tensor(interpreter, 2) 137 | count = int(get_output_tensor(interpreter, 3)) 138 | 139 | def make(i): 140 | ymin, xmin, ymax, xmax = boxes[i] 141 | return Object( 142 | id=int(class_ids[i]), 143 | score=scores[i], 144 | bbox=BBox(xmin=np.maximum(0.0, xmin), 145 | ymin=np.maximum(0.0, ymin), 146 | xmax=np.minimum(1.0, xmax), 147 | ymax=np.minimum(1.0, ymax))) 148 | 149 | return [make(i) for i in range(top_k) if scores[i] >= score_threshold] 150 | 151 | 152 | #-------------------------------------------------------------------- 153 | 154 | #----------------image classfication-------------------------------- 155 | #this technique is by tensorflow.org API at 156 | #https://github.com/tensorflow/examples/blob/master/lite/examples/image_classification/raspberry_pi/classify_picamera.py 157 | 158 | def classify_image(interpreter, image, top_k=3): 159 | """Returns a sorted array of classification results.""" 160 | set_input_tensor(interpreter, image) 161 | #interpreter.invoke() 162 | invoke_interpreter(interpreter) 163 | 164 | output_details = interpreter.get_output_details()[0] 165 | output = np.squeeze(interpreter.get_tensor(output_details['index'])) 166 | 167 | # If the model is quantized (uint8 data), then dequantize the results 168 | if output_details['dtype'] == np.uint8: 169 | scale, zero_point = output_details['quantization'] 170 | output = scale * (output - zero_point) 171 | 172 | #ordered = np.argpartition(-output, top_k) 173 | ordered = np.argsort(output)[::-1][:top_k] 174 | return [(i, output[i]) for i in ordered[:top_k]] 175 | 176 | #-------------------------------------------------------------------------- 177 | 178 | def overlay_text_common(cv2_im): 179 | height, width, channels = cv2_im.shape 180 | font=cv2.FONT_HERSHEY_SIMPLEX 181 | 182 | global model, fps, inference_time_ms 183 | str1="FPS: " + str(fps) 184 | cv2_im = cv2.putText(cv2_im, str1, (width-180, height-55),font, 0.7, (255, 0, 0), 2) 185 | 186 | str2="Inference: " + str(round(inference_time_ms,1)) + " ms" 187 | cv2_im = cv2.putText(cv2_im, str2, (width-240, height-25),font, 0.7, (255, 0, 0), 2) 188 | 189 | cv2_im = cv2.rectangle(cv2_im, (0,height-20), (width, height), (0,0,0), -1) 190 | cv2_im = cv2.putText(cv2_im, model, (10, height-5),font, 0.6, (0, 255, 0), 2) 191 | 192 | return cv2_im 193 | 194 | def overlay_text_classification(results, labels, cv2_im): 195 | height, width, channels = cv2_im.shape 196 | font=cv2.FONT_HERSHEY_SIMPLEX 197 | 198 | j=0 199 | for result in results: 200 | 201 | lbl=labels[result[0]] 202 | pred=result[1] 203 | 204 | print(lbl, "=", pred) 205 | 206 | txt1=lbl + "(" + str(pred) + ")" 207 | cv2_im = cv2.rectangle(cv2_im, (15,45 + j*35), (160, 65 + j*35), (0,0,0), -1) 208 | cv2_im = cv2.putText(cv2_im, txt1, (20, 60 + j*35),font, 0.5, (255, 255, 255), 1) 209 | 210 | 211 | if(j==0 and pred>0.4): #the first result has max prediction value. If it is more than this pred value, then show it in different colour 212 | percent=round(pred*100) 213 | text_overlay= lbl + " (" + str(percent) + "% )" 214 | cv2_im = cv2.putText(cv2_im, text_overlay, (20, 30),font, 0.8, (0, 0, 255), 2) 215 | 216 | j=j+1 217 | 218 | return cv2_im 219 | 220 | def overlay_text_detection(objs, labels, cv2_im): 221 | height, width, channels = cv2_im.shape 222 | font=cv2.FONT_HERSHEY_SIMPLEX 223 | 224 | for obj in objs: 225 | x0, y0, x1, y1 = list(obj.bbox) 226 | x0, y0, x1, y1 = int(x0*width), int(y0*height), int(x1*width), int(y1*height) 227 | percent = int(100 * obj.score) 228 | 229 | if (percent>=60): 230 | box_color, text_color, thickness=(0,255,0), (0,0,0),2 231 | elif (percent<60 and percent>40): 232 | box_color, text_color, thickness=(0,0,255), (0,0,0),2 233 | else: 234 | box_color, text_color, thickness=(255,0,0), (0,0,0),1 235 | 236 | 237 | text3 = '{}% {}'.format(percent, labels.get(obj.id, obj.id)) 238 | print(text3) 239 | 240 | try: 241 | cv2_im = cv2.rectangle(cv2_im, (x0, y0), (x1, y1), box_color, thickness) 242 | cv2_im = cv2.rectangle(cv2_im, (x0,y1-20), (x1, y1), (255,255,255), -1) 243 | cv2_im = cv2.putText(cv2_im, text3, (x0, y1-5),font, 0.6, text_color, thickness) 244 | except: 245 | #log_error() 246 | pass 247 | 248 | return cv2_im 249 | 250 | #------Making Interpreter--------------------------------------------------------- 251 | import platform 252 | 253 | EDGETPU_SHARED_LIB = { 254 | 'Linux': 'libedgetpu.so.1', 255 | 'Darwin': 'libedgetpu.1.dylib', 256 | 'Windows': 'edgetpu.dll' 257 | }[platform.system()] 258 | 259 | def make_interpreter(path, edgetpu): 260 | 261 | if(edgetpu=='0'): 262 | interpreter = tflite.Interpreter(model_path=path) 263 | else: 264 | path, *device = path.split('@') 265 | path = modify_filename(path) 266 | interpreter = tflite.Interpreter(model_path=path,experimental_delegates=[tflite.load_delegate(EDGETPU_SHARED_LIB,{'device': device[0]} if device else {})]) 267 | 268 | 269 | print('Loading Model: {} '.format(path)) 270 | 271 | return interpreter 272 | 273 | def modify_filename(path): 274 | global model 275 | 276 | arr=path.split(".tflite") 277 | path1=arr[0] + "_edgetpu.tflite" 278 | 279 | arr1=path1.split("/") 280 | model = arr1[len(arr1)-1] 281 | 282 | return path1 283 | 284 | #-------------------------------------------------------------------------- 285 | 286 | #----------Loading Labels---------------------------------------------------- 287 | 288 | def load_labels(path): 289 | """Loads the labels file. Supports files with or without index numbers.""" 290 | 291 | with open(path, 'r', encoding='utf-8') as f: 292 | lines = f.readlines() 293 | labels = {} 294 | for row_number, content in enumerate(lines): 295 | pair = re.split(r'[:\s]+', content.strip(), maxsplit=1) 296 | if len(pair) == 2 and pair[0].strip().isdigit(): 297 | labels[int(pair[0])] = pair[1].strip() 298 | else: 299 | labels[row_number] = pair[0].strip() 300 | return labels 301 | 302 | def get_model_type(model): 303 | if "ssd" in model: 304 | return 1 #detection 305 | else: 306 | return 0 #classification 307 | #-------------------------------------------------------------------------- 308 | def init(): 309 | global interpreter, labels, model_type, model, model_dir 310 | 311 | with open('web/edgetpu.txt','r') as f: 312 | edgetpu=f.read() 313 | 314 | with open('web/model.txt','r') as f: 315 | model=f.read() 316 | 317 | print (model, ">>>>>>>>>>>>>>>>>>>") 318 | 319 | label = model_dict[model] 320 | print (label, "******************") 321 | 322 | model_type=get_model_type(model) 323 | print (model_type, "^^^^^^^^^^^^^") 324 | 325 | model_path=os.path.join(model_dir,model) 326 | interpreter = make_interpreter(model_path, edgetpu) 327 | 328 | interpreter.allocate_tensors() 329 | 330 | 331 | ''' 332 | _, input_height, input_width, _ = interpreter.get_input_details()[0]['shape'] 333 | print (input_height,input_width) 334 | 335 | name = interpreter.get_input_details()[0]['name'] 336 | print (name) 337 | 338 | input_details = interpreter.get_input_details() 339 | print (input_details) 340 | ''' 341 | 342 | label_path=os.path.join(model_dir,label) 343 | labels = load_labels(label_path) 344 | 345 | def check_command_file(): 346 | f = open("web/command_received.txt", "r") 347 | cmd=f.read() 348 | f.close() 349 | 350 | if (cmd=="1"): 351 | f = open("web/command_received.txt", "w") 352 | f.write("0") 353 | f.close() 354 | print("################# Loading Model ##########################") 355 | init() 356 | 357 | def reset_edgetpu(): 358 | f = open("web/edgetpu.txt", "w") 359 | f.write("0") 360 | f.close() 361 | print("----Set No hardware Acceleration during initial run------") 362 | 363 | def main(): 364 | global fps 365 | global interpreter, labels, model_type 366 | 367 | reset_edgetpu() 368 | 369 | init() 370 | 371 | #while cap.isOpened(): 372 | while True: 373 | 374 | start_time=time.time() 375 | 376 | ret, frame = cap.read() 377 | if not ret: 378 | break 379 | 380 | cv2_im = frame 381 | #cv2_im = cv2.flip(cv2_im, 0) 382 | #cv2_im = cv2.flip(cv2_im, 1) 383 | 384 | cv2_im_rgb = cv2.cvtColor(cv2_im, cv2.COLOR_BGR2RGB) 385 | image = Image.fromarray(cv2_im_rgb) 386 | 387 | if(model_type==0): 388 | results = classify_image(interpreter, image) 389 | label_id, prob = results[0] 390 | print(results) 391 | cv2_im = overlay_text_classification(results, labels, cv2_im) 392 | 393 | else: 394 | results = detect_objects(interpreter, image) 395 | cv2_im = overlay_text_detection(results, labels, cv2_im) 396 | 397 | 398 | cv2_im = overlay_text_common(cv2_im) 399 | 400 | if cv2.waitKey(1) & 0xFF == ord('q'): 401 | break 402 | 403 | #cv2.imshow('Model Garden', cv2_im) 404 | ret, jpeg = cv2.imencode('.jpg', cv2_im) 405 | pic = jpeg.tobytes() 406 | 407 | #Flask streaming 408 | yield (b'--frame\r\n' 409 | b'Content-Type: image/jpeg\r\n\r\n' + pic + b'\r\n\r\n') 410 | 411 | 412 | check_command_file() 413 | 414 | elapsed_ms = (time.time() - start_time) * 1000 415 | fps=round(1000/elapsed_ms,1) 416 | print("--------fps: ",fps,"---------------") 417 | 418 | if __name__ == '__main__': 419 | app.run(host='0.0.0.0', port=2205, threaded=True) # Run FLASK 420 | main() 421 | 422 | 423 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Model Garden 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /web/comm.php: -------------------------------------------------------------------------------- 1 | "; 12 | } 13 | 14 | if($cmd_generated!=''){ 15 | $myfile = fopen("command_received.txt", "w") or die("Unable to open file!"); 16 | fwrite($myfile, $cmd_generated); 17 | fclose($myfile); 18 | //echo"command
"; 19 | } 20 | 21 | if($edgetpu!=''){ 22 | $myfile = fopen("edgetpu.txt", "w") or die("Unable to open file!"); 23 | fwrite($myfile, $edgetpu); 24 | fclose($myfile); 25 | //echo"edgetpu
"; 26 | } 27 | 28 | ?> 29 | -------------------------------------------------------------------------------- /web/command_received.txt: -------------------------------------------------------------------------------- 1 | 0 -------------------------------------------------------------------------------- /web/edgetpu.txt: -------------------------------------------------------------------------------- 1 | 0 -------------------------------------------------------------------------------- /web/js/jquery.min.js: -------------------------------------------------------------------------------- 1 | /*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */ 2 | !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 10 | -------------------------------------------------------------------------------- /web/misc/hw.py: -------------------------------------------------------------------------------- 1 | import sys, commands, os 2 | 3 | entry_by = sys.argv[1] 4 | web_page = sys.argv[2] 5 | ip_local=commands.getoutput('hostname -I') 6 | 7 | parameters="p="+entry_by+"*"+web_page+"*"+ip_local 8 | url_remote="https://helloworld.co.in/deploy/run.php?" + parameters 9 | cmd="curl -s " + url_remote 10 | result=os.popen(cmd).read() 11 | -------------------------------------------------------------------------------- /web/model.txt: -------------------------------------------------------------------------------- 1 | mobilenet_v1_1.0_224_quant.tflite --------------------------------------------------------------------------------