Python图片格式批量转换器教程
📚 前言
编程基础第一期《11-30》-- 在图像处理工作中,我们经常需要将大量图片从一种格式转换为另一种格式。本教程将介绍如何使用Python的Pillow库开发一个简单但功能强大的图片格式批量转换器,帮助你高效处理图片格式转换任务。
目录
- 📚 前言
- 🛠️ 开发环境准备
- 💡 核心功能
- 🧩 技术要点
- 1. Pillow库基础
- 2. 文件系统操作
- 3. 用户界面
- 📝 代码实现与解析
- 1. 导入必要的库
- 2. 图片格式转换核心函数
- 3. 批量转换功能
- 4. 命令行界面
- 5. 图形用户界面
- 6. 主函数
- 🎮 使用方法
- 命令行方式
- GUI方式
- 🔍 进阶知识点
- 1. 图像处理基础
- 2. Pillow高级特性
- 3. 性能优化
- 🚀 可扩展功能
- 📝 总结
🛠️ 开发环境准备
- Python 3.6+
- Pillow库 (PIL的fork版本)
安装Pillow库:
pip install pillow
💡 核心功能
- 支持多种常见图片格式之间的转换(JPG, PNG, BMP, GIF, TIFF等)
- 批量处理指定文件夹中的所有图片
- 可选择保留原始图片或仅保留转换后的图片
- 支持调整图片质量和大小
- 简单的命令行界面和图形用户界面(GUI)两种使用方式
🧩 技术要点
1. Pillow库基础
Pillow是Python图像处理库(PIL)的一个分支,提供了丰富的图像处理功能。主要用到的模块:
Image
: 图像对象的创建、读取和保存ImageOps
: 图像操作,如调整大小、翻转等ImageEnhance
: 图像增强,如亮度、对比度调整
2. 文件系统操作
- 使用
os
和pathlib
模块处理文件路径 - 递归遍历目录
- 文件类型判断
3. 用户界面
- 命令行参数解析
- 简单GUI界面构建(使用tkinter)
📝 代码实现与解析
1. 导入必要的库
from PIL import Image
import os
import sys
import argparse
from pathlib import Path
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
知识点:
PIL.Image
: Pillow的核心模块,用于图像处理os
和pathlib
: 文件系统操作argparse
: 命令行参数解析tkinter
: Python标准GUI库
2. 图片格式转换核心函数
def convert_image(input_path, output_path, format, quality=95, resize=None):"""转换单个图片的格式参数:input_path - 输入图片路径output_path - 输出图片路径format - 目标格式 (如 'JPEG', 'PNG')quality - 图片质量 (1-100, 仅对JPEG格式有效)resize - 调整大小的元组 (width, height) 或 None返回:bool - 转换是否成功"""try:# 打开图片img = Image.open(input_path)# 如果是RGBA模式且转换为JPEG,需要转换为RGB模式if img.mode == 'RGBA' and format.upper() == 'JPEG':img = img.convert('RGB')# 调整大小if resize:img = img.resize(resize, Image.LANCZOS)# 保存转换后的图片if format.upper() == 'JPEG':img.save(output_path, format=format, quality=quality)else:img.save(output_path, format=format)return Trueexcept Exception as e:print(f"转换图片 {input_path} 时出错: {e}")return False
知识点:
Image.open()
: 打开图片文件- 图像模式转换: RGBA转RGB(JPEG不支持透明通道)
Image.LANCZOS
: 高质量的图像缩放算法- 异常处理: 捕获并处理可能的错误
3. 批量转换功能
def batch_convert(input_dir, output_dir, target_format, quality=95, resize=None, recursive=False, keep_original=True):"""批量转换指定目录中的图片参数:input_dir - 输入目录output_dir - 输出目录target_format - 目标格式quality - 图片质量resize - 调整大小的元组recursive - 是否递归处理子目录keep_original - 是否保留原始图片返回:tuple - (成功数量, 失败数量)"""# 支持的图片格式supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff']# 创建输出目录os.makedirs(output_dir, exist_ok=True)success_count = 0failed_count = 0# 遍历目录for root, dirs, files in os.walk(input_dir):# 如果不递归处理子目录且不是根目录,则跳过if not recursive and root != input_dir:continue# 创建对应的输出子目录rel_path = os.path.relpath(root, input_dir)if rel_path != '.':current_output_dir = os.path.join(output_dir, rel_path)os.makedirs(current_output_dir, exist_ok=True)else:current_output_dir = output_dir# 处理文件for file in files:# 检查文件扩展名ext = os.path.splitext(file)[1].lower()if ext not in supported_formats:continue# 构建输入和输出路径input_path = os.path.join(root, file)output_filename = os.path.splitext(file)[0] + '.' + target_format.lower()output_path = os.path.join(current_output_dir, output_filename)# 转换图片if convert_image(input_path, output_path, target_format, quality, resize):success_count += 1# 如果不保留原始图片且不是在原目录操作,则删除原始图片if not keep_original and input_dir != output_dir:try:os.remove(input_path)except:passelse:failed_count += 1return (success_count, failed_count)
知识点:
os.walk()
: 递归遍历目录os.path.relpath()
: 获取相对路径os.makedirs()
: 创建多级目录- 文件扩展名处理: 使用
os.path.splitext()
分离文件名和扩展名
4. 命令行界面
def setup_cli():"""设置命令行参数解析器"""parser = argparse.ArgumentParser(description='批量转换图片格式')parser.add_argument('input', help='输入目录或文件')parser.add_argument('output', help='输出目录')parser.add_argument('format', help='目标格式 (如: jpg, png, bmp)')parser.add_argument('-q', '--quality', type=int, default=95, help='图片质量 (1-100, 默认: 95)')parser.add_argument('-r', '--recursive', action='store_true', help='递归处理子目录')parser.add_argument('-k', '--keep', action='store_true', help='保留原始图片')parser.add_argument('--resize', nargs=2, type=int, metavar=('WIDTH', 'HEIGHT'),help='调整图片大小')return parser.parse_args()
知识点:
argparse
: 命令行参数解析- 参数类型: 位置参数、可选参数、标志参数
- 参数类型转换: 使用
type=int
将字符串转换为整数
5. 图形用户界面
class ImageConverterGUI:def __init__(self, root):self.root = rootself.root.title("图片格式批量转换器")self.root.geometry("600x450")self.root.resizable(True, True)# 创建主框架main_frame = ttk.Frame(root, padding="10")main_frame.pack(fill=tk.BOTH, expand=True)# 输入目录ttk.Label(main_frame, text="输入目录:").grid(column=0, row=0, sticky=tk.W, pady=5)self.input_dir = tk.StringVar()ttk.Entry(main_frame, width=50, textvariable=self.input_dir).grid(column=1, row=0, pady=5)ttk.Button(main_frame, text="浏览...", command=self.browse_input).grid(column=2, row=0, padx=5, pady=5)# 输出目录ttk.Label(main_frame, text="输出目录:").grid(column=0, row=1, sticky=tk.W, pady=5)self.output_dir = tk.StringVar()ttk.Entry(main_frame, width=50, textvariable=self.output_dir).grid(column=1, row=1, pady=5)ttk.Button(main_frame, text="浏览...", command=self.browse_output).grid(column=2, row=1, padx=5, pady=5)# 目标格式ttk.Label(main_frame, text="目标格式:").grid(column=0, row=2, sticky=tk.W, pady=5)self.format_var = tk.StringVar(value="JPEG")formats = ["JPEG", "PNG", "BMP", "GIF", "TIFF"]ttk.Combobox(main_frame, textvariable=self.format_var, values=formats, width=10).grid(column=1, row=2, sticky=tk.W, pady=5)# 图片质量ttk.Label(main_frame, text="图片质量:").grid(column=0, row=3, sticky=tk.W, pady=5)self.quality_var = tk.IntVar(value=95)quality_frame = ttk.Frame(main_frame)quality_frame.grid(column=1, row=3, sticky=tk.W, pady=5)ttk.Scale(quality_frame, from_=1, to=100, variable=self.quality_var, orient=tk.HORIZONTAL, length=200).pack(side=tk.LEFT)ttk.Label(quality_frame, textvariable=self.quality_var).pack(side=tk.LEFT, padx=5)# 调整大小ttk.Label(main_frame, text="调整大小:").grid(column=0, row=4, sticky=tk.W, pady=5)resize_frame = ttk.Frame(main_frame)resize_frame.grid(column=1, row=4, sticky=tk.W, pady=5)self.resize_enabled = tk.BooleanVar(value=False)ttk.Checkbutton(resize_frame, text="启用", variable=self.resize_enabled).pack(side=tk.LEFT)ttk.Label(resize_frame, text="宽:").pack(side=tk.LEFT, padx=(10, 0))self.width_var = tk.IntVar(value=800)ttk.Entry(resize_frame, width=5, textvariable=self.width_var).pack(side=tk.LEFT, padx=(0, 5))ttk.Label(resize_frame, text="高:").pack(side=tk.LEFT)self.height_var = tk.IntVar(value=600)ttk.Entry(resize_frame, width=5, textvariable=self.height_var).pack(side=tk.LEFT)# 递归处理self.recursive_var = tk.BooleanVar(value=False)ttk.Checkbutton(main_frame, text="递归处理子目录", variable=self.recursive_var).grid(column=1, row=5, sticky=tk.W, pady=5)# 保留原始图片self.keep_original_var = tk.BooleanVar(value=True)ttk.Checkbutton(main_frame, text="保留原始图片", variable=self.keep_original_var).grid(column=1, row=6, sticky=tk.W, pady=5)# 转换按钮ttk.Button(main_frame, text="开始转换", command=self.start_conversion).grid(column=1, row=7, pady=10)# 进度条self.progress_var = tk.DoubleVar()ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100).grid(column=0, row=8, columnspan=3, sticky=(tk.W, tk.E), pady=5)# 状态标签self.status_var = tk.StringVar(value="就绪")ttk.Label(main_frame, textvariable=self.status_var).grid(column=0, row=9, columnspan=3, sticky=tk.W, pady=5)def browse_input(self):directory = filedialog.askdirectory()if directory:self.input_dir.set(directory)def browse_output(self):directory = filedialog.askdirectory()if directory:self.output_dir.set(directory)def start_conversion(self):input_dir = self.input_dir.get()output_dir = self.output_dir.get()target_format = self.format_var.get()quality = self.quality_var.get()recursive = self.recursive_var.get()keep_original = self.keep_original_var.get()# 检查输入if not input_dir or not output_dir:messagebox.showerror("错误", "请指定输入和输出目录")return# 检查调整大小参数resize = Noneif self.resize_enabled.get():try:width = self.width_var.get()height = self.height_var.get()if width <= 0 or height <= 0:raise ValueError("宽度和高度必须大于0")resize = (width, height)except:messagebox.showerror("错误", "调整大小参数无效")return# 开始转换self.status_var.set("转换中...")self.root.update()try:success, failed = batch_convert(input_dir, output_dir, target_format, quality,resize, recursive, keep_original)self.status_var.set(f"转换完成。成功: {success}, 失败: {failed}")messagebox.showinfo("完成", f"转换完成\n成功: {success}\n失败: {failed}")except Exception as e:self.status_var.set(f"转换出错: {str(e)}")messagebox.showerror("错误", f"转换过程中出错:\n{str(e)}")
知识点:
tkinter
: Python标准GUI库- 布局管理: 使用
grid
布局 - 控件使用: 标签、输入框、按钮、复选框、组合框、进度条等
- 事件处理: 按钮点击事件
- 文件对话框: 使用
filedialog
选择目录
6. 主函数
def main():# 检查是否有命令行参数if len(sys.argv) > 1:# 命令行模式args = setup_cli()# 检查输入和输出目录if not os.path.exists(args.input):print(f"错误: 输入路径 '{args.input}' 不存在")return# 调整大小参数resize = tuple(args.resize) if args.resize else None# 开始转换print(f"开始转换图片从 {args.input} 到 {args.output},格式: {args.format}")success, failed = batch_convert(args.input, args.output, args.format.upper(),args.quality, resize, args.recursive, args.keep)print(f"转换完成。成功: {success}, 失败: {failed}")else:# GUI模式root = tk.Tk()app = ImageConverterGUI(root)root.mainloop()if __name__ == "__main__":main()
总代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-"""
图片格式批量转换器
功能: 批量将图片从一种格式转换为另一种格式,支持调整大小和质量
作者: Python开发者
"""from PIL import Image
import os
import sys
import argparse
from pathlib import Path
import tkinter as tk
from tkinter import filedialog, messagebox, ttkdef convert_image(input_path, output_path, format, quality=95, resize=None):"""转换单个图片的格式参数:input_path - 输入图片路径output_path - 输出图片路径format - 目标格式 (如 'JPEG', 'PNG')quality - 图片质量 (1-100, 仅对JPEG格式有效)resize - 调整大小的元组 (width, height) 或 None返回:bool - 转换是否成功"""try:# 打开图片img = Image.open(input_path)# 如果是RGBA模式且转换为JPEG,需要转换为RGB模式if img.mode == 'RGBA' and format.upper() == 'JPEG':img = img.convert('RGB')# 调整大小if resize:img = img.resize(resize, Image.LANCZOS)# 保存转换后的图片if format.upper() == 'JPEG':img.save(output_path, format=format, quality=quality)else:img.save(output_path, format=format)return Trueexcept Exception as e:print(f"转换图片 {input_path} 时出错: {e}")return Falsedef batch_convert(input_dir, output_dir, target_format, quality=95,resize=None, recursive=False, keep_original=True):"""批量转换指定目录中的图片参数:input_dir - 输入目录output_dir - 输出目录target_format - 目标格式quality - 图片质量resize - 调整大小的元组recursive - 是否递归处理子目录keep_original - 是否保留原始图片返回:tuple - (成功数量, 失败数量)"""# 支持的图片格式supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.gif', '.tiff']# 创建输出目录os.makedirs(output_dir, exist_ok=True)success_count = 0failed_count = 0# 遍历目录for root, dirs, files in os.walk(input_dir):# 如果不递归处理子目录且不是根目录,则跳过if not recursive and root != input_dir:continue# 创建对应的输出子目录rel_path = os.path.relpath(root, input_dir)if rel_path != '.':current_output_dir = os.path.join(output_dir, rel_path)os.makedirs(current_output_dir, exist_ok=True)else:current_output_dir = output_dir# 处理文件for file in files:# 检查文件扩展名ext = os.path.splitext(file)[1].lower()if ext not in supported_formats:continue# 构建输入和输出路径input_path = os.path.join(root, file)output_filename = os.path.splitext(file)[0] + '.' + target_format.lower()output_path = os.path.join(current_output_dir, output_filename)# 转换图片if convert_image(input_path, output_path, target_format, quality, resize):success_count += 1# 如果不保留原始图片且不是在原目录操作,则删除原始图片if not keep_original and input_dir != output_dir:try:os.remove(input_path)except:passelse:failed_count += 1return (success_count, failed_count)def setup_cli():"""设置命令行参数解析器"""parser = argparse.ArgumentParser(description='批量转换图片格式')parser.add_argument('input', help='输入目录或文件')parser.add_argument('output', help='输出目录')parser.add_argument('format', help='目标格式 (如: jpg, png, bmp)')parser.add_argument('-q', '--quality', type=int, default=95,help='图片质量 (1-100, 默认: 95)')parser.add_argument('-r', '--recursive', action='store_true',help='递归处理子目录')parser.add_argument('-k', '--keep', action='store_true',help='保留原始图片')parser.add_argument('--resize', nargs=2, type=int, metavar=('WIDTH', 'HEIGHT'),help='调整图片大小')return parser.parse_args()class ImageConverterGUI:def __init__(self, root):self.root = rootself.root.title("图片格式批量转换器")self.root.geometry("600x450")self.root.resizable(True, True)# 创建主框架main_frame = ttk.Frame(root, padding="10")main_frame.pack(fill=tk.BOTH, expand=True)# 输入目录ttk.Label(main_frame, text="输入目录:").grid(column=0, row=0, sticky=tk.W, pady=5)self.input_dir = tk.StringVar()ttk.Entry(main_frame, width=50, textvariable=self.input_dir).grid(column=1, row=0, pady=5)ttk.Button(main_frame, text="浏览...", command=self.browse_input).grid(column=2, row=0, padx=5, pady=5)# 输出目录ttk.Label(main_frame, text="输出目录:").grid(column=0, row=1, sticky=tk.W, pady=5)self.output_dir = tk.StringVar()ttk.Entry(main_frame, width=50, textvariable=self.output_dir).grid(column=1, row=1, pady=5)ttk.Button(main_frame, text="浏览...", command=self.browse_output).grid(column=2, row=1, padx=5, pady=5)# 目标格式ttk.Label(main_frame, text="目标格式:").grid(column=0, row=2, sticky=tk.W, pady=5)self.format_var = tk.StringVar(value="JPEG")formats = ["JPEG", "PNG", "BMP", "GIF", "TIFF"]ttk.Combobox(main_frame, textvariable=self.format_var, values=formats, width=10).grid(column=1, row=2,sticky=tk.W, pady=5)# 图片质量ttk.Label(main_frame, text="图片质量:").grid(column=0, row=3, sticky=tk.W, pady=5)self.quality_var = tk.IntVar(value=95)quality_frame = ttk.Frame(main_frame)quality_frame.grid(column=1, row=3, sticky=tk.W, pady=5)ttk.Scale(quality_frame, from_=1, to=100, variable=self.quality_var, orient=tk.HORIZONTAL, length=200).pack(side=tk.LEFT)ttk.Label(quality_frame, textvariable=self.quality_var).pack(side=tk.LEFT, padx=5)# 调整大小ttk.Label(main_frame, text="调整大小:").grid(column=0, row=4, sticky=tk.W, pady=5)resize_frame = ttk.Frame(main_frame)resize_frame.grid(column=1, row=4, sticky=tk.W, pady=5)self.resize_enabled = tk.BooleanVar(value=False)ttk.Checkbutton(resize_frame, text="启用", variable=self.resize_enabled).pack(side=tk.LEFT)ttk.Label(resize_frame, text="宽:").pack(side=tk.LEFT, padx=(10, 0))self.width_var = tk.IntVar(value=800)ttk.Entry(resize_frame, width=5, textvariable=self.width_var).pack(side=tk.LEFT, padx=(0, 5))ttk.Label(resize_frame, text="高:").pack(side=tk.LEFT)self.height_var = tk.IntVar(value=600)ttk.Entry(resize_frame, width=5, textvariable=self.height_var).pack(side=tk.LEFT)# 递归处理self.recursive_var = tk.BooleanVar(value=False)ttk.Checkbutton(main_frame, text="递归处理子目录", variable=self.recursive_var).grid(column=1, row=5,sticky=tk.W, pady=5)# 保留原始图片self.keep_original_var = tk.BooleanVar(value=True)ttk.Checkbutton(main_frame, text="保留原始图片", variable=self.keep_original_var).grid(column=1, row=6,sticky=tk.W, pady=5)# 转换按钮ttk.Button(main_frame, text="开始转换", command=self.start_conversion).grid(column=1, row=7, pady=10)# 进度条self.progress_var = tk.DoubleVar()ttk.Progressbar(main_frame, variable=self.progress_var, maximum=100).grid(column=0, row=8, columnspan=3,sticky=(tk.W, tk.E), pady=5)# 状态标签self.status_var = tk.StringVar(value="就绪")ttk.Label(main_frame, textvariable=self.status_var).grid(column=0, row=9, columnspan=3, sticky=tk.W, pady=5)def browse_input(self):directory = filedialog.askdirectory()if directory:self.input_dir.set(directory)def browse_output(self):directory = filedialog.askdirectory()if directory:self.output_dir.set(directory)def start_conversion(self):input_dir = self.input_dir.get()output_dir = self.output_dir.get()target_format = self.format_var.get()quality = self.quality_var.get()recursive = self.recursive_var.get()keep_original = self.keep_original_var.get()# 检查输入if not input_dir or not output_dir:messagebox.showerror("错误", "请指定输入和输出目录")return# 检查调整大小参数resize = Noneif self.resize_enabled.get():try:width = self.width_var.get()height = self.height_var.get()if width <= 0 or height <= 0:raise ValueError("宽度和高度必须大于0")resize = (width, height)except:messagebox.showerror("错误", "调整大小参数无效")return# 开始转换self.status_var.set("转换中...")self.root.update()try:success, failed = batch_convert(input_dir, output_dir, target_format, quality,resize, recursive, keep_original)self.status_var.set(f"转换完成。成功: {success}, 失败: {failed}")messagebox.showinfo("完成", f"转换完成\n成功: {success}\n失败: {failed}")except Exception as e:self.status_var.set(f"转换出错: {str(e)}")messagebox.showerror("错误", f"转换过程中出错:\n{str(e)}")def main():# 检查是否有命令行参数if len(sys.argv) > 1:# 命令行模式args = setup_cli()# 检查输入和输出目录if not os.path.exists(args.input):print(f"错误: 输入路径 '{args.input}' 不存在")return# 调整大小参数resize = tuple(args.resize) if args.resize else None# 开始转换print(f"开始转换图片从 {args.input} 到 {args.output},格式: {args.format}")success, failed = batch_convert(args.input, args.output, args.format.upper(),args.quality, resize, args.recursive, args.keep)print(f"转换完成。成功: {success}, 失败: {failed}")else:# GUI模式root = tk.Tk()app = ImageConverterGUI(root)root.mainloop()if __name__ == "__main__":main()
知识点:
- 命令行模式和GUI模式的切换
sys.argv
: 获取命令行参数tkinter
主循环:root.mainloop()
🎮 使用方法
命令行方式
# 基本用法
python image_converter.py 输入目录 输出目录 目标格式# 示例: 将input_folder中的图片转换为PNG格式并保存到output_folder
python image_converter.py input_folder output_folder png# 高级用法
python image_converter.py input_folder output_folder jpg -q 85 -r --resize 800 600
GUI方式
直接运行程序,不带任何参数:
python image_converter.py
然后在图形界面中:
- 选择输入目录
- 选择输出目录
- 设置目标格式和其他选项
- 点击"开始转换"按钮
🔍 进阶知识点
1. 图像处理基础
- 像素: 图像的基本单位
- 颜色模式: RGB, RGBA, CMYK, 灰度等
- 图像格式特点:
- JPEG: 有损压缩,不支持透明度,适合照片
- PNG: 无损压缩,支持透明度,适合图标和截图
- GIF: 支持动画,有限的颜色数量
- BMP: 无压缩,文件较大
- TIFF: 高质量,支持多页,常用于专业印刷
2. Pillow高级特性
- 图像增强: 亮度、对比度、锐化等调整
- 滤镜效果: 模糊、锐化、边缘检测等
- 图像合成: 图层混合、水印等
- 批处理: 多进程处理提高效率
3. 性能优化
- 使用生成器减少内存占用
- 多线程/多进程处理提高转换速度
- 缩略图生成优化
🚀 可扩展功能
-
批量水印添加:为图片添加文字或图片水印
-
图片批量裁剪:自动裁剪图片到指定比例或尺寸
-
批量图片优化:自动调整亮度、对比度和图片锐化
-
批量重命名:根据规则批量重命名图片文件
-
元数据处理:保留或清除EXIF信息
📝 总结
通过这个图片格式批量转换器项目,我们学习了以下Python编程知识:
- Pillow库的基本使用
- 文件系统操作
- 命令行参数解析
- GUI界面开发
- 批处理和异常处理
- 图像处理基础知识
物物而不物于物,念念而不念于念
相关文章:

Python图片格式批量转换器教程
📚 前言 编程基础第一期《11-30》-- 在图像处理工作中,我们经常需要将大量图片从一种格式转换为另一种格式。本教程将介绍如何使用Python的Pillow库开发一个简单但功能强大的图片格式批量转换器,帮助你高效处理图片格式转换任务。 目录 &…...

从公开到私密:重新思考 Web3 的数据安全
去中心化存储是 Web3 的基石之一,使用户和应用能够在无需依赖中心化服务商的情况下存储数据。但自由也带来了一个重大挑战:数据安全。在一个无许可的世界中,如何确保用户文档、游戏资产或 AI 数据集等敏感内容是私密的、可控访问的࿰…...

计算机网络常见体系结构、分层必要性、分层设计思想以及专用术语介绍
计算机网络体系结构 从本此开始,我们就要开始介绍有关计算机网络体系结构的知识了。内容包括: 常见的计算机网络体系结构 计算机网络体系结构分层的必要性 计算机网络体系结构的设计思想 举例说明及专用术语 计算机网络体系结构是计算机网络课程中…...

接口自动化测试用例的编写方法
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 phpunit 接口自动化测试系列 Post接口自动化测试用例 Post方式的接口是上传接口,需要对接口头部进行封装,所以没有办法在浏览器下直接调…...
解决Docker存储空间不足问题
虚拟机磁盘扩展实战:解决Docker存储空间不足问题 问题背景 在虚拟机中运行的Linux系统上,Docker服务因根分区空间不足而无法正常运行。初始状态如下: [rootlocalhost ~]# df -h / 文件系统 容量 已用 可用 已用% 挂载点…...

基于SpringBoot的商家销售管理网站的设计与实现
湖南软件职业技术大学 本科毕业设计(论文) 设计(论文)题目 基于SpringBoot的商家销售管理网站的设计与实现 学生姓名 学生学号 所在学院 专业班级 校内指导教师 企业指导教师 毕业设计(论文)真实性承诺及声明 学生对毕业设计(论文)真实性承诺 本人郑重声明:所提交的毕…...
【数据集】高分辨率(1 km)月尺度中国气候(降水+最高/低温)数据集(1952–2019)
目录 数据描述🧩 输入数据⚙️ 数据处理流程一、ChinaClim_baseline(基准气候表面)二、ChinaClim_time-series(时序气候数据)📊 评估与验证方法📤 数据下载月最低气温月最高气温python绘制代码参考论文《1 km monthly precipitation and temperatures dataset for Ch…...

word中表格拉不动以及插入图片有间距
1、word中表格插入图片始终有间隙,怎么调表格高度和宽度都消除不了间隙,如下所示: 可以在表布局—单元格边距—修改上下左右边距为0即可 2、经过上述调整后左右没有间隔了,但图片上下有间隔,直觉是行距问题,…...
JavaSE:面向对象进阶之接口(Interface)
JavaSE 面向对象进阶之接口(Interface) 一、接口的核心概念 接口是一种完全抽象的类型,它定义了一组方法签名(契约),但不包含方法实现。接口的核心作用是: 规范行为:强制实现类遵…...

【Java学习笔记】接口
接口 应用场景引出 一、接口的介绍 1. 接口的基本结构 interface 接口名{属性抽象方法 }引出关键字:implements 2. 子类实现接口 class a implements 接口名{}3. 接口中的属性说明:属性默认是public static final修饰的 (1)f…...

代码随想录打卡|Day50 图论(拓扑排序精讲 、dijkstra(朴素版)精讲 )
图论part08 拓扑排序精讲 代码随想录讲解链接 题目链接 思路 在这个题目之中,个别文件的处理依赖于别的文件,因此,文件的处理顺序十分重要。我们用图来表示文件的处理顺序,文件s指向文件t,则说明如果要正确的处理文…...
Wan2.1 图生视频模型内部协作流程
Wan2.1 图生视频模型内部协作流程 flyfish Wan2.1作为一个多模态生成模型,其内部涉及多个子模型的协同工作。 1. 模型架构概览 Wan2.1主要由以下核心组件构成: 文本编码器:基于T5的文本理解模型,将prompt转换为语义向量图像编…...

SI24R05国产低功耗2.4GHz+125K低频唤醒SoC人员定位/畜牧业牛羊定位/资产管理定位方案芯片
目录 SI24R05简介功能框图 主要特性开发工具方案特性 SI24R05简介 Si24R05 是一款高度集成的低功耗 SOC 芯片,具有低功耗、Low Pin Count、 宽电压工作范围,集成了 13/14/15/16 位精度的 ADC、LVD、UART、SPI、I2C、TIMER、WUP、IWDG、RTC、无线收发器、…...
qt QAxWidget
QAxWidget 是 Qt 中用于嵌入 ActiveX 控件或 COM 对象的类,主要用于 Windows 平台。以下是其使用方法的详细步骤和示例: 1. 环境配置 在 .pro 文件中添加 axcontainer 模块: QT axcontainer2. 基本使用 创建控件实例 #include <QAxW…...
机器学习与深度学习04-逻辑回归02
目录 前文回顾6.正则化在逻辑回归中的作用7.特征工程是什么8.逻辑回归的预测结果如何9.什么是ROC曲线和AUC值10.如何处理类不平衡问题11.什么是交叉验证 前文回顾 上一篇文章地址:链接 6.正则化在逻辑回归中的作用 逻辑回归中,正则化是一种用于控制模…...
CQF预备知识:Python相关库 -- NumPy 基础知识 - 通用函数
文中内容仅限技术学习与代码实践参考,市场存在不确定性,技术分析需谨慎验证,不构成任何投资建议。 通用函数 另请参阅 通用函数(ufunc) 通用函数(或简称 ufunc)是一种对 ndarrays 进行逐元素操…...

基于ELK的分布式日志实时分析与可视化系统设计
目录 一、ELK平台介绍 1.ELK概述 2.Elasticsearch 3.Logstash 4.Kibana 二、部署ES群集 1.资源清单 2.基本配置 3.安装Elasticsearch(elk1上、elk2上、elk3上) 4.安装logstash(elk1上) 5.Filebeat 6.安装Kibana&#x…...
@Async 注解 走的是主线程 还是子线程呢
Asyncz注解所在的包 package org.springframework.scheduling.annotation; Async 注解在Spring框架中用于标记一个方法为异步方法。当这个方法被调用时,它不会阻塞调用线程,而是会在一个单独的线程中执行。因此,Async 注解走的是子线程&…...
前端面经 React 组件常见的声明方式
react类组件和函数式组件 函数组件返回值的内容就是要渲染的内容 函数组件使用useState更新状态 ,使用类中变量更新 常见hook 官方 : useEffect 处理副作用,请求APIuseState 更新UIuseLayout 同步更新,会阻塞进程,…...

酒店管理系统设计与实现
本科毕业设计(论文) 设计(论文)题目 酒店管理系统设计与实现 学生姓名 学生学号 所在学院 专业班级 校内指导教师 李建 企业指导教师 毕业设计(论文)真实性承诺及声明 学生对毕业设计(论文)真实性承诺 本人郑重声明:所提交的毕业设计(论文)作品是本人在指导教师的指…...

OpenCV---pointPolygonTest
一、基本概念与用途 pointPolygonTest 是 OpenCV 中用于判断点与多边形关系的重要函数,常用于: 目标检测:判断像素点是否属于检测到的轮廓区域碰撞检测:检测物体是否重叠图像分割:确定点是否在分割区域内几何分析&am…...

Qt 的简单示例 -- 地址簿
这个工程里有两个窗口,都是QWidget派生的窗口 主窗口: 1. 运用了布局,按钮控件,单行编辑框,富文本编辑框等窗口部件; 2. 运用了 QMap 类; 3. 实现了点击按钮弹出子窗口的功能,这里子…...
Linux 下 C 语言实现工厂模式
Linux 下 C 语言实现工厂模式:设计理念与实战 🧠 一、工厂模式简介什么是工厂模式?C 语言实现设计模式的挑战 🏗️ 二、实现简单工厂模式(Simple Factory)1. 定义传感器接口(device.h࿰…...

什么是DevOps的核心目标?它如何解决传统开发与运维之间的冲突?
在当今数字化转型加速的时代,DevOps 已成为软件开发领域备受瞩目的明星理念。今天,本文将聚焦于 DevOps 的核心目标,并深入探讨它如何巧妙化解传统开发与运维之间的冲突,为大家揭开 DevOps 的神秘面纱并分享实用经验。本次介绍的与…...
RocketMQ 死信队列(DLQ)实战:原理 + 开发 + 运维 + 架构应用指南
🚀RocketMQ 死信队列(DLQ)实战:原理 开发 运维 架构应用指南 第一章:什么是死信队列(DLQ)? 1.1 死信队列定义 在 RocketMQ 中,死信队列(Dead Letter Que…...

Android studio 查看aar源码出现/* compiled code */
如图查看aar源码时看不到具体实现,在排除是sdk版本导致的问题后,下面说解决方法 打开设置,找到插件 输入decompiler 搜索 这个是自带的反编译工具,启用就好了...

用HTML5+JavaScript实现汉字转拼音工具
用HTML5JavaScript实现汉字转拼音工具 前一篇博文(https://blog.csdn.net/cnds123/article/details/148067680)提到,当需要将拼音添加到汉字上面时,用python实现比HTML5JavaScript实现繁琐。在这篇博文中用HTML5JavaScript实现汉…...

基于Java,SpringBoot,Vue,UniAPP医院预约挂号买药就诊病例微信小程序系统设计
摘要 随着医疗信息化的不断推进以及“互联网医疗”模式的广泛普及,传统医院挂号流程中存在的排队时间长、资源分配不均等问题日益凸显,急需通过数字化手段加以解决。本研究设计并实现了一套基于Java、SpringBoot、Vue与UniAPP技术栈的医院预约挂号微信小…...

ONNX模型的动态和静态量化
引言 通常我们将模型转换为onnx格式之后,模型的体积可能比较大,这样在某些场景下就无法适用。最近想在移动端部署语音识别、合成模型,但是目前的效果较好的模型动辄几个G,于是便想着将模型压缩一下。本文探索了两种压缩方法&…...
PHP 垃圾回收高级特性
PHP 垃圾回收高级特性 1. 循环引用与内存泄漏 单纯的引用计数在遇到循环引用时会导致内存泄漏,主要原因是引用计数无法正确识别那些仅通过循环引用相互关联但实际上已经不可达的对象。 1.1 引用计数的基本原理 引用计数是一种内存管理机制,通过维护每…...