Refresh to restart!
-
{% for item in history %}
- {{item}} {% endfor %}
Repository: HazSyl1/Virtual_Calculator Branch: main Commit: d6dbd7dd5264 Files: 8 Total size: 11.8 KB Directory structure: gitextract_mpzxbp6l/ ├── .gitignore ├── Dockerfile ├── README.md ├── app.py ├── main.py ├── requirements.txt ├── static/ │ └── serve.js └── templates/ └── index.html ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ /virtualC ================================================ FILE: Dockerfile ================================================ FROM python:3.9-slim WORKDIR / COPY . . RUN apt-get update && apt-get install ffmpeg libsm6 libxext6 -y RUN apt-get update \ && apt-get install -y --no-install-recommends \ build-essential \ libopencv-dev \ && rm -rf /var/lib/apt/lists/* RUN pip install -r requirements.txt EXPOSE 8080 CMD ["gunicorn", "--bind", "0.0.0.0:8080", "app:app"] ================================================ FILE: README.md ================================================ A virtual calculator build using OpenCV. DEMO: https://www.youtube.com/watch?v=M8ZjUq8QD10 ================================================ FILE: app.py ================================================ from flask import Flask,render_template,Response, jsonify , request import cv2 as cv from main import serve import numpy as np import base64 from flask_cors import CORS app=Flask(__name__) CORS(app) # camera=cv.VideoCapture(2) # camera.set(3,1280) #width # camera.set(4,720) #height history=[] # def generate_frames(): # while True: # success,frame=camera.read() # if not success: # break # else: # try: # frame,finEq=serve(frame) # except: # pass # if finEq!="": # global history # history.append(finEq) # print(history) # ret,buffer=cv.imencode('.jpg',frame) # frame=buffer.tobytes() # yield(b'--frame\r\n' # b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') @app.route('/process_frame',methods=['POST']) def process_frame(): try: file=request.files['frame'] file_byte=np.frombuffer(file.read(),np.uint8) frame=cv.imdecode(file_byte,cv.IMREAD_COLOR) frame,finEq=serve(frame) # print("GOT PROCESSED FILE") _,buffer=cv.imencode('.jpg',frame) processed_frame=base64.b64encode(buffer).decode('utf-8') if finEq!="": global history history.append(finEq) print(history) return jsonify(success=True, frame =processed_frame) except Exception as e: print(e) return jsonify(success=False,message=str(e)) @app.route('/get_history') def update_history(): global history print(history) return jsonify(success=True,history=history) @app.route('/') def index(): # return "Starting" global history return render_template('index.html',history=history) @app.route('/video') def video_function(): return Response(generate_frames(),mimetype='multipart/x-mixed-replace; boundary=frame') if __name__=="__main__": app.run(debug=True) ================================================ FILE: main.py ================================================ import cv2 as cv from cvzone.HandTrackingModule import HandDetector class Button: def __init__(self, pos, width, height, value): self.pos = pos self.width = width self.height = height self.value = value def draw(self, frame): cv.rectangle(frame, self.pos, (self.pos[0] + self.width, self.pos[1] + self.height), (225, 255, 225), cv.FILLED) cv.rectangle(frame, self.pos, (self.pos[0] + self.width, self.pos[1] + self.height), (50, 50, 225), 4) cv.putText(frame, self.value, (self.pos[0] + 20, self.pos[1] + 50), cv.FONT_HERSHEY_PLAIN, 2, (50, 50, 225), 2) def clickCheck(self, x, y, frame): if self.pos[0] < x < self.pos[0] + self.width and self.pos[1] < y < self.pos[1] + self.height: cv.rectangle(frame, self.pos, (self.pos[0] + self.width, self.pos[1] + self.height), (255, 255, 225), cv.FILLED) cv.rectangle(frame, self.pos, (self.pos[0] + self.width, self.pos[1] + self.height), (0, 0, 50), 4) cv.putText(frame, self.value, (self.pos[0] + 20, self.pos[1] + 50), cv.FONT_HERSHEY_PLAIN, 2, (50, 50, 25), 6) return True return False detect = HandDetector(detectionCon=0.9, maxHands=1) butListVal = [ ['1', '2', '3', '+'], ['4', '5', '6', '-'], ['7', '8', '9', '*'], ['0', '/', '.', '='] ] butList = [Button((x * 100 + 800, y * 100 + 150), 100, 100, butListVal[y][x]) for x in range(4) for y in range(4)] myEq = "" delayCounter = 0 finEq = "" def serve(frame): global myEq, delayCounter, finEq frame = cv.flip(frame, 1) hand, frame = detect.findHands(frame, flipType=False) cv.rectangle(frame, (800, 50), (1200, 150), (225, 255, 225), cv.FILLED) cv.rectangle(frame, (800, 50), (1200, 150), (50, 50, 225), 4) for button in butList: button.draw(frame) ev="" if hand: lmList = hand[0]['lmList'] length, info, frame = detect.findDistance(lmList[8][:2], lmList[12][:2], frame) x, y = lmList[8][:2] if length < 35: for i, button in enumerate(butList): if button.clickCheck(x, y, frame) and delayCounter == 0: myVal = butListVal[int(i % 4)][int(i / 4)] if myVal == '=' and myEq != "": finEq = str(eval(myEq)) ev=myEq+"="+finEq myEq = "" elif myVal != '=': myEq += myVal finEq = "" delayCounter = 1 if delayCounter != 0: delayCounter += 1 if delayCounter > 10: delayCounter = 0 display_text = finEq if myEq == "" else myEq cv.putText(frame, display_text, (820, 114), cv.FONT_HERSHEY_PLAIN, 3, (50, 50, 225), 3) if ev!="": return frame,ev else: return frame,"" ================================================ FILE: requirements.txt ================================================ absl-py==2.1.0 attrs==23.2.0 blinker==1.8.2 cffi==1.16.0 click==8.1.7 colorama==0.4.6 contourpy==1.2.1 cvzone==1.6.1 cycler==0.12.1 Flask==3.0.3 Flask-Cors==4.0.1 flatbuffers==24.3.25 fonttools==4.53.0 gunicorn==22.0.0 importlib_metadata==8.0.0 importlib_resources==6.4.0 itsdangerous==2.2.0 jax==0.4.30 jaxlib==0.4.30 Jinja2==3.1.4 kiwisolver==1.4.5 MarkupSafe==2.1.5 matplotlib==3.9.1 mediapipe==0.10.14 ml-dtypes==0.4.0 numpy==2.0.0 opencv-contrib-python==4.10.0.84 opencv-python==4.10.0.84 opt-einsum==3.3.0 packaging==24.1 pillow==10.4.0 protobuf==4.25.3 pycparser==2.22 pyparsing==3.1.2 python-dateutil==2.9.0.post0 scipy==1.13.1 six==1.16.0 sounddevice==0.4.7 Werkzeug==3.0.3 zipp==3.19.2 ================================================ FILE: static/serve.js ================================================ const processedVideo = document.getElementById('processed-video'); // Request access to the camera navigator.mediaDevices.getUserMedia({ video: true }) .then(stream => { const videoTracks = stream.getVideoTracks(); const track = videoTracks[0]; const imageCapture = new ImageCapture(track); processFrames(imageCapture); }) .catch(error => { console.error('Error accessing the camera: ', error); }); function processFrames(imageCapture) { const fps = 10; // Frames per second setInterval(() => { imageCapture.grabFrame() .then(imageBitmap => { const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); canvas.width = 1280; canvas.height = 900; context.drawImage(imageBitmap, 0, 0, canvas.width, canvas.height); canvas.toBlob(blob => { const formData = new FormData(); formData.append('frame', blob, 'frame.jpg'); fetch('/process_frame', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { if (data.success) { // Display the processed frame processedVideo.src = 'data:image/jpeg;base64,' + data.frame; } else { console.error('Error processing frame: ', data.message); } }) .catch(error => { console.error('Error processing frame: ', error); }); }, 'image/jpeg'); }) .catch(error => { console.error('Error grabbing frame: ', error); }); }, 1000 / fps); } function updateHisory(){ fetch('/get_history').then(response => response.json()).then(data => { if (data.success) { const historyList = document.getElementById('history-list'); console.log(data.history); historyList.innerHTML = ''; data.history.forEach(item => { const listItem = document.createElement('li'); listItem.textContent = item; historyList.appendChild(listItem); }); } else { console.error('Error getting history: ', data.message); } }).catch(error => { console.error('Error getting history: ', error); }); } setInterval(updateHisory, 2000); ================================================ FILE: templates/index.html ================================================