news 2026/10/17 18:30:03

基于PaddleHub的实时皮影戏交互系统:姿态估计与物理模拟实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于PaddleHub的实时皮影戏交互系统:姿态估计与物理模拟实战

1. 项目缘起与整体设计思路

皮影戏这门老手艺,我小时候在庙会上见过几回,一块白布、几根竹签、一盏油灯,艺人手指翻飞之间,孙悟空就能跟白骨精打得天昏地暗。后来一直想,能不能用代码把这套东西复刻出来——不是做那种冷冰冰的动画,而是让机器也学会“操纵皮影”的那股子灵动劲儿。这个项目就是冲着这个念头去的:用飞桨的PaddleHub做一套能实时驱动皮影角色动作的交互系统,让用户通过摄像头或者键盘就能“演”一出皮影戏。

先说清楚这个项目到底能干什么。核心功能有三块:第一,用PaddleHub里现成的姿态估计模型抓取人体关键点,把人的动作映射到皮影角色的关节上;第二,把皮影的各个部件(头、躯干、上臂、前臂、大腿、小腿)做成可独立旋转的图层,每个图层对应一个骨骼节点;第三,加一层简单的物理惯性模拟,让皮影的动作带点“竹签操控”的迟滞感,而不是像机器人那样硬邦邦地跳。适合谁来参考?我觉得有两类人比较对口:一类是做过一点Python、想找个有意思的AI项目练手的开发者;另一类是对传统皮影戏感兴趣、想用数字手段做点新表达的设计师或艺术工作者。不需要你懂深度学习原理,PaddleHub已经把模型封装得很傻瓜了,但基本的Python和图像处理概念得有。

为什么选PaddleHub而不是自己训模型?这里头有个很实际的考量。皮影戏的动作识别有个特点——它不要求毫米级的精度,但要求实时性和鲁棒性。你想想,皮影戏本来就是夸张的、写意的,关节角度差个十度八度根本看不出来,但要是帧率掉到15fps以下,那股流畅劲儿就没了。PaddleHub的human_pose_estimation模型在CPU上就能跑到25fps左右(i5-10400实测),GPU上更是轻松过60fps,而且它输出的COCO 17关键点格式刚好够用——鼻子、左右肩、左右肘、左右腕、左右髋、左右膝、左右踝,这些点映射到皮影的关节上绰绰有余。自己训一个模型?光是标注数据就得搭进去几周,而且效果未必比这个预训练模型好,性价比太低。

再说皮影角色的设计思路。传统皮影的关节连接方式其实跟人体骨骼模型很像,但有个关键区别:皮影的关节是“铰接”的,只能绕一个轴旋转,不像人的肩关节那么灵活。这个限制反而是好事——它让动作映射变得简单了。我把皮影拆成11个独立部件:头、颈、胸、腰、左上臂、左前臂、右上臂、右前臂、左腿、右腿、手。每个部件是一个PNG图层,锚点设在关节连接处。渲染的时候按顺序叠加,后画的盖住先画的,模拟皮影的层叠关系。这里有个细节:传统皮影是半透明的牛皮做的,光从后面打过来会有透光效果。我在代码里用alpha通道模拟了这个——每个图层的透明度设成0.85,边缘再加一圈深色描边,看起来就有那股子“皮”的质感了。

动作映射的逻辑是这套系统的核心。PaddleHub输出的是17个关键点的坐标和置信度,我需要把这些坐标转换成每个关节的旋转角度。拿手臂举例:左肩坐标是(x1,y1),左肘是(x2,y2),那么左上臂的旋转角度就是atan2(y2-y1, x2-x1)减去一个基准角度。听起来简单,但实际做的时候有几个坑。第一个坑是坐标系的差异——PaddleHub输出的坐标是图像坐标系,原点在左上角,y轴向下;而皮影图层的旋转是围绕锚点的,角度是逆时针为正。这两个得统一,不然皮影会像照镜子一样反着动。第二个坑是置信度过滤——当某个关键点置信度低于0.3时,说明模型没看清,这时候不能直接用这个点的坐标,得用上一帧的角度做平滑过渡,否则皮影会突然抽搐一下。

物理惯性模拟这块,我加了一个简单的弹簧阻尼系统。每个关节的角度不是直接等于目标角度,而是通过一个二阶微分方程逼近:角加速度 = k*(目标角度 - 当前角度) - c*角速度。k是弹簧刚度,c是阻尼系数。调参的时候发现,k=0.15、c=0.6这组值出来的效果最像真人操控皮影——动作有跟随感,但不会太拖沓。如果k太大,皮影就变成机器人了;c太大,动作又软绵绵的没力气。这个参数跟帧率有关,如果你的循环跑在30fps,这组值可以直接用;跑在60fps的话,k和c都得翻倍。

2. 核心细节解析与实操要点

2.1 PaddleHub环境搭建与模型选型

先把环境搭起来。PaddleHub的安装本身不复杂,但有几个版本兼容性的坑得提前说。我试过paddlepaddle 2.4和2.5两个版本,2.5在Windows上有个OpenMP的冲突问题,跑姿态估计的时候会报“libiomp5md.dll already initialized”的错。解决办法是在代码最开头加一行import os; os.environ['KMP_DUPLICATE_LIB_OK']='TRUE',虽然官方说这可能导致性能下降,但实测下来帧率只掉了2帧左右,可以接受。如果你用Linux,这个问题基本不会遇到。

安装命令是这样的:

pip install paddlepaddle==2.4.2 pip install paddlehub==2.4.0

注意paddlehub的版本要跟paddlepaddle匹配,2.4.0的hub配2.4.x的paddle最稳。装完之后用hub install human_pose_estimation把姿态估计模型拉下来,模型大小大概200MB左右,第一次跑会自动下载。

模型选型上,PaddleHub里跟姿态估计相关的有两个:human_pose_estimation和openpose_body_estimation。前者是基于HRNet的,精度高但速度稍慢;后者是基于OpenPose的,速度快但关键点少几个。皮影戏这个场景我选了human_pose_estimation,原因是它输出的17个关键点里包含了手腕和脚踝的精细位置,这对皮影的手部动作特别重要——皮影戏里手的姿势往往比身体姿态更有表现力。OpenPose那个模型对手腕的估计不够准,做“翻手”“抖腕”这些动作时会丢细节。

提示:如果你打算在树莓派或者低功耗设备上跑,建议换OpenPose那个模型,虽然精度差一点,但帧率能翻倍。皮影戏对精度的容忍度比想象中高。

2.2 皮影部件的图层拆分与锚点设置

皮影部件的拆分是个细活。我一开始想偷懒,直接用一张完整的皮影图,然后整体旋转——结果做出来的东西像个纸片人在晃,完全没有关节活动的感觉。后来老老实实拆成11个图层,每个图层单独导出PNG,背景透明。拆的时候有个原则:每个部件的旋转锚点必须设在它跟父部件的连接处。比如左上臂的锚点设在肩关节位置,左前臂的锚点设在肘关节位置。这样旋转的时候,前臂会跟着上臂动,形成自然的父子关系。

锚点的坐标怎么定?我是在Photoshop里用参考线标出来的,导出的时候记下每个锚点在图层内的相对坐标(0到1之间)。比如左上臂图层是200x80像素,肩关节在图层的最右端中间,那锚点就是(1.0, 0.5)。这个相对坐标在代码里乘以图层的实际显示尺寸,就能得到绝对锚点位置。

图层的绘制顺序也有讲究。传统皮影是“后层压前层”,靠近观众的那一侧部件画在最上面。我的顺序是:远侧手臂→远侧腿→躯干→近侧腿→近侧手臂→头。这样当皮影转身的时候,手臂会自然地挡住身体,看起来有立体感。如果你把顺序搞反了,皮影就会像纸片一样扁平,失去那种“关节交错”的层次感。

还有一个细节:皮影的关节连接处不能是直角切口,得画成圆弧形。因为旋转的时候,直角切口会露出背景,看起来像断了。圆弧形切口的话,无论怎么转,连接处都是平滑过渡的。这个在画素材的时候就得注意,后期用代码补是补不出来的。

2.3 姿态到关节角度的映射算法

映射算法的核心是一组三角函数,但实际写起来比想象中麻烦。我先把PaddleHub输出的17个关键点整理成一个字典,键是关节名,值是(x, y, confidence)。然后定义每个皮影关节对应的关键点对。比如左上臂对应的是左肩和左肘,左前臂对应的是左肘和左腕。

计算角度的时候,我用了一个辅助函数:

import math def calc_angle(p1, p2): dx = p2[0] - p1[0] dy = p2[1] - p1[1] return math.degrees(math.atan2(-dy, dx))

注意这里-dy是因为图像坐标系的y轴向下,而旋转角度是逆时针为正,所以得取反。这个函数返回的是相对于水平向右方向的角度,范围是-180到180度。

但皮影的每个部件都有一个“静止角度”——就是它在初始姿态下的角度。比如左上臂在初始状态下是垂直向下的,那它的静止角度就是-90度(因为atan2(-1, 0)是-90度)。实际旋转角度 = 当前角度 - 静止角度。这个差值才是我们要应用到图层上的旋转量。

置信度处理是另一个关键点。PaddleHub输出的每个关键点都带一个0到1的置信度,低于0.3的基本可以认为是噪声。我的做法是:如果某个关键点的置信度低于阈值,就不更新对应的关节角度,而是保持上一帧的角度,同时用一个低通滤波器做平滑。滤波器的公式是:

current_angle = 0.7 * current_angle + 0.3 * target_angle

这个0.7和0.3的权重是调出来的。权重太偏向target,动作会抖;太偏向current,动作会滞后。0.7/0.3这组值在30fps下表现最好。

注意:不要对所有关节用同一个平滑系数。手腕和脚踝这些末端关节可以响应快一点(0.5/0.5),而躯干和头部可以慢一点(0.8/0.2),这样出来的动作更有“鞭子效应”——根部稳、梢部灵。

2.4 物理惯性模拟的参数调校

弹簧阻尼系统的实现很简单,但调参是个体力活。我写了一个小脚本,把k和c做成滑动条,实时看效果。调了大概两个小时,最后定下来k=0.15、c=0.6(30fps下)。这个组合的物理意义是:关节以大约0.3秒的时间常数逼近目标角度,超调量控制在5%以内。用人话说就是——动作跟得上,但不会“啪”一下到位,而是有个柔和的减速过程。

如果你想让皮影的动作更“重”一点,比如演武将的时候,可以把k降到0.08、c加到0.8,这样动作会更迟缓、更有分量感。反过来,演小旦的时候用k=0.25、c=0.4,动作就轻快灵动。这个参数可以做成预设,根据角色类型切换。

还有一个隐藏参数是“最大角速度”。物理上关节不可能无限快旋转,我加了一个限制:每帧角度变化不超过15度。这个限制在快速动作时特别有用——比如用户突然挥手,如果没有这个限制,皮影的手臂会瞬间甩过去,看起来像鬼畜。加了限制之后,手臂会以最大速度追过去,反而更有“操控感”。

3. 完整实操流程与核心环节实现

3.1 从零搭建项目骨架

项目目录结构是这样的:

shadow_puppet/ ├── assets/ │ ├── head.png │ ├── torso.png │ ├── l_upper_arm.png │ ├── l_forearm.png │ ├── r_upper_arm.png │ ├── r_forearm.png │ ├── l_thigh.png │ ├── l_shin.png │ ├── r_thigh.png │ ├── r_shin.png │ └── hand.png ├── config.json ├── pose_tracker.py ├── puppet_renderer.py └── main.py

config.json里存的是每个部件的锚点坐标、静止角度、父子关系。比如:

{ "l_upper_arm": { "anchor": [1.0, 0.5], "rest_angle": -90, "parent": "torso", "keypoints": ["left_shoulder", "left_elbow"] } }

pose_tracker.py负责调PaddleHub拿关键点,puppet_renderer.py负责根据角度渲染皮影,main.py是主循环。这个拆分的好处是——如果你想换一个姿态估计模型,只需要改pose_tracker.py,渲染部分完全不用动。

3.2 姿态跟踪模块的实现细节

pose_tracker.py的核心是一个类:

import paddlehub as hub import cv2 import numpy as np class PoseTracker: def __init__(self): self.model = hub.Module(name="human_pose_estimation") self.prev_keypoints = None self.smooth_factor = 0.3 def get_keypoints(self, frame): result = self.model.keypoint_detection(images=[frame]) keypoints = result[0]['data'] # keypoints是17个点的列表,每个点是[x, y, score] if self.prev_keypoints is not None: for i in range(len(keypoints)): if keypoints[i][2] < 0.3: keypoints[i] = self.prev_keypoints[i] else: keypoints[i][0] = (1-self.smooth_factor)*self.prev_keypoints[i][0] + self.smooth_factor*keypoints[i][0] keypoints[i][1] = (1-self.smooth_factor)*self.prev_keypoints[i][1] + self.smooth_factor*keypoints[i][1] self.prev_keypoints = keypoints return keypoints

这里有个性能优化的点:keypoint_detection每次调用都会重新加载模型吗?不会,PaddleHub的Module在初始化的时候就把模型加载到内存了,后续调用只是前向推理。但如果你在循环里反复创建PoseTracker实例,那就会反复加载模型,帧率直接掉到个位数。所以PoseTracker一定要在循环外面初始化一次。

另一个坑是图像格式。PaddleHub的keypoint_detection接受的是numpy数组,通道顺序是BGR(OpenCV默认)。如果你从摄像头读帧,直接传进去就行。但如果你从文件读图片,记得用cv2.imread而不是PIL,因为PIL读出来是RGB,直接传给PaddleHub会得到错误的关键点位置。

3.3 皮影渲染模块的图层变换

渲染部分我用的是PIL的Image.rotate,但这里有个性能陷阱——PIL的rotate是每次生成一个新的图像对象,如果每帧都对11个图层做rotate再合成,帧率会掉得很厉害。我的优化方案是:预先把每个图层的旋转版本缓存起来,按角度分桶。比如每5度一个桶,从-180度到180度一共72个桶。渲染的时候根据当前角度找到最近的桶,直接用缓存好的图像。这样每帧只需要做图像粘贴,不需要做旋转计算。实测下来,这个优化让渲染帧率从18fps提到了45fps。

缓存的生成在初始化阶段完成:

def precompute_rotations(image, anchor, step=5): cache = {} for angle in range(-180, 181, step): rotated = image.rotate(angle, resample=Image.BILINEAR, center=anchor) cache[angle] = rotated return cache

注意center参数要传锚点的绝对坐标,不是相对坐标。这个锚点坐标是图层尺寸乘以相对锚点得到的。

合成的时候,我按照父子关系递归地计算每个部件的绝对位置。比如左上臂的位置 = 躯干位置 + 躯干旋转后的偏移量。这个偏移量在初始化的时候算好,存成一个变换矩阵。每帧只需要用当前角度更新矩阵,然后应用到图层上。

提示:如果你的皮影图层比较大(比如2048x2048),预计算72个旋转版本会占很多内存。这时候可以把step调大一点,比如10度一个桶,内存占用直接减半,视觉上几乎看不出差别。

3.4 主循环与交互逻辑

主循环的逻辑很直接:读帧→跟踪姿态→计算角度→渲染皮影→显示。但有几个细节决定了体验的好坏。

第一是帧率控制。我用了一个简单的计时器,如果这一帧的处理时间小于33毫秒(30fps),就sleep到33毫秒再跑下一帧。这样能保证动作的流畅度稳定,不会因为某几帧算得快就突然加速。

第二是键盘交互。除了摄像头驱动,我还加了键盘控制模式——用方向键控制皮影的四肢,空格键切换动作预设。这个模式在摄像头不好用的时候(比如光线太暗)可以兜底。键盘控制的实现很简单,维护一个目标角度字典,按键的时候修改目标角度,然后走同样的物理模拟流程。

第三是背景合成。皮影戏得有块“白布”当背景。我用了一个纯白色的画布,然后在上面加了一层淡淡的纹理(用高斯噪声生成),模拟布料的质感。皮影图层叠加在纹理之上,最后再整体加一层暖色调的滤镜,看起来就像油灯打出来的光。

def render_frame(puppet_layers, background): canvas = background.copy() for layer in puppet_layers: canvas.paste(layer.image, layer.position, layer.image) # 暖色调滤镜 canvas = apply_warm_filter(canvas) return canvas

暖色调滤镜的实现是调整RGB通道的增益:R通道乘1.1,G通道乘1.0,B通道乘0.85。这个简单的操作能让画面立刻有“旧时光”的感觉。

4. 常见问题与排查技巧实录

4.1 姿态估计不准的几种情况

问题一:关键点抖动严重。这是最常见的问题,尤其是手部和脚部的关键点。原因通常是摄像头分辨率不够或者光线不均匀。解决办法有三个:一是把摄像头分辨率调到720p以上,480p的话手腕关键点基本没法用;二是加一个简单的平滑滤波,就是我前面说的那个0.7/0.3的指数平滑;三是如果某个关键点连续多帧置信度都低于0.3,就把它标记为“丢失”,用上一帧的角度加上一个衰减因子来估计。

问题二:左右不分。PaddleHub有时候会把左肩和右肩搞反,尤其是在用户侧身的时候。这个问题的根源是模型对遮挡的处理不够好。我的解决办法是加一个“左右一致性检查”:如果左肩的x坐标大于右肩的x坐标(在正常面对摄像头的情况下),就说明左右可能反了,这时候交换左右关键点。这个检查不是100%准确,但能解决大部分情况。

问题三:背景干扰。如果背景里有其他人或者类似人体的物体,模型可能会把背景里的人也算进去。解决办法是只取置信度最高的那个人。PaddleHub的keypoint_detection默认返回所有人的关键点,我加了一个筛选逻辑:计算每个人的平均置信度,只保留最高的那个。

4.2 渲染性能优化的几个手段

手段一:降低图层分辨率。皮影图层不需要4K,1080p足够了。我把所有图层缩放到原来的50%,渲染速度直接翻倍,视觉上几乎看不出差别。因为皮影本来就是写意的,边缘稍微糊一点反而更有味道。

手段二:跳过不必要的旋转计算。如果某个关节的角度变化小于1度,就不更新它的旋转缓存。这个优化在动作缓慢的时候特别有效,能省下30%左右的计算量。

手段三:用numpy做图像合成。PIL的paste是逐像素操作的,速度慢。我后来换成了numpy的数组切片赋值,速度快了大概40%。具体做法是把图层转成numpy数组,然后用alpha通道做加权平均。

def blend_layer(canvas, layer, x, y): h, w = layer.shape[:2] alpha = layer[:,:,3:4] / 255.0 canvas[y:y+h, x:x+w, :3] = canvas[y:y+h, x:x+w, :3] * (1-alpha) + layer[:,:,:3] * alpha

4.3 常见问题速查表

问题现象可能原因排查方法解决方案
皮影不动摄像头没读到帧打印帧的shape检查摄像头索引,换cv2.VideoCapture(1)试试
动作反向坐标系没统一打印关键点坐标检查calc_angle里的-dy有没有漏
关节错位锚点设置错误单独渲染一个图层看旋转中心重新标定锚点,确保在关节连接处
帧率低于15fps旋转缓存没命中打印缓存命中率增大角度分桶的step,或降低图层分辨率
皮影闪烁置信度过滤太激进打印每帧的置信度把阈值从0.3降到0.2,或加长平滑窗口
手部动作丢失手腕关键点置信度低单独看手腕的置信度用肘部角度推算手腕角度,或加键盘控制兜底

4.4 几个踩过的坑和独家技巧

坑一:PaddleHub的模型在第一次调用时特别慢。第一次跑keypoint_detection大概要3到5秒,因为要初始化计算图。解决办法是在主循环之前先拿一张空白图跑一次,把模型“预热”好。这个预热操作能让后续的帧率稳定在正常水平。

坑二:OpenCV的窗口和PIL的图像格式不兼容。我用PIL渲染完皮影之后,要转成numpy数组才能用cv2.imshow显示。转换的时候注意通道顺序——PIL是RGB,OpenCV是BGR,得用cv2.cvtColor转一下,不然颜色会偏。

坑三:物理模拟的数值稳定性。如果k和c调得太大,弹簧阻尼系统会发散,角度会震荡到无穷大。我加了一个硬限制:角度变化率超过每秒720度就截断。这个限制在正常调参下不会触发,但能防止程序崩溃。

技巧一:用动作预设做“关键帧”。除了实时驱动,我还加了几个预设动作——比如“翻跟头”“耍金箍棒”“走路”。这些预设是一组关键帧角度序列,播放的时候用插值过渡。这个功能在演示的时候特别有用,因为不是每个人都能对着摄像头做出标准的皮影动作。

技巧二:加一个“镜像模式”。默认情况下,用户抬左手,皮影也抬左手。但皮影戏的表演者通常是在幕布后面,观众看到的是镜像。所以我加了一个开关,可以切换是否水平翻转。这个功能实现很简单,就是把所有关键点的x坐标用图像宽度减一下。

技巧三:用音频驱动节奏。我后来扩展了一下,加了一个简单的节拍检测——从麦克风读音频,检测到鼓点的时候让皮影做一个“亮相”动作。这个功能让皮影戏的表演感强了很多,虽然实现只是几行代码的事。

5. 项目扩展方向与个人体会

这套东西跑通之后,我试了几个扩展方向,有些效果不错,有些踩了坑。第一个扩展是加多个皮影角色——同时跟踪两个人,分别驱动两个皮影,让他们对打。这个在技术上是可行的,PaddleHub支持多人检测,但渲染的时候要注意图层的遮挡顺序,两个皮影交叠的时候得根据y坐标动态调整谁在前谁在后。第二个扩展是加场景元素——比如山、树、云,这些用简单的视差滚动就能做出纵深感。第三个扩展是录制和回放——把每帧的关节角度存成JSON,回放的时候直接读角度,不需要再跑姿态估计,这样录制的视频可以做到60fps满帧。

踩过的坑也有几个。一个是PaddleHub在Mac M1上的兼容性问题,paddlepaddle的M1版本当时还不完善,跑起来会报架构错误,后来换了x86的Python才解决。另一个是摄像头的自动曝光——在光线变化的时候,摄像头的曝光会突然调整,导致连续几帧的关键点全丢。解决办法是手动锁定曝光,用cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.25)把自动曝光关掉。

我个人在实际操作中的体会是,皮影戏这个项目的难点不在AI部分,而在“味道”的把握。PaddleHub已经把姿态估计做得足够好了,但要让皮影看起来有“戏”,得在细节上花功夫——关节的迟滞感、图层的透光效果、动作的夸张程度,这些都不是模型能给的,得靠手动调。我调那个弹簧阻尼参数调了整整一个下午,最后出来的效果才勉强让自己满意。所以如果你打算复现这个项目,建议在物理模拟和渲染效果上多花点时间,那才是决定成败的地方。

最后分享一个小技巧:如果你觉得实时驱动太累,可以先用摄像头录一段自己的动作,存成视频文件,然后用视频文件驱动皮影。这样你可以反复调整动作,直到满意为止,再也不用对着摄像头手舞足蹈了。这个“离线驱动”模式在调试阶段特别有用,强烈建议先把这个流程跑通,再去搞实时驱动。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 18:27:19

AI辅助开发登录界面:从需求拆解到前后端联调全流程

前一阵折腾了几个小项目&#xff0c;发现用AI辅助开发这件事&#xff0c;真正难的不是写代码&#xff0c;而是怎么把一个模糊的需求描述成机器能理解的任务。这个系列写到第三篇&#xff0c;正好拿“登录界面”这个看似简单、实际坑不少的场景来聊聊。如果你正准备用AI帮忙搭一…

作者头像 李华
网站建设 2026/10/17 18:21:23

2020A题炉温曲线:热传导模型、参数反演与传送带速度优化

简介&#xff1a;这份资源是2020年全国大学生数学建模竞赛A题「炉温曲线」的讲评资料&#xff0c;面向备战数模竞赛的高校学生及指导教师&#xff0c;帮助读者系统理解该赛题的建模思路与求解方法。压缩包内仅含1个PDF文件&#xff0c;约26.94MB&#xff0c;内容围绕赛题展开完…

作者头像 李华
网站建设 2026/10/17 18:16:40

汇编优化实战:表驱动选择、条件伪指令与移位指令全解析

第一次写带功能菜单的程序时&#xff0c;我老老实实把每个按键值都判断一遍&#xff1a;CMP AL, 0、JE&#xff0c;然后CMP AL, 1、JE……也就五六个分支&#xff0c;写完连我自己都看不下去。旁边带我的前辈扫了一眼代码&#xff0c;只说了一句&#xff1a;“别让 CPU 一条一条…

作者头像 李华
网站建设 2026/10/17 18:16:04

大图切块与小目标检测:从切图到结果合并的完整实践指南

做目标检测的人&#xff0c;迟早会遇到这么一类项目&#xff1a;图特别大&#xff0c;目标特别小。你拿着一张四千乘三千的航拍图&#xff0c;里面要找的是十几个像素的车辆或屋顶&#xff0c;直接丢进检测器&#xff0c;要么显存不够跑不起来&#xff0c;要么跑起来了但漏检漏…

作者头像 李华