扑克牌识别是计算机视觉中的一个应用领域,主要用于自动识别扑克牌的花色和点数。
python
import cv2
import numpy as np
def preprocess_card_image(image):
预处理扑克牌图像
# 转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 高斯模糊去噪
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 边缘检测
edges = cv2.Canny(blurred, 50, 150)
return edges
def detect_card_contour(edges):
检测扑克牌轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
# 近似多边形
epsilon = 0.02 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, epsilon, True)
# 如果是四边形且面积足够大
if len(approx) == 4 and cv2.contourArea(contour) > 1000:
return approx
return None
python
import torch
import torch.nn as nn
from torchvision import models, transforms
class PokerCardClassifier(nn.Module):
def __init__(self, num_classes=52):
super.__init__
# 使用预训练的ResNet作为基础网络
self.backbone = models.resnet18(pretrained=True)
self.backbone.fc = nn.Linear(self.backbone.fc.in_features, num_classes)
def forward(self, x):
return self.backbone(x)
# 数据预处理
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor,
transforms.Normalize(mean=[0.485, 0.456, 0.406],
红龙扑克app官方下载std=[0.229, 0.224, 0.225])
])
python
class PokerCardRecognizer:
def __init__(self, model_path=None):
self.suits = ['Hearts', 'Diamonds', 'Clubs', 'Spades']
self.ranks = ['Ace', '2', '3', '4', '5', '6', '7', '8',
'9', '10', 'Jack', 'Queen', 'King']
if model_path:
self.model = self.load_model(model_path)
else:
self.model = None
def extract_card_region(self, image):
提取扑克牌区域
# 1. 预处理
processed = preprocess_card_image(image)
# 2. 检测轮廓
contour = detect_card_contour(processed)
if contour is not None:
# 3. 透视变换矫正
warped = self.perspective_transform(image, contour)
return warped
return None
def perspective_transform(self, image, contour):
透视变换将扑克牌校正为矩形
# 对四个顶点排序:左上、右上、右下、左下
points = contour.reshape(4, 2)
rect = np.zeros((4, 2), dtype="float32")
# 计算四个点的中心
s = points.sum(axis=1)
rect[0] = points[np.argmin(s)] # 左上
rect[2] = points[np.argmax(s)] # 右下
# 计算点之间的差异
diff = np.diff(points, axis=1)
rect[1] = points[np.argmin(diff)] # 右上
rect[3] = points[np.argmax(diff)] # 左下
# 定义目标矩形尺寸
width = 200
height = 300
dst = np.array([
[0, 0],
[width-1, 0],
[width-1, height-1],
[0, height-1]
], dtype="float32")
# 计算透视变换矩阵
M = cv2.getPerspectiveTransform(rect, dst)
warped = cv2.warpPerspective(image, M, (width, height))
return warped
def recognize_card(self, card_image):
识别扑克牌
if self.model:
# 使用深度学习模型识别
return self.deep_learning_recognition(card_image)
else:
# 使用传统方法识别
return self.traditional_recognition(card_image)
def traditional_recognition(self, card_image):
传统识别方法
# 提取左上角区域(包含花色和点数)
corner_region = card_image[10:60, 10:50]
# 颜色分析识别花色
suit = self.recognize_suit_by_color(corner_region)
# 模板匹配识别点数
rank = self.recognize_rank_by_template(corner_region)
return f"{rank} of {suit}
def recognize_suit_by_color(self, region):
通过颜色识别花色
hsv = cv2.cvtColorvtColor(region, cv2.COLOR_BGR2HSV)
# 红色范围
red_lower1 = np.array([0, 100, 100])
red_upper1 = np.array([10, 255, 255])
red_lower2 = np.array([160, 100, 100])
100])
red_upper2 = np.array([180, 255, 255])
red_mask1 = cv2.inRange(hsv, red_lower1, red_upper1)
red_mask2 = cv2.inRange(hsv, red_lower2, red_upper2)
red_mask = red_mask1 | red_mask2
red_pixels = cv2.countNonZero(red_mask)
if red_pixels > 100:
return "Hearts" # 或 Diamonds,需要进一步区分
else:
return "Clubs" # 或 Spades,需要进一步区分
python
def main:
# 初始化识别器
recognizer = PokerCardRecognizer
# 读取图像
image = cv2.imread('poker_table.jpg')
# 检测并识别所有扑克牌
cards = detect_all_cards(image, recognizer)
for i, card_info in enumerate(cards):
print(f"Card {i+1}: {card_info['rank']} of {card_info['suit']}")
cv2.imshow(f"Card {i+1}", card_info['image'])
cv2.waitKey(0)
cv2.destroyAllWindows
def detect_all_cards(image, recognizer):
检测图像中的所有扑克牌
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
edges = cv2.Canny(blurred, 50, 150)
# 查找轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cards = []
for contour in contours:
if cv2.contourArea(contour) > 5000: # 过滤小轮廓
epsilon = 0.02 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)
if len(approx) == 4:
card_image = recognizer.extract_card_region(image)
if card_image is not None:
recognition_result = recognizer.recognize_card(card_image)
cards.append({
'image': card_image,
'contour': contour,
'recognition': recognition_result
})
return cards
1. 多尺度检测:在不同尺度下检测扑克牌
2. 非极大值抑制:避免重复检测同一张牌
3. GPU加速:使用CUDA加速DA加速深度学习推理
4. 缓存机制:缓存已识别的模板结果
这个框架可以根据具体需求进行调整和扩展,以适应不同的应用场景。