一个标准的ComfyUI扩展项目应包含以下文件:
├── README.md # 项目说明文档
├── __init__.py # 扩展入口文件
├── [主要功能文件].py # 核心功能实现
└── requirements.txt # 依赖项配置
每个节点类需要定义以下基本属性:
class YourNode:
RETURN_TYPES = ("IMAGE",) # 返回值类型
FUNCTION = "process" # 处理函数名称
CATEGORY = "image/pattern" # 节点分类使用 INPUT_TYPES 类方法定义节点的输入参数:
@classmethod
def INPUT_TYPES(cls):
return {
"required": { # 必需参数
"param_name": ("TYPE", {
"default": default_value,
"min": min_value, # 数值类型可选
"max": max_value, # 数值类型可选
"step": step_value # 数值类型可选
})
}
}为了确保节点的可维护性和复用性,应遵循以下原则:
-
单一职责:
- 每个节点应专注于单一的功能或转换
- 避免在一个节点中实现多个不相关的功能
- 功能应该是原子的,不可再分
-
参数精简:
- 只暴露必要的参数
- 参数应具有明确的用途和合理的默认值
- 避免冗余或相互依赖的参数
-
输入输出清晰:
- 明确定义输入和输出的数据类型
- 保持数据流的简单性和直观性
- 避免复杂的数据转换和状态管理
-
错误处理:
- 提供清晰的错误信息
- 对异常情况进行适当处理
- 保护节点不受无效输入的影响
-
输入图像格式处理:
# 处理输入图像格式(从Tensor转为NumPy数组) if isinstance(image, torch.Tensor): img = (image[0] * 255).cpu().numpy().astype(np.uint8) else: img = (image[0] * 255).astype(np.uint8) # 检查图像维度 if len(img.shape) != 3: raise ValueError("输入图像必须是3通道RGB图像") height, width, channels = img.shape if channels != 3: raise ValueError(f"输入图像必须是3通道RGB图像,当前通道数:{channels}")
-
输出图像格式转换:
# 创建新图像,确保尺寸与输入图像一致 result_img = Image.new('RGB', (width, height), 'black') # ... 图像处理逻辑 ... # 转换为ComfyUI标准格式 result_array = np.array(result_img) / 255.0 result_tensor = torch.from_numpy(result_array).float() # 确保输出张量的维度与ComfyUI期望的格式一致 result_tensor = result_tensor.unsqueeze(0) return (result_tensor,)
-
参数类型不匹配问题:
- 问题描述:在定义节点参数时,如果参数类型与实际处理函数中的期望类型不匹配,可能导致运行时错误
- 解决方案:
- 在INPUT_TYPES中明确定义参数类型和范围
- 在处理函数中添加类型检查和转换
- 使用适当的默认值和范围限制
-
参数范围设置:
- 问题描述:参数范围设置不当可能导致功能异常或性能问题
- 解决方案:
- 根据实际需求设置合理的最小值和最大值
- 考虑性能影响,避免过大的参数范围
- 添加参数验证逻辑
-
参数依赖关系:
- 问题描述:某些参数可能相互依赖,需要确保它们的值在合理范围内
- 解决方案:
- 在处理函数中添加参数关系验证
- 使用条件判断确保参数组合有效
- 提供清晰的错误提示
示例代码:
def process(self, image, min_radius, max_radius):
# 参数验证
if min_radius >= max_radius:
raise ValueError("最小半径必须小于最大半径")
# 类型转换和范围检查
min_radius = int(min_radius)
max_radius = int(max_radius)
if min_radius < 1:
raise ValueError("最小半径不能小于1")
# 处理逻辑
...-
最佳实践:
- 在INPUT_TYPES中使用描述性的参数名称
- 为每个参数提供合理的默认值
- 添加参数验证和错误处理
- 在文档中清晰说明参数的用途和限制
- 定期测试边界条件和异常情况
-
图像格式转换最佳实践:
- 始终检查输入图像类型,确保正确处理Tensor和NumPy数组
- 在进行图像处理操作前,确保将图像数据范围调整到合适的区间(如0-255)
- 使用astype()明确指定数据类型,避免精度问题
- 在返回结果前,确保转换为ComfyUI期望的格式(通常是float32类型的Tensor)
- 保持输入输出图像尺寸的一致性,避免意外的尺寸变化
- 在创建新图像时,显式指定尺寸参数,确保与输入图像匹配
-
常见错误处理:
- 检查图像维度是否正确(通常需要[batch, height, width, channels]格式)
- 注意数据类型转换可能带来的精度损失
- 处理图像格式转换时的内存使用问题
- 确保正确处理GPU和CPU之间的数据传输(使用.cpu()方法)
- 对图像尺寸和通道数进行明确的验证,提供清晰的错误信息
- 在进行图像变换操作时,验证坐标是否在有效范围内
明确指定依赖版本,避免兼容性问题:
numpy>=1.21.0
opencv-python>=4.5.0
torch>=1.7.0
Pillow>=8.0.0
- 功能模块化:将不同功能的代码分离到不同的文件中
- 使用类封装:将相关的功能和数据封装在类中
- 提供清晰的文档注释
- 对输入参数进行验证
- 使用适当的异常处理机制
- 提供有意义的错误信息
- 避免不必要的数据转换
- 合理使用内存资源
- 考虑批处理操作
- 使用print语句或日志记录中间结果
- 检查图像格式和数值范围
- 验证参数有效性
包含以下内容:
- 功能说明
- 安装方法
- 使用说明
- 参数说明
- 示例展示
- 函数和类的文档字符串
- 关键算法步骤说明
- 参数说明和返回值说明
- 版本号管理
- 更新日志维护
- 许可证说明
- 兼容性测试
- 图像格式转换问题
- 参数范围验证
- 性能优化建议
- 依赖冲突处理
-
图像格式转换错误:
- 确保在转换前检查图像类型(Tensor/NumPy)
- 验证图像维度和通道数
- 注意数据类型转换时的精度损失
-
内存管理问题:
- 及时释放大型图像数据
- 避免不必要的数据复制
- 使用适当的数据类型减少内存占用
-
参数范围验证:
- 明确指定参数的有效范围
- 提供合理的默认值
- 添加参数类型检查
-
配置文件错误:
- 使用标准的配置文件格式
- 提供配置模板和示例
- 添加配置验证机制
-
数据类型转换:
- 确保输入数组类型正确(如uint8、float32等)
- 注意数值范围的转换(如0-255到0-1的归一化)
- 处理特殊值(如NaN、Inf)的检查
-
参数验证:
- 检查矩阵维度和通道数
- 验证核大小的奇偶性要求
- 确保阈值范围的合法性
-
错误处理:
- 捕获并处理OpenCV异常
- 提供详细的错误信息和建议
- 实现优雅的降级处理
-
性能优化:
- 避免频繁的数据类型转换
- 合理使用就地操作(in-place operation)
- 注意内存管理和资源释放
-
Commit信息规范:
-
必须使用引号包裹commit信息,这是强制要求:
# 正确示例 git commit -m "feat: 添加新功能" git commit -m "fix: 修复图像处理bug" # 错误示例 git commit -m feat: 添加新功能 # 没有使用引号 git commit -m 'fix: 修复bug' # 使用了单引号
-
采用统一的commit前缀:
- feat: 新功能
- fix: 修复bug
- docs: 文档更新
- style: 代码格式调整
- refactor: 代码重构
- test: 测试相关
- chore: 构建过程或辅助工具的变动
-
-
分支管理:
- 主分支保持稳定
- 功能开发使用feature分支
- 版本发布使用release分支
-
代码提交前检查:
- 运行测试确保功能正常
- 检查代码格式
- 更新文档和注释
- 代码风格规范
- Pull Request流程
- Issue提交指南
- ComfyUI官方文档
- 相关技术文档
- 示例项目
MIT License