OpenCV HighGUI 模块使用指南(Python 版)
用户让我编写一个 HighGUI 模块的使用指南,包括函数的使用和应用场景的实现。首先,我需要回顾 HighGUI 模块的主要功能:图像显示、视频捕获、鼠标和键盘事件。然后,按照用户提供的结构,整理每个部分的函数详解、代码示例和应用场景。
首先,图像显示部分,需要介绍 imshow、waitKey、destroyAllWindows。要给出基本用法,比如显示图像,处理按键事件。然后是视频捕获,VideoCapture 和 VideoWriter 的使用,包括打开摄像头、读取帧、保存视频。接下来是鼠标和键盘事件,setMouseCallback 的用法,处理点击、拖拽等事件。
应用场景方面,需要具体的例子,比如图像标注工具、实时视频处理、交互式绘图。每个场景要有完整的代码示例,注释清晰。还要考虑最佳实践,比如资源释放、异常处理、性能优化。
需要检查每个函数的参数说明,确保准确。比如 VideoCapture 的参数可以是设备索引或文件路径,VideoWriter 的编码格式。鼠标事件的回调函数参数解释。
还要考虑用户可能的问题,比如中文显示乱码,这时候需要提到使用 Matplotlib 或其他方法。另外,视频播放的流畅性,如何处理帧率。
最后,整理结构,确保指南逻辑清晰,从基础到高级,每个部分有代码示例和应用场景。检查代码的正确性,比如文件读取、窗口销毁、资源释放等。
以下是 OpenCV HighGUI 模块的详细使用指南,涵盖核心功能、函数详解、代码示例及典型应用场景,结构清晰,实战性强:
OpenCV HighGUI 模块权威指南(Python 版)
一、模块概述
highgui 模块是 OpenCV 的图形用户界面与媒体 I/O 核心,提供以下核心功能:
- 图像显示:窗口管理、键盘交互
- 视频处理:摄像头捕获、视频文件读写
- 用户交互:鼠标事件、实时标注
- 媒体 I/O:图像 / 视频的读取与保存
二、核心功能详解与实战
1. 图像显示与窗口管理
1.1 核心函数
| 函数名称 | 功能描述 | 核心参数说明 | 示例代码 |
|---|---|---|---|
cv2.imshow() | 显示图像 | winname(窗口名), mat(图像数据) | cv2.imshow("Image", img) |
cv2.waitKey() | 等待按键事件 | delay(毫秒,0 表示无限等待) | key = cv2.waitKey(0) |
cv2.destroyAllWindows() | 关闭所有窗口 | 无 | cv2.destroyAllWindows() |
cv2.namedWindow() | 创建可调整大小的窗口 | winname, flags=cv2.WINDOW_NORMAL | cv2.namedWindow("Resizeable", cv2.WINDOW_NORMAL) |
1.2 实战:图像查看器(支持按键保存)
python
import cv2# 读取图像
img = cv2.imread("example.jpg")
if img is None:raise FileNotFoundError("图像文件不存在")# 显示图像
cv2.imshow("Image Viewer", img)# 按键处理(ESC 退出,S 保存)
while True:key = cv2.waitKey(0)if key == 27: # ESCbreakelif key == ord('s'): # S 保存cv2.imwrite("saved_image.jpg", img)print("图像已保存")cv2.destroyAllWindows()
应用场景
- 图像标注:显示图像并通过按键标记类别(如
1标记汽车,2标记行人)。 - 医学影像查看:支持窗口缩放(
WINDOW_NORMAL)和对比度调整。
2. 视频捕获与处理
2.1 核心函数
| 函数名称 | 功能描述 | 核心参数说明 | 示例代码 |
|---|---|---|---|
cv2.VideoCapture() | 打开摄像头或视频文件 | index(设备索引,0 为内置摄像头)或文件路径 | cap = cv2.VideoCapture(0) |
cap.read() | 读取视频帧 | 无,返回 (ret, frame) | ret, frame = cap.read() |
cv2.VideoWriter() | 保存视频 | filename, fourcc, fps, frameSize | fourcc = cv2.VideoWriter_fourcc(*'mp4v')out = cv2.VideoWriter("output.mp4", fourcc, 20.0, (640, 480)) |
2.2 实战:实时视频滤波(摄像头捕获)
python
import cv2
import numpy as np# 初始化摄像头
cap = cv2.VideoCapture(0)
if not cap.isOpened():raise IOError("无法打开摄像头")# 初始化视频写入(可选)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter("filtered_video.mp4", fourcc, 20.0, (640, 480))while True:ret, frame = cap.read()if not ret:break# 实时滤波(高斯模糊)frame = cv2.GaussianBlur(frame, (5, 5), 0)# 显示与保存cv2.imshow("Live Filter", frame)out.write(frame) # 保存视频if cv2.waitKey(1) & 0xFF == 27: # ESC 退出break# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()
应用场景
- 安防监控:实时捕获摄像头画面并保存(
VideoWriter)。 - 手势识别:结合
VideoCapture与imgproc模块实现实时跟踪。
3. 用户交互(鼠标与键盘事件)
3.1 核心函数
| 函数名称 | 功能描述 | 核心参数说明 | 示例代码 |
|---|---|---|---|
cv2.setMouseCallback() | 设置鼠标事件回调 | winname, on_mouse(回调函数) | cv2.setMouseCallback("Image", mouse_callback) |
cv2.getTrackbarPos() | 获取滑动条位置 | trackbarname, winname | threshold = cv2.getTrackbarPos("Thresh", "Control") |
3.2 实战:交互式图像标注(鼠标绘制矩形)
python
import cv2
import numpy as npdrawing = False
start_point = (-1, -1)def mouse_callback(event, x, y, flags, param):global drawing, start_pointif event == cv2.EVENT_LBUTTONDOWN:drawing = Truestart_point = (x, y)elif event == cv2.EVENT_MOUSEMOVE and drawing:# 实时绘制预览img_copy = param.copy()cv2.rectangle(img_copy, start_point, (x, y), (0, 255, 0), 2)cv2.imshow("Annotator", img_copy)elif event == cv2.EVENT_LBUTTONUP:drawing = Falsex1, y1 = start_pointx2, y2 = x, y# 保存 ROIroi = param[min(y1, y2):max(y1, y2), min(x1, x2):max(x1, x2)]cv2.imwrite("roi.jpg", roi)print(f"ROI 已保存:{(min(x1,x2), min(y1,y2), abs(x2-x1), abs(y2-y1))}")# 初始化
img = cv2.imread("scene.jpg")
cv2.namedWindow("Annotator")
cv2.setMouseCallback("Annotator", mouse_callback, img)while True:cv2.imshow("Annotator", img)if cv2.waitKey(1) & 0xFF == 27: # ESC 退出breakcv2.destroyAllWindows()
应用场景
- 数据集标注:鼠标绘制边界框并保存 ROI(如 COCO 格式)。
- 交互式调试:通过滑动条实时调整算法参数(如阈值、滤波核大小)。
三、完整应用场景实现
场景 1:实时视频目标跟踪(摄像头 + 鼠标交互)
流程
- 捕获视频帧 → 2. 鼠标选择跟踪区域 → 3. 实时跟踪 → 4. 显示结果。
完整代码
python
import cv2
import numpy as np# 初始化摄像头
cap = cv2.VideoCapture(0)
if not cap.isOpened():raise IOError("摄像头打开失败")# 鼠标选择 ROI
roi_selected = False
roi = Nonedef select_roi(event, x, y, flags, param):global roi_selected, roiif event == cv2.EVENT_LBUTTONDOWN:roi = (x, y)elif event == cv2.EVENT_LBUTTONUP:x1, y1 = roix2, y2 = x, yroi = (min(x1, x2), min(y1, y2), abs(x2-x1), abs(y2-y1))roi_selected = True# 创建窗口并设置回调
cv2.namedWindow("Tracking")
cv2.setMouseCallback("Tracking", select_roi)while True:ret, frame = cap.read()if not ret:breakif roi_selected:# 简单跟踪(ROI 位置固定,实际项目需使用跟踪算法)x, y, w, h = roicv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)cv2.imshow("Tracking", frame)if cv2.waitKey(1) & 0xFF == 27: # ESC 退出breakcap.release()
cv2.destroyAllWindows()
场景 2:图像标注工具(支持键盘分类)
流程
- 显示图像 → 2. 鼠标绘制 ROI → 3. 键盘选择类别(1-5)→ 4. 保存标注。
完整代码
python
import cv2
import json# 配置
IMAGE_PATH = "dataset_image.jpg"
CLASSES = ["car", "person", "bike", "tree", "sky"]# 初始化
img = cv2.imread(IMAGE_PATH)
annotations = []
current_class = 0# 鼠标回调(绘制矩形)
drawing = False
start = (-1, -1)def mouse_callback(event, x, y, flags, param):global drawing, startif event == cv2.EVENT_LBUTTONDOWN:drawing = Truestart = (x, y)elif event == cv2.EVENT_LBUTTONUP:drawing = Falsex1, y1 = startx2, y2 = x, ybbox = [min(x1, x2), min(y1, y2), abs(x2-x1), abs(y2-y1)]annotations.append({"class": CLASSES[current_class],"bbox": bbox})print(f"标注保存:{CLASSES[current_class]} {bbox}")# 创建窗口
cv2.namedWindow("Annotator")
cv2.setMouseCallback("Annotator", mouse_callback)while True:# 绘制界面img_copy = img.copy()cv2.putText(img_copy, f"Class: {CLASSES[current_class]} (1-5)", (10, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)# 显示cv2.imshow("Annotator", img_copy)key = cv2.waitKey(1) & 0xFF# 键盘处理if key == 27: # ESC 退出breakelif 48 <= key <= 52: # 1-5 选择类别current_class = key - 48elif key == ord('s'): # S 保存with open("annotations.json", "w") as f:json.dump(annotations, f)print(f"保存 {len(annotations)} 个标注")cv2.destroyAllWindows()
四、最佳实践与注意事项
1. 资源管理
- 及时释放:视频捕获后务必调用
cap.release()和out.release()。 - 窗口清理:使用
destroyAllWindows()避免内存泄漏。
2. 性能优化
- 降低分辨率:实时视频处理时缩小尺寸(
cv2.resize(frame, (640, 480)))。 - 减少延迟:
waitKey(1)替代waitKey(0)提升帧率。
3. 中文显示
- HighGUI 不直接支持中文窗口标题,解决方案:
python
# 使用 Matplotlib 显示(支持中文) import matplotlib.pyplot as plt plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.title("中文标题") plt.show()
4. 视频编码
- 常见编码:
- MP4:
fourcc = cv2.VideoWriter_fourcc(*'mp4v') - AVI:
fourcc = cv2.VideoWriter_fourcc(*'XVID')
- MP4:
- 兼容性:使用
fourcc = -1打开编码选择对话框(Windows 仅支持部分编码)。
五、函数速查表
| 功能分类 | 函数名称 | 核心参数示例 | 输出 / 用途 |
|---|---|---|---|
| 图像显示 | cv2.imshow() | winname="Image", mat=img | 显示图像 |
| 视频捕获 | cv2.VideoCapture(0) | 设备索引(0 为摄像头) | 视频捕获对象 |
| 鼠标事件 | cv2.setMouseCallback() | winname, on_mouse | 注册鼠标回调函数 |
| 视频写入 | cv2.VideoWriter() | filename, fourcc, fps, size | 视频写入对象 |
| 按键处理 | cv2.waitKey(1) | 延迟(ms) | 等待按键(返回 ASCII 码) |
六、扩展学习建议
1. 滑动条交互(实时参数调整)
python
def on_trackbar(val):global thresholdthreshold = valcv2.namedWindow("Control")
cv2.createTrackbar("Threshold", "Control", 127, 255, on_trackbar)while True:threshold = cv2.getTrackbarPos("Threshold", "Control")# 使用 threshold 处理图像...
2. 多窗口管理
python
cv2.namedWindow("Original", cv2.WINDOW_AUTOSIZE)
cv2.namedWindow("Processed", cv2.WINDOW_NORMAL) # 可调整大小cv2.imshow("Original", img)
cv2.imshow("Processed", processed_img)
3. 视频编解码调试
python
# 打印支持的编解码器
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
if fourcc == -1:print("不支持 MP4 编码,尝试其他格式(如 XVID)")
七、总结与学习路径
plaintext
HighGUI 学习路径:
基础 → 图像显示 → 视频捕获 → 鼠标交互 → 高级应用(标注工具、实时跟踪)推荐项目:
1. 交互式图像标注工具(鼠标 + 键盘)
2. 实时视频滤镜(摄像头 + 滑动条参数调整)
3. 视频稳定器(捕获 + 几何变换)性能优化:
- 视频流:使用 `CAP_FFMPEG` 后端加速(`cv2.VideoCapture("file.mp4", cv2.CAP_FFMPEG)`)
- 多线程:分离视频捕获与处理线程(`threading.Thread`)
八、完整代码仓库(示例)
python
# HighGUI 模块综合应用示例
import cv2# 1. 图像显示(支持按键保存)
img = cv2.imread("lena.jpg")
cv2.imshow("Image", img)
if cv2.waitKey(0) == ord('s'):cv2.imwrite("saved_lena.jpg", img)# 2. 视频捕获(摄像头 + 灰度转换)
cap = cv2.VideoCapture(0)
while cap.isOpened():ret, frame = cap.read()if not ret: breakgray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)cv2.imshow("Gray Video", gray)if cv2.waitKey(1) & 0xFF == 27:break
cap.release()# 3. 鼠标交互(绘制圆形)
def draw_circle(event, x, y, flags, param):if event == cv2.EVENT_LBUTTONDBLCLK:cv2.circle(param, (x, y), 50, (0, 255, 0), -1)img = np.zeros((500, 500, 3), np.uint8)
cv2.namedWindow("Draw")
cv2.setMouseCallback("Draw", draw_circle, img)
while True:cv2.imshow("Draw", img)if cv2.waitKey(1) & 0xFF == 27:break
cv2.destroyAllWindows()
九、环境配置与依赖
bash
# 安装 OpenCV
pip install opencv-python# 验证安装
python -c "import cv2; print(cv2.__version__)" # 需 4.5+
通过此指南,开发者可全面掌握 HighGUI 模块的核心功能,从基础图像显示到复杂交互应用,结合标注工具、实时视频处理等实战项目,快速构建图形用户界面与媒体处理解决方案。每个代码示例均可独立运行,方便在实际开发中复用和扩展。建议结合官方文档(HighGUI 模块)进行深入学习。
相关文章:
OpenCV HighGUI 模块使用指南(Python 版)
用户让我编写一个 HighGUI 模块的使用指南,包括函数的使用和应用场景的实现。首先,我需要回顾 HighGUI 模块的主要功能:图像显示、视频捕获、鼠标和键盘事件。然后,按照用户提供的结构,整理每个部分的函数详解、代码示…...
PyTorch 面试题及参考答案(精选100道)
PyTorch 的动态计算图与 TensorFlow 的静态计算图有何区别?动态图的优势是什么? PyTorch 的动态计算图和 TensorFlow 的静态计算图在构建方式、灵活性和调试难度等方面存在显著区别。 在构建方式上,TensorFlow 的静态计算图需要先定义好整个…...
android......
事件源,就是视图对象,先注册一个监听器,等待用户触发了屏幕,一旦触发会立即产生一个事件源,事件源会生成一个用户点击的触发事件,此刻监听器会立马监听到 ,然后监听器调用回调方法 UI理解 全称用…...
常见中间件漏洞(tomcat)
CVE-2017-12615 当在Tomcat的conf(配置目录下)/web.xml配置文件中添加readonly设置为false时,将导致该漏洞产生,(需要允许put请求) , 攻击者可以利用PUT方法通过精心构造的数据包向存在漏洞的服务器里面上传…...
计算机网络高频(二)TCP/IP基础
计算机网络高频(二)TCP/IP基础 1.什么是TCP/IP⭐⭐ TCP/IP是一种网络通信协议,它是互联网中最常用的协议之一。TCP/IP有两个基本的协议:TCP(传输控制协议)和IP(互联网协议)。 TCP(Transmission Control Protocol,传输控制协议)是一种可靠的、面向连接的协议。它负…...
国际护士节知识竞赛主持稿串词
在这充满火热激情的季节,我们又迎来了5.12国际护士节。让我们首先向辛勤奋战在护理工作一线的全县广大护士姐妹们道一声: (男)让我们再一次以热烈的掌声欢迎他们:预祝各参赛代表队在护理知识竞赛中赛出风格,赛出水平,取得满意的成绩。 (女)…...
Elasticsearch:可配置的推理 API 端点分块设置
作者:来自 Elastic Daniel Rubinstein Elasticsearch 开放推理 API 现已支持可配置的分块,以便在文档摄取时处理语义文本字段。 Elasticsearch 推理 API 允许用户利用各种提供商的机器学习模型执行推理操作。其中一个常见用例是在索引中支持用于语义搜索…...
数据结构之链表(双链表)
目录 一、双向带头循环链表 概念 二、哨兵位的头节点 优点: 头节点的初始化 三、带头双向链表的实现 1.双链表的销毁 2.双链表的打印 3.双链表的尾插和头插 尾插: 头插: 4.双链表的尾删和头删 尾删: 头删: …...
uniapp从 vue2 项目迁移到 vue3流程
以下是必须为迁移到 vue3 进行调整的要点,以便 vue2 项目可以在 vue3 上正常运行。 1. 在index.js中创建应用程序实例 // Before - Vue 2 import Vue from vue import App from ./App // with no need for vue3 Vue.config.productionTip false // vue3 is no lon…...
案例:网络命名空间模拟隔离主机场景
场景描述 假设我们需要在同一台物理机上模拟两台独立的主机(Host A 和 Host B),它们分别位于不同的网络命名空间中,并通过虚拟以太网对(veth pair)进行通信。目标是展示网络命名空间的隔离性和跨命名空间的…...
23种设计模式-生成器(Builder)设计模式
工厂方法设计模式 🚩什么是生成器设计模式?🚩生成器设计模式的特点🚩生成器设计模式的结构🚩生成器设计模式的优缺点🚩生成器设计模式的Java实现🚩代码总结🚩总结 🚩什么…...
算法训练营第二十二天 | 回溯算法(四)
文章目录 前言一、Leetcode 491.递增子序列二、Leetcode 46.全排列三、Leetcode 47.全排列Ⅱ 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启…...
NLP高频面试题(十一)——RLHF的流程有哪些
随着大语言模型(如GPT系列)的快速发展,RLHF(Reinforcement Learning from Human Feedback,即基于人类反馈的强化学习)逐渐成为训练高质量模型的重要方法。本文将简单清晰地介绍RLHF的整体流程。 一、RLHF …...
测试用例设计方法与Prompt转化:一键生成高效提示词的实用指南
在测试工程师的日常工作中,设计测试用例是确保软件质量的关键环节。然而,如何快速、高效地设计出覆盖率高、逻辑严密的测试用例却是一个常见的挑战。本文将结合常用的测试用例设计方法,探索如何通过Prompt(提示词)转化…...
蓝桥杯备考:BFS最短路径之Meteor Shower S流星雨
本题是一个BFS最短路问题,我们可以先把时刻的矩阵搞出来,哪些时刻哪些方块儿不能走用来剪枝 如果第一次走到永远不会被扎到的区域,那时候就是我们的最短距离 定义方向向量 #include <iostream> #include <queue> #include <c…...
【 <二> 丹方改良:Spring 时代的 JavaWeb】之 Spring Boot 中的 RESTful API 设计:从上手到骨折
<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、开篇整活…...
【深度学习与大模型基础】第8章-概率分布
一、概率质量函数 什么是概率质量函数? 概率质量函数是用来描述离散随机变量的概率分布的工具。它告诉我们,某个离散随机变量取某一个特定值的概率是多少。 举个例子:抛硬币 假设你有一个程序,模拟抛硬币的结果。硬币有两个可能…...
数据结构5(初):排序
目录 1、排序的概念以及常见的排序算法 1.1、排序的概念 1.2、常见的排序算法 2、常见排序算法的实现 2.1、插入排序 2.1.1、直接插入排序 2.1.2、希尔排序 2.2、选择排序 2.2.1、直接选择排序 2.2.2、堆排序 2.3、交换排序 2.3.1、冒泡排序 2.3.2、快速排序 2.3.…...
表达式括号匹配(stack)(信息学奥赛一本通-1353)
【题目描述】 假设一个表达式有英文字母(小写)、运算符(,—,∗,/)和左右小(圆)括号构成,以“ ”作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号…...
RabbitMQ 详细原理解析
RabbitMQ 是一个基于 AMQP(Advanced Message Queuing Protocol) 协议的开源消息代理中间件,广泛用于分布式系统中的异步通信、服务解耦、流量削峰等场景。其核心设计围绕生产者、消费者、队列、交换机和虚拟主机等组件,结合 AMQP …...
2025-03-23 学习记录--C/C++-C语言 sprintf()实现将多个值按指定格式拼接成字符串
C语言 sprintf()实现将多个值按指定格式拼接成字符串 举个例子 🌰:将字符串 “m” 与数字 0、1、2 动态拼接成 “m0”、“m1”、“m2”:👇🏻 #include <stdio.h> // 包含标准输入输出库,用于使用输入…...
【小程序开发】完整项目结构长啥样?
Hello,欢迎来到AI技术库。AI写代码的时代,人人都可以成为程序员。欢迎继续【小程序开发】系列课。上节课中,我们学习了【手把手教你小程序开发】什么是大前端?,本节课,我们学习第二篇 小程序的完整项目结构。 本文适合阅读对象: 1. 非计算机专业AI爱好者;2. 小程序开发…...
JVM的组成及各部分的作用
JVM(Java虚拟机)是Java程序运行的核心环境,负责将Java字节码转换为机器码并执行。以下是JVM的主要组成部分及其作用: 1. 类加载器子系统(Class Loader Subsystem) 作用 加载:将 .class 文件加载…...
计算机网络精讲day2———计算机网络的性能指标(下)
性能指标5:时延带宽积 时延带宽积传播时延*带宽 这里要注意是传播时延不是发送时延 重点:管道法解析时延带宽积 我们以一个圆柱形管道来代表链路,管道的长度是链路的传播时延(以时间作为单位单位表示链路长度)&#x…...
Android LiveData 的 `setValue` 与 `postValue` 区别详解
Android LiveData 的 setValue 与 postValue 区别详解 一、核心区别 线程限制 • setValue:必须且仅能在主线程调用,否则会抛出 IllegalStateException。 • postValue:可在任意线程调用,内部通过 Handler 将任务切换到主线程执行 setValue。 数据更新机制 • setValue:同…...
【多线程】初始线程和Thread类
一. 线程 1. 线程的引入 虽然进程已经可以解决并发编程这种问题,但是进程在频繁进行创建和销毁的时候,系统开销非常大,如果一个服务器向你发送多个请求,针对每一个请求,都需要创建一个进程来应答,每个进程…...
WebLogic中间件常见漏洞
一、后台弱⼝令GetShell 1.环境搭建 cd vulhub-master/weblogic/weak_password docker-compose up -d 2.访问网站并登陆后台 /console/login/LoginForm.jsp 默认账号密码:weblogic/Oracle123 3.点击部署,点击安装ÿ…...
[笔记.AI]多头自注意力机制(Multi-Head Attention)
多头自注意力是深度学习领域,特别是自然语言处理(NLP)和Transformer模型中的关键概念。其发展源于对序列数据中复杂依赖关系的建模需求,特别是在Transformer架构的背景下。 举例 比喻-读长篇文章 用一个简单的比喻来理解“多头注…...
【基于ROS的A*算法实现路径规划】A* | ROS | 路径规划 | Python
### 记录一下使用Python实现ROS平台A*算法路径规划 ### 代码可自取 :Xz/little_projecthttps://gitee.com/Xz_zh/little_project.git 目录 一、思路分析 二、算法实现 三、路径规划实现 一、思路分析 要求使用A*算法实现路径规划,可以将该任务分为三…...
keda基于postgresql伸缩dify-api服务
1 概述 dify-api使用postgresql来存储数据,在dify控制台每新建一个聊天机器的聊天框,就会在conversations表里新插入一条记录,并且不断地更新字段updated_at,示例如下: dify# select * from conversations limit 1; …...
