Building an AI-Powered Card Counter with TensorFlow

Community Article Published June 27, 2024

image/jpeg

Card counting in Blackjack has long been a strategy used by skilled players to gain an advantage over the house. Traditionally, this requires keeping a mental tally of high and low cards dealt. With advancements in artificial intelligence and computer vision, we can now automate this process. This guide will walk you through building an AI-powered card counter using TensorFlow, which can recognize cards from a live video stream and count them using the Hi-Lo system.

Overview

We'll cover the following steps:

  1. Data Collection
  2. Data Preprocessing
  3. Building and Training a Convolutional Neural Network (CNN)
  4. Integrating the CNN with a Live Video Stream
  5. Counting Cards in Real-Time

1. Data Collection

First, we need a dataset of playing card images. This dataset should include multiple images of each card (2 through Ace) from various decks and angles to ensure our model is robust. Label these images according to their ranks.

Collecting Images

  • Search for publicly available playing card datasets or manually take photos of cards.
  • Ensure diversity in lighting, backgrounds, and angles to make the model more adaptable.

Organizing Data

  • Create directories for each card rank (e.g., 2, 3, 4, ..., 10, J, Q, K, A).
  • Place corresponding images into these directories.

2. Data Preprocessing

Next, we'll preprocess our images to ensure they are suitable for training a neural network.

Resizing and Normalizing

  • Resize all images to a consistent size (e.g., 64x64 pixels).
  • Normalize pixel values to a range of 0 to 1.

Splitting Data

  • Divide your dataset into training, validation, and test sets (e.g., 70% training, 20% validation, 10% test).

Preprocessing Code

import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# Define directories
train_dir = 'dataset/train'
val_dir = 'dataset/validation'
test_dir = 'dataset/test'

# Image data generators
train_datagen = ImageDataGenerator(rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True)
val_datagen = ImageDataGenerator(rescale=1./255)
test_datagen = ImageDataGenerator(rescale=1./255)

# Load datasets
train_data = train_datagen.flow_from_directory(train_dir, target_size=(64, 64), batch_size=32, class_mode='sparse')
val_data = val_datagen.flow_from_directory(val_dir, target_size=(64, 64), batch_size=32, class_mode='sparse')
test_data = test_datagen.flow_from_directory(test_dir, target_size=(64, 64), batch_size=32, class_mode='sparse')

3. Building and Training the CNN

We will now define, compile, and train a Convolutional Neural Network (CNN) to recognize the cards.

Defining the Model

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense

model = Sequential([
    Conv2D(32, (3, 3), activation='relu', input_shape=(64, 64, 3)),
    MaxPooling2D(pool_size=(2, 2)),
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D(pool_size=(2, 2)),
    Flatten(),
    Dense(128, activation='relu'),
    Dense(13, activation='softmax')  # 13 classes for card ranks
])

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

Training the Model

model.fit(train_data, epochs=25, validation_data=val_data)

Evaluating the Model

loss, accuracy = model.evaluate(test_data)
print(f'Test Accuracy: {accuracy}')

4. Integrating with a Live Video Stream

Now, let's integrate our trained model with a live video stream to recognize cards in real-time.

Capturing Video Frames

import cv2

cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    if not ret:
        break

    # Preprocess the frame (resize and normalize)
    img = cv2.resize(frame, (64, 64))
    img = img / 255.0
    img = img.reshape(1, 64, 64, 3)

    # Predict the card
    prediction = model.predict(img)
    card_index = prediction.argmax()

    # Map index to card label
    card_labels = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
    card_label = card_labels[card_index]

    # Display the prediction on the frame
    cv2.putText(frame, card_label, (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)
    cv2.imshow('Card Classifier', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

5. Counting Cards in Real-Time

We can now integrate the card recognition with our card counting function to keep a running tally of the count in Blackjack.

Card Counting Function

def count_cards(cards):
    count = 0
    for card in cards:
        if card in ['2', '3', '4', '5', '6']:
            count += 1
        elif card in ['10', 'J', 'Q', 'K', 'A']:
            count -= 1
    return count

Updating the Card Count in Real-Time

current_count = 0
recognized_cards = []

cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    if not ret:
        break

    img = cv2.resize(frame, (64, 64))
    img = img / 255.0
    img = img.reshape(1, 64, 64, 3)

    prediction = model.predict(img)
    card_index = prediction.argmax()
    card_label = card_labels[card_index]

    recognized_cards.append(card_label)
    current_count = count_cards(recognized_cards)

    cv2.putText(frame, f'Card: {card_label}', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)
    cv2.putText(frame, f'Count: {current_count}', (50, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)
    cv2.imshow('Card Classifier', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

Conclusion

By following these steps, you can build a sophisticated AI-powered card counter using TensorFlow. This project demonstrates the power of deep learning and computer vision in automating complex tasks like card counting in Blackjack. As with any AI model, the performance can be further improved with more data, better preprocessing, and more sophisticated model architectures.