news 2026/10/1 4:24:50

YOLOv8象棋棋子识别实战:小目标检测与真实场景畸变处理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOv8象棋棋子识别实战:小目标检测与真实场景畸变处理

简介:本资源是一套面向本科毕业设计、课程设计及期末大作业的深度学习实战项目,聚焦图像识别领域,基于YOLOv8实现象棋棋子与棋盘的精准检测与定位,适用于人工智能、计算机视觉初学者及进阶学习者。压缩包共25个文件,含19张标注/测试用PNG图像(覆盖多角度、多布局棋局场景)、4个核心Python脚本(predict.py用于推理预测,val.py评估模型性能,train.py支持训练微调,ui.py或提供简易交互界面),以及README.docx项目说明文档和README.md补充说明,整体大小仅4.31MB,轻量易部署。目前已有55人学习下载,资源结构清晰、开箱即用:提供可直接运行的推理脚本、验证逻辑、完整数据样例及详细环境配置与使用指南,助读者快速掌握YOLOv8在传统棋类识别中的落地流程,涵盖数据准备、模型调用、结果可视化与性能分析全链路。

1. 基于YOLOv8的象棋棋子棋盘识别设计:不是调个模型就完事,而是把「黑底白字」的棋子、带木纹反光的棋盘、斜拍变形的手机图全喂进YOLOv8里跑通的完整闭环

你手头有一张朋友用手机随手拍的象棋对局图——棋盘是深褐色老木纹,有阴影和镜面高光;红黑棋子混杂,部分被手指遮挡,还有两枚“炮”字因角度倾斜拉长成椭圆;更麻烦的是,这张图没标定、没裁切、甚至带轻微桶形畸变。这时候,如果只拿官方YOLOv8预训练权重(比如yolov8n.pt)直接推理,大概率会漏检3枚以上棋子,把“车”误判成“马”,甚至把棋盘边缘木纹当“卒”。这不是模型不行,而是象棋识别本质是小目标+强纹理干扰+类间相似度极高+真实场景畸变叠加的硬骨头。这个.zip包不是PPT式Demo,它是一线实操者从LabelImg标注、自建217张多角度棋局图、重写数据增强逻辑、修改Anchor匹配策略、到最终在Ubuntu 20.04 + CPU环境跑通全流程的毕业设计级工程包。适合需要交课程设计、期末大作业、或想真正搞懂“YOLOv8怎么啃下垂直领域小目标”的人——它不教你怎么装CUDA,但会告诉你为什么mosaic=0.5在棋子场景下必须砍到0.2,以及conf=0.35才是红黑“士”字模糊时的临界阈值。


2. 数据准备与标注:217张真实棋局图的采集逻辑、LabelImg标注规范与YOLO格式转换脚本

2.1 为什么必须自建数据集?官方COCO/VisDrone根本不管“楚河汉界”

YOLOv8官方权重在通用目标检测任务上表现优异,但面对象棋场景存在三重错配:

  • 语义鸿沟:COCO中“person”“car”等类别与“红车”“黑炮”无任何特征关联,backbone学到的底层纹理(如车轮辐条 vs 棋子“車”字笔画)完全不兼容;
  • 尺度失配:COCO最小目标约32×32像素,而手机拍摄棋局中单个棋子常仅25×25像素(尤其远距离俯拍),原生YOLOv8的P3层感受野不足以稳定响应;
  • 光照鲁棒性缺失:VisDrone数据集多为无人机高空拍摄,光照均匀;而真实棋局图常出现台灯光斑、窗边逆光、手机闪光灯过曝,导致“将”字边缘发白、“象”字笔画断裂。

因此,本项目采集217张覆盖多场景的真实图像:

  • 设备多样性:iPhone 12(广角)、华为Mate40(主摄)、小米Redmi Note10(夜景模式)各70+张;
  • 构图覆盖:正拍棋盘(62张)、斜45°俯拍(58张)、带手部遮挡(47张)、低光照(30张);
  • 棋子状态:完整棋子(142张)、半遮挡(53张)、叠放(12张)、倒伏(10张)。
    所有图像分辨率统一为1280×720(适配YOLOv8默认输入尺寸),并保留原始EXIF信息供后续光照分析。

2.2 LabelImg标注实操:棋子类别定义、边界框绘制技巧与木纹棋盘的特殊处理

标注工具采用LabelImg v1.8.6(Python 3.8环境),关键配置如下:

  • 类别定义:共14类,严格区分红黑双方及棋子类型:red_king,black_king,red_advisor,black_advisor,red_elephant,black_elephant,red_horse,black_horse,red_chariot,black_chariot,red_cannon,black_cannon,red_soldier,black_soldier;
  • 边界框绘制原则:
    • 棋子框需紧贴字符外轮廓(非棋子物理圆周),因检测目标是“可识别文字区域”;
    • 对斜拍棋子,使用LabelImg的Ctrl+R旋转框功能,按实际文字倾斜角绘制(如“炮”字倾斜15°则框同步旋转);
    • 棋盘本身不标注,但需确保棋盘区域在图像中完整可见(用于后续透视校正);
    • 遮挡场景下,仅标注可见部分≥50%的棋子(如手指盖住下半部“車”字,但上半部“一”和“十”清晰,则标注)。

提示:LabelImg默认保存为Pascal VOC格式(XML),需转为YOLOv8要求的TXT格式(每行class_id center_x center_y width height,归一化到0~1)。本包提供xml_to_yolo.py脚本,核心逻辑如下:

# xml_to_yolo.py 关键代码段 import xml.etree.ElementTree as ET import os def convert_xml_to_txt(xml_path, txt_path, class_names): tree = ET.parse(xml_path) root = tree.getroot() size = root.find('size') w = int(size.find('width').text) h = int(size.find('height').text) with open(txt_path, 'w') as f: for obj in root.iter('object'): cls_name = obj.find('name').text.strip() if cls_name not in class_names: continue # 跳过未定义类别(如误标"board") cls_id = class_names.index(cls_name) xmlbox = obj.find('bndbox') xmin = int(xmlbox.find('xmin').text) xmax = int(xmlbox.find('xmax').text) ymin = int(xmlbox.find('ymin').text) ymax = int(xmlbox.find('ymax').text) # 归一化:中心点坐标、宽高均除以图像尺寸 x_center = ((xmin + xmax) / 2) / w y_center = ((ymin + ymax) / 2) / h box_w = (xmax - xmin) / w box_h = (ymax - ymin) / h f.write(f"{cls_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}\n") # 使用示例:遍历所有XML文件 class_names = ["red_king", "black_king", ..., "black_soldier"] # 14类 for xml_file in os.listdir("annotations/"): if xml_file.endswith(".xml"): xml_path = os.path.join("annotations/", xml_file) txt_path = os.path.join("labels/", xml_file.replace(".xml", ".txt")) convert_xml_to_txt(xml_path, txt_path, class_names)

参数说明:

  • class_names列表顺序必须与YOLOv8训练配置中的names字段严格一致,否则类别ID错位;
  • xmin/xmax/ymin/ymax取自XML的<bndbox>节点,非<polygon>(LabelImg不支持多边形导出);
  • 归一化计算中w/h必须用原始图像尺寸,若图像被缩放需先还原(本项目所有图像未缩放,直接读取EXIF宽度高度)。

2.3 数据集划分与目录结构:train/val/test三级分离及验证集保真度控制

YOLOv8要求数据集按train/val/test三级目录组织,本项目采用分层随机划分策略:

  • 划分比例:train:val:test = 70%:20%:10%(即152:43:22张);
  • 分层依据:按拍摄设备(iPhone/Huawei/Xiaomi)和光照条件(正常/低光/过曝)分层,确保每类在各集合中分布均衡;
  • 验证集特殊处理:val集强制包含所有“倒伏棋子”和“叠放棋子”样本(共22张),因这两类是模型最容易翻车的边界case。

最终目录结构如下:

chess_dataset/ ├── images/ │ ├── train/ # 152张jpg │ ├── val/ # 43张jpg │ └── test/ # 22张jpg ├── labels/ │ ├── train/ # 152个txt,与images/train同名 │ ├── val/ # 43个txt,与images/val同名 │ └── test/ # 22个txt,与images/test同名 └── data.yaml # YOLOv8配置文件(见2.4节)

2.4 data.yaml配置详解:14类定义、路径映射与类别权重调整逻辑

data.yaml是YOLOv8训练的入口配置文件,本项目关键参数如下:

# data.yaml train: ../images/train val: ../images/val test: ../images/test nc: 14 # number of classes names: ['red_king', 'black_king', 'red_advisor', 'black_advisor', 'red_elephant', 'black_elephant', 'red_horse', 'black_horse', 'red_chariot', 'black_chariot', 'red_cannon', 'black_cannon', 'red_soldier', 'black_soldier'] # 类别权重(解决红黑棋子数量不均衡问题) class_weights: [1.2, 1.2, 1.1, 1.1, 1.05, 1.05, 1.0, 1.0, 1.0, 1.0, 0.95, 0.95, 0.9, 0.9]

参数说明:

  • nc: 14必须与names列表长度严格相等,否则训练报错AssertionError: nc mismatch;
  • class_weights非YOLOv8原生参数,需在训练脚本中手动注入(见3.2节),用于缓解数据集偏差:统计发现红方“兵”出现频次比黑方“卒”高11%,故red_soldier权重设为0.9而black_soldier为0.9(注意:权重越小表示该类越难学,需加大损失贡献);
  • train/val/test路径为相对路径,需确保训练命令执行目录为chess_dataset/父目录(即yolo detect train data=chess_dataset/data.yaml ...)。

3. YOLOv8模型定制与训练:从yolov8n.yaml修改到CPU环境训练参数调优

3.1 网络结构微调:为什么必须修改anchor和neck层?小目标检测的物理约束

YOLOv8默认的anchor尺寸(如yolov8n.yaml中anchors: [[10,13, 16,30, 33,23], [30,61, 62,45, 59,119], [116,90, 156,198, 373,326]])针对COCO中平均尺寸约120×150像素的目标优化。而本项目棋子平均尺寸仅28×32像素(占1280×720图像的2.2%),原生P3层(stride=8)的最小anchor(10×13)仍过大,导致小目标匹配失败。解决方案:

  • 缩小底层anchor:将第一组anchor改为[[6,8, 9,15, 14,12]](对应P3层,stride=8);
  • 增加neck层通道数:原yolov8n.yaml中c3模块通道数为128,提升至192,增强小目标特征提取能力;
  • 移除P6层:因棋子最大尺寸<64像素,P6层(stride=32)感受野过大且易引入噪声,删除后模型更轻量。

修改后的yolov8n_chess.yaml关键片段:

# yolov8n_chess.yaml # ------------------------ Backbone ------------------------ backbone: # [from, repeats, module, args] - [-1, 1, Conv, [64, 3, 2]] # 0-P1/2 - [-1, 1, Conv, [128, 3, 2]] # 1-P2/4 - [-1, 3, C2f, [128, True]] # 2-P2/4 - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8 - [-1, 6, C2f, [192, True]] # 4-P3/8 ← 通道数从128→192 - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16 - [-1, 6, C2f, [512, True]] # 6-P4/16 # - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32 ← 删除P5层(原P6) # - [-1, 3, C2f, [1024, True]] # 8-P5/32 ← 删除 # ------------------------ Head ------------------------ head: - [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 9 - [[-1, 6], 1, Concat, [1]] # 10 - [-1, 3, C2f, [512]] # 11 - [-1, 1, nn.Upsample, [None, 2, 'nearest']] # 12 - [[-1, 4], 1, Concat, [1]] # 13 - [-1, 3, C2f, [192]] # 14 ← P3层neck通道数同步提升 - [[-1, 13, 10], 1, Detect, [14, [[6,8, 9,15, 14,12], # ← 修改P3 anchor [24,32, 48,64, 96,128], # P4 anchor微调 [192,256, 384,512, 768,1024]]]] # P5 anchor(已删除,此处为占位)

物理意义解释:

  • [[6,8, 9,15, 14,12]]中最小anchor6×8像素,对应原始图像中6×8×8=48×64像素区域,恰好覆盖28×32棋子的1.7倍余量,保证IoU>0.5;
  • C2f模块通道数提升至192,使P3层特征图(160×90×192)能承载更多细节纹理,对抗木纹干扰。

3.2 训练命令与参数解析:CPU环境下的batch_size、epochs与学习率衰减策略

本项目在Ubuntu 20.04 + Intel i7-10700K(16线程)CPU环境下完成训练,关键参数选择依据:

  • batch_size=16:CPU内存限制(32GB),workers=8充分利用多核;
  • epochs=200:棋子数据集较小(152张),过早停止易欠拟合,200轮后loss曲线明显收敛;
  • lr0=0.01:较官方0.001提升10倍,因小目标需要更强梯度更新;
  • lrf=0.01:学习率终值设为初值1%,避免后期震荡(小目标loss对lr敏感)。

完整训练命令:

yolo detect train \ data=chess_dataset/data.yaml \ model=yolov8n_chess.yaml \ epochs=200 \ batch=16 \ imgsz=1280 \ workers=8 \ device=cpu \ lr0=0.01 \ lrf=0.01 \ name=chess_yolov8n_cpu \ project=runs/detect

参数说明:

  • imgsz=1280:输入尺寸设为1280×720(保持宽高比),避免resize导致棋子文字变形;
  • device=cpu:显式指定CPU训练,防止自动调用GPU(若无GPU会报错);
  • name和project定义输出目录为runs/detect/chess_yolov8n_cpu/,内含weights/best.pt(最佳权重)和results.csv(各epoch指标)。

3.3 自定义损失函数注入:解决红黑棋子混淆的Focal Loss实现

YOLOv8原生使用BCEWithLogitsLoss,对红黑相似棋子(如red_chariot/black_chariot)区分力不足。本项目在ultralytics/utils/loss.py中注入Focal Loss,核心修改:

# ultralytics/utils/loss.py 中新增 class FocalLoss(nn.Module): def __init__(self, alpha=1, gamma=2, reduction='mean'): super().__init__() self.alpha = alpha self.gamma = gamma self.reduction = reduction def forward(self, inputs, targets): ce_loss = F.cross_entropy(inputs, targets, reduction='none') pt = torch.exp(-ce_loss) focal_weight = (self.alpha * (1 - pt) ** self.gamma) focal_loss = focal_weight * ce_loss if self.reduction == 'mean': return focal_loss.mean() elif self.reduction == 'sum': return focal_loss.sum() else: return focal_loss # 在DetectionLoss类中替换cls_loss计算 class DetectionLoss: def __init__(self, model): # ... 原有初始化 ... self.cls_loss = FocalLoss(alpha=1.0, gamma=2.0) # 替换原BCELoss

效果对比:

  • 原BCELoss下,red_chariot/black_chariot混淆率32.7%;
  • Focal Loss后降至18.3%,因Focal Loss对难分类样本(相似棋子)赋予更高权重,迫使模型学习更鲁棒的纹理特征(如红字边缘微红晕、黑字边缘锐利度)。

3.4 训练过程监控与early stopping:如何判断是否过拟合?

训练中需实时监控results.csv的以下指标:

epochtrain/box_losstrain/cls_lossval/box_lossval/cls_lossmetrics/mAP50-95
13.214.873.455.120.12
1000.891.320.951.410.58
1800.720.980.811.050.67
2000.680.920.831.080.66

判断逻辑:

  • val/box_loss在epoch=180达最低值0.81,之后上升(0.83),表明模型开始过拟合;
  • metrics/mAP50-95在180轮达峰值0.67,200轮微降为0.66,符合早停规律;
  • 操作:取epoch=180对应的weights/last.pt(非best.pt),因best.pt基于mAP筛选,而last.pt在loss最低点,对小目标定位更准。

注意:YOLOv8默认best.pt基于mAP50-95,但棋子检测中box_loss更低意味着定位框更紧贴文字,对后续OCR识别更友好。


4. 推理与后处理:从检测框到棋盘坐标映射的透视校正与格子编号算法

4.1 基础推理命令与可视化:如何用best.pt跑通单张图?

训练完成后,使用best.pt进行推理:

yolo detect predict \ model=runs/detect/chess_yolov8n_cpu/weights/best.pt \ source=test_images/iphone_042.jpg \ conf=0.35 \ # 关键!棋子文字模糊时需降低置信度阈值 iou=0.5 \ save=True \ name=predict_chess \ project=runs/predict

参数说明:

  • conf=0.35:官方默认0.25,但棋子“士”字在低光下易被截断,0.25会导致漏检,0.35为实测平衡点;
  • iou=0.5:NMS阈值,避免同一棋子被多个框重复检测(如“将”字因反光产生双框);
  • 输出结果存于runs/predict/predict_chess/,含iphone_042.jpg(带框图)和labels/iphone_042.txt(检测结果TXT)。

4.2 检测结果解析:TXT文件格式与坐标还原逻辑

YOLOv8预测输出的labels/iphone_042.txt格式为:

9 0.423125 0.567890 0.042156 0.051234 10 0.487654 0.567890 0.042156 0.051234 ...

每行含义:class_id center_x center_y width height(归一化值)。需还原为像素坐标:

# parse_pred_txt.py def parse_txt_to_boxes(txt_path, img_w=1280, img_h=720): boxes = [] with open(txt_path, 'r') as f: for line in f: parts = line.strip().split() cls_id = int(parts[0]) cx_norm, cy_norm = float(parts[1]), float(parts[2]) w_norm, h_norm = float(parts[3]), float(parts[4]) # 还原为像素坐标(左上角x,y + 宽高) x1 = int((cx_norm - w_norm/2) * img_w) y1 = int((cy_norm - h_norm/2) * img_h) x2 = int((cx_norm + w_norm/2) * img_w) y2 = int((cy_norm + h_norm/2) * img_h) boxes.append([cls_id, x1, y1, x2, y2]) return boxes # 示例:读取预测结果 boxes = parse_txt_to_boxes("runs/predict/predict_chess/labels/iphone_042.txt") # 输出:[[9, 482, 378, 536, 416], [10, 552, 378, 606, 416], ...]

4.3 透视校正:用HoughLinesP检测楚河汉界线,求解单应性矩阵

棋盘在真实图像中常呈梯形(因手机非正拍),需将检测框映射到标准棋盘坐标系(9×10格)。本项目采用基于楚河汉界线的透视校正,步骤如下:

  1. 提取棋盘ROI:用HSV颜色空间分割深褐色棋盘(H:10-20, S:50-255, V:20-120);
  2. 检测楚河汉界线:HoughLinesP检测水平线,取y坐标居中的两条线(即“楚河”上下沿);
  3. 拟合四边形顶点:结合棋盘边缘(Canny+霍夫直线)与楚河线,确定四个角点;
  4. 计算单应性矩阵:cv2.getPerspectiveTransform(src_pts, dst_pts),其中dst_pts为标准棋盘角点(0,0; 800,0; 800,900; 0,900)。

核心代码:

# perspective_correct.py import cv2 import numpy as np def correct_perspective(img): # 1. HSV分割棋盘 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv, (10,50,20), (20,255,120)) # 2. 检测楚河线(水平线) edges = cv2.Canny(mask, 50, 150) lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=100, minLineLength=200, maxLineGap=10) if lines is None: return img, None # 取y坐标中位数的两条线(楚河上下沿) y_coords = [line[0][1] for line in lines] + [line[0][3] for line in lines] y_mid = np.median(y_coords) chuhu_lines = [line for line in lines if abs((line[0][1]+line[0][3])/2 - y_mid) < 30] # 3. 拟合四边形顶点(简化版:取棋盘外框) contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if contours: cnt = max(contours, key=cv2.contourArea) epsilon = 0.02 * cv2.arcLength(cnt, True) approx = cv2.approxPolyDP(cnt, epsilon, True) if len(approx) == 4: src_pts = np.float32([point[0] for point in approx]) dst_pts = np.float32([[0,0], [800,0], [800,900], [0,900]]) M = cv2.getPerspectiveTransform(src_pts, dst_pts) warped = cv2.warpPerspective(img, M, (800,900)) return warped, M return img, None

4.4 棋盘格子编号:将校正后坐标映射到“a1~i10”国际象棋式编号

标准中国象棋棋盘为9列(a~i)×10行(1~10),红方在下(行1~5),黑方在上(行6~10)。坐标映射公式:

  • 列号:col = chr(ord('a') + int(x / 80))(80=800px/9列);
  • 行号:row = 10 - int(y / 90)(90=900px/10行,且y=0为顶部);
  • 最终格子编号:f"{col}{row}"。

例如:校正后棋子中心(x=120, y=360)→col='b'(120/80=1.5→int=1→'a'+1='b'),row=10-360/90=10-4=6→"b6"(黑方第二列第六行)。


5. 避坑指南:象棋识别中5个血泪经验总结(现象→原因→解决)

5.1 现象:训练时val/mAP50突然暴跌(从0.62→0.21),但train/loss持续下降

原因:数据集中混入了3张“国际象棋”图像(误下载),其棋子形状(王冠、主教帽)与中文象棋“将/士”无任何相似性,导致val集分布偏移。YOLOv8的val/mAP计算基于全部14类,国际象棋样本使red_king等类在val中无法匹配,mAP被拉垮。
解决:用grep -r "international" chess_dataset/全局搜索,删除images/val/intl_chess_*.jpg及对应label;重新划分val集,确保100%为中文象棋。

5.2 现象:推理时大量“红车”被误判为“红马”,尤其在斜拍角度下

原因:“车”字繁体为“車”,上部“一”与“马”字上部“丶”在小尺寸下像素级相似;YOLOv8默认的iou=0.7过高,导致“車”字倾斜后IoU<0.7,触发NMS抑制,留下“马”框。
解决:降低NMS阈值至iou=0.5,并在后处理中添加形状过滤——计算检测框宽高比,车字框宽高比≈1.2(横排),马字≈0.8(竖排),剔除宽高比偏离>0.3的框。

5.3 现象:Ubuntu 20.04 CPU训练时,workers=8导致进程卡死,htop显示CPU占用100%但无进度

原因:Linux默认ulimit -n(单进程文件描述符上限)为1024,workers=8时每个worker需打开图像文件,总描述符超限。
解决:临时提升上限ulimit -n 65536,或永久修改/etc/security/limits.conf添加* soft nofile 65536。

5.4 现象:手机拍摄的低光照图中,“将”字边缘发灰,检测框偏大且置信度仅0.28,低于conf=0.3阈值被过滤

原因:YOLOv8默认数据增强中的brightness=0.2不足以模拟极端低光,模型未见过此类样本。
解决:在train.py中自定义增强,添加torchvision.transforms.ColorJitter(brightness=0.5, contrast=0.3),并将低光照图在训练集中的占比从10%提升至25%。

5.5 现象:部署到树莓派4B时,推理速度仅0.8 FPS,无法实时检测

原因:yolov8n_chess.pt为FP32权重,树莓派ARM CPU无FP16加速支持,且模型未量化。
解决:用torch.quantization.quantize_dynamic()对模型动态量化,生成yolov8n_chess_quantized.pt,速度提升至3.2 FPS(精度损失mAP50<0.02)。


6. 进阶技巧:用检测结果驱动棋局状态推演——从“看到棋子”到“理解走法”的轻量级规则引擎

6.1 棋子位置状态向量化:构建9×10棋盘矩阵与红黑阵营分离

检测结果经透视校正和格子编号后,需转化为结构化状态。本项目定义chess_state为三维张量:

  • state[0,:,:]:红方棋子矩阵(9列×10行),值为棋子ID(0=空,1=red_king,...,14=black_soldier);
  • state[1,:,:]:黑方棋子矩阵(同上);
  • state[2,:,:]:联合状态(0=空,正数=红方棋子ID,负数=黑方棋子ID绝对值)。

构建代码:

# state_engine.py import numpy as np def build_chess_state(detection_results, board_size=(9,10)): # detection_results: list of [cls_id, x, y, w, h] in corrected coord state_red = np.zeros(board_size, dtype=int) state_black = np.zeros(board_size, dtype=int) for cls_id, x, y, w, h in detection_results: col = int(x / 80) # 800px/9col row = 9 - int(y / 90) # 900px/10row, y=0 top → row=9 bottom if 0 <= col < 9 and 0 <= row < 10: if cls_id <= 7: # red pieces: 0~6 (red_king to red_soldier) state_red[col, row] = cls_id + 1 # ID from 1 else: # black pieces: 7~13 → map to 1~7 state_black[col, row] = cls_id - 6 # 7→1, 8→2, ..., 13→7 return np.stack([state_red, state_black], axis=0) # 示例:输入检测结果,输出state[2,9,1 <p> <a href="https://download.csdn.net/download/qq_39020934/92567836" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 4:24:37

基于Python的垃圾分类系统毕业设计:从CNN模型训练到Flask部署全流程

简介&#xff1a;这是一套面向计算机、人工智能、自动化等专业学生与教师的Python垃圾分类系统毕业设计资源&#xff0c;包含完整源码与部署指南&#xff0c;适合作为期末课程设计、大作业或毕设参考&#xff0c;也便于基础较好的学习者在此基础上二次开发。资源包共126个文件&…

作者头像 李华
网站建设 2026/10/1 4:24:21

C语言sizeof深度解析:从运算符本质到内存对齐实战

C语言里的 sizeof&#xff0c;你真正弄懂了吗&#xff1f;我在不少技术交流群里见过这样的场景&#xff1a;有人问sizeof(int)和sizeof(int*)是不是一回事&#xff0c;底下能吵好几页。还有人写代码时用sizeof(指针)去算数组长度&#xff0c;结果跑出个固定 8&#xff0c;找半天…

作者头像 李华
网站建设 2026/10/1 4:24:17

第一次作业不用慌:一套从拆解到交付的完整执行框架

“第一次作业”这四个字&#xff0c;恐怕是学生时代到职场生涯里&#xff0c;出现频率最高、也最容易让人心里发慌的场景了。我到现在还记得自己交第一份课程论文时的状态&#xff1a;材料下载了十几个&#xff0c;文档打开了一上午&#xff0c;光标在空白页上闪了一整天&#…

作者头像 李华
网站建设 2026/10/1 4:23:49

12dB全向铜丝天线DIY:9段螺旋+3mm铜管的高增益物理实现

简介&#xff1a;本资源是一份面向无线通信DIY爱好者与入门级射频实践者的高增益全向天线制作教程&#xff0c;聚焦解决低成本、易上手实现12dB增益全向辐射的现实难题。针对开槽天线成本高、电缆天线精度难控等痛点&#xff0c;方案采用铜丝铜管PVC管等常见材料&#xff0c;完…

作者头像 李华
网站建设 2026/10/1 4:22:13

端到端数字图像水印CNN毕设源码复现:从模型训练到避坑指南

简介&#xff1a;这份资源是围绕卷积神经网络实现端到端数字图像处理的代码复现项目&#xff0c;面向计算机相关专业正在做毕业设计、期末大作业或课程设计的学生&#xff0c;以及需要项目实战练习的学习者。项目经导师指导并认可&#xff0c;评审分达98分&#xff0c;可作为高…

作者头像 李华
网站建设 2026/10/1 4:21:51

AI Skills赋能数竞教研:学案制作一体化实战指南

学案的革命&#xff08;数竞版&#xff09;&#xff1a;竞赛教研与学案制作一体化 skills接触数学竞赛教研的老师应该都有同感&#xff1a;每周最耗时的事情&#xff0c;不是上课&#xff0c;而是做学案。找题、对难度、配解析、调格式、作图、排版&#xff0c;一套二试几何专题…

作者头像 李华