计算机视觉——从环境配置到跨线计数的完整实现基于 YOLOv12 与质心追踪器的实时人员监控优秀的系统

news/2025/11/21 19:53:37/文章来源:https://www.cnblogs.com/gccbuaa/p/19254326

引言

在本课中,我们将继续探索 YOLOv12,它是第一个融入注意力机制的 YOLO 模型——包括 RELAN区域注意力(Area Attention) 以及用于快速推理的可选 FlashAttention 支持等创新。正如我们在上一个教程中所介绍的,YOLOv12 引入了一个灵活的架构,支持先前版本(例如 YOLOv11 和 YOLOv8)提供的所有主要任务,包括目标检测、分割、分类和姿态估计。

我们还介绍了 运行 YOLOv12 的两种方式

在本教程中,我们将超越静态推理,演示 如何将 YOLOv12 应用于一个真实的、基于摄像头的应用人员追踪监控

无论是购物中心、地铁站还是校园大门,实时追踪进出空间的人数可以提供宝贵的操作洞察。我们将展示如何:

在这里插入图片描述

仅使用一个输入视频,你的系统将:

让我们从头开始构建它。

为什么人员追踪监控很重要

图 2 中,使用俯视摄像头设置来监控商场和商业空间中的人流。

在这里插入图片描述

统计进出空间的人数不仅仅是一个有趣的计算机视觉项目——它对多个行业都具有实际影响。

在购物中心,了解高峰时段和客流量趋势有助于零售商优化店铺布局、规划促销活动和更有效地管理人力。办公楼和校园可以使用进出统计来确保占用合规性并减少能源浪费。在地铁站、机场和大型活动场所,实时人群监控对于运营效率和公共安全都至关重要。

传统上,这些系统需要昂贵的传感器或手动记录。但是借助强大的模型(例如 YOLOv12)和简单的摄像头设置,我们现在可以仅使用 Python、OpenCV 和深度学习来构建一个准确且可扩展的解决方案。

在我们深入实现之前,让我们简要了解一下系统的结构。

它们如何协同工作

图 3 提供了我们人员追踪监控系统中核心组件如何相互作用的高级概述。
在这里插入图片描述

YOLOv12 处理人员检测,质心追踪器管理跨帧的目标身份,而跨线逻辑则统计进出的人数。

在后面的章节中,我们将更详细地分解这个流程——包括质心匹配的工作原理、如何分配 ID,以及我们如何判断某人是“进入”还是“离开”。

YOLOv12 如何实现实时应用

YOLOv12 不仅仅是 YOLO 家族中的又一次迭代——它是第一个通过集成注意力机制而摆脱传统纯 CNN 设计的模型,同时仍保持了 YOLO 闻名的惊人速度。

早期的 YOLO 版本(例如 YOLOv11 和 YOLOv8)严重依赖卷积骨干网络。虽然速度快,但这些模型缺乏全局推理能力,这限制了它们在更复杂和杂乱场景中的性能。YOLOv12 通过引入以下创新改变了这一点:

这种组合赋予了 YOLOv12 两方面的优势——既有类似 Transformer 的上下文感知能力,又有 YOLO 级别的速度。

更重要的是,YOLOv12 保留了对现代 YOLO 变体中你所期望的所有主要计算机视觉任务的支持,包括:

这就是为什么它非常适合实时视频应用(例如,我们在本教程中构建的应用)。无论你是在校园大门统计人数,还是在零售店追踪客流量,YOLOv12 都能确保你快速获得准确的检测结果,即使在边缘设备或云 GPU 上也是如此。

配置你的开发环境

要开始使用我们的人员追踪监控系统,你需要安装一些必要的库并加载 YOLOv12 模型。我们将使用 Ultralytics 库 来运行推理。它支持 YOLOv12,并为模型加载和预测提供了简单的接口。

好消息是?在本教程中,你无需担心 FlashAttention 或从源代码构建。Ultralytics pip 包快速、简洁,即使在 Colab GPU 或你的本地机器上也能流畅运行,无需注意力加速。

运行以下单元格来安装我们将需要的一切:

$ pip install -q ultralytics opencv-python matplotlib

加载 YOLOv12 模型

安装完成后,你可以从 Ultralytics 包中加载 YOLOv12 模型。我们将使用 YOLOv12-Small 变体(yolo12s.pt),因为它在实时应用中提供了速度和准确性的良好平衡:

from ultralytics import YOLO
# Load the YOLOv12-small model
model = YOLO("yolo12s.pt")

确保 yolo12s.pt 文件存在于你的当前工作目录中。如果尚未提供,我们稍后会在 notebook 中下载它。

一旦你的环境设置完成,我们将获取输入视频并开始构建检测和追踪管道。

下载输入视频

为了演示人员追踪监控的实际应用,我们将使用一个预先录制的俯视监控式视频——非常适合追踪人员在固定场景中的移动。

这个输入视频将作为我们检测和追踪管道的基础。

安装 gdown

$ pip install gdown

下载视频

从 University 门户检索文件 ID 后,将其插入到下面的命令中:

# Replace FILE_ID with the actual file ID from the download link
!gdown --id YOUR_FILE_ID_HERE -O example_02.mp4

一旦视频准备就绪,我们将在深入代码之前,逐步讲解检测和追踪系统的工作原理。

可视化推理和追踪管道

在深入代码之前,了解我们系统的各个组件如何相互作用非常重要。

高级概述

我们的管道分为三个主要阶段,如图 4 所示:

在这里插入图片描述

  1. 检测(Detection): YOLOv12 在每一帧上运行,识别出帧中所有的人员。它返回一个边界框列表,每个边界框都包围着一个人。
  2. 追踪(Tracking): 质心追踪器接收这些边界框,并将它们与前一帧中已知的、已追踪的目标进行匹配。如果匹配成功,它会更新现有目标的质心位置。如果检测到的目标无法匹配,它会被注册为一个新的目标。
  3. 计数(Counting): 对于每个已追踪的目标,我们检查它的质心是否穿过我们预定义的虚拟线。如果穿过,我们根据其运动方向(“进入”或“离开”)更新相应的计数器。

详细追踪器分解

质心追踪器是一个简单但高效的算法,用于在视频帧之间保持目标身份。它通过计算每个检测到的边界框的中心点(即质心)来工作。

在这里插入图片描述

以下是质心追踪器在每一帧上执行的核心步骤:

  1. 计算质心: 对于 YOLOv12 在当前帧中检测到的每个人员,计算其边界框的中心点(x,y)坐标。
  2. 匹配质心: 将当前帧中的新质心与前一帧中已追踪目标(已分配 ID 的目标)的现有质心进行比较。
  3. 使用欧几里得距离: 匹配是基于欧几里得距离完成的。如果一个新质心与一个现有质心足够接近(低于某个预设距离阈值),我们假设它们是同一个目标。
  4. 更新目标: 如果找到匹配,我们更新现有目标的质心位置,并记录其运动历史。
  5. 注册新目标: 如果一个新质心无法与任何现有目标匹配,它被视为一个新的目标,并分配一个新的唯一 ID。
  6. 注销旧目标: 如果一个已追踪的目标在连续几帧中没有被检测到(即没有新的质心与之匹配),我们假设它已经离开了视野或被遮挡,并将其从追踪器中注销。

这个简单的方法在我们的场景中效果非常好,因为它快速且对遮挡具有一定的鲁棒性。

实现质心追踪器

现在我们已经理解了理论,让我们开始编写 CentroidTracker 类。

我们将使用一个 Python 字典来存储我们正在追踪的目标。字典的键是唯一的对象 ID,值是包含目标质心坐标的列表。

from collections import OrderedDict
import numpy as np
from scipy.spatial import distance as dist
class CentroidTracker:
def __init__(self, maxDisappeared=50, maxDistance=50):
# 初始化下一个可用的对象 ID
self.nextObjectID = 0
# 存储已追踪目标的字典:键是对象 ID,值是质心坐标
self.objects = OrderedDict()
# 存储目标“消失”帧数的字典
self.disappeared = OrderedDict()
# 目标在被注销前可以“消失”的最大连续帧数
self.maxDisappeared = maxDisappeared
# 用于将新质心与现有质心匹配的最大距离
self.maxDistance = maxDistance

类初始化

__init__ 方法中,我们初始化:

  • self.nextObjectID: 下一个可用的唯一 ID,从 0 开始。
  • self.objects: 一个有序字典,用于存储我们正在追踪的目标。
  • self.disappeared: 一个有序字典,用于存储每个目标在被注销前已经“消失”的连续帧数。
  • self.maxDisappeared: 一个超参数,用于控制一个目标在被注销前可以“消失”的最大帧数。
  • self.maxDistance: 一个超参数,用于控制将新检测与现有目标匹配的最大欧几里得距离。

注册和注销

registerderegister 方法是管理 self.objectsself.disappeared 字典的核心。

def register(self, centroid):
# 注册一个新目标,为其分配下一个可用的 ID
# 并初始化其消失计数为 0
self.objects[self.nextObjectID] = centroid
self.disappeared[self.nextObjectID] = 0
self.nextObjectID += 1
def deregister(self, objectID):
# 注销一个目标:从两个字典中移除它
del self.objects[objectID]
del self.disappeared[objectID]

更新逻辑(匹配、注册、注销)

update 方法是追踪器的核心。它接收当前帧中的新边界框列表,并执行匹配、注册和注销逻辑。

def update(self, rects):
# 检查当前帧中是否没有检测到边界框
if len(rects) == 0:
# 增加所有现有目标的消失计数
for objectID in list(self.disappeared.keys()):
self.disappeared[objectID] += 1
# 如果目标的消失计数超过最大限制,则注销它
if self.disappeared[objectID] > self.maxDisappeared:
self.deregister(objectID)
# 返回已追踪目标的列表
return self.objects
# 初始化一个数组来存储当前帧中输入边界框的质心
inputCentroids = np.zeros((len(rects), 2), dtype="int")
# 遍历边界框并计算质心
for (i, (startX, startY, endX, endY)) in enumerate(rects):
cX = int((startX + endX) / 2.0)
cY = int((startY + endY) / 2.0)
inputCentroids[i] = (cX, cY)
# 如果我们当前没有追踪任何目标,则注册所有新检测
if len(self.objects) == 0:
for i in range(0, len(inputCentroids)):
self.register(inputCentroids[i])
# 否则,我们尝试匹配现有目标和新检测
else:
# 获取现有目标 ID 和质心
objectIDs = list(self.objects.keys())
objectCentroids = list(self.objects.values())
# 计算现有质心和输入质心之间的距离
D = dist.cdist(np.array(objectCentroids), inputCentroids)
# 执行匹配
rows = D.min(axis=1).argsort()
cols = D.argmin(axis=1)[rows]
usedRows = set()
usedCols = set()
# 遍历匹配
for (row, col) in zip(rows, cols):
# 如果我们已经使用了行或列索引,则跳过
if row in usedRows or col in usedCols:
continue
# 如果距离超过了最大距离,则跳过
if D[row, col] > self.maxDistance:
continue
# 匹配成功,更新目标
objectID = objectIDs[row]
self.objects[objectID] = inputCentroids[col]
self.disappeared[objectID] = 0
usedRows.add(row)
usedCols.add(col)
# 处理未匹配的现有目标(可能消失了)
unusedRows = set(range(0, D.shape[0])).difference(usedRows)
for row in unusedRows:
objectID = objectIDs[row]
self.disappeared[objectID] += 1
# 检查是否应该注销目标
if self.disappeared[objectID] > self.maxDisappeared:
self.deregister(objectID)
# 处理未匹配的新检测(注册为新目标)
unusedCols = set(range(0, D.shape[1])).difference(usedCols)
for col in unusedCols:
self.register(inputCentroids[col])
# 返回已追踪目标的列表
return self.objects

质心追踪器:常见问题解答

问:为什么使用欧几里得距离而不是 IoU(交并比)?

答: IoU 是目标检测中常用的指标,用于衡量两个边界框的重叠程度。然而,对于追踪而言,质心追踪器 依赖于目标的中心点,而不是整个边界框的重叠。

  • 速度: 计算质心之间的欧几里得距离比计算 IoU 快得多。在实时应用中,速度至关重要。
  • 简单性: 质心追踪器是一种非常轻量级的方法,易于实现和调试。
  • 鲁棒性: 对于人员追踪,即使边界框由于姿态变化而略有波动,质心也往往保持稳定。

问:maxDisappearedmaxDistance 是如何工作的?

答:

  • maxDisappeared 决定了一个目标在被系统遗忘之前可以“消失”(即没有被检测到)多少帧。这有助于处理短暂的遮挡。
  • maxDistance 是一个阈值。如果一个新检测到的质心与任何现有目标的质心之间的距离超过这个值,它将被视为一个全新的目标,而不是现有目标的延续。这有助于防止目标 ID 在拥挤场景中发生错误切换。

在视频帧上运行 YOLOv12

现在我们已经有了 CentroidTracker 类,我们可以将其与 YOLOv12 的检测结果结合起来。

加载模型和 OpenCV 视频对象

我们首先加载 YOLOv12 模型,并设置视频输入和输出对象。

# 导入必要的包
import cv2
from ultralytics import YOLO
# 加载 YOLOv12 模型
model = YOLO("yolo12s.pt")
# 初始化视频流和输出写入器
cap = cv2.VideoCapture("example_02.mp4")
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 设置视频输出
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('people_counter.mp4', fourcc, fps, (width, height))

设置追踪和计数

接下来,我们初始化 CentroidTracker 实例和用于计数的变量。我们还定义了我们的虚拟线,用于判断人员是“进入”还是“离开”。

# 初始化质心追踪器
ct = CentroidTracker(maxDisappeared=40, maxDistance=50)
# 初始化计数器
people_in = 0
people_out = 0
# 定义虚拟线(例如,在视频高度的 50% 处)
line_y = height // 2
cv2.line(frame, (0, line_y), (width, line_y), (0, 255, 255), 2)
# 存储每个目标的运动历史(用于判断方向)
object_history = {}

逐帧推理和追踪

我们进入主循环,逐帧读取视频,执行 YOLOv12 推理,并更新追踪器。

# 循环处理视频帧
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 1. YOLOv12 推理
results = model(frame, verbose=False)
# 提取人员边界框
rects = []
for r in results:
boxes = r.boxes
for box in boxes:
# 确保我们只处理“人员”类别(COCO 数据集中通常是 0)
if int(box.cls[0]) == 0:
# 获取边界框坐标
x1, y1, x2, y2 = box.xyxy[0].int().tolist()
rects.append((x1, y1, x2, y2))
# 2. 更新质心追踪器
objects = ct.update(rects)

更新追踪器和统计运动

objects 字典更新后,我们遍历每个已追踪的目标,记录其运动历史,并检查是否穿过了虚拟线。

# 3. 统计运动
for (objectID, centroid) in objects.items():
# 存储或更新目标的质心历史
if objectID not in object_history:
object_history[objectID] = []
object_history[objectID].append(centroid)
# 保持历史记录为最近的几帧
if len(object_history[objectID]) > 10:
object_history[objectID].pop(0)
# 检查是否穿过线
if len(object_history[objectID]) >= 2:
# 获取最近的两个质心
prev_centroid = object_history[objectID][-2]
curr_centroid = object_history[objectID][-1]
# 检查是否穿过线
if prev_centroid[1] < line_y and curr_centroid[1] >= line_y:# 从上到下:进入people_in += 1elif prev_centroid[1] > line_y and curr_centroid[1] <= line_y:# 从下到上:离开people_out += 1

绘制输出并保存帧

最后,我们绘制追踪结果和计数器。

# 4. 绘制输出并保存帧
for (objectID, centroid) in objects.items():
# 绘制质心和 ID
cv2.circle(frame, tuple(centroid), 4, (0, 255, 0), -1)
cv2.putText(frame, f"ID {objectID}", (centroid[0] - 10, centroid[1] - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)
# 显示计数器
cv2.putText(frame, f"In: {people_in}", (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 255, 0), 2)
cv2.putText(frame, f"Out: {people_out}", (10, 70),
cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2)
# 绘制虚拟线(再次绘制以确保它在所有内容之上)
cv2.line(frame, (0, line_y), (width, line_y), (0, 255, 255), 2)
# 写入输出视频
out.write(frame)

在这个最终的可视化步骤中,我们用实时追踪信息注释帧。对于每个被检测到的人员,我们在其质心处绘制一个小的绿色圆圈,并使用 cv2.putText 用唯一的 ID 标记他们。我们还叠加了穿过参考线“进入”和“离开”的人数总计。

这些统计数据显示在帧的左上角。添加所有注释后,该帧将使用 out.write(frame) 写入输出视频,从而在最终保存的视频中保留可视化和计数逻辑。

清理

cap.release()
out.release()
cv2.destroyAllWindows()
print(f"Done! Saved as people_counter.mp4")

这个最后一步释放了视频对象并完成了处理。

使用 YOLOv12 和质心追踪器可视化人员追踪监控

图 6 中,你可以看到我们的实时人员计数系统正在运行,它结合了 YOLOv12 进行检测和质心追踪器进行身份管理和运动分析。

在这里插入图片描述

在这个演示中:

一个有趣的观察:紧挨着 ID 6 旁边行走的人尚未被分配 ID。发生这种情况是因为 YOLOv12 在该特定帧中没有以足够高的置信度检测到他们,这可能是由于遮挡或仅部分可见。同时,ID 7 离得更远但完全可见,被更早地检测和注册。

这种行为在 图 7 中也可见。紧挨着 ID 6 的个体还没有 ID,表明尚未对其进行检测。

在这里插入图片描述

这种情况突显了实时检测系统的动态性质,其中 ID 是根据何时发生完整、高置信度的检测来分配的,而不是简单地根据接近度。这种能力确保了即使在真实世界条件下(例如,遮挡和交错可见性),也能进行稳健的追踪和准确的人员计数。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/972513.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实用指南:【记录】MAC本地微调大模型(MLX + Qwen2.5)并利用Ollama接入项目实战

实用指南:【记录】MAC本地微调大模型(MLX + Qwen2.5)并利用Ollama接入项目实战2025-11-21 19:51 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overf…

搜维尔科技:利用MANUS数据手套实现灵巧远程操作:对20自由度灵巧手进行控制

实现人类级别的灵巧性需要精准、低延迟的人机控制。ByteDexter系统集成了MANUS Quantum Metagloves和Meta Quest 3,能够实时远程操控20自由度连杆驱动的拟人化机械手。该系统可实现精准的捏握、稳定的强力抓取和高级的…

CTF reverse入门记录

好吧,今天正式入坑CTF的reverse和pwn了,当然先从reverse开始入手。 先是写一下buuctf的writeup和一些ida的技巧 一个是显示二进制编码 显示中文 导出数据 显示动态字符串 处理反编译失败黄粱一梦,终是一空本文来自博…

开发智联笔记项目时的js问题

问题分析 应用需要以下JS文件:jsmind.js - 核心脑图库 jsmind.draggable.js - 拖拽功能 jsmind.undo.js - 撤销重做功能解决方案 1. 获取缺失的JS文件 需要下载这些JS文件并放在 static 目录下: jsmind.js - 核心文件…

nju实验一选择器

本次实验将介绍几种常用的多路选择器的设计方法;Verilog语言中的always语句块、if-else语句和case语句的使用等。最后请读者自行设计一个多路选择器,熟悉电路设计的基本流程和Quartus的使用。实验一选择器 2选1多路选…

上海金蝶代理商推荐——上海宝蝶信息技术有限公司

一、企业概况 上海宝蝶信息技术有限公司成立于2016年,总部位于上海市松江区,是金蝶集团在上海地区的铂金合作伙伴,专注服务于国内ERP应用市场。 公司深耕中小制造企业全栈数字化服务,以金蝶云PLM+ERP、灵当CRM、致…

11.21模拟赛

T1 分层图板子,代码在 luogu。 T2 给定长度为 \(n\) 的数列 \(a\),维护 \(m\) 次操作,每次操作包括以下两种:1 x:要求输出包含 \(a_x\) 的最大子段和,即求 \(\max_{1 \leq l \leq x \leq r \leq n} \left\{ \sum…

HTML---------------图片转换(草稿)

<!DOCTYPE html> <html><head><meta charset="utf-8"><title>童心少年</title></head><body> <h1 onclick = "updateimage()">点击一下…

爱与时间反应鲜红色慢慢退却 一次次重复直到忘记了誓言

test45 今天怎么第一版 t1/t2 都是假的(构造字符串 数据范围不是特别大直接改条件 \(a_i=a_j/a_i\neq a_j\),你并查集前一种之后看一下符不符合第二种,如果符合的话肯定有解,比方说你考虑每个连通块给不同颜色。 注…

Mac 安装 JDK 8u281(JDK-8u281-1.dmg)详细步骤(附安装包)

Mac 安装 JDK 8u281(JDK-8u281-1.dmg)详细步骤(附安装包)​一、准备工作下载文件 安装包下载:https://pan.quark.cn/s/24c8755b74f0 ,下载了 JDK-8u281-1.dmg文件,它一般是个安装包。找到文件 打开你的 “下载”…

chrome: 允许远程调试

一,默认不能从远程访问chrome的调试端口: 例子: $ google-chrome --remote-debugging-port=9222 --user-data-dir=/data/python/xianyu/userdata 通过局域网ip访问:本地可以访问:二,通过端口转发供远程访问 $ soca…

Agent skills 实战

背景: 通过编码方式编写符合规范的ofd文件。 过程:通过调研,锁定使用 ofdrw和easyofd两种 java ofd生成工具上,最终选择easyofd组件(大模型不认识该组件)。那接下来遇到的问题是,大模型不知道怎样使用这两种组件。…

Vue 路由的学习

Vue 路由完全指南 Vue路由完全指南:从基础到实战,轻松掌握页面跳转核心 在Vue开发中,路由是实现单页面应用(SPA)页面切换的核心技术。无论是Vue2还是Vue3,路由都扮演着"导航指挥官"的角色,负责管理不…

P8809 [蓝桥杯 2022 国 C] 近似 GCD 题解

考虑到非常困难。再简单的计数题也要认真看一眼。 P8809 [蓝桥杯 2022 国 C] 近似 GCD 思路 考虑刻画充要条件去计数。发现一个子区间合法的充要条件是至多一个数不是 \(g\) 的倍数。 将不是 \(g\) 倍数的东西看作 1,…

推荐一款超级好用的命令行工具 http-server

推荐一款超级好用的命令行工具 http-server前言很多时候前端开发的项目需要放到线上才能出现一些问题,本地环境看不出来,此时很多小伙伴可能会喜欢用Live Serve来启动本地项目,但是部分框架打包的dist包无法通过Liv…

J 组要考,S 组也要考

在 CSP 竞赛中,J 组与 S 组是两项并行的赛事。在竞赛生涯中,许多人可能会认为只需专注其中一组即可,认为另一组无关紧要。然而,实际上,这两者都至关重要:J 组要考,S 组同样也要考。 正如鲁迅先生所言:“紫题是…

估值 7 亿美元,Wispr 要做语音操作系统,还要自研 ASR;马斯克:实时视频理解和生成是未来丨日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的技术」、「有亮点的产品」、「有思考的文章」、「有态…

AI浪潮下的新动向:协作、法律与未来工作

最近刷新闻,发现AI领域又炸开锅了。从OpenAI的群聊功能到商标纠纷,再到马斯克对未来的大胆预测,这些事件不仅让我这个学软件工程的看得津津有味,还引发了不少关于技术发展和就业的思考。先说说OpenAI的新功能“群聊…

day11-Dify智能体-发布-工作流

今日内容 1 对接大模型 # 0 Coze 是一个成熟的商业软件-咱们用户只需要访问地址--》直接使用 --》本身集成了大模型-豆包、deepseek大模型,插件:图像生成---》使用扣token-更适合小白-Coze 用gpt模型?用不了,没有提…