Last active
January 30, 2023 14:32
-
-
Save hughpearse/2e4f90999a230bdff9ba823826a98a70 to your computer and use it in GitHub Desktop.
desktop webcam app
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#python37 | |
# Author: Hugh Pearse | |
# Description: display webcam with background removal (body segmentation) in transparant window and follow mouse cursor | |
# | |
# Setup instructions: | |
# python -m venv sandbox | |
# sandbox\Scripts\activate | |
# pip install absl-py==1.4.0 astunparse==1.6.3 cachetools==5.3.0 certifi==2022.12.7 charset-normalizer==3.0.1 flatbuffers==23.1.21 gast==0.4.0 google-auth==2.16.0 google-auth-oauthlib==0.4.6 google-pasta==0.2.0 grpcio==1.51.1 h5py==3.8.0 idna==3.4 importlib-metadata==6.0.0 keras==2.11.0 libclang==15.0.6.1 Markdown==3.4.1 MarkupSafe==2.1.2 numpy==1.23.5 oauthlib==3.2.2 opencv-python==4.7.0.68 opt-einsum==3.3.0 packaging==20.9 Pillow==9.4.0 protobuf==3.19.6 pyasn1==0.4.8 pyasn1-modules==0.2.8 pyfakewebcam==0.1.0 pyparsing==3.0.9 PyQt5==5.15.8 PyQt5-Qt5==5.15.2 PyQt5-sip==12.11.1 requests==2.28.2 requests-oauthlib==1.3.1 rsa==4.9 six==1.16.0 tensorboard==2.11.2 tensorboard-data-server==0.6.1 tensorboard-plugin-wit==1.8.1 tensorflow==2.11.0 tensorflow-estimator==2.11.0 tensorflow-hub==0.12.0 tensorflow-intel==2.11.0 tensorflow-io-gcs-filesystem==0.30.0 tensorflowjs==3.18.0 termcolor==2.2.0 tf-bodypix==0.4.2 tfjs-graph-converter==1.6.1 typing_extensions==4.4.0 urllib3==1.26.14 Werkzeug==2.2.2 wrapt==1.14.1 zipp==3.12.0 | |
# python ./app.py | |
# | |
# Statically compile: | |
# open anaconda console | |
# sandbox\Scripts\activate | |
# pip install pyinstaller==5.7.0 | |
# pyinstaller app.py -F --noconsole | |
# .\dist\app.exe | |
# | |
# References | |
# https://www.codepile.net/pile/ey9KAnxn | |
# https://github.com/nicknochnack/BodyPixBackgroundRemoval/blob/main/BodyPix%20Background%20Removal.ipynb | |
# https://pypi.org/project/tf-bodypix/ | |
import sys | |
from PyQt5.QtGui import (QImage, QPixmap, QCursor) | |
from PyQt5.QtWidgets import (QWidget, QApplication, QVBoxLayout, QLabel) | |
from PyQt5.QtCore import (Qt, pyqtSignal, QThread) | |
import cv2 | |
from tf_bodypix.api import download_model, load_model, BodyPixModelPaths | |
from time import sleep | |
class MainWindow(QWidget): | |
def __init__(self): | |
super(MainWindow, self).__init__() | |
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) | |
self.setAttribute(Qt.WA_TranslucentBackground) | |
self.VBL = QVBoxLayout() | |
self.FeedLabel = QLabel() | |
self.VBL.addWidget(self.FeedLabel) | |
self.Worker1 = Worker1() | |
self.Worker1.start() | |
self.Worker1.ImageUpdate.connect(self.ImageUpdateSlot) | |
self.setLayout(self.VBL) | |
def ImageUpdateSlot(self, Image): | |
self.FeedLabel.setPixmap(QPixmap.fromImage(Image)) | |
cursor = QCursor() | |
cursor_pos = cursor.pos() | |
self.move(round( cursor_pos.x() - Image.width() / 2), round(cursor_pos.y())) | |
def CancelFeed(self): | |
self.Worker1.stop() | |
class Worker1(QThread): | |
ImageUpdate = pyqtSignal(QImage) | |
def run(self): | |
self.ThreadActive = True | |
Capture = cv2.VideoCapture(0) | |
self.bodypix_model = load_model(download_model( | |
BodyPixModelPaths.MOBILENET_FLOAT_50_STRIDE_16 | |
)) | |
while self.ThreadActive: | |
ret, frame = Capture.read() | |
width,height,dimension=frame.shape | |
newWidth, newHeight = round(width // 2), round(height // 2) | |
frame = cv2.resize(frame, (newHeight, newWidth)) | |
if ret: | |
sleep(0.05) | |
result = self.bodypix_model.predict_single(frame) | |
mask = result.get_mask(threshold=0.5).numpy().astype(dtype='uint8') | |
mask = result.get_part_mask(mask, ["left_face","right_face"]) | |
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) | |
Image = cv2.bitwise_and(frame, frame, mask=mask) | |
FlippedImage = cv2.flip(Image, 1) | |
ConvertToQtFormat = QImage(FlippedImage.data, FlippedImage.shape[1], FlippedImage.shape[0], QImage.Format_RGBA8888) | |
Pic = ConvertToQtFormat.scaled(round(640/3), round(480/3), Qt.KeepAspectRatio) | |
self.ImageUpdate.emit(Pic) | |
def stop(self): | |
self.ThreadActive = False | |
self.quit() | |
if __name__ == "__main__": | |
App = QApplication(sys.argv) | |
Root = MainWindow() | |
Root.show() | |
sys.exit(App.exec()) |
Author
hughpearse
commented
Jan 28, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment