|
import cv2 |
|
import numpy as np |
|
from PIL import Image |
|
import mediapipe as mp |
|
import time |
|
import gradio as gr |
|
import glob |
|
|
|
DOMINANT_HAND = "Right" |
|
|
|
width_, height_, = 144, 96 |
|
|
|
drawing_flag = False |
|
sleepy_time = time.time() |
|
|
|
output_frames = [] |
|
|
|
|
|
def find_hands(brain, img): |
|
if img is not None: |
|
|
|
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) |
|
results = brain.process( |
|
img_rgb) |
|
all_hands = [] |
|
h, w, _ = img.shape |
|
if results.multi_hand_landmarks: |
|
for hand_type, hand_lms in zip(results.multi_handedness, |
|
results.multi_hand_landmarks): |
|
hand = {} |
|
lm_list = [] |
|
for lm in hand_lms.landmark: |
|
px, py, pz = int(lm.x * w), int(lm.y * h), int( |
|
lm.z * w) |
|
lm_list.append([px, py, pz]) |
|
|
|
hand["lm_list"] = lm_list |
|
hand["type"] = hand_type.classification[0].label |
|
all_hands.append(hand) |
|
return all_hands |
|
|
|
else: |
|
return 0 |
|
|
|
|
|
|
|
def is_drawing(index, thumb): |
|
npindex = np.array((index[0], index[1])) |
|
npthumb = np.array((thumb[0], thumb[1])) |
|
if np.linalg.norm(npindex - npthumb) < 30: |
|
return True |
|
else: |
|
return False |
|
|
|
|
|
def save(landmarks): |
|
if landmarks[8][1] < landmarks[6][1]: |
|
if landmarks[12][1] < landmarks[10][1]: |
|
if landmarks[16][1] < landmarks[14][1]: |
|
if landmarks[20][1] < landmarks[18][1]: |
|
return True |
|
else: |
|
return False |
|
|
|
|
|
def clear(landmarks): |
|
if landmarks[4][1] < landmarks[3][1] < landmarks[2][1] < landmarks[8][1]: |
|
return True |
|
else: |
|
return False |
|
|
|
|
|
def show(video): |
|
cam = cv2.VideoCapture(video) |
|
width = cam.get(cv2.CAP_PROP_FRAME_WIDTH) |
|
height = cam.get(cv2.CAP_PROP_FRAME_HEIGHT) |
|
|
|
detector = mp.solutions.hands.Hands(min_detection_confidence=0.8) |
|
|
|
paper = np.zeros((int(height), int(width), 3), dtype=np.uint8) |
|
paper.fill(255) |
|
|
|
past_holder = () |
|
palette = cv2.imread('palette_small.jpg') |
|
|
|
page_num = 0 |
|
|
|
color = (0, 0, 0) |
|
|
|
global sleepy_time |
|
|
|
while cam.isOpened(): |
|
|
|
x, rgb_image = cam.read() |
|
rgb_image_f = cv2.flip(rgb_image, 1) |
|
|
|
hands = find_hands(detector, rgb_image_f) |
|
|
|
if x: |
|
try: |
|
if hands: |
|
hand1 = hands[0] if hands[0]["type"] == DOMINANT_HAND else hands[1] |
|
lm_list1 = hand1["lm_list"] |
|
handedness = hand1["type"] |
|
|
|
if handedness == DOMINANT_HAND: |
|
idx_coords = lm_list1[8][0], lm_list1[8][1] |
|
|
|
cv2.circle(rgb_image_f, idx_coords, 5, color, cv2.FILLED) |
|
|
|
if idx_coords[1] < 72: |
|
if idx_coords[0] < 71: |
|
color = (0, 0, 255) |
|
if 71 < idx_coords[0] < 142: |
|
color = (0, 115, 255) |
|
if 142 < idx_coords[0] < 213: |
|
color = (0, 229, 255) |
|
if 213 < idx_coords[0] < 284: |
|
color = (0, 195, 88) |
|
if 284 < idx_coords[0] < 356: |
|
color = (195, 85, 0) |
|
if 356 < idx_coords[0] < 427: |
|
color = (195, 0, 68) |
|
if 427 < idx_coords[0] < 498: |
|
color = (195, 0, 143) |
|
if 498 < idx_coords[0] < 569: |
|
color = (0, 0, 0) |
|
if 569 < idx_coords[0]: |
|
color = (255, 255, 255) |
|
|
|
if len(past_holder) and drawing_flag: |
|
cv2.line(paper, past_holder, idx_coords, color, 5) |
|
cv2.line(rgb_image_f, past_holder, idx_coords, color, 5) |
|
|
|
|
|
cv2.circle(rgb_image_f, idx_coords, 5, color, cv2.FILLED) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if clear(lm_list1) and time.time() - sleepy_time > 3: |
|
paper = np.zeros((height, width, 3), dtype=np.uint8) |
|
paper.fill(255) |
|
print("page cleared") |
|
sleepy_time = time.time() |
|
|
|
past_holder = idx_coords |
|
|
|
if is_drawing(idx_coords, lm_list1[4]): |
|
drawing_flag = True |
|
else: |
|
drawing_flag = False |
|
|
|
except: |
|
pass |
|
|
|
finally: |
|
if True: |
|
rgb_image_f[0:48, ] = palette |
|
presenter = cv2.resize(rgb_image_f, (width_, height_)) |
|
h, w, _ = rgb_image_f.shape |
|
paper[0:height_, w - width_: w] = presenter |
|
|
|
else: |
|
break |
|
|
|
paper = cv2.cvtColor(paper, cv2.COLOR_RGB2BGR) |
|
im = Image.fromarray(paper) |
|
output_frames.append(paper) |
|
im.save("paper%s.png" % page_num) |
|
page_num += 1 |
|
|
|
img_array = [] |
|
for filename in glob.glob('*.png'): |
|
imggg = cv2.imread(filename) |
|
img_array.append(imggg) |
|
|
|
video_output = cv2.VideoWriter('any.webm', cv2.VideoWriter_fourcc(*'VP80'), 30, (640, 480)) |
|
|
|
for i in range(len(img_array)): |
|
video_output.write(img_array[i]) |
|
video_output.release() |
|
|
|
return 'any.webm' |
|
|
|
|
|
iface = gr.Interface(fn=show, inputs=gr.inputs.Video(source="webcam"), outputs='video') |
|
|
|
iface.launch(share=True, enable_queue=True) |
|
|