
MathWorks 开发团队的几位成员自称 Raspberry Pi 兼德州扑克狂热爱好者,因此我们决定打造一台 Raspberry Pi 扑克玩家,以在牌局中帮助我们巧妙地下注。扑克玩家需要完成 3 个主要步骤:(1) 识别牌;(2) 识别手牌;以及 (3) 下注。我将展示如何使用 MATLAB 完成相应步骤的编程,并将算法部署到 Raspberry Pi。
友情提示:玩牌需谨慎,学习无限制。
各位玩家们,不如现在就报名参加 6 月 22 日小迈步——MATLAB 助力硬件玩家玩转唯美夜景。学习用 Simulink 建模低光照图像增强,通过仿真探索对算法进行优化以适应 FPGA 平台。从模型自动生成 HDL 代码,与 HDL 仿真器联合仿真,并将综合后的 bit 文件下载到实际的硬件中,实现 FPGA 在环验证测试。
点击跳转报名:


图 1:项目中使用的硬件;图中的是 Raspberry Pi 3B+*考虑到性能问题,建议使用 RPi 3B+ 及更高版本
图 2:将网络摄像头采集的图像作为神经网络输入,对牌进行识别第一步:Raspberry Pi 识别牌。Pi 连接的网络摄像头采集牌图像,深度学习模型识别牌。MATLAB 支持多种常用深度学习网络,包括 SqueezeNet、AlexNet 和 GoogLeNet。之所以选择 SqueezeNet,是因为它足够小,支持部署到 Raspberry Pi,而且预测精度相对较高。此处是一个展示如何使用 AlexNet 进行迁移学习的简单文档示例,但您可以轻松地从 AlexNet 切换到其他(更现代的)网络,如 SqueezeNet 或 ResNet。
为了训练深度学习算法,我们需要收集希望能够识别的牌图像。我们使用网络摄像头拍摄了一系列快照,确保展示不同光线下不同方向的牌。我们手动选出那些以最低模糊/失真度采集了每张牌特征的图像,然后旋转每张图像,以避免网络过拟合,并确保可以识别不同方向的牌。用于生成训练数据的代码相当简单,generateCardData.m 中提供了完整代码%% Initialize variablesNumImages
= 200; % Max = 1000
suits = ['D' 'C' 'H' 'S'];
rank = ['A' '2' '3' '4' '5' '6' '7' '8' '9' 'T' 'J' 'Q' 'K'];%%
Get input from command line and validate
disp('Show the card to the webcam and enter the card name in short form. ex: "2D" for Diamond-Two, AC for Club-Ace');
cardname = input('Enter card name in short form:','s');if ~ischar(cardname) || (numel(cardname) ~= 2) || ~contains(rank,cardname(1)) || ~
contains(suits,cardname(2))
error('Invalid cardname');end...% Capture input from webcam and save to file.for i = 1:1000
waitbar(i/1000,waitBarHandle,['Saving image: ' num2str(i)]);
im = snapshot(cam);
if mod(i,
2)
im = imrotate(im,180);
end
if i <= NumImages
imwrite(im,fullfile(cardsDirectory,[cardname,num2str(i) '.png']));
else
imwrite(im,fullfile(unusedImgsDirectory,[cardname,num2str(i) '.png']));
endend
waitbar(1,waitBarHandle,['Capturing images for ',cardname,' completed.']);
我们最终获得了超过 10,000 张图像,继而使用它们训练模型。我们并未在训练期间将所有图像文件逐个加载到内存,而是使用 imageDatastore,通过它来处理整个图像集合。使用 augmentedImageDatastore 函数将图像大小调整为 SqueezeNet 的预定义输入大小。此函数可通过一行代码快速有效地调整图像大小,如下所示。net = squeezenet;
inputSize = net.Layers(1).InputSize;
audsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain);
augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);
基于这些图像进行迁移学习后,我们的网络可在所有测试图像中有效识别牌。成功识别单张牌后,Pi 扑克玩家就可以识别手牌了。图 4 中的流程图对实现方法进行了说明。
我们使用下表中的手牌示例更有效地理解此流程图。请注意,每手牌中的最后 5 张牌是公用牌,由所有玩家共用。(C:梅花;D:方块;H:红心;S:黑桃;T:点数 10。)识别牌和手牌后,(Pi) 扑克玩家就可以下注了。投注算法非常简单,完全取决于识别的手牌。高牌的最低下注额是 1 美元,加注额是 1 美元,随后每增加一手下注增加 1 美元,皇家同花顺最高下注 10 美元。当然,如果您正在研究此算法,可以根据个人感受对算法进行重新设计,增强(或降低)攻击性。我们通过 MATLAB 算法生成 C++ 代码,然后使用 MATLAB Coder 将其嵌入 Raspberry Pi。我们编写了 main_poker_player.cpp 函数,将它作为可执行文件主脚本,指定要为哪些函数生成代码。生成的代码和可执行文件(包括修改后的 AlexNet 和投注逻辑算法)直接下载到 Pi 以便独立执行 – 只需接入相机并运行 .exe 文件即可。
图 5:使用 MATLAB Coder 生成代码并部署到 Raspberry Pi介绍到此结束,我们已经了解如何在 MATLAB 中构建 Raspberry Pi 扑克玩家。尽管这是一个不错的起点,但一定还有改进的余地,我建议您修改代码使其更加完善。例如,您可以尝试构建更精密的投注算法,以实现提高下注甚至虚张声势等功能。代码已公布到 FileExchange 上,您可以点击“阅读原文”获取。
友情提示:玩牌需谨慎,学习无限制。
各位玩家们,不如现在就报名参加 6 月 22 日小迈步——MATLAB 助力硬件玩家玩转唯美夜景。学习用 Simulink 建模低光照图像增强,通过仿真探索对算法进行优化以适应 FPGA 平台。从模型自动生成 HDL 代码,与 HDL 仿真器联合仿真,并将综合后的 bit 文件下载到实际的硬件中,实现 FPGA 在环验证测试。
扫码立即注册:
