Skip to main content

Computer Vision Helping Library/Functions

Project description

cvfiq

A Python Computer Vision library that makes it easy to run image processing and AI functions using OpenCV and MediaPipe.

Requirements

Library Min Max
Python 3.8 3.12
opencv-python 4.7.0 4.13.0.92
mediapipe 0.10.0 0.10.32
numpy 1.21.0 2.4.2
pyserial 3.0 3.5

Installation

pip install cvfiq

For ClassificationModule (optional, choose one):

pip install cvfiq[keras]        # standalone Keras
pip install cvfiq[tensorflow]   # TensorFlow

Modules

Face Detection

from cvfiq.FaceDetectionModule import FaceDetector
import cv2

cap = cv2.VideoCapture(0)
detector = FaceDetector()

while True:
    success, img = cap.read()
    img, bboxs = detector.findFaces(img)

    if bboxs:
        # bboxInfo keys: "id", "bbox", "score", "center", "keypoints"
        center = bboxs[0]["center"]
        keypoints = bboxs[0]["keypoints"]  # rightEye, leftEye, nose, mouth, rightEar, leftEar
        cv2.circle(img, center, 5, (255, 0, 255), cv2.FILLED)

    cv2.imshow("Image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Hand Tracking

from cvfiq.HandTrackingModule import HandDetector
import cv2

cap = cv2.VideoCapture(0)
detector = HandDetector(detectionCon=0.8, maxHands=2)

while True:
    success, img = cap.read()
    hands, img = detector.findHands(img)

    if hands:
        hand1 = hands[0]
        lmList1 = hand1["lmList"]   # 21 landmarks [x, y, z]
        bbox1   = hand1["bbox"]     # x, y, w, h
        center1 = hand1["center"]   # cx, cy
        type1   = hand1["type"]     # "Left" or "Right"

        fingers1 = detector.fingersUp(hand1)  # [thumb, index, middle, ring, pinky]

        # 2D distance between two landmarks
        length, info, img = detector.findDistance(lmList1[8][0:2], lmList1[4][0:2], img)

        # 3D distance (uses z-depth)
        length3d = detector.findDistance3D(lmList1[8], lmList1[4])

        # Angle between 3 landmarks (index tip - wrist - thumb tip)
        angle = detector.findAngle(lmList1[8], lmList1[0], lmList1[4])

        if len(hands) == 2:
            hand2 = hands[1]
            lmList2 = hand2["lmList"]
            length, info, img = detector.findDistance(lmList1[8][0:2], lmList2[8][0:2], img)

    cv2.imshow("Image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Pose Estimation

from cvfiq.PoseModule import PoseDetector
import cv2

cap = cv2.VideoCapture(0)
detector = PoseDetector(smoothAlpha=0.5)  # 0=max smooth, 1=no smooth

while True:
    success, img = cap.read()
    img = detector.findPose(img)
    lmList, bboxInfo = detector.findPosition(img, bboxWithHands=False)

    if lmList:
        # Calculate angle at elbow (landmarks 11, 13, 15)
        angle = detector.findAngle(img, 11, 13, 15)
        # Check if angle is within range
        isCorrect = detector.angleCheck(angle, targetAngle=90, addOn=20)

    if bboxInfo:
        center = bboxInfo["center"]
        cv2.circle(img, center, 5, (255, 0, 255), cv2.FILLED)

    cv2.imshow("Image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Face Mesh

from cvfiq.FaceMeshModule import FaceMeshDetector
import cv2

cap = cv2.VideoCapture(0)
detector = FaceMeshDetector(maxFaces=2, refineLandmarks=False)

while True:
    success, img = cap.read()
    img, faces = detector.findFaceMesh(img)

    if faces:
        face = faces[0]

        # Get specific region landmarks
        leftEye  = detector.getRegion(face, FaceMeshDetector.LEFT_EYE)
        lips     = detector.getRegion(face, FaceMeshDetector.LIPS)

        # Detect blink
        blink = detector.blinkDetector(face)
        # {"left": bool, "right": bool, "leftEAR": float, "rightEAR": float}

        # Detect mouth open
        mouth = detector.mouthOpen(face)
        # {"open": bool, "ratio": float}

    cv2.imshow("Image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Selfie Segmentation (Background Removal)

from cvfiq.SelfiSegmentationModule import SelfiSegmentation
import cv2

cap = cv2.VideoCapture(0)
segmentor = SelfiSegmentation(model=1)  # 0=general, 1=landscape (faster)
imgBg = cv2.imread("background.jpg")

while True:
    success, img = cap.read()
    imgOut = segmentor.removeBG(img, imgBg=imgBg, threshold=0.1)
    # imgOut = segmentor.removeBG(img, imgBg=(0, 255, 0))  # solid color BG

    cv2.imshow("Output", imgOut)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Gesture Recognition (requires model file)

from cvfiq.GestureModule import GestureDetector
import cv2

# Download model: https://storage.googleapis.com/mediapipe-models/gesture_recognizer/gesture_recognizer/float16/latest/gesture_recognizer.task
cap = cv2.VideoCapture(0)
detector = GestureDetector(modelPath='gesture_recognizer.task')

while True:
    success, img = cap.read()
    gestures, img = detector.findGestures(img)

    for g in gestures:
        print(g["hand"], g["gesture"], g["score"])
        # Gestures: Thumb_Up, Thumb_Down, Victory, Open_Palm,
        #           Closed_Fist, Pointing_Up, ILoveYou, None

    cv2.imshow("Gesture", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Face Landmarker + Expressions (requires model file)

from cvfiq.FaceLandmarkerModule import FaceLandmarker
import cv2

# Download model: https://storage.googleapis.com/mediapipe-models/face_landmarker/face_landmarker/float16/latest/face_landmarker.task
cap = cv2.VideoCapture(0)
detector = FaceLandmarker(modelPath='face_landmarker.task')

while True:
    success, img = cap.read()
    faces, img = detector.findFaces(img)

    if faces:
        face = faces[0]

        smiling    = detector.isSmiling(face)
        blinking   = detector.isBlinking(face, eye='both')
        mouthOpen  = detector.isMouthOpen(face)
        expression = detector.getExpression(face)
        # expressions: smiling, mouth_open, blink_left, blink_right, brow_down, neutral

        # Raw blendshape value (0.0 - 1.0)
        jawScore = detector.getBlendshape(face, FaceLandmarker.JAW_OPEN)

    cv2.imshow("FaceLandmarker", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Object Detection (requires model file)

from cvfiq.ObjectDetectorModule import ObjectDetector
import cv2

# Download model: https://storage.googleapis.com/mediapipe-models/object_detector/efficientdet_lite0/int8/latest/efficientdet_lite0.tflite
cap = cv2.VideoCapture(0)
detector = ObjectDetector(modelPath='efficientdet_lite0.tflite', scoreThreshold=0.5)

while True:
    success, img = cap.read()
    objects, img = detector.findObjects(img)

    # Filter by label
    people = detector.getObjectsByLabel(objects, 'person')
    count  = detector.countObjects(objects, 'person')
    # objInfo keys: "label", "score", "bbox": (x,y,w,h), "center": (cx,cy)

    cv2.imshow("ObjectDetector", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

ArUco Marker Detection

from cvfiq.ArucoModule import ArucoDetector
import cv2

cap = cv2.VideoCapture(0)
detector = ArucoDetector(dictType='4x4_50')

while True:
    success, img = cap.read()
    markers, img = detector.findMarkers(img)
    # markerInfo keys: "id", "corners": [[x,y]x4], "center": (cx,cy)

    if markers:
        # Estimate 3D pose (distance in meters)
        poses, img = detector.estimatePose(img, markers, markerSize=0.05)
        for pose in poses:
            print(f"ID:{pose['id']}  dist:{pose['distance']:.3f}m")

    cv2.imshow("ArUco", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

# Generate a marker image and save it
detector = ArucoDetector()
markerImg = detector.generateMarker(markerId=0, size=200)
cv2.imwrite("marker_0.png", markerImg)

DNN Classification (no TensorFlow needed)

from cvfiq.DNNModule import DNNClassifier
import cv2

cap = cv2.VideoCapture(0)
classifier = DNNClassifier('model.onnx', labelsPath='labels.txt', imgSize=(224, 224))
# classifier.useGPU()  # enable CUDA if available

while True:
    success, img = cap.read()

    # Single prediction
    scores, index, confidence = classifier.getPrediction(img)

    # Top-3 predictions
    topK = classifier.getTopK(img, k=3)
    # [("cat", 0.92), ("dog", 0.05), ("bird", 0.01)]

    cv2.imshow("DNN", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Video Stabilizer

from cvfiq.VideoStabilizerModule import VideoStabilizer
import cv2

cap = cv2.VideoCapture(0)
stabilizer = VideoStabilizer(smoothRadius=15, border='black')
# border options: 'black', 'replicate', 'reflect'

while True:
    success, img = cap.read()
    imgStab = stabilizer.stabilize(img)

    smoothness = stabilizer.getSmoothness()  # 0.0 (shaky) to 1.0 (smooth)

    cv2.imshow("Stabilized", imgStab)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

stabilizer.reset()  # reset when switching video source
cap.release()
cv2.destroyAllWindows()

Color Detection

from cvfiq.ColorModule import ColorFinder
import cv2

cap = cv2.VideoCapture(0)
myColorFinder = ColorFinder(trackBar=False)

# Custom color HSV range
hsvVals = {'hmin': 10, 'smin': 55, 'vmin': 215, 'hmax': 42, 'smax': 255, 'vmax': 255}

while True:
    success, img = cap.read()

    # Single color
    imgColor, mask = myColorFinder.update(img, 'red')   # built-in: red, green, blue
    imgColor, mask = myColorFinder.update(img, hsvVals)  # custom HSV

    # Multiple colors at once
    results = myColorFinder.updateMulti(img, ['red', 'green', 'blue'])
    # results["red"]["imgColor"], results["red"]["mask"]

    # Save / load custom color profiles
    myColorFinder.saveColor('orange', hsvVals, 'colors.json')
    loaded = myColorFinder.loadColor('orange', 'colors.json')

    cv2.imshow("Color", imgColor)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

FPS Counter

import cvfiq
import cv2

fpsReader = cvfiq.FPS(avgCount=10)  # average over 10 frames
cap = cv2.VideoCapture(0)

while True:
    success, img = cap.read()
    fps, img = fpsReader.update(img, pos=(20, 50), color=(0, 255, 0), scale=3, thickness=3)
    cv2.imshow("Image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

PID Controller

from cvfiq.PIDModule import PID
from cvfiq.FaceDetectionModule import FaceDetector
import cv2

cap = cv2.VideoCapture(0)
detector = FaceDetector()

# [Kp, Ki, Kd], target, iLimit = integral windup clamp
xPID = PID([1, 0.0001, 0.5], targetVal=320, iLimit=[-500, 500])
yPID = PID([1, 0.0001, 0.5], targetVal=240, axis=1, limit=[-100, 100], iLimit=[-500, 500])

while True:
    success, img = cap.read()
    img, bboxs = detector.findFaces(img)

    if bboxs:
        cx, cy = bboxs[0]["center"]
        xVal = int(xPID.update(cx))
        yVal = int(yPID.update(cy))
        xPID.draw(img, [cx, cy])
        yPID.draw(img, [cx, cy])
    else:
        xPID.reset()  # reset state when face lost
        yPID.reset()

    cv2.imshow("Image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Live Plot

import cvfiq
import cv2
import math

xPlot = cvfiq.LivePlot(w=640, h=480, yLimit=[-100, 100])
x = 0

while True:
    x = (x + 1) % 360
    val = int(math.sin(math.radians(x)) * 100)
    imgPlot = xPlot.update(val, color=(255, 0, 255))
    cv2.imshow("Plot", imgPlot)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cv2.destroyAllWindows()

Stack Images

import cvfiq
import cv2

cap = cv2.VideoCapture(0)

while True:
    success, img = cap.read()
    imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    imgList = [img, img, imgGray, img, imgGray, img]
    stackedImg = cvfiq.stackImages(imgList, cols=3, scale=0.4)
    cv2.imshow("Stacked", stackedImg)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Arduino Serial Communication

from cvfiq.SerialModule import SerialObject
import time

# Auto-detect Arduino, or specify port
arduino = SerialObject(portNo=None, baudRate=9600, digits=3, timeout=1)

while True:
    # Send data: "$001001000" (3 digits per value)
    arduino.sendData([1, 1, 0])

    # Receive data (with timeout — won't hang)
    data = arduino.getData()
    print(data)

    time.sleep(0.1)

Classification (Teachable Machine)

from cvfiq.ClassificationModule import Classifier
import cv2

cap = cv2.VideoCapture(0)
classifier = Classifier('Model/keras_model.h5', 'Model/labels.txt', imgSize=224)

while True:
    success, img = cap.read()

    # Returns: (all scores list, top index, confidence)
    scores, index, confidence = classifier.getPrediction(img)
    print(f"Predicted: index={index}  confidence={confidence:.2f}")

    cv2.imshow("Image", img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Utility Functions

import cvfiq
import cv2

img = cv2.imread("image.jpg")

# Stack multiple images into one window
stacked = cvfiq.stackImages([img, img, img], cols=3, scale=0.5)

# Fancy bounding box with corner lines
img = cvfiq.cornerRect(img, bbox=(100, 100, 200, 150))

# Find contours with area filter
imgCon, contours = cvfiq.findContours(img, imgPre, minArea=1000, filter=4)  # filter=4: rectangle only

# Overlay transparent PNG
img = cvfiq.overlayPNG(imgBack=img, imgFront=imgPNG, pos=[50, 50])

# Rotate image
img = cvfiq.rotateImage(img, angle=45, scale=1)

# Text with background rectangle
img, rect = cvfiq.putTextRect(img, "Hello", pos=(50, 50), scale=2, thickness=2)

Module Overview

Module Class Description
FaceDetectionModule FaceDetector Face detection + 6 keypoints
FaceMeshModule FaceMeshDetector 468 face landmarks, blink & mouth detection
HandTrackingModule HandDetector 21 hand landmarks, finger detection, 2D/3D distance, angle
PoseModule PoseDetector Body pose estimation, angle, smoothing
SelfiSegmentationModule SelfiSegmentation Real-time background removal
GestureModule GestureDetector Built-in gesture recognition (Tasks API)
FaceLandmarkerModule FaceLandmarker 478 landmarks + 52 expression blendshapes (Tasks API)
ObjectDetectorModule ObjectDetector 80-class object detection (Tasks API)
ArucoModule ArucoDetector ArUco marker detection + 3D pose estimation
DNNModule DNNClassifier ONNX/TFLite classification via OpenCV DNN
VideoStabilizerModule VideoStabilizer Real-time video stabilization
ColorModule ColorFinder HSV color detection, save/load profiles, multi-color
ClassificationModule Classifier Teachable Machine model inference
FPS FPS Averaged FPS counter
PIDModule PID PID controller with windup clamp
PlotModule LivePlot Real-time graph in OpenCV window
SerialModule SerialObject Arduino serial communication
Utils stackImages, cornerRect, findContours, overlayPNG, rotateImage, putTextRect

License

MIT License — see LICENSE.txt

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cvfiq-0.3.tar.gz (31.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cvfiq-0.3-py3-none-any.whl (37.6 kB view details)

Uploaded Python 3

File details

Details for the file cvfiq-0.3.tar.gz.

File metadata

  • Download URL: cvfiq-0.3.tar.gz
  • Upload date:
  • Size: 31.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for cvfiq-0.3.tar.gz
Algorithm Hash digest
SHA256 f6643e590f0cd82f66d0b11ab35db770ac9a618f6c27a555c2c78d0bae3b7bb8
MD5 7766662b2270d8b1daa2ea9f64355062
BLAKE2b-256 8df470376a59460cc4d54f693c6404c0b24944a62b59f4ae551c8087d871d26c

See more details on using hashes here.

File details

Details for the file cvfiq-0.3-py3-none-any.whl.

File metadata

  • Download URL: cvfiq-0.3-py3-none-any.whl
  • Upload date:
  • Size: 37.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for cvfiq-0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 18c2e827e9bc0c3605a53d5cef01a4251576daec8fc15a33f981f78c863e408a
MD5 62adcac84d2153e83ecacc3b9e7f3d84
BLAKE2b-256 b07386aa74e19bb4a405fa40dddea020dae16fbdd3b20bc641f3393fec2c6c19

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page