AI PokerDetector

A custom built AI-powered poker assistant designed to detect cards in real time, calculate winning probabilities, and provide game insights using computer vision and machine learning.

Tech Stack

  • Python (real-time processing)
  • YOLOv8 (custom-trained model on 22,000+ labeled images)
  • OpenCV (frame analysis and image handling)
  • PyTorch (GPU-accelerated inference)
  • Tkinter (interactive GUI for live detections)

Key Features

  • Real-time card detection from video feed
  • Automated tracking of player and community cards
  • Instant win probability calculations
  • Dynamic game state reset and error handling
  • Scalable architecture for future AI enhancements

About This Project

This AI PokerDetector was designed to bring machine learning to real-time gameplay. Using a custom-trained YOLOv8 model, it identifies cards from live video input and maintains a structured game state to calculate odds dynamically. This project combines computer vision, probability analysis, and a functional user interface to provide valuable insights during poker sessions.

Code Snippet 1: [Best Hand Evaluation Logic]

This algorithm evaluates the strongest possible 5-card poker hand from any set of cards, caching results to speed up repeated calculations during real-time play.

from itertools import combinations

#Cache for hand evaluations
HAND_CACHE = {}

def evaluate_hand(cards):
    """Return the best possible 5-card hand and its rank."""
    if len(cards) < 5:
        return (0, "Not enough cards")

    # Sort cards for deterministic cache key
    key = tuple(sorted(cards))
    if key in HAND_CACHE:
        return HAND_CACHE[key]

    best_score = (0, "High Card")
    for combo in combinations(cards, 5):
        score = evaluate_five(combo)
        if score[0] > best_score[0]:
            best_score = score

    HAND_CACHE[key] = best_score
    return best_score

Code Snippet 2: [Real-Time Card Detection Function]

This function integrates my trained YOLOv8 model with OpenCV and MSS, capturing frames from either a live webcam or screen feed, processing detections in real-time, and returning structured results for the PokerBot's game state engine.

from ultralytics import YOLO
import cv2, numpy as np, mss

model = YOLO("runs/detect/train_medium/weights/best.pt")
sct = mss.mss()
cap = cv2.VideoCapture(0)

def detect_cards(source_mode="webcam", source_monitor=1, conf_thresh=0.5, display=False):
    detected = {"player": [], "community": []}

    # Grab frame from screen or webcam
    if source_mode == "screen":
        frame = cv2.cvtColor(np.array(sct.grab(sct.monitors[source_monitor])), cv2.COLOR_BGRA2BGR)
    else:
        ret, frame = cap.read()
        if not ret:
            return detected, None

    # Run YOLO prediction
    results = model.predict(source=frame, conf=conf_thresh, verbose=False)

    for r in results:
        for box in r.boxes:
            cls = int(box.cls[0])
            label = model.names[cls]
            conf = float(box.conf[0])
            detected["player"].append((label, conf))

            if display:
                x1, y1, x2, y2 = map(int, box.xyxy[0])
                cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
                cv2.putText(frame, f"{label} {conf:.2f}", (x1, y1 - 10),
                            cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)

    return detected, frame

Code Snippet 3: [Autonomous Game State Management]

This component allows the PokerBot to intelligently track detected cards, lock unique cards into player/community slots, and automatically reset the game state when a new hand starts.

class GameState:
    def __init__(self):
        self.player_cards = [None, None]
        self.community_cards = [None, None, None, None, None]
        self.locked_cards = set()
        self.missing_frames = 0

    def add_card(self, label, conf):
        if conf < 0.79 or label in self.locked_cards:
            return
        if None in self.player_cards:
            self.player_cards[self.player_cards.index(None)] = label
        elif None in self.community_cards:
            self.community_cards[self.community_cards.index(None)] = label
        self.locked_cards.add(label)

    def check_auto_reset(self, detections, threshold_frames=2):
        if all(self.player_cards) and all(self.community_cards):
            if len(detections["player"]) + len(detections["community"]) == 0:
                self.missing_frames += 1
                if self.missing_frames >= threshold_frames:
                    print("Auto-resetting game state...")
                    self.reset()
            else:
                self.missing_frames = 0