I am trying to make an AR paint program using python and opencv library, but for some reason when I run my code the program does not draw the line and I don't know why. I followed this tutorial on yt: https://www.youtube.com/watch?v=ZiwZaAVbXQo&t=201s and simpyfied it by cutting out the color selection menue and removing the HandTrackingModule.py file because I just imported the HandDetector from cvzone.HandTrackingModule library and edited some parts because I use the latest version of opencv.
So the error is that my program does not draw the line.
I am using cvzone version 1.5.2 (the latest)
This is my code:
import cv2
import numpy as np
import os
from cvzone.HandTrackingModule import HandDetector #----> this is the library I imported whcih was made by him
brushThickness = 25
drawColor = (0, 0, 0)
cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
detector = HandDetector(detectionCon=0.65,maxHands=1) #here I imported the HandDetector
xp, yp = 0, 0
imgCanvas = np.zeros((480, 640, 3), np.uint8)
while True:
# 1. Import image
success, img = cap.read()
img = cv2.flip(img, 1)
# 2. Find Hand Landmarks
hands, img = detector.findHands(img, flipType=False)
if hands:
lmList = hands[0]['lmList'] #this was the change I made because my version does not support his line
#he used : lmList = detector.findPosition(img, draw=False)
if len(lmList) != 0:
# tip of index and middle fingers
x1, y1 = lmList[8][:2]
x2, y2 = lmList[12][:2]
# 3. Check which fingers are up
fingers = detector.fingersUp(hands[0])
# 4. If two index fingers are up - drawing mode -----> somewhere here is the error becuase my program does not draw the line
if fingers[1] == 1 and fingers[2] == 1:
cv2.circle(img, (x1, y1), 15, drawColor, cv2.FILLED)
if xp == 0 and yp == 0:
xp, yp = x1, y1
cv2.line(img, (xp, yp), (x1, y1), drawColor, brushThickness)
xp, yp = x1, y1
# Clear Canvas when all fingers are up
if all (x >= 1 for x in fingers):
imgCanvas = np.zeros((480, 640, 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, img, imgInv)
img = cv2.bitwise_or(img, img, imgCanvas)
cv2.imshow("Image", img)
cv2.waitKey(1)
I messed up the loop orders, Here is the solution (I also added that the line erases after all fingers are raised):
import cv2
import numpy as np
from cvzone.HandTrackingModule import HandDetector
brushThickness = 25
drawColor = (255, 0, 255)
cap = cv2.VideoCapture(0)
cap.set(3, 640)
cap.set(4, 480)
detector = HandDetector(detectionCon=0.65,maxHands=1)
xp, yp = 0, 0
imgCanvas = np.zeros((480, 640, 3), np.uint8)
while True:
success, img = cap.read()
img = cv2.flip(img, 1)
hands, img = detector.findHands(img)
if hands:
lmList = hands[0]['lmList']
if len(lmList) != 0:
# tip of index and middle fingers
x1, y1 = lmList[8][:2]
x2, y2 = lmList[12][:2]
#Check which fingers are up
fingers = detector.fingersUp(hands[0])
#Drawing Mode - Index finger is up
if fingers == [0, 1, 0, 0, 0]:
cv2.circle(img, (x1, y1), 15, drawColor, cv2.FILLED)
#print("Drawing Mode")
if xp == 0 and yp == 0:
xp, yp = x1, y1
#ce je sam img pol update vsakic in nemors risat, rise v canvas
cv2.line(imgCanvas, (xp, yp), (x1, y1), drawColor, brushThickness)
xp, yp = x1, y1
#reset when two fingers are up
if fingers == [0, 1, 1, 0, 0]:
xp, yp = x1, y1
# Clear Canvas when all fingers are up
if all (x >= 1 for x in fingers):
imgCanvas = np.zeros((480, 640, 3), np.uint8)
#zdruzis canvas pa img
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)
cv2.imshow("Image", img)
#cv2.imshow("Canvas", imgCanvas)
cv2.waitKey(1)