If the article is an original article, please indicate the source of the original article when reprinting it.
1. Project introduction
With the advent of the artificial intelligence era, many technologies have achieved unprecedented development, making people more aware of the power of online virtual technology.
Identify the key points of the hand through mediapipe, detect the middle finger, and realize the operation of drawing in the air.
Use the distance between two fingers to click to select a color or eraser.
2. Operation
1. Environment
The environment is built using the environment mediapipe_env built in the previous article.
Open the terminal and enter the following command to activate the environment:
conda activate mediapipe
This time I used pycharm, the software was installed by myself, and the community version was installed.
Create a directory, import the project into pycharm, and then set the environment
Click Add New Interpreter
Select environment python.exe
Terminal selection must be powershell.exe
Once set, you can operate it from the terminal in pycharm
2. Run
Import the code and right-click to run
3. Result
3. Code
The principles and processes are not introduced here. People who want to learn will not stop learning because of these, so they need to understand it by themselves. The project is not difficult and the code is relatively uncomplicated. Directly upload the source code
There are two files in total, AiVirtualPainter.py and HandTrackingModule.py
AiVirtualPainter.py implements the painting function, and HandTrackingModule.py implements hand key point recognition.
AiVirtualPainter.py
import cv2
import HandTrackingModule as htm
import os
import numpy as np
folderPath = "PainterImg/"
mylist = os.listdir(folderPath)
overlayList = []
for imPath in mylist:
image = cv2.imread(f'{folderPath}/{imPath}')
overlayList.append(image)
header = overlayList[0]
color = [255, 0, 0]
brushThickness = 15
eraserThickness = 40
cap = cv2.VideoCapture(0) # 若使用笔记本自带摄像头则编号为0 若使用外接摄像头 则更改为1或其他编号
cap.set(3, 1280)
cap.set(4, 720)
# cap.set(3, 800)
# cap.set(4, 500)
detector = htm.handDetector()
xp, yp = 0, 0
imgCanvas = np.zeros((720, 1280, 3), np.uint8) # 新建一个画板
# imgCanvas = np.zeros((500, 800, 3), np.uint8) # 新建一个画板
while True:
# 1.import image
success, img = cap.read()
img = cv2.flip(img, 1) # 翻转
# 2.find hand landmarks
img = detector.findHands(img)
lmList = detector.findPosition(img, draw=True)
if len(lmList) != 0:
x1, y1 = lmList[8][1:]
x2, y2 = lmList[12][1:]
# 3. Check which fingers are up
fingers = detector.fingersUp()
# 4. If Selection Mode – Two finger are up
if fingers[1] and fingers[2]:
if y1 < 153:
if 0 < x1 < 320:
header = overlayList[0]
color = [50, 128, 250]
elif 320 < x1 < 640:
header = overlayList[1]
color = [0, 0, 255]
elif 640 < x1 < 960:
header = overlayList[2]
color = [0, 255, 0]
elif 960 < x1 < 1280:
header = overlayList[3]
color = [0, 0, 0]
img[0:1280][0:153] = header
# 5. If Drawing Mode – Index finger is up
if fingers[1] and fingers[2] == False:
cv2.circle(img, (x1, y1), 15, color, cv2.FILLED)
print("Drawing Mode")
if xp == 0 and yp == 0:
xp, yp = x1, y1
if color == [0, 0, 0]:
cv2.line(img, (xp, yp), (x1, y1), color, eraserThickness) # ??
cv2.line(imgCanvas, (xp, yp), (x1, y1), color, eraserThickness)
else:
cv2.line(img, (xp, yp), (x1, y1), color, brushThickness) # ??
cv2.line(imgCanvas, (xp, yp), (x1, y1), color, brushThickness)
xp, yp = x1, y1
# Clear Canvas when all fingers are up
# if all (x >= 1 for x in fingers):
# imgCanvas = np.zeros((720, 1280, 3), np.uint8)
# 实时显示画笔轨迹的实现
imgGray = cv2.cvtColor(imgCanvas, cv2.COLOR_BGR2GRAY)
_, imgInv = cv2.threshold(imgGray, 50, 255, cv2.THRESH_BINARY_INV)
imgInv = cv2.cvtColor(imgInv, cv2.COLOR_GRAY2BGR)
img = cv2.bitwise_and(img, imgInv)
img = cv2.bitwise_or(img, imgCanvas)
img[0:1280][0:153] = header
cv2.imshow("Image", img)
# cv2.imshow("Canvas", imgCanvas)
# cv2.imshow("Inv", imgInv)
cv2.waitKey(1)
HandTrackingModule.py
import cv2
import mediapipe as mp
import time
import math
class handDetector():
def __init__(self, mode=False, maxHands=2, detectionCon=0.8, trackCon=0.8):
self.mode = mode
self.maxHands = maxHands
self.detectionCon = detectionCon
self.trackCon = trackCon
self.mpHands = mp.solutions.hands
self.hands = self.mpHands.Hands(self.mode, self.maxHands, self.detectionCon, self.trackCon)
self.mpDraw = mp.solutions.drawing_utils
self.tipIds = [4, 8, 12, 16, 20]
def findHands(self, img, draw=True):
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
self.results = self.hands.process(imgRGB)
print(self.results.multi_handedness) # 获取检测结果中的左右手标签并打印
if self.results.multi_hand_landmarks:
for handLms in self.results.multi_hand_landmarks:
if draw:
self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS)
return img
def findPosition(self, img, draw=True):
self.lmList = []
if self.results.multi_hand_landmarks:
for handLms in self.results.multi_hand_landmarks:
for id, lm in enumerate(handLms.landmark):
h, w, c = img.shape
cx, cy = int(lm.x * w), int(lm.y * h)
# print(id, cx, cy)
self.lmList.append([id, cx, cy])
if draw:
cv2.circle(img, (cx, cy), 12, (255, 0, 255), cv2.FILLED)
return self.lmList
def fingersUp(self):
fingers = []
# 大拇指
if self.lmList[self.tipIds[0]][1] > self.lmList[self.tipIds[0] - 1][1]:
fingers.append(1)
else:
fingers.append(0)
# 其余手指
for id in range(1, 5):
if self.lmList[self.tipIds[id]][2] < self.lmList[self.tipIds[id] - 2][2]:
fingers.append(1)
else:
fingers.append(0)
# totalFingers = fingers.count(1)
return fingers
def findDistance(self, p1, p2, img, draw=True, r=15, t=3):
x1, y1 = self.lmList[p1][1:]
x2, y2 = self.lmList[p2][1:]
cx, cy = (x1 + x2) // 2, (y1 + y2) // 2
if draw:
cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), t)
cv2.circle(img, (x1, y1), r, (255, 0, 255), cv2.FILLED)
cv2.circle(img, (x2, y2), r, (255, 0, 255), cv2.FILLED)
cv2.circle(img, (cx, cy), r, (0, 0, 255), cv2.FILLED)
length = math.hypot(x2 - x1, y2 - y1)
return length, img, [x1, y1, x2, y2, cx, cy]
def main():
pTime = 0
cTime = 0
cap = cv2.VideoCapture(0)
detector = handDetector()
while True:
success, img = cap.read()
img = detector.findHands(img) # 检测手势并画上骨架信息
lmList = detector.findPosition(img) # 获取得到坐标点的列表
if len(lmList) != 0:
print(lmList[4])
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
cv2.putText(img, 'fps:' + str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
cv2.imshow('Image', img)
cv2.waitKey(1)
if __name__ == "__main__":
main()
There are a lot of source codes online. If you don’t understand, you can contact the blogger and communicate with each other.
Learning never ends, AI is the future development direction, make a little progress every day, and achieve lifelong learning.
If there is any infringement or you need the complete code, please contact the blogger in time.