Skip to content

Commit 707b911

Browse files
Merge pull request prathimacode-hub#966 from TusharAMD/Python_Virtual_Camera
Python virtual camera
2 parents 36a2d51 + 3f0575b commit 707b911

File tree

11 files changed

+232
-0
lines changed

11 files changed

+232
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Privacy Virtual Camera
2+
![Privacy](https://cdn0.iconfinder.com/data/icons/bubbly-icons/512/Eye_Sight_Privacy_Visibility_Retina_Look_View_Search-512.png)
3+
4+
5+
## Aim
6+
7+
This project is a virtual camera that will be made using OpenCV which will enable user to hide his/her face during video call and only outline of their face will be seen.
8+
9+
![Animation](https://github.com/TusharAMD/Awesome_Python_Scripts/blob/Python_Virtual_Camera/ImageProcessingScripts/Privacy%20Virtual%20Camera/Images/Screenshots/animation.gif?raw=true)
10+
11+
## Purpose
12+
13+
There are many reasons when users don't wish to show their face and don't want the other person to recognize their identity from their voice. In simpler words, users wish to hide identity and at the same time have a video chat. There can be various examples like medical help, or if the judge has to provide an unbiased verdict without knowing someone's race, gender, etc. For such reasons, we can use just an outline of the face and the speech will be converted into text and will be displayed below the video.
14+
15+
## Short description of package/script
16+
17+
- This program uses virtual camera technique to convert open cv video output stream into camera input
18+
- It is necessary to have OBS virtual camera plugin to be installed
19+
- When the user runs vcam.py file the virtual camera will be started and he/she can use that camera in any meeting application
20+
- Also user can speak through their microphone and text will be displayed.
21+
22+
23+
## Workflow of the Project
24+
25+
1. User face is captured and send into script
26+
2. Face mesh is created and placed on plain canvas
27+
3. At same time user microphone input is taken and converted into text
28+
4. This is saved in text file and then retrieved from there into program function
29+
5. Text is placed in image and send to virtual camera
30+
6. This image now can be displayed in video chat
31+
32+
33+
34+
## Setup instructions
35+
36+
1. Install OBS virtual camera plugin
37+
2. Attach Webcamera and Microphone to PC
38+
3. Run vcam.py script
39+
4. You can optionally change the image of mask, color of face outline and also background
40+
5. Open any meet application and in camera section select OBS virtual camera
41+
6. You should see privacy virtual camera output on the screen
42+
43+
## Compilation Steps
44+
45+
This program using multiprocessing and it runs 2 functions i.e. "takesinput" and "program" simultaneously.
46+
When user runs the script a plain canvas of specified solid color is created.
47+
On that the face mesh is placed using mediapipe library
48+
Also a face mask can be applied on eyes.
49+
The face mask are placed according to the eye position and also size is mantained in respect of face dimensions.
50+
In takesinput function the microphone input is converted into text using speech recognition library and displayed on the canvas
51+
This image is then send to virtual camera and can me used in any meet application
52+
53+
54+
## Output
55+
56+
![3](https://raw.githubusercontent.com/TusharAMD/Awesome_Python_Scripts/Python_Virtual_Camera/ImageProcessingScripts/Privacy%20Virtual%20Camera/Images/Screenshots/3.jpg)
57+
![1](https://raw.githubusercontent.com/TusharAMD/Awesome_Python_Scripts/Python_Virtual_Camera/ImageProcessingScripts/Privacy%20Virtual%20Camera/Images/Screenshots/1.jpg)
58+
![2](https://raw.githubusercontent.com/TusharAMD/Awesome_Python_Scripts/Python_Virtual_Camera/ImageProcessingScripts/Privacy%20Virtual%20Camera/Images/Screenshots/2.jpg)
59+
60+
61+
## Author(s)
62+
63+
Tushar Amdoskar
64+
65+
[Tushar's Website](https://tusharamd.github.io/)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Python is best programming language
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pyvirtualcam==0.8.0
2+
cvzone==1.4.1
3+
SpeechRecognition==3.8.1
4+
numpy==1.17.3
5+
mediapipe==0.8.3.1
6+
opencv_python==4.5.3.56
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
import cv2
2+
import pyvirtualcam # For making virtual camera
3+
from pyvirtualcam import PixelFormat
4+
import numpy as np
5+
import mediapipe as mp # Face Mesh
6+
7+
import multiprocessing # Enables python to run 2 processes at same time
8+
import time
9+
import speech_recognition as sr # Speech Recognizer
10+
import cvzone as cv
11+
12+
## This function is used to take real time microphone input from user
13+
14+
def takesinput():
15+
r = sr.Recognizer()
16+
mic = sr.Microphone(device_index=1)
17+
#print(sr.Microphone.list_microphone_names())
18+
text=""
19+
with mic as source:
20+
21+
while True:
22+
r.adjust_for_ambient_noise(source) # To avoid taking background noise
23+
audio = r.listen(source)
24+
try:
25+
text=r.recognize_google(audio)
26+
except:
27+
pass
28+
29+
#result.value=text
30+
print(text)
31+
fh = open("Utils/words.txt","w+") # Saving Text in words text file (to be retrieved later)
32+
fh.write(text)
33+
print(fh.read(),"from takesinput")
34+
fh.close()
35+
36+
37+
def program():
38+
print(1)
39+
mp_drawing = mp.solutions.drawing_utils # For face mesh
40+
mp_face_mesh = mp.solutions.face_mesh
41+
face_cascade = cv2.CascadeClassifier(r'C:\Users\tusha\AppData\Local\Programs\Python\Python38\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml')
42+
camera_no=0
43+
'''
44+
try:
45+
camera_no = int(input("Enter Camera Number : "))
46+
except:
47+
pass
48+
# Set up webcam capture.
49+
'''
50+
vcam = cv2.VideoCapture(camera_no) # Change camera no if camera doesn't detect
51+
52+
if not vcam.isOpened():
53+
raise RuntimeError('Could not open video source')
54+
55+
#Settings for virtual camera
56+
pref_width = 1280
57+
pref_height = 720
58+
pref_fps_in = 30
59+
vcam.set(cv2.CAP_PROP_FRAME_WIDTH, pref_width)
60+
vcam.set(cv2.CAP_PROP_FRAME_HEIGHT, pref_height)
61+
vcam.set(cv2.CAP_PROP_FPS, pref_fps_in)
62+
63+
width = int(vcam.get(cv2.CAP_PROP_FRAME_WIDTH))
64+
height = int(vcam.get(cv2.CAP_PROP_FRAME_HEIGHT))
65+
fps_in = vcam.get(cv2.CAP_PROP_FPS)
66+
print(f'Webcam capture started ({width}x{height} @ {fps_in}fps)') # Prints fps of vcam
67+
68+
69+
###### CUSTOM CHANGES CAN BE MADE HERE #######
70+
images=['Images/mask1.png','Images/mask2.png','Images/mask3.png','Images/mask4.png']
71+
mask_img = cv2.imread(images[0],cv2.IMREAD_UNCHANGED) #### Change this Image to any Eye wear of your choice
72+
colorsavailable=[(255,255,255),(0,255,255),(0,0,255),(255,0,255),(0,0,255),(0,0,0),(100,20,100),(208, 253, 255)]
73+
chooseColor=colorsavailable[0]
74+
bgColor=colorsavailable[6]
75+
##############################################
76+
77+
78+
fps_out = 20
79+
with pyvirtualcam.Camera(width, height, fps_out, fmt=PixelFormat.BGR, print_fps=fps_in) as cam:
80+
print(f'Virtual cam started: {cam.device} ({cam.width}x{cam.height} @ {cam.fps}fps)')
81+
while True:
82+
ret, frame = vcam.read()
83+
faces=face_cascade.detectMultiScale(frame, 1.2, 5, 0, (120, 120), (350, 350)) #Detecting face using face cascade
84+
if not ret:
85+
raise RuntimeError('Error fetching frame')
86+
87+
# Send to virtual cam.
88+
img = np.zeros((480,640,3), dtype=np.uint8)
89+
img.fill(255)
90+
img = np.full((480, 640, 3), bgColor, np.uint8) # Making a plain canvas with specific solid color
91+
face_mesh = mp_face_mesh.FaceMesh(
92+
static_image_mode=True,
93+
max_num_faces=1,
94+
min_detection_confidence=0.5)
95+
96+
results = face_mesh.process(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)) # Landmarks stored here
97+
drawing_spec = mp_drawing.DrawingSpec(color=chooseColor,thickness=1, circle_radius=0)
98+
if not results.multi_face_landmarks:
99+
continue
100+
for face_landmarks in results.multi_face_landmarks:
101+
#print('face_landmarks:', face_landmarks)
102+
mp_drawing.draw_landmarks(
103+
image=img,
104+
landmark_list=face_landmarks,
105+
connections=mp_face_mesh.FACE_CONNECTIONS,
106+
landmark_drawing_spec=drawing_spec,
107+
connection_drawing_spec=drawing_spec)
108+
for ids,landmrk in enumerate(face_landmarks.landmark):
109+
#print(landmrk,ids)
110+
# 25 is for left eye and 339 is for right eye
111+
if ids == 25:
112+
#cv2.putText(img, str(ids), (int(landmrk.x*640),int(landmrk.y*480)), cv2.FONT_HERSHEY_SIMPLEX,0.1, (255,0,255), 1, cv2.LINE_AA)
113+
x1=landmrk.x*640
114+
y1=landmrk.y*480
115+
if ids == 339:
116+
x2=landmrk.x*640
117+
y2=landmrk.y*480
118+
119+
# getting size of canvas and mask image used
120+
hf,wf,cf=img.shape
121+
hb,wb,cb=mask_img.shape
122+
mask_img=cv2.resize(mask_img, (int(x2-x1)+100, int(y2-y1)+100),interpolation=cv2.INTER_AREA)
123+
124+
#try and except used because it causes error when head is not detected
125+
126+
try:
127+
img = cv.overlayPNG(img,mask_img,[int(x1)-40,int(y1)-70])
128+
except:
129+
pass
130+
131+
132+
133+
# Retrieve the detected text from takesinput process
134+
fh = open("Utils/words.txt","r")
135+
text=fh.read()
136+
fh.close()
137+
138+
text = "Captions : " + text
139+
140+
# Place it on canvas
141+
img = cv2.putText(img, str(text), (20,400), cv2.FONT_HERSHEY_SIMPLEX,0.5, (0,0,255), 1, cv2.LINE_AA)
142+
#cv2.imshow("image", img)
143+
cam.send(img)
144+
if cv2.waitKey(1) == ord('q'):
145+
break
146+
147+
148+
149+
150+
151+
152+
# Wait until it's time for the next frame.
153+
cam.sleep_until_next_frame()
154+
# Running 2 processes using multiprocessing
155+
p1 = multiprocessing.Process(target=takesinput)
156+
p2 = multiprocessing.Process(target=program)
157+
if __name__ == '__main__':
158+
159+
p1.start() # Starting both process
160+
p2.start()

0 commit comments

Comments
 (0)