opencv Probiererei

Datum:2023-09-20

Als Fortsetzung zu Bilderkennung.

Install

Wir installieren in ein neues python Environment, damit wissen wir was wirklich gebraucht wird und übersehen (weniger) was zufällig schon installiert ist.

Neuen Arbeitsordner anlegen

mkdir test
cd test
python -m venv .

dann haben wir im Verzeichnis test eine eigene python-Umgebung.

Im unix ist dort ein Verzeichnis bin, darin ist eine Datei activate. Diese Datei im laufenden Interpreter (shell) inkludieren source bin/activate, dann ändert sich der Prompt (der Text der auf der Kommandozeile am Anfang steht in (test) ....

Wenn man jetzt python ausführt wird der python-Interpreter aus dem Verzeichnis bin verwendet.

Dort gibt es auch den Befehl pip mit dem wir zur python-Umgebung im Verzeichnis test Bibliothekskomponenten hinzuinstallieren können.

TODO besseres Wort für Bibliothekskomponente ?

TODO wie geht das im Windows ?

Auflisten was bereits da ist:

(test) opencv/test$ pip list
Package    Version
---------- -------
pip        22.3.1
setuptools 65.5.0

[notice] A new release of pip available: 22.3.1 -> 23.2.1
[notice] To update, run: pip install --upgrade pip
(test) opencv/test$ pip install --upgrade pip
Requirement already satisfied: pip in ./lib/python3.10/site-packages (22.3.1)
Collecting pip
  Using cached pip-23.2.1-py3-none-any.whl (2.1 MB)
Installing collected packages: pip
  Attempting uninstall: pip
    Found existing installation: pip 22.3.1
    Uninstalling pip-22.3.1:
      Successfully uninstalled pip-22.3.1
Successfully installed pip-23.2.1

opencv und Handerkennung installieren

Im Verzeichnis test mit aktiviertem test-Environment

(test) pip install opencv-python

Test cv2 installation with test-cv2.py

import cv2

# use local file path
img = cv2.imread("logo.jpg")
print(img.shape)

cv2.imshow("logo", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Was bedeutet die 0 bei cv2.waitKey ?

Entweder google oder die Dokumentation des Moduls befragen.

python starten

>>> import cv2, pydoc
>>> help(cv2.waitKey)
Help on built-in function waitKey:

waitKey(...)
  waitKey([, delay]) -> retval
  .   @brief Waits for a pressed key.
  .
  .   The function waitKey waits for a key event infinitely (
  .   when \f$\texttt{delay}\leq 0\f$ ) or for delay milliseconds,
  .   when it is positive. Since the OS has a minimum time between
  .   switching threads, the function will not wait exactly delay ms,
  ...

Die 0 bedeutet ewig Warten.

Test cv2 camera access

import cv2

video_capture = cv2.VideoCapture(0)

while True:
    ret, frame = video_capture.read(0)
    print(ret, frame)
    cv2.imshow('Video', frame)
    if cv2.waitKey(1) & 0xff == ord('c'):
        break

video_capture.release()
cv2.destroyAllWindows()

VideoCapture(0) To open default camera using default backend just pass 0. see: https://docs.opencv.org/3.4/d8/dfe/classcv_1_1VideoCapture.html

Es sollte ein Fenster geöffnet werden und das von der default Kamera aufgenommene Bild angezeigt werden.

Wenn etwas nicht funktioniert ist wahrscheinlich ret False.

gleich zur

Hand detection

pip install cvzone mediapipe

cvzone/Examples/HandTrackingExample.py from https://github.com/cvzone/cvzone/tree/master

starten

[ WARN:0@0.896] global cap_v4l.cpp:982 open VIDEOIO(V4L2:/dev/video2): can't open camera by index
[ERROR:0@1.032] global obsensor_uvc_stream_channel.cpp:156 getStreamChannelGroup Camera index out of range
Traceback (most recent call last):
  File "/home/engelbert/work/opencv/test/HandTracking.py", line 22, in <module>
    hands, img = detector.findHands(img, draw=True, flipType=True)
  File "/home/engelbert/work/opencv/test/lib/python3.10/site-packages/cvzone/HandTrackingModule.py", line 54, in findHands
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
cv2.error: OpenCV(4.8.0) /io/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'

Die Fehlermeldung ist irreführend, es hat nichts mit cvtColor sondern mit camera by index zu tun ... ich habe nur eine interne deshalb

cap = cv2.VideoCapture(0)

anstatt cap = cv2.VideoCapture(2).

HandTracking.py

# from https://github.com/cvzone/cvzone/tree/master

from cvzone.HandTrackingModule import HandDetector
import cv2

# Initialize the webcam to capture video
# The '2' indicates the third camera connected to your computer; '0' would usually refer to the built-in camera
cap = cv2.VideoCapture(0)

# Initialize the HandDetector class with the given parameters
detector = HandDetector(staticMode=False, maxHands=2, modelComplexity=1, detectionCon=0.5, minTrackCon=0.5)

# Continuously get frames from the webcam
while True:
    # Capture each frame from the webcam
    # 'success' will be True if the frame is successfully captured, 'img' will contain the frame
    success, img = cap.read()

    # Find hands in the current frame
    # The 'draw' parameter draws landmarks and hand outlines on the image if set to True
    # The 'flipType' parameter flips the image, making it easier for some detections
    hands, img = detector.findHands(img, draw=True, flipType=True)

    # Check if any hands are detected
    if hands:
        # Information for the first hand detected
        hand1 = hands[0]  # Get the first hand detected
        lmList1 = hand1["lmList"]  # List of 21 landmarks for the first hand
        bbox1 = hand1["bbox"]  # Bounding box around the first hand (x,y,w,h coordinates)
        center1 = hand1['center']  # Center coordinates of the first hand
        handType1 = hand1["type"]  # Type of the first hand ("Left" or "Right")

        # Count the number of fingers up for the first hand
        fingers1 = detector.fingersUp(hand1)
        print(f'H1 = {fingers1.count(1)}', end=" ")  # Print the count of fingers that are up

        # Calculate distance between specific landmarks on the first hand and draw it on the image
        length, info, img = detector.findDistance(lmList1[8][0:2], lmList1[12][0:2], img, color=(255, 0, 255),
                                                  scale=10)

        # Check if a second hand is detected
        if len(hands) == 2:
            # Information for the second hand
            hand2 = hands[1]
            lmList2 = hand2["lmList"]
            bbox2 = hand2["bbox"]
            center2 = hand2['center']
            handType2 = hand2["type"]

            # Count the number of fingers up for the second hand
            fingers2 = detector.fingersUp(hand2)
            print(f'H2 = {fingers2.count(1)}', end=" ")

            # Calculate distance between the index fingers of both hands and draw it on the image
            length, info, img = detector.findDistance(lmList1[8][0:2], lmList2[8][0:2], img, color=(255, 0, 0),
                                                      scale=10)

        print(" ")  # New line for better readability of the printed output

    # Display the image in a window
    cv2.imshow("Image", img)

    # Keep the window open and update it for each frame; wait for 1 millisecond between frames
    cv2.waitKey(1)

Changes to HandDetect

  • Build exit with character c like in test-camera.py

    if cv2.waitKey(1) & 0xff == ord('c'):
        break
    
  • and release resources

    cap.release()
    cv2.destroyAllWindows()
    

Interesting things

The information about the hand is a dictionary

lmList1 = hand1["lmList"]  # List of 21 landmarks for the first hand
bbox1 = hand1["bbox"]  # Bounding box around the first hand (x,y,w,h coordinates)
center1 = hand1['center']  # Center coordinates of the first hand
handType1 = hand1["type"]  # Type of the first hand ("Left" or "Right")

and the HandDetector has methods to extract information on fingers from the list of landmarks.

# Count the number of fingers up for the first hand
fingers1 = detector.fingersUp(hand1)
# Print the count of fingers that are up
print(f'H1 = {fingers1.count(1)}', end=" ")

TODO landmark 8 and 12 are special ?

# Calculate distance between specific landmarks on the
# first hand and draw it on the image
length, info, img = detector.findDistance(lmList1[8][0:2],
                    lmList1[12][0:2], img, color=(255, 0, 255),
                                          scale=10)

Letzte Version der HandErkennung.