Python图片格式批量转换器教程

article/2025/7/28 0:47:47

📚 前言

编程基础第一期《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

💡 核心功能

  1. 支持多种常见图片格式之间的转换(JPG, PNG, BMP, GIF, TIFF等)
  2. 批量处理指定文件夹中的所有图片
  3. 可选择保留原始图片或仅保留转换后的图片
  4. 支持调整图片质量和大小
  5. 简单的命令行界面和图形用户界面(GUI)两种使用方式

🧩 技术要点

1. Pillow库基础

Pillow是Python图像处理库(PIL)的一个分支,提供了丰富的图像处理功能。主要用到的模块:

  • Image: 图像对象的创建、读取和保存
  • ImageOps: 图像操作,如调整大小、翻转等
  • ImageEnhance: 图像增强,如亮度、对比度调整

2. 文件系统操作

  • 使用ospathlib模块处理文件路径
  • 递归遍历目录
  • 文件类型判断

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的核心模块,用于图像处理
  • ospathlib: 文件系统操作
  • 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. 选择输入目录
  2. 选择输出目录
  3. 设置目标格式和其他选项
  4. 点击"开始转换"按钮
    在这里插入图片描述

🔍 进阶知识点

1. 图像处理基础

  • 像素: 图像的基本单位
  • 颜色模式: RGB, RGBA, CMYK, 灰度等
  • 图像格式特点:
    • JPEG: 有损压缩,不支持透明度,适合照片
    • PNG: 无损压缩,支持透明度,适合图标和截图
    • GIF: 支持动画,有限的颜色数量
    • BMP: 无压缩,文件较大
    • TIFF: 高质量,支持多页,常用于专业印刷

2. Pillow高级特性

  • 图像增强: 亮度、对比度、锐化等调整
  • 滤镜效果: 模糊、锐化、边缘检测等
  • 图像合成: 图层混合、水印等
  • 批处理: 多进程处理提高效率

3. 性能优化

  • 使用生成器减少内存占用
  • 多线程/多进程处理提高转换速度
  • 缩略图生成优化

🚀 可扩展功能

  1. 批量水印添加:为图片添加文字或图片水印

  2. 图片批量裁剪:自动裁剪图片到指定比例或尺寸

  3. 批量图片优化:自动调整亮度、对比度和图片锐化

  4. 批量重命名:根据规则批量重命名图片文件

  5. 元数据处理:保留或清除EXIF信息

📝 总结

通过这个图片格式批量转换器项目,我们学习了以下Python编程知识:

  1. Pillow库的基本使用
  2. 文件系统操作
  3. 命令行参数解析
  4. GUI界面开发
  5. 批处理和异常处理
  6. 图像处理基础知识

物物而不物于物,念念而不念于念


http://www.hkcw.cn/article/eKpPIJKKsH.shtml

相关文章

Java Math类API全解析

Java中Math类的常用API Java的Math类提供了丰富的数学计算方法&#xff0c;包含静态方法可直接调用&#xff0c;适用于基本数值运算、三角函数、指数对数等场景。以下是常用API分类说明&#xff1a; 基本运算方法 // 绝对值 int absValue Math.abs(-5); // 5// 最大值与…

飞牛fnNAS的Docker应用之迅雷篇

目录 一、“迅雷”应用安装 二、启动迅雷 三、迅雷账号登录 四、修改“迅雷”下载保存路径 1、下载路径准备 2、停止“迅雷”Docker容器 3、修改存储位置 4、重新启动Docker容器 5、再次“启用”迅雷 五、测试 1、在PC上添加下载任务 2、手机上管理 3、手机添加下…

Science Advances 上海理工大学与美国杜克大学(Duke University)共同开发了一种仿生复眼相机

编辑丨%科学家开发了一种 AI 辅助的仿生复眼相机。炎炎夏日&#xff0c;相信各位读者都有被蚊子骚扰过的恼火记忆。但往往想要清剿蚊子的时候&#xff0c;却被它灵巧地躲开&#xff0c;再难找到。诸如蚊子这种节肢动物的视觉系统已经进化了 5 亿多年&#xff0c;从寒武纪一直到…

C# 结合PaddleOCRSharp搭建Http网络服务

Windows打开端口&#xff1a; 控制面板 > 系统和安全 > 防火墙> 高级设置 → 入站规则 → 右侧选择 → 新建规则 → 端口 → 协议类型 TCP→ 端口 using System; using System.Drawing; using System.IO; using System.Net; using System.Text; using System.Threadi…

Real SQL Programming

目录 SQL in Real Programs Options Stored Procedures Advantages of Stored Procedures Parameters in PSM SQL in Real Programs We have seen only how SQL is used at the generic query interface --- an environment where we sit at a terminal and ask queries …

华为OD机试真题——跳格子3(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《跳格子3》: 目录 题目名称…

UE5蓝图暴露变量,类似Unity中public一个变量,在游戏运行时修改变量实时变化和看向目标跟随目标Find Look at Rotation

UE5蓝图中暴露变量&#xff0c;类似Unity中public一个变量&#xff0c;在游戏运行时修改变量实时变化 1&#xff0c;添加变量 2&#xff0c;设置变量的值 3&#xff0c;点开小眼睛&#xff0c;此变量显示在编辑器中&#xff0c;可以运行时修改 看向目标跟随目标Find Look at R…

第 1 章:学习起步

1. React Native前置知识要求 在开始学习React Native之前&#xff0c;有一些前置知识你需要了解。不过别担心&#xff0c;我会带你逐步掌握这些内容&#xff0c;让你顺利入门。 1.1. JavaScript是必须掌握的 学习React Native&#xff0c;JavaScript是基础。你需要了解Java…

BERT***

​​1.预训练&#xff08;Pre-training&#xff09;​​ 是深度学习中的一种训练策略&#xff0c;指在大规模无标注数据上预先训练模型&#xff0c;使其学习通用的特征表示&#xff0c;再通过​​微调&#xff08;Fine-tuning&#xff09;​​ 适配到具体任务 2.sentence-lev…

在Mathematica中使用WhenEvent求解微分方程

WhenEvent[event,action]指定当事件event触发时&#xff0c;方程在 NDSolve 及相关函数中执行的操作action。 模拟一个每次弹起后保持95%速度的弹跳球 NDSolve[{y[t] -9.81, y[0] 5, y[0] 0, WhenEvent[y[t] 0, y[t] -> -0.95 y[t]]}, y, {t, 0, 10}]; Plot[y[t] /. %…

Nature:多模态大模型LLMs如何驱动多组学与生命科学研究新范式?

高通量组学技术的快速进步引发了生物数据的爆炸式增长&#xff0c;远超当前对分子层面规律的解析能力。在自然语言处理领域&#xff0c;大语言模型&#xff08;LLMs&#xff09;通过整合海量数据构建统一模型&#xff0c;已显现突破数据困境的潜力。 Nature的这篇文章中&#x…

ubuntu20.04安装教程(图文详解)

Ubuntu 24.04 LTS&#xff0c;代号 Noble Numbat&#xff0c;于 2024 年 4 月 25 日发布&#xff0c;现在可以从 Ubuntu 官方网站及其镜像下载。此版本将在 2029 年 4 月之前接收为期五年的官方安全和维护更新。 关于 Ubuntu 24.04 LTS 的一些关键点&#xff1a; 发布日期&am…

Linux中Shell脚本的常用命令

一、设置主机名称 1、通过修改系统文件来修改主机名称 [rootsakura1 桌面]# vim /etc/hostname sakura /etc/hostname&#xff1a;Linux 系统中存储主机名的配置文件。修改完文件后&#xff0c;在当前的shell中是不生效的&#xff0c;需要关闭当前shell后重新开启才能看到效…

Redisson学习专栏(二):核心功能深入学习(分布式锁,分布式集合,原子操作与计数器,事件与监听)

本文是“Redisson学习专栏”第二篇&#xff0c;聚焦其核心分布式功能实现原理与最佳实践 文章目录 前言&#xff1a;分布式系统核心能力实践一、分布式锁&#xff1a;高并发下的守卫者1.1 可重入锁 (Reentrant Lock)1.2 公平锁 (Fair Lock)1.3 联锁 (MultiLock)1.4 红锁 (RedLo…

学习路之PHP--easyswoole_panel安装使用

学习路之PHP--easyswoole_panel安装使用 一、新建文件夹二、安装三、改配置地址四、访问 IP:Port 自动进入index.html页面 一、新建文件夹 /www/wwwroot/easyswoole_panel 及配置ftp 解压easyswoole_panel源码 https://github.com/easyswoole-panel/easyswoole_panel 二、安…

基于分布式状态机的集装箱智能道口软件架构方法

集装箱码头对进出场道口的通过能力始终是要求最高的&#xff0c;衡量道口的直接指标为道口通行效率&#xff0c;道口通行效率直接体现了集装箱码头的作业效率以及对外服务水平&#xff0c;进而直接影响到码头的综合能力。所以&#xff0c;码头普遍使用智能道口实现24小时无人值…

2014药柜设计问题

1 题目描述 D题 储药柜的设计 储药柜的结构类似于书橱&#xff0c;通常由若干个横向隔板和竖向隔板将储药柜分割成若干个储药槽(如图1所示)。为保证药品分拣的准确率&#xff0c;防止发药错误&#xff0c;一个储药槽内只能摆放同一种药品。药品在储药槽中的排列方式如图2所示。…

c# 获取电脑 分辨率 及 DPI 设置

using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices;/// <summary> /// 这个可以 /// </summary> class Program {static void Main(){//设置DPI感知try{SetProcessDpiAwareness(…

2025年渗透测试面试题总结-匿名[校招]红队攻防工程师(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 匿名[校招]红队攻防工程师 1. 00截断的原理 2. Java回显通用思路及JDK差异 3. Redis利用姿势及环境差异 …

高级数据结构与算法期末考试速成记录

高级数据结构与算法期末考试速成记录 0.分治中的一些知识点 Master公式&#xff08;又称主定理&#xff0c;Master Theorem&#xff09;是一种用于快速求解分治递归算法时间复杂度 的数学工具&#xff0c;适用于递归式形如以下形式的算法&#xff1a; T ( n ) a T ( n b ) …