0

0

【PaddleDetection】结合51单片机搭建微信跳一跳物理外挂

P粉084495128

P粉084495128

发布时间:2025-07-18 10:46:23

|

960人浏览过

|

来源于php中文网

原创

本文介绍了一个基于深度学习的跳一跳物理外挂制作过程。先准备PaddleDetection,自制199张图片数据集并标注,转成COCO格式。用PPYOLO_Tiny训练模型,经验证、导出后部署。电脑将坐标距离转成按压时间,通过上位机代码向51单片机发指令,单片机按指令操作,还提供了相关代码。

☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜

【paddledetection】结合51单片机搭建微信跳一跳物理外挂 - php中文网

前言

 单片机原理课的作业做了一个OpenCV+汇编51的没啥用的跳一跳物理外挂,觉得可以换成用深度学习进行目标检测,于是就来试一试

效果图:

【PaddleDetection】结合51单片机搭建微信跳一跳物理外挂 - php中文网

效果动图:

【PaddleDetection】结合51单片机搭建微信跳一跳物理外挂 - php中文网

一、准备工作

1. 准备PaddleDetection

In [ ]
#安装PaddleDetection!git clone https://gitee.com/paddlepaddle/PaddleDetection.git work/PaddleDetection
In [ ]
#安装前置!pip install --upgrade -r work/PaddleDetection/requirements.txt -i https://mirror.baidu.com/pypi/simple

2. 自制数据集

 采集199张图片并剪裁(差一张强迫症狂喜(狗头)),使用EasyData平台进行数据标注(他那个智能标注还挺好用的,标完直接传到AIstudio上)

ONLYOFFICE
ONLYOFFICE

用ONLYOFFICE管理你的网络私人办公室

下载

【PaddleDetection】结合51单片机搭建微信跳一跳物理外挂 - php中文网

In [ ]
#解压数据集!unzip -q 'data/data109105/JumpData V1.zip' -d data/
!mkdir data/JumpData
!mkdir data/JumpData/Image
!mkdir data/JumpData/Label
!mkdir data/JumpData/Anno
!mv data/DatasetId_230079_1631965091/*.json data/JumpData/Label
!mv data/DatasetId_230079_1631965091/*.jpg data/JumpData/Image
!rm -rf data/DatasetId_230079_1631965091
!rm -rf data/JumpData/Label/screen2.json

 转成COCO格式的标注文件(这地方之前搞错了,训练半天精度上不去,后面才发现是我标注文件做错了)

In [ ]
#整理Json文件import osimport json

classlist = [{'supercategory': 'none', 'id': 1, 'name': 'player'}, 
             {'supercategory': 'none', 'id': 2, 'name': 'platform'}]#trainidxcount = 0imgcountidx = 0JumpData_train = {}
imagelist_train = []
labellist_train = []for idx, imagename in enumerate(os.listdir('data/JumpData/Image')[0:179]):
    imagelist_train.append({'file_name': imagename, 'height': 600, 'width': 1080, 'id': idx})
    jsonname = os.path.splitext(imagename)[0] + '.json'
    with open(os.path.join('data/JumpData/Label', jsonname)) as f:
        data = json.load(f)        for label in data['labels']:
            x1 = label['x1']
            y1 = label['y1']
            w = label['x2'] - label['x1']
            h = label['y2'] - label['y1']
            area = (w * h)            if label['name'] == 'platform':
                classidx = 2
            else:
                classidx = 1
            idxcount += 1
            labellist_train.append({'area': area, 
                              'iscrowd': 0, 
                              'bbox': [x1, y1, w, h], 
                              'category_id': classidx, 
                              'ignore': 0, 
                              'segmentation': [], 
                              'image_id': imgcountidx, 
                              'id': idxcount})
        imgcountidx += 1#validxcount = 0imgcountidx = 0JumpData_val = {}
imagelist_val = []
labellist_val = []for idx, imagename in enumerate(os.listdir('data/JumpData/Image')[179:199]):
    imagelist_val.append({'file_name': imagename, 'height': 600, 'width': 1080, 'id': idx})
    jsonname = os.path.splitext(imagename)[0] + '.json'
    with open(os.path.join('data/JumpData/Label', jsonname)) as f:
        data = json.load(f)        for label in data['labels']:
            x1 = label['x1']
            y1 = label['y1']
            w = label['x2'] - label['x1']
            h = label['y2'] - label['y1']
            area = (w * h)            if label['name'] == 'platform':
                classidx = 2
            else:
                classidx = 1
            idxcount += 1
            labellist_val.append({'area': area, 
                              'iscrowd': 0, 
                              'bbox': [x1, y1, w, h], 
                              'category_id': classidx, 
                              'ignore': 0, 
                              'segmentation': [], 
                              'image_id': imgcountidx, 
                              'id': idxcount})
        imgcountidx += 1JumpData_train['images'] = imagelist_train
JumpData_train['type'] = 'instances'JumpData_train['annotations'] = labellist_train
JumpData_train['categories'] = classlist

JumpData_val['images'] = imagelist_val
JumpData_val['type'] = 'instances'JumpData_val['annotations'] = labellist_val
JumpData_val['categories'] = classlist
json.dump(JumpData_train, open('data/JumpData/Anno/JumpData_train.json', 'w'), indent=4)
json.dump(JumpData_val, open('data/JumpData/Anno/JumpData_val.json', 'w'), indent=4)

二、开始训练

 使用PPYOLO_Tiny进行训练,配置文件请见work/Config/Yml文件夹

In [29]
#模型训练!export CUDA_VISIBLE_DEVICES=0!python work/PaddleDetection/tools/train.py \
    -c work/Config/Yml/PPYOLO_TINY_JUMP.yml \
    --eval

三、效果验证

In [31]
#模型预测!python work/PaddleDetection/tools/infer.py \
    -c work/Config/Yml/PPYOLO_TINY_JUMP.yml \
    -o weights=work/output/PPYOLO_TINY_JUMP/best_model.pdparams \
    --infer_img=work/Config/screen.png \
    --draw_threshold=0.5 \
    --output_dir=work/imgresult

四、模型导出

In [ ]
#导出模型!python work/PaddleDetection/tools/export_model.py \
    -c work/Config/Yml/PPYOLO_TINY_JUMP.yml \
    -o weights=work/output/PPYOLO_TINY_JUMP/best_model.pdparams \
    --output_dir=work/inference_model
In [ ]
#模型预测(导出后)!python work/PaddleDetection/deploy/python/infer.py \
    --model_dir=work/inference_model/PPYOLO_TINY_JUMP \
    --image_file=work/Config/screen.png \
    --output_dir=work/inferenceresult

五、模型部署

电脑根据模型得出的结果将坐标距离转化为屏幕按压时间,然后对51单片机发出指令,下面给出上位机代码以及51单片机的汇编代码,完整上位机包已在work/UARTServo.zip给出,汇编代码直接导进Keil中编译成HEX文件烧录至单片机内即可

1. 上位机代码

In [ ]
import osimport cv2import timeimport serialimport paddlefrom Predict import PredictConfig, Detector, predict_imagedef getscreen():
    os.system("adb shell rm /sdcard/screen.png")
    os.system("del C:\\Users\\Blang\\Desktop\\screen.png") 
    os.system("adb shell screencap -p /sdcard/screen.png")      
    os.system("adb pull /sdcard/screen.png C:/Users/Blang/Desktop")
    img = cv2.imread('C:/Users/Blang/Desktop/screen.png')
    img = img[850:1450, :]    return img    
def getposition(image_file):
    paddle.enable_static()
    threshold = 0.5
    model_dir = 'inference_model/PPYOLO_TINY_JUMP'
    pred_config = PredictConfig(model_dir)
    detector = Detector(pred_config, model_dir)
    results = predict_image(detector, image_file, threshold)    return results    
def calculate(results):
    player_position = []
    platform_position = []    for result in results:
        classid = result[0]
        xmin = result[2]
        ymin = result[3]
        xmax = result[4]
        ymax = result[5]
        w = xmax - xmin
        h = ymax - ymin        if classid == 0:
            player_x = xmin + w / 2
            player_y = ymax
            player_position.append([player_x, player_y])        else:
            platform_x = xmin + w / 2
            platform_y = ymax
            platform_position.append([platform_x, platform_y])    for player in player_position:        for platform in platform_position:            if player[1] < platform[1]:                continue
            else:
                player_x = player[0]
                player_y = player[1]
                platform_x = platform[0]
                platform_y = platform[1]
    distance = ((platform_x - player_x)**2 + (platform_y - player_y)**2)**0.5
    presstime = distance * 1.5 + 200
    presstime = presstime * 0.001
    return presstimedef sendcommand(presstime):
    ser=serial.Serial("COM5", 2400, timeout=5)
    result=ser.write(chr(0x32).encode("utf-8"))
    time.sleep(presstime)
    result=ser.write(chr(0x31).encode("utf-8"))
    ser.close()
    time.sleep(1)    
while True:
    img = getscreen()
    results = getposition(img)
    presstime = calculate(results)
    sendcommand(presstime)

2. 汇编代码

In [ ]
	ORG 	0000H
	LJMP 	MAIN
	ORG		000BH
	LJMP	Timer0Interrupt
	ORG 	0023H
	LJMP 	UARTInterrupt
	ORG     0100H
MAIN:
	LCALL	InitAll
	LCALL 	InitTimer0
	LCALL 	InitUART
	LCALL	PWM
	LJMP MAIN
/***********************************/
InitAll:
	MOV		R7, #50D
	MOV 	SP, #60H
	MOV 	TMOD, #22H/***********************************/
InitTimer0:
    MOV TH0, #0A4H
    MOV TL0, #0A4H
    SETB EA
    SETB ET0
    SETB TR0
	SETB P3.5
	SETB P3.6
	RET
PWM:
	MOV 	A, #200D
	SUBB 	A, R1
	MOV 	R2, A
	MOV 	A, R1
	MOV 	R0, A
DELAY:
	CJNE 	R0, #00H, $
	CLR 	P3.5
	CLR 	P3.6
	MOV 	A, R2
	MOV 	R0, A
	CJNE 	R0, #00H, $
	SETB 	P3.5
	SETB	P3.6
	MOV 	A, R1
	MOV 	R0, A
	DJNZ 	R7, DELAY
    RET
Timer0Interrupt:
	DEC 	R0
    RETI
/***********************************/
InitUART:
	MOV 	SCON, #50H
	MOV 	TH1, #0F3H
	MOV 	TL1, TH1
	MOV 	PCON, #00H
	SETB 	EA
	SETB 	ES
	SETB 	TR1
	RET
UARTInterrupt:
	CLR     ES
	PUSH 	ACC
	JB 		RI, Is_Receive
	RETI
Is_Receive:
	CLR 	RI
	MOV 	A, SBUF
	CJNE    A, #31H, NEXT_POSITION
	MOV 	R1, #8D NEXT_POSITION:
	CJNE    A, #32H, GOBACK
	MOV 	R1, #20DGOBACK:
	SETB    ES
	POP 	ACC
	RETI
/***********************************/
END

相关文章

微信app下载
微信app下载

微信是一款手机通信软件,支持通过手机网络发送语音短信、视频、图片和文字。微信可以单聊及群聊,还能根据地理位置找到附近的人,带给大家全新的移动沟通体验,有需要的小伙伴快来保存下载体验吧!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
单片机编程软件有哪些
单片机编程软件有哪些

单片机常用的编程软件有:1、Keil编程开发环境;2、IAR;3、STC-ISP;4、STM32CubeIDE;5、Altium Designer。更多关于单片机编程软件的内容,大家可以访问本专题下面的文章。

1228

2023.10.12

单片机编程软件推荐
单片机编程软件推荐

常见的单片机编程软件可分为三类:1、专有软件,如keil uvision和iar embedded workbench;2、开源软件,如arduino ide和eclipse with cdt;3、跨平台软件,如visual studio code和atom。想了解更多单片机的相关内容,可以阅读本专题下面的文章。

523

2024.05.20

plc和单片机的区别
plc和单片机的区别

plc和单片机的区别:1、体积和结构不同:PLC体型通常较大,带有模块化结构,由多个组件组成,而单片机体型更小,通常由一个单芯片组成;2、存储容量不同:PLC通常具有较大的存储容量,用于存储程序和数据,单片机存储容量通常较小,但足以满足其应用需求;3、可编程性不同等等。想了解更多plc的相关内容,可以阅读本专题下面的文章。

620

2024.05.30

树莓派和单片机的区别
树莓派和单片机的区别

树莓派和单片机的主要区别在于功能和应用。树莓派基于linux操作系统,拥有强大的计算能力和丰富的软件生态系统,适用于物联网、小型服务器、教育和爱好者项目等场景。单片机基于简单的微控制器,计算能力有限,主要用于嵌入式系统和控制特定设备,如工业控制、家用电器和医疗设备。想了解更多树莓派和单片机的相关内容,可以阅读本专题下面的文章。

408

2024.06.03

dsp和单片机的区别
dsp和单片机的区别

dsp专注于数字信号处理,具有更高的处理能力、专门架构、指令集和存储器结构,但功耗也更高。单片机更适合一般任务,具有较低的处理能力、更通用的架构和指令集,以及较小的存储器结构和功耗。想了解更多dsp和单片机的相关内容,可以阅读本专题下面的文章。

680

2024.06.04

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

1

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

2

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

0

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

0

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.6万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号