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