From 33ee68d8128f0694b88e1a9b4be3581735769cc8 Mon Sep 17 00:00:00 2001 From: khemendra kumar Date: Mon, 11 Jan 2021 17:25:30 +0530 Subject: [PATCH] example app backend code Signed-off-by: khemendra kumar Change-Id: Ia20a5041dbff08a0e34350c41b86fde8c4f7abd0 --- example-apps/ROBO/retail_app/Dockerfile | 15 +- .../ROBO/retail_app/inventry/capture_frame.py | 53 ++++++ .../ROBO/retail_app/inventry/retail_app.py | 183 ++++++++++++++++++--- example-apps/ROBO/retail_app/requirements.txt | 6 +- 4 files changed, 223 insertions(+), 34 deletions(-) create mode 100644 example-apps/ROBO/retail_app/inventry/capture_frame.py diff --git a/example-apps/ROBO/retail_app/Dockerfile b/example-apps/ROBO/retail_app/Dockerfile index c84560a..3d76af3 100644 --- a/example-apps/ROBO/retail_app/Dockerfile +++ b/example-apps/ROBO/retail_app/Dockerfile @@ -25,8 +25,9 @@ RUN sed -i "s|umask 022|umask 027|g" /etc/profile # Create the home directory for the new app user. RUN mkdir -p /usr/app RUN mkdir -p /usr/app/bin -RUN mkdir -p /usr/app/detection -RUN mkdir -p /usr/app/resources +RUN mkdir -p /usr/app/inventry +RUN mkdir -p /usr/app/test/resources +RUN mkdir -p /usr/app/images # Set the home directory to our app user's home. ENV APP_HOME=/usr/app @@ -69,9 +70,11 @@ WORKDIR $APP_HOME # Copy the application & scripts COPY config.py requirements.txt run.py $APP_HOME/ -COPY detection $APP_HOME/monitoring/ -COPY resources $APP_HOME/resources/ -COPY configs/*.sh $APP_HOME/bin +COPY inventry $APP_HOME/inventry/ +COPY test $APP_HOME/test/ +COPY test/resources $APP_HOME/test/resources/ +#COPY configs/*.sh $APP_HOME/bin +COPY configs/start.sh $APP_HOME/bin RUN chmod 750 $APP_HOME &&\ chmod -R 550 $APP_HOME/bin &&\ @@ -80,7 +83,7 @@ RUN chmod 750 $APP_HOME &&\ chown -R $USER_NAME:$GROUP_NAME $APP_HOME # Exposed port -EXPOSE 9997 +EXPOSE 9996 # Change to the app user. USER $USER_NAME diff --git a/example-apps/ROBO/retail_app/inventry/capture_frame.py b/example-apps/ROBO/retail_app/inventry/capture_frame.py new file mode 100644 index 0000000..eb66edc --- /dev/null +++ b/example-apps/ROBO/retail_app/inventry/capture_frame.py @@ -0,0 +1,53 @@ +# +# Copyright 2020 Huawei Technologies Co., Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import cv2 + + +class VideoCamera(object): + """ + opneCV to capture frame from a camera + """ + def __init__(self, url): + self.video = cv2.VideoCapture(url) + + def delete(self): + self.video.release() + + def get_frame(self): + """ + get a frame from camera url + """ + success, image = self.video.read() + return success, image + + +class VideoFile(object): + """ + opneCV to capture frame from a video stream + """ + def __init__(self, video_name): + self.video = cv2.VideoCapture("./test/resources/" + video_name) + + def delete(self): + self.video.release() + + def get_frame(self): + """ + get a frane from stream + """ + success, image = self.video.read() + return success, image diff --git a/example-apps/ROBO/retail_app/inventry/retail_app.py b/example-apps/ROBO/retail_app/inventry/retail_app.py index 7de018e..e3f98d3 100644 --- a/example-apps/ROBO/retail_app/inventry/retail_app.py +++ b/example-apps/ROBO/retail_app/inventry/retail_app.py @@ -18,11 +18,14 @@ import config from flask_sslify import SSLify from flask import Flask, request, jsonify, Response from flask_cors import CORS -from camera_driver.capture_frame import VideoCamera, VideoFile -from influxdb import InfluxDBClient +# from camera_driver.capture_frame import VideoCamera, VideoFile +# from capture_frame import VideoCamera, VideoFile +# from influxdb import InfluxDBClient import json import time import requests +import os +import cv2 app = Flask(__name__) @@ -34,18 +37,20 @@ app.config['supports_credentials'] = True app.config['CORS_SUPPORTS_CREDENTIALS'] = True app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg']) +ALLOWED_VIDEO_EXTENSIONS = {'mp4'} count = 0 listOfMsgs = [] listOfCameras = [] listOfVideos = [] +mock_func = 1 -class inventry_info: +class inventory_info: """ Store the data and manage multiple input video feeds """ def __init__(self, current_count=0, total_count=0, time=0): - self.type = "Shelf_INV" + self.type = "Shelf_INV1" self.labels = "Bottles" self.current_count = current_count self.total_count = total_count @@ -76,32 +81,90 @@ class inventry_info: return self.time -def store_data(inventry_info): +# temporary copied capture_frame file to this due to docker issue for module +# import + +class VideoCamera(object): + """ + opneCV to capture frame from a camera + """ + def __init__(self, url): + self.video = cv2.VideoCapture(url) + + def delete(self): + self.video.release() + + def get_frame(self): + """ + get a frame from camera url + """ + success, image = self.video.read() + return success, image + + +class VideoFile(object): + """ + opneCV to capture frame from a video stream + """ + def __init__(self, video_name): + self.video = cv2.VideoCapture("./test/resources/" + video_name) + + def delete(self): + self.video.release() + + def get_frame(self): + """ + get a frane from stream + """ + success, image = self.video.read() + return success, image + + +def store_data(inventory_info): """ store time series data in influx db """ # TODO config, schema table, DB, fill data set create_database() - store_info_db(inventry_info) + store_info_db(inventory_info) -def shelf_inventry(video_capture, camera_info): +def mock_table(inven_info): + current_count = 3 + labels = "Bottles" + total_count = 6 + inven_info.setcurrentcount(current_count) + inven_info.settotalcount(total_count) + inven_info.setlabel(labels) + inven_info.utime = time.time() + # store_data(inven_info) + local_store(inven_info) + + +def shelf_inventory(video_capture, camera_info, true=None): """ - 人脸识别 + shelf_inventory """ global count + global mock_func + labels = "bottles" process_this_frame = 0 - while True: - success, frame = video_capture.get_frame() - if not success: - break - if process_this_frame == 0: - url = config.detection_url + "/v1/obj_detection/detect" - # info1 = cv2.imencode(".jpg", rgb_small_frame)[1].tobytes() - data = json.loads(requests.post(url, data=frame, - verify=config.ssl_cacertpath).text) - inven_info = inventry_info() + if mock_func == 1: + inven_info = inventory_info() + mock_table(inven_info) + else: + while True: + success, frame = video_capture.get_frame() + if not success: + break + if process_this_frame == 0: + url = config.detection_url + "/v1/obj_detection/detect" + # info1 = cv2.imencode(".jpg", rgb_small_frame)[1].tobytes() + data = json.loads(requests.post + (url, data=frame, + verify=config.ssl_cacertpath).text) + inven_info = inventory_info() current_count = data[count] labels = data[labels] total_count = inven_info.current_count + inven_info.total_count @@ -109,7 +172,24 @@ def shelf_inventry(video_capture, camera_info): inven_info.settotalcount(total_count) inven_info.setlabel(labels) inven_info.utime = time.time() - store_data(inven_info) + # store_data(inven_info) + local_store(inven_info) + + +def local_store(inven_info): + """ + store "shelf" data to array + + :param inven_info: Inventry object + :return: None + """ + if len(listOfMsgs) >= 100: + listOfMsgs.pop() + newdict = {"shelfName": inven_info.type, "ObjType": inven_info.labels, + "currentCount": inven_info.current_count, + "totalCount": inven_info.total_count, + "time": time.time()} + listOfMsgs.insert(0, newdict) def store_info_db(inven_info): @@ -142,11 +222,55 @@ def create_database(): :return: None """ global db_client +# proxy = {"http": "http://{}:{}".format(config.IPADDRESS, config.PORT)} +# db_client = InfluxDBClient(host=config.IPADDRESS, port=config.PORT, +# proxies=proxy, database=config.DATABASE_NAME) +# db_client.create_database(config.DATABASE_NAME) - proxy = {"http": "http://{}:{}".format(config.IPADDRESS, config.PORT)} - db_client = InfluxDBClient(host=config.IPADDRESS, port=config.PORT, - proxies=proxy, database=config.DATABASE_NAME) - db_client.create_database(config.DATABASE_NAME) + +@app.route('/v1/inventry/table', methods=['GET']) +def inventry_table(): + """ + return inventry table + + :return: inventry table + """ + return jsonify(listOfMsgs) + + +@app.route('/v1/inventry/image', methods=['GET']) +def detected_image(): + """ + return inventry table + + :return: inventry table + """ + return jsonify(listOfMsgs) + + +def allowed_videofile(filename): + """ + File types to upload:mp4 + param: filename: + """ + return '.' in filename and \ + filename.rsplit('.', 1)[1].lower() in ALLOWED_VIDEO_EXTENSIONS + + +@app.route('/v1/monitor/video', methods=['POST']) +def upload_video(): + app.logger.info("Received message from ClientIP [" + request.remote_addr + + "] Operation [" + request.method + "]" + + " Resource [" + request.url + "]") + if 'file' in request.files: + files = request.files.getlist("file") + for file in files: + if allowed_videofile(file.filename): + file.save(os.path.join(app.config['VIDEO_PATH'], + file.filename)) + else: + raise IOError('video format error') + return Response("success") @app.route('/v1/monitor/cameras', methods=['POST']) @@ -175,13 +299,13 @@ def get_camera(name, rtspurl, location): video_file = VideoFile(camera_info["rtspurl"]) video_dict = {camera_info["name"]: video_file} listOfVideos.append(video_dict) - return Response(shelf_inventry(video_file, camera_info["name"]), + return Response(shelf_inventory(video_file, camera_info["name"]), mimetype='multipart/x-mixed-replace; boundary=frame') else: video_file = VideoCamera(camera_info["rtspurl"]) video_dict = {camera_info["name"]: video_file} listOfVideos.append(video_dict) - return Response(shelf_inventry(video_file, camera_info["name"]), + return Response(shelf_inventory(video_file, camera_info["name"]), mimetype='multipart/x-mixed-replace; boundary=frame') @@ -209,7 +333,14 @@ def query_cameras(): + "] Operation [" + request.method + "]" + " Resource [" + request.url + "]") return jsonify(listOfCameras) - return Response("success") + + +@app.route('/', methods=['GET']) +def hello_world(): + app.logger.info("Received message from ClientIP [" + request.remote_addr + + "] Operation [" + request.method + "]" + + " Resource [" + request.url + "]") + return Response("Hello MEC Developer") def start_server(handler): diff --git a/example-apps/ROBO/retail_app/requirements.txt b/example-apps/ROBO/retail_app/requirements.txt index 9e7cae3..dd037ca 100644 --- a/example-apps/ROBO/retail_app/requirements.txt +++ b/example-apps/ROBO/retail_app/requirements.txt @@ -14,8 +14,10 @@ # limitations under the License. # -flask -requests +flask~=1.1.2 +requests~=2.18.4 flask_sslify opencv-python flask_cors + +influxdb~=5.3.1 \ No newline at end of file -- 2.16.6