1.介绍
微信小程序里的“跳一跳”是一款国民级休闲游戏,玩家通过按住屏幕的时间长短来控制棋子跳跃距离,精准落在下一个平台上。游戏规则简单,但要拿到高分却需要极强的节奏感和手眼协调能力。
这个项目不仅是对 AI 视觉识别和嵌入式控制的一次综合实践,更想探索一个有趣的问题:机器能否像人一样“看懂”游戏规则,并用物理动作完成操作? 同时,它也展示了 AI 如何从虚拟世界走向物理交互,为未来人机协同提供一种趣味范本。
2.传感器
| 硬件 | 型号 | 作用 |
| 主控板 | Arduino Uno | 上传模式,离线运行 |
| 视觉传感器 | 二哈2视觉传感器 | 加载目标检测训练模型 |
| 执行器 | SG90 舵机 180° | 模拟手指按压屏幕动作 |
| 触摸笔头 | 电容笔+接地线 | |
| 固定结构 | 舵机支架、3D 打印件 | |
| 其他 | USB数据线、杜邦线若干、12v锂电池 | 供电与信号连接 |
3.注意事项
3.1.二哈2需单独供电
连接附赠的转接板,必须单独供电,否则二哈2会绿屏、反复重启。
3.2.电容笔接地
电容笔金属端必须连接导线悬空接地,不然电容笔按下动作失效。
3.3.采集数据处理
通过截图的手机为完全竖版,必须借助ai制作python裁切图片的程序,批量裁切得到正方形数据,进行标注。
4.制作过程
4.1.3D打印外观件
设计外观件,预留线路、传感器位置开槽。
4.2.连接线路
Arduino Uno *1、舵机 *1、数字大按钮模块 *2、二哈2 *1

4.3.数据采集与裁切
由于得到的是竖版,训练误差较大,因此借助ai设计批量裁切图片程序。

import os
import sys
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
# 尝试导入 Pillow 库
try:
from PIL import Image
except ImportError:
print("错误:未安装 Pillow 库。请运行以下命令安装:")
print("pip install Pillow")
try:
root = tk.Tk()
root.withdraw()
messagebox.showerror("缺少依赖", "未安装 Pillow 库,请安装后重试。\n\n命令:pip install Pillow")
root.destroy()
except:
pass
sys.exit(1)
def crop_center_square(image_path: str, output_path: str, skip_existing: bool = True) -> bool:
"""
将图片按最短边从正中心裁剪为正方形,并保存到指定路径。
:param image_path: 原始图片路径
:param output_path: 输出图片路径
:param skip_existing: 若输出文件已存在,是否跳过(True=跳过并返回False)
:return: 是否成功裁剪并保存
"""
if skip_existing and os.path.exists(output_path):
return False
try:
with Image.open(image_path) as img:
width, height = img.size
side = min(width, height)
left = (width - side) // 2
top = (height - side) // 2
right = left + side
bottom = top + side
cropped = img.crop((left, top, right, bottom))
cropped.save(output_path)
return True
except Exception as e:
print(f"处理失败:{image_path} - {e}")
return False
class BatchCropper:
def __init__(self, root):
self.root = root
self.root.title("批量图片正方形裁剪工具")
self.root.geometry("500x250")
self.root.resizable(False, False)
# 说明标签
info_label = tk.Label(
root,
text="选择多张图片,程序将自动按最短边\n从正中心裁剪出正方形区域",
justify="center",
font=("微软雅黑", 10)
)
info_label.pack(pady=10)
# 选择文件按钮
self.select_btn = tk.Button(
root,
text="选择多张图片并裁剪",
command=self.start_batch,
width=20,
height=2,
bg="#4CAF50",
fg="white",
font=("微软雅黑", 10)
)
self.select_btn.pack(pady=10)
# 进度条
self.progress = ttk.Progressbar(root, orient="horizontal", length=400, mode="determinate")
self.progress.pack(pady=10)
# 状态标签
self.status_label = tk.Label(root, text="就绪", fg="gray")
self.status_label.pack(pady=5)
# 退出按钮
exit_btn = tk.Button(root, text="退出", command=root.quit, width=10)
exit_btn.pack(pady=5)
def start_batch(self):
"""选择多张图片并开始批量裁剪"""
file_paths = filedialog.askopenfilenames(
title="选择多张图片",
filetypes=[
("图像文件", "*.jpg *.jpeg *.png *.bmp *.tiff *.webp"),
("所有文件", "*.*")
]
)
if not file_paths:
return
# 禁用按钮,避免重复点击
self.select_btn.config(state="disabled", text="处理中...")
self.progress["value"] = 0
self.progress["maximum"] = len(file_paths)
# 使用 update_idletasks 保持界面响应,逐张处理(不另开线程,简单可靠)
success_count = 0
for i, file_path in enumerate(file_paths, 1):
# 更新状态标签
filename = os.path.basename(file_path)
self.status_label.config(text=f"正在处理:{filename}")
self.root.update_idletasks()
# 生成输出路径(原文件夹,添加 _square 后缀)
dir_name = os.path.dirname(file_path)
base_name, ext = os.path.splitext(filename)
output_name = f"{base_name}_square{ext}"
output_path = os.path.join(dir_name, output_name)
# 执行裁剪
if crop_center_square(file_path, output_path, skip_existing=True):
success_count += 1
# 更新进度条
self.progress["value"] = i
self.root.update_idletasks()
# 处理完成,恢复按钮并显示结果
self.select_btn.config(state="normal", text="选择多张图片并裁剪")
self.status_label.config(text=f"完成!成功:{success_count} / {len(file_paths)}")
messagebox.showinfo("批量处理完成", f"共处理 {len(file_paths)} 张图片\n成功裁剪 {success_count} 张\n已跳过已存在的正方形图片。")
self.progress["value"] = 0
def main():
root = tk.Tk()
app = BatchCropper(root)
root.mainloop()
if __name__ == "__main__":
main()4.4.数据标注

4.5.数据校验

5.完整积木

6.改进与不足
6.1.部分模型识别不出
关卡较多,采集的数据近90份有限,仍需要多采集,并标注。
6.2.反光
房间LED灯会反射到手机屏幕导致识别失败,需要遮挡光线直射。
6.3.按下数据不准
变化公式仍然在摸索中,不断调试优化接近数值。.
7.作品全样



返回首页
回到顶部



评论