标签: 个人收藏

  • GitHub热门智能体开源项目,让你秒变AI大神!

    GitHub热门智能体开源项目,让你秒变AI大神!

    AI发烧友们,大家好!最近是不是感觉哪里都在谈“智能体(Agent)”?从自动编程到智能决策,它俨然成了AI界的新晋“顶流”。但面对海量信息,你是否也曾感到无从下手:教程太浅、门槛太高,想亲手实践却找不到合适的项目?别担心!今天,我们就为大家精选了GitHub上10个高星智能体开源项目,涵盖从通用框架到垂直工具,从单机作战到多体协同,并附上保姆级介绍与实战指南。收藏这篇文章,你的智能体学习之路将事半功倍!

    智能体是什么?为什么它值得关注?

    简单来说,智能体是一个“会独立思考、自主行动的AI助手”。你只需给定一个目标,它便能自主规划任务、调用工具、执行步骤,甚至与其他智能体协同完成复杂工作。目前,智能体已广泛应用于科研、办公、游戏开发等领域。而开源项目,正是我们快速入门的“捷径”——无需从零造轮子,基于成熟代码稍作修改,你就能打造属于自己的智能体,高效又实用!

    先唠两句:啥是智能体?为啥要学?

    说白了,智能体就是“能自己干活的AI助手”——给它个目标,它会自己拆解任务、调用工具、调整策略,甚至和其他AI“组队打工”。现在从科研、办公到游戏、机器人,到处都能看到它的身影。而开源项目就是咱普通人的“快车道”:不用从零造轮子,直接改改代码就能搭自己的智能体,香到不行!

    10个必玩智能体开源项目,按头安利!

    1. AutoGPT:智能体界的“开山网红”

    介绍:当年一句“AI自主完成任务”直接引爆GitHub的狠角色!基于GPT模型,能自己规划、搜索、执行任务,堪称“AI版自动化脚本”。

    10个项目横向对比表(选项目不纠结!)

    项目名核心优势适用人群技术门槛部署难度最佳场景
    AutoGPT入门简单,自主性强新手、小白简单任务自动化
    MetaGPT分工清晰,输出质量高开发者、产品软件开发、项目规划
    LangChain万能工具箱,兼容性强全阶段开发者自定义智能体开发
    AutoGen多智能体协作,微软背书进阶开发者中高复杂决策、团队协作
    BabyAGI代码极简,原理清晰学习者、新手理解智能体逻辑
    HuggingGPT多模型联合,成本低开发者、研究者中高中高多模态任务、本地部署
    AgentGPT零代码,网页直接用纯新手、体验党快速测试、简单任务
    GPT-Researcher学术向专业,文献整理学生、研究员论文写作、文献综述
    CrewAI团队管理逻辑强项目管理者多角色协作、复杂任务
    AgentQL自然语言查数据业务、数据岗数据分析、报表生成


    主要功能

    • 自主拆解复杂任务(比如“写一篇AI发展报告”→ 拆成查资料、整理数据、写初稿、润色)
    • 调用搜索引擎、文件工具,甚至控制其他软件
    • 支持自定义目标和规则,灵活性拉满

    应用场景:自动写报告、数据整理、批量处理文件、简单的科研辅助
    部署方法

    1. 克隆仓库:git clone https://github.com/Significant-Gravitas/AutoGPT.git
    2. 安装依赖:pip install -r requirements.txt
    3. 配置OpenAI API密钥和目标,运行python -m autogpt即可
      亮点&小槽点:入门简单,适合新手练手;但偶尔会“钻牛角尖”,需要手动干预调整目标。
      GitHub链接:https://github.com/Significant-Gravitas/AutoGPT

    2. MetaGPT:多智能体“职场协作”神器

    介绍:由国内团队开发的“全流程智能体框架”,核心是模拟“职场团队分工”——比如产品经理、开发、测试各司其职,合力完成项目。
    主要功能

    • 内置“角色分工”系统:支持产品经理(提需求)、架构师(画方案)、开发(写代码)等角色
    • 自动生成文档、代码、测试用例,甚至能输出项目计划
    • 多智能体实时沟通协作,像真人团队一样推进任务
      应用场景:小型软件开发、项目规划、团队协作流程模拟、创业项目原型设计
      部署方法
    1. 克隆仓库:git clone https://github.com/geekan/MetaGPT.git
    2. 安装依赖:pip install -r requirements.txt
    3. 配置API密钥,输入需求(比如“开发一个贪吃蛇游戏”),运行python startup.py "你的需求"
      亮点&小槽点:分工超清晰,输出质量高;但对硬件和API额度要求稍高,新手可能需要先调参。
      GitHub链接:https://github.com/geekan/MetaGPT

    3. LangChain:智能体的“工具箱”(必学!)

    介绍:虽然不算纯智能体,但绝对是构建智能体的“基础设施”!把各种AI模型、工具、数据串起来,让你轻松搭出复杂智能体。
    主要功能

    • 集成主流大模型(GPT、LLaMA、文心一言等)和工具(搜索、数据库、API调用)
    • 提供“记忆模块”:让智能体记住对话历史和任务状态
    • 支持“链(Chain)”和“智能体(Agent)”两种模式,灵活组合功能
      应用场景:自定义智能体开发、聊天机器人、知识库问答、数据分析助手
      部署方法
    1. 直接安装库:pip install langchain
    2. 搭配具体模型(如OpenAI):pip install openai
    3. 参考文档写代码:定义工具→设置智能体→调用执行
      亮点&小槽点:兼容性超强,几乎所有智能体项目都绕不开它;但需要点代码基础,纯小白可能要先补Python。
      GitHub链接:https://github.com/langchain-ai/langchain

    4. AutoGen:微软出品的“智能体协作平台”

    介绍:微软研究院开源的多智能体框架,主打“让多个AI智能体聊天协作”,甚至能和人类实时互动,解决复杂问题。
    主要功能

    • 支持“智能体-智能体”“智能体-人类”混合协作
    • 自动分配任务、调用工具,还能辩论优化方案(比如两个智能体吵架改代码哈哈)
    • 兼容多种大模型,支持本地部署(不用依赖OpenAI)
      应用场景:复杂决策、代码审查、学术研究协作、多人任务分配
      部署方法
    1. 安装:pip install pyautogen
    2. 写配置文件:定义智能体角色、模型、工具权限
    3. 启动对话:python your_script.py 让智能体们开始“打工”
      亮点&小槽点:微软背书,稳定性强;协作逻辑超灵活,但配置稍复杂,建议先看官方示例。
      GitHub链接:https://github.com/microsoft/autogen

    5. BabyAGI:极简任务智能体

    介绍:名字萌但功能硬核!用不到200行代码实现“目标-任务-执行”闭环,适合新手理解智能体核心逻辑。
    主要功能

    • 核心逻辑:设定目标→生成任务→执行任务→更新任务列表
    • 支持用向量数据库存储任务记忆,避免重复劳动
    • 可自定义执行工具(比如加个网页爬虫、计算器)
      应用场景:学习智能体原理、搭建轻量任务助手(如定时查天气、整理邮件)
      部署方法
    1. 克隆仓库:git clone https://github.com/yoheinakajima/babyagi.git
    2. 安装依赖:pip install -r requirements.txt
    3. 配置OpenAI和向量数据库密钥,运行python babyagi.py输入目标
      亮点&小槽点:代码极简,新手能看懂;但功能基础,复杂任务需要自己加工具。
      GitHub链接:https://github.com/yoheinakajima/babyagi.git

    6. HuggingGPT: Hugging Face+GPT的“强强联合”

    介绍:浙大团队开源的“大模型调度官”!让GPT当“指挥官”,调用Hugging Face上的1000+开源模型干活,成本低还强。
    主要功能

    • GPT负责拆解任务、选模型,Hugging Face模型负责具体执行(如图像识别、翻译、代码生成)
    • 支持文本、图像、语音等多模态任务,全能选手
    • 本地部署可选,不用完全依赖API
      应用场景:多模态任务处理(如“给图片写文案+翻译”)、低成本智能体开发
      部署方法
    1. 克隆仓库:git clone https://github.com/microsoft/HuggingGPT.git
    2. 安装依赖:pip install -r requirements.txt
    3. 配置OpenAI和Hugging Face密钥,运行示例脚本
      亮点&小槽点:模型资源丰富,成本可控;但对设备算力有要求,本地跑大模型可能卡。
      GitHub链接:https://github.com/microsoft/HuggingGPT

    7. AgentGPT:浏览器直接玩的“零代码智能体”

    介绍:懒人福音!不用装环境,打开网页就能创建智能体,输入目标直接跑,新手友好度拉满。
    主要功能

    • 网页端可视化操作,填个目标就能启动智能体
    • 实时显示任务拆解和执行过程,像“看AI打工直播”
    • 支持保存历史记录,随时复盘调整
      应用场景:快速测试智能体效果、新手入门体验、简单任务自动化(如写提纲、查信息)
      部署方法
    1. 直接用在线版:https://agentgpt.reworkd.ai/(偶尔需要排队)
    2. 本地部署:克隆仓库后按文档配置Next.js环境,启动即可
      亮点&小槽点:零代码门槛,谁都能玩;但功能有限,复杂任务还是得用本地项目。
      GitHub链接:https://github.com/reworkd/AgentGPT

    8. GPT-Researcher:学术党狂喜的“论文助手”

    介绍:专注“学术研究”的智能体!输入研究主题,自动搜文献、读论文、整理观点,还能生成带引用的报告。
    主要功能

    • 自动搜索学术数据库(Google Scholar、Arxiv等)和权威来源
    • 提取核心观点、对比不同研究,生成结构化报告(带参考文献格式)
    • 支持自定义研究深度和报告风格(如摘要、综述、批判性分析)
      应用场景:写论文查资料、文献综述、快速了解研究领域进展
      部署方法
    1. 克隆仓库:git clone https://github.com/assafelovic/gpt-researcher.git
    2. 安装依赖:pip install -r requirements.txt
    3. 配置API密钥,运行python main.py输入研究主题
      亮点&小槽点:学术向超专业,省超多查文献时间;但依赖英文资源,中文文献支持一般。
      GitHub链接:https://github.com/assafelovic/gpt-researcher

    9. CrewAI:多智能体“团队管理”框架

    介绍:把智能体变成“团队成员”,你当“老板”给任务,它自动分配角色、设目标、追进度,主打一个省心。
    主要功能

    • 可视化定义角色(如“市场分析师”“文案写手”)、技能和目标
    • 智能体间自动沟通协作,遇到问题会“请示”你
    • 支持集成各种工具(API、数据库、爬虫)扩展能力
      应用场景:内容创作团队、市场调研、项目管理、多步骤任务处理
      部署方法
    1. 安装库:pip install crewai
    2. 写代码定义角色、任务和工具
    3. 启动团队:crew.kickoff() 坐等结果
      亮点&小槽点:团队管理逻辑超清晰,适合复杂协作;但文档较少,新手可能需要多试。
      GitHub链接:https://github.com/joaomdmoura/crewai

    10. AgentQL:智能体+数据库的“数据查询神器”

    介绍:让智能体直接“懂数据库”!输入自然语言问题(比如“查下上月销售额前5的产品”),自动生成SQL并查结果。
    主要功能

    • 自然语言转SQL,不用学代码也能查数据库
    • 支持MySQL、PostgreSQL等主流数据库,兼容性强
    • 自动校验SQL正确性,避免查错数据
      应用场景:数据分析、业务报表生成、非技术人员查数据
      部署方法
    1. 安装:pip install agentql
    2. 连接数据库,配置API密钥
    3. 用自然语言提问:agent.query("你的问题")
      亮点&小槽点:数据查询超方便,非技术党狂喜;但复杂查询可能需要手动调整SQL。
      GitHub链接:https://github.com/AgentQL/agentql

  • AI开源项目推荐清单赶紧收藏,开启你的开源AI宝藏库!

    在AI技术日新月异的今天,你是否也曾面临这些困惑:强大的模型总是闭源收费?想动手实践却不知从何开始?工具繁多却难以找到真正高效可靠的选项?本文正是为你量身打造的“寻宝图”。我们深入GitHub,为你精挑细选了10个涵盖不同领域的顶级开源AI项目

    10个必收藏的AI开源项目 | GitHub高星推荐 | 大模型/图像生成/语音识别/目标检测

    从驱动对话的大语言模型(LLaMA),到创造视觉奇迹的图像生成器(Stable Diffusion);从精准的语音识别工具(Whisper),到实时目标检测系统(YOLOv8);乃至帮助你快速构建应用的开发框架(LangChain, Gradio)——每一款都经过社区验证,兼具创新性与实用性。无论你是开发者、研究者、学生还是技术爱好者,这份清单都将为你提供从学习探索到项目实战的强力支持。现在,就让我们一起解锁这些开源神器,将 cutting-edge 的AI能力,转化为你手中的利刃。

    不管你是想练手、做项目,还是直接薅来干活,这篇清单都能让你直呼“捡到宝”!话不多说,上硬菜~

    1. LLaMA:Meta家的“平民大模型”

    详细介绍:这是Meta(脸书母公司)开源的大语言模型家族,从70亿参数到700亿参数应有尽有,主打一个“轻量能跑、开源免费”。普通人下载后,在消费级显卡上就能微调,不用再眼巴巴看着大厂模型流口水~

    核心特点

    • 尺寸灵活:从7B到70B参数,电脑配置不够也能玩小规格;
    • 微调友好:社区有超多现成工具(比如Alpaca-LoRA),新手也能快速调教;
    • 多语言支持:对中文、英文等主流语言适配都不错。

    应用场景:做聊天机器人、个性化问答系统、内容生成工具,甚至训练垂直领域小模型(比如法律、医疗)都合适。

    项目对比:和闭源的GPT-4比,LLaMA胜在“免费开源”,普通人也能下载微调;但论综合能力,GPT-4还是老大哥。和其他开源大模型(比如Mistral)比,LLaMA的生态更成熟,社区工具多到用不完~

    GitHub地址:https://github.com/facebookresearch/llama

    2. Stable Diffusion:AI绘画界的“扛把子”

    详细介绍:提到AI画图,没人能绕开Stable Diffusion!由Stability AI开源,支持文本生成图像、图像修复、风格迁移,关键是完全免费商用(非商用更没问题),普通电脑装个WebUI就能玩到飞起。

    核心特点

    • 插件狂魔:千种风格模型、LoRA微调、ControlNet控图,玩法多到离谱;
    • 本地化部署:不用蹭在线接口,自己电脑就能生成,隐私性拉满;
    • 社区活跃:每天都有新模型、新教程,小白也能快速出“大作”。

    应用场景:设计插画、海报制作、游戏美术辅助、表情包生成,甚至修复老照片、给线稿上色都超好用。

    项目对比:和Midjourney比,Stable Diffusion胜在“免费开源+本地化”,但出图效率和精细度稍弱;和DALL-E比,它的可控性更强,插件生态甩对手十条街~

    GitHub地址:https://github.com/Stability-AI/stablediffusion

    3. Whisper:OpenAI的“语音魔术师”

    详细介绍:OpenAI开源的语音识别模型,能把语音转文字、文字转语音,还支持99种语言!关键是准确率超高,连带口音的中文、英文都能轻松识别,简直是会议记录、视频字幕的救星。

    核心特点

    • 多任务全能:语音转文字、文字转语音、翻译(比如日语语音直接转中文文字)全拿下;
    • 小模型也能打:哪怕用base(基础)模型,准确率也甩很多商用工具一条街;
    • 开箱即用:Python几行代码就能调用,不用复杂配置。

    应用场景:会议纪要自动生成、视频字幕批量制作、播客转文字、多语言语音翻译工具开发。

    项目对比:和百度语音API比,Whisper胜在“本地部署+免费”,但实时性稍弱;和Google Speech-to-Text比,它对小语种和口音的兼容性更好~

    GitHub地址:https://github.com/openai/whisper

    4. LangChain:LLM应用的“胶水框架”

    详细介绍:想把大模型和数据库、API、知识库结合起来?LangChain就是干这个的!它像“乐高积木”一样,把各种AI组件拼起来,让你轻松开发聊天机器人、问答系统、智能助手,不用从零写代码。

    核心特点

    • 组件丰富:支持连接各种大模型(GPT、LLaMA、Claude)、数据库(MySQL、MongoDB)、搜索引擎;
    • 流程可控:能设计AI的思考步骤(比如“先查资料再回答”),避免大模型“瞎编”;
    • 入门简单:文档超详细,跟着教程走,半小时就能搭个简单的问答工具。

    应用场景:开发企业知识库问答机器人、带记忆功能的聊天助手、基于私有数据的AI分析工具。

    项目对比:和同类框架LlamaIndex比,LangChain更侧重“流程编排”,适合复杂应用;LlamaIndex则强在“数据处理”,新手入门可能更简单~

    GitHub地址:https://github.com/langchain-ai/langchain

    5. YOLOv8:目标检测界的“闪电侠”

    详细介绍:YOLO系列的最新版,主打“又快又准”的目标检测。能瞬间识别图片/视频里的人、车、动物、物体,在普通显卡上就能实时处理视频流,工业级场景都在用它。

    核心特点

    • 速度狂魔:每秒能处理几十帧视频,监控摄像头实时分析毫无压力;
    • 轻量化:小模型能在手机、嵌入式设备上跑,大模型精度堪比专业工具;
    • 开箱即用:预训练模型直接丢图就能识别,微调自己的数据也超简单。

    应用场景:智能监控(比如识别异常行为)、自动驾驶辅助(识别行人车辆)、工业质检(检测产品缺陷)、手机拍照识物APP。

    项目对比:和Faster R-CNN比,YOLOv8速度快10倍以上,精度稍低但够用;和SSD比,它的小目标识别能力更强,适合复杂场景~

    GitHub地址:https://github.com/ultralytics/ultralytics

    6. AutoGPT:AI界的“自律打工人”

    详细介绍:让AI自己“思考、规划、执行”的工具!你只需要给它一个目标(比如“写一篇关于AI开源项目的推文”),它会自动查资料、生成大纲、写内容,甚至能调用其他工具,全程不用你插手。

    核心特点

    • 自主决策:不用一步步指挥,AI自己拆解任务、调整策略;
    • 工具集成:能联网查信息、用搜索引擎、调用API,像个真人助理;
    • 开源免费:虽然还在完善中,但基础功能已经能用,适合尝鲜。

    应用场景:自动写报告、市场调研分析、内容创作辅助、复杂问题拆解(比如“规划一场AI技术分享会”)。

    项目对比:和ChatGPT的“单次对话”比,AutoGPT胜在“多步骤自主执行”,但容易“走偏”;和同类工具BabyAGI比,它的界面更友好,新手更容易上手~

    GitHub地址:https://github.com/Significant-Gravitas/AutoGPT

    7. Diffusers:AI生成的“工具箱”

    详细介绍:Hugging Face开源的生成模型库,里面不仅有Stable Diffusion的核心代码,还有各种图像生成、音频生成、视频生成模型。相当于给开发者搭了个“AI生成工厂”,想调参、改模型?用它就对了。

    核心特点

    • 模型丰富:除了图像生成,还有文生视频(如Video Diffusion)、图像修复等模型;
    • 代码简洁:几行代码就能调用复杂模型,调参改配置超方便;
    • 和Hugging Face生态无缝衔接:能直接用Hub上的模型,不用自己下载。

    应用场景:开发自定义AI绘画工具、研究生成模型原理、二次开发生成模型(比如加新功能)。

    项目对比:和Stable Diffusion的WebUI比,Diffusers更适合“开发者”做二次开发;WebUI则适合“普通用户”直接用~

    GitHub地址:https://github.com/huggingface/diffusers

    8. FastChat:大模型的“聊天服务员”

    详细介绍:想给你的LLaMA、Mistral等开源大模型加个聊天界面?FastChat一键搞定!它支持多模型部署、对话历史管理、API调用,还能搭个网页版聊天框,小白也能快速拥有自己的“ChatGPT”。

    核心特点

    • 多模型兼容:主流开源大模型都能装,切换模型像换手机壁纸一样简单;
    • 部署方便:一条命令启动服务,网页端、API端同时可用;
    • 支持多用户:能当服务器让多人同时用,适合小团队共享。

    应用场景:搭建私有聊天机器人、测试开源大模型效果、给模型加个可视化界面方便演示。

    项目对比:和同类工具vLLM比,FastChat更侧重“聊天交互”,界面更友好;vLLM则强在“高并发部署”,适合大规模使用~

    GitHub地址:https://github.com/lm-sys/FastChat

    9. MONAI:医疗AI的“专业助手”

    详细介绍:专门为医疗影像AI开发的框架,基于PyTorch,集成了各种医学图像预处理、分割、分类工具。医生和开发者用它能快速开发肿瘤检测、器官分割等模型,不用再从零处理DICOM这类特殊格式。

    核心特点

    • 医疗专用:支持DICOM格式、3D影像处理(CT/MRI常用),贴合医疗场景;
    • 模型丰富:内置肿瘤分割、病灶检测等预训练模型,开箱即用;
    • 合规友好:遵循医疗数据隐私规范,适合医院、科研机构使用。

    应用场景:医学影像辅助诊断(比如CT肺结节检测)、病灶分割、医疗图像分析研究。

    项目对比:和普通CV框架(如PyTorch Lightning)比,MONAI胜在“医疗专用工具多”,不用自己写医学图像预处理代码~

    GitHub地址:https://github.com/Project-MONAI/MONAI

    10. Gradio:AI模型的“快速装裱师”

    详细介绍:开发者的“界面救星”!不用学前端,几行Python代码就能给你的AI模型(不管是图像生成、语音识别还是分类模型)加个网页交互界面,支持上传图片、输入文字、实时显示结果,演示、测试超方便。

    核心特点

    • 代码极简:哪怕只会写print,也能搭出能用的界面;
    • 实时更新:改代码不用重启服务,刷新网页就能看效果;
    • 支持多类型输入输出:文字、图片、音频、视频都能搞定。

    应用场景:快速演示AI模型效果、给客户/老板展示项目、收集用户反馈、教学中的模型可视化。

    项目对比:和Streamlit比,Gradio更侧重“快速交互”,界面组件更丰富;Streamlit则强在“数据可视化”,适合展示分析结果~

    GitHub地址:https://github.com/gradio-app/gradio


    以上10个AI开源项目,从大模型、绘画、语音到开发工具,基本覆盖了当下最火的AI应用场景。

  • WEBP/PNG/HEIC批量转JPG:李哥的一键式图片格式转换神器

    WEBP/PNG/HEIC批量转JPG:李哥的一键式图片格式转换神器

    兄弟们,是不是经常遇到这些头疼事?

    • 从网站扒下来的图片全是 WEBP​ 格式,编辑软件打不开?
    • PNG​ 图片虽然清晰,但体积太大,上传发布总受限制?
    • 用苹果设备拍的照片是 HEIC​ 格式,在Windows电脑上就成了“天书”?

    别慌!李哥出手,必属精品!今天给大家带来的这款 「批量图片格式转换JPG工具」,就是专门治这些“格式不服”的!它就像你图片库里的“格式统一大师”,管你什么WEBP、PNG还是HEIC,统统给咱变成最通用、最省心的 JPG​ 格式!

    真正的“傻瓜式”操作:把脚本和图片放一个文件夹,双击运行,剩下的交给程序。自动安装环境、自动转换、自动整理文件,你只管喝杯茶等着收JPG就行!特别加入了 HEIC 格式支持,再也不用为苹果照片在电脑上打不开而发愁了。转换后的JPG、原始文件、转换失败的图片,会自动分门别类存到 convert/source/failed/三个文件夹里,井井有条,绝不乱套。万一有同名文件?不存在的!程序会自动给你加上序号,保证一个文件都不会被覆盖。

    下载脚本 -> 双击运行 -> 收获一文件夹整齐的JPG图片!

    李哥已经把代码和详细的使用说明都准备好了,就等你来取。赶紧下载试试,从此告别图片格式转换的烦恼!做人呢,最重要的就是开心!用李哥的工具,让你的图片处理也开心起来!

    核心解读:

    作用:自动检查并安装必要的Python库(Pillow和pillow-heif)启用HEIC文件格式支持(苹果设备照片格式)

    创建虚拟环境并安装python库

    # 退出当前环境
    deactivate
    
    # 删除损坏的虚拟环境
    cd ~/Documents/env
    rm -rf myenv
    
    # 重新创建虚拟环境
    python3 -m venv myenv
    
    # 激活新环境
    source myenv/bin/activate
    
    # 检查pip是否正常
    pip --version
    
    # 安装Pillow
    pip install Pillow
    
    # 检查安装是否成功
    python3 -c "from PIL import Image; print('Pillow安装成功!')"

    创建三个目录:

    • convert/– 存放转换后的JPG文件
    • source/– 存放原始图片文件
    • failed/– 存放转换失败的文件

    智能移动文件到指定目录,自动处理重名文件(添加序号)输出格式JPG (.jpg) – 通用的有损压缩图片格式

    文件整理逻辑

    转换前目录结构:
    当前目录/
    ├── image1.webp
    ├── image2.png
    ├── image3.heic
    └── convert_images.py
    
    转换后目录结构:
    当前目录/
    ├── convert/           # 转换后的JPG文件
    │   ├── image1.jpg
    │   ├── image2.jpg
    │   └── image3.jpg
    ├── source/            # 原始文件(已移动)
    │   ├── image1.webp
    │   ├── image2.png
    │   └── image3.heic
    ├── failed/            # 转换失败的文件
    └── convert_images.py

    实现代码:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import os
    import glob
    import shutil
    import sys
    import subprocess
    
    def check_and_install_dependencies():
        """检查并安装必要的依赖"""
        dependencies = ['Pillow', 'pillow-heif']
        missing_deps = []
        
        # 检查Pillow
        try:
            from PIL import Image
            print("✓ Pillow 已安装")
        except ImportError:
            missing_deps.append('Pillow')
        
        # 检查pillow-heif
        try:
            import pillow_heif
            print("✓ pillow-heif 已安装")
        except ImportError:
            missing_deps.append('pillow-heif')
        
        # 安装缺失的依赖
        if missing_deps:
            print(f"❌ 缺少依赖: {', '.join(missing_deps)}")
            print("正在安装依赖...")
            
            for dep in missing_deps:
                try:
                    if dep == 'Pillow':
                        subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'Pillow'])
                    elif dep == 'pillow-heif':
                        subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'pillow-heif'])
                    print(f"✓ {dep} 安装成功")
                except subprocess.CalledProcessError:
                    print(f"❌ {dep} 安装失败,尝试使用镜像源...")
                    try:
                        subprocess.check_call([sys.executable, '-m', 'pip', 'install', dep, 
                                             '-i', 'https://pypi.tuna.tsinghua.edu.cn/simple/'])
                        print(f"✓ {dep} 安装成功(使用镜像源)")
                    except:
                        print(f"❌ {dep} 安装失败,请手动安装: pip install {dep}")
                        return False
            # 重新检查
            try:
                from PIL import Image
                import pillow_heif
                print("✓ 所有依赖安装成功")
                return True
            except ImportError as e:
                print(f"❌ 依赖安装后仍然失败: {e}")
                return False
        return True
    
    def setup_heic_support():
        """设置HEIC支持"""
        try:
            import pillow_heif
            pillow_heif.register_heif_opener()
            print("✓ HEIC格式支持已启用")
            return True
        except Exception as e:
            print(f"❌ HEIC支持初始化失败: {e}")
            return False
    
    def create_directories():
        """创建必要的目录"""
        directories = ['convert', 'source', 'failed']
        for directory in directories:
            if not os.path.exists(directory):
                os.makedirs(directory)
                print(f"✓ 创建目录: {directory}/")
    
    def move_file_to_directory(original_file, directory):
        """移动文件到指定目录"""
        try:
            filename = os.path.basename(original_file)
            destination = os.path.join(directory, filename)
            
            # 如果目标文件已存在,添加序号
            counter = 1
            base_name, ext = os.path.splitext(filename)
            while os.path.exists(destination):
                new_filename = f"{base_name}_{counter}{ext}"
                destination = os.path.join(directory, new_filename)
                counter += 1
            
            shutil.move(original_file, destination)
            return True
        except Exception as e:
            print(f"⚠ 移动文件失败 {original_file}: {e}")
            return False
    
    def convert_image_file(input_file, temp_jpg_file, is_heic=False):
        """转换图片文件"""
        try:
            from PIL import Image
            
            if is_heic:
                # HEIC文件特殊处理
                try:
                    import pillow_heif
                    heif_file = pillow_heif.open_heif(input_file)
                    image = Image.frombytes(
                        heif_file.mode, 
                        heif_file.size, 
                        heif_file.data,
                        "raw",
                        heif_file.mode,
                        heif_file.stride,
                    )
                except:
                    # 如果直接读取失败,尝试通过PIL打开
                    pillow_heif.register_heif_opener()
                    image = Image.open(input_file)
            else:
                # 其他格式文件
                image = Image.open(input_file)
            
            # 处理图片模式
            if image.mode in ('RGBA', 'LA', 'P'):
                background = Image.new('RGB', image.size, (255, 255, 255))
                if image.mode == 'P':
                    image = image.convert('RGBA')
                if image.mode == 'RGBA':
                    background.paste(image, mask=image.split()[-1])
                else:
                    background.paste(image)
                image = background
            elif image.mode != 'RGB':
                image = image.convert('RGB')
            
            # 保存为JPG
            image.save(temp_jpg_file, "JPEG", quality=85, optimize=True)
            return True, "成功"
            
        except Exception as e:
            return False, str(e)
    
    def batch_convert_images():
        """批量转换图片"""
        print("=== 图片格式批量转换工具 ===")
        
        # 检查并安装依赖
        if not check_and_install_dependencies():
            print("❌ 依赖安装失败,无法继续")
            return
        
        # 设置HEIC支持
        heic_supported = setup_heic_support()
        
        # 创建目录
        create_directories()
        
        # 收集文件
        files_to_convert = []
        for pattern in ['*.webp', '*.WEBP', '*.png', '*.PNG', '*.heic', '*.HEIC']:
            files_to_convert.extend(glob.glob(pattern))
        
        files_to_convert = sorted(list(set(files_to_convert)))
        files_to_convert = [f for f in files_to_convert if not any(f.startswith(d) for d in ['convert/', 'source/', 'failed/'])]
        
        if not files_to_convert:
            print("❌ 未找到可转换的图片文件")
            return
        
        # 分类统计
        webp_files = [f for f in files_to_convert if f.lower().endswith('.webp')]
        png_files = [f for f in files_to_convert if f.lower().endswith('.png')]
        heic_files = [f for f in files_to_convert if f.lower().endswith('.heic')]
        
        print(f"找到 {len(files_to_convert)} 个文件:")
        print(f"  WEBP: {len(webp_files)} 个, PNG: {len(png_files)} 个, HEIC: {len(heic_files)} 个")
        
        if heic_files and not heic_supported:
            print("⚠ HEIC文件将无法转换")
        
        # 转换统计
        results = {'success': 0, 'failed': 0, 'skipped': 0}
        
        for i, input_file in enumerate(files_to_convert, 1):
            filename_without_ext = os.path.splitext(os.path.basename(input_file))[0]
            temp_jpg_file = filename_without_ext + ".jpg"
            final_jpg_path = os.path.join('convert', temp_jpg_file)
            
            # 跳过已存在
            if os.path.exists(final_jpg_path):
                print(f"{i}/{len(files_to_convert)} ⚡ 跳过已存在: {final_jpg_path}")
                results['skipped'] += 1
                continue
            
            file_size = os.path.getsize(input_file) / 1024
            file_ext = os.path.splitext(input_file)[1].upper()
            is_heic = input_file.lower().endswith('.heic')
            
            print(f"{i}/{len(files_to_convert)} 🔄 转换: {os.path.basename(input_file)} ({file_size:.1f} KB)", end="")
            
            try:
                if is_heic and not heic_supported:
                    success, message = False, "HEIC支持未启用"
                else:
                    success, message = convert_image_file(input_file, temp_jpg_file, is_heic)
                
                if success:
                    # 移动成功文件
                    if os.path.exists(temp_jpg_file):
                        move_file_to_directory(temp_jpg_file, 'convert')
                    move_file_to_directory(input_file, 'source')
                    results['success'] += 1
                    print(" -> ✅ 完成")
                else:
                    # 移动失败文件
                    move_file_to_directory(input_file, 'failed')
                    results['failed'] += 1
                    print(f" -> ❌ 失败: {message}")
                    
            except Exception as e:
                move_file_to_directory(input_file, 'failed')
                results['failed'] += 1
                print(f" -> 💥 异常: {str(e)}")
        
        # 输出结果
        print(f"\n=== 转换完成 ===")
        print(f"✅ 成功: {results['success']}, ❌ 失败: {results['failed']}, ⚡ 跳过: {results['skipped']}")
    
    if __name__ == "__main__":
        batch_convert_images()
        input("\n按Enter键退出...")

  • 立省万元!李哥教你如何使用translate.js实现WP菜单的JavaScript翻译

    立省万元!李哥教你如何使用translate.js实现WP菜单的JavaScript翻译

    你是不是也在为WordPress网站加个多语言菜单而发愁?一想到那些名声在外的翻译插件,脑海里

    是不是立刻浮现出每年上千元的续费账单?

    是不是受够了那个一旦启用就让网站速度变慢的“庞然大物”?

    是不是在面对复杂的设置界面时,感觉像是在操作一架航天飞机,而你只是想骑个自行车出门买个菜?

    兄弟,我懂你。这种感觉,就像是只想拧一颗螺丝,却被迫买下整个五金店。别再忍受了!今天,李哥(LeePoet.cn)就带你彻底摆脱这种“高消费、低体验”的困境。这篇文章,将为你揭开一条“技术平权”之路。

    我们不用求助于任何重型插件,不花一分钱授权费,仅凭几行简洁的JavaScript代码,就能为你的WordPress菜单实现流畅、优雅的多语言切换功能。我们要用的神器,就是轻量级前端翻译库——translate.js

    学完这一招,你不仅能立刻省下未来几年上万元的插件费用,更能收获一个速度更快、完全受你掌控的网站。从此,插件更新、兼容性冲突、账单提醒,这些都与你无关。这不仅是省钱的技巧,更是一种技术的自由。跟着我的步骤,让我们一起对臃肿的翻译插件说“不”,亲手打造属于你自己的极速多语言方案!

    接下来,我们将从第一步“准备translate.js库文件”开始……

    1.先把translate.js上传到服务器,本地调用比https://cdn.staticfile.net/translate.js/3.18.66/translate.js速度更快。

    2.安装插入代码插件,如 “Header and Footer Scripts” 或 “Insert Headers and Footers”。把translate.js的JavaScript代码放到footer或才head里。

    <script src="https://www.你的域名及JS路径.cn/leepoetjs/translate.js"></script> 
    
    <script>
    translate.selectLanguageTag.languages = 'english,chinese_simplified,japanese,spanish,deutsch,french,korean';
    translate.request.listener.delayExecuteTime = 500;
    translate.service.use('client.edge'); //设置机器翻译服务通道
    translate.listener.start(); //开启页面元素动态监控
    translate.selectLanguageTag.show = false;//false隐藏选择框,true打开
    translate.execute();//完成翻译初始化,进行翻译
    </script>

    3.通过函数文件添加需要调用的translate.js,在主题的functions.php文件中添加:

    //调用翻译translate.js
    function add_language_switcher_script() {
        ?>
        <script>
    //添加switchToEnglish()英文函数
        function switchToEnglish() {
            if (typeof translate !== 'undefined' && typeof translate.changeLanguage === 'function') {
                translate.changeLanguage('english');
            }
        }
    //添加switchToChineseSimplified()中文函数
        function switchTochinese_simplified() {
            if (typeof translate !== 'undefined' && typeof translate.changeLanguage === 'function') {
                translate.changeLanguage('chinese_simplified');
            }
        }		
        </script>
        <?php
    }
    add_action('wp_head', 'add_language_switcher_script');

    2.进入WordPress后台 → 外观​ → 菜单,点击创建新菜单或选择现有菜单,在左侧自定义链接部分添加:

    点击添加到菜单,在菜单编辑器中,点击该菜单项展开设置

    • URL:#
    • 链接文字:English或您想要的文字
    • URL字段中替换为:javascript:translate.changeLanguage(‘english’);
    #导航标签字段
    <li href="#" onclick="javascript:switchToEnglish(); return false;">English</li>
    <li href="#" onclick="javascript:switchTochinese_simplified(); return false;">简体中文</li>

    然后保存菜单。*如果需要其它语言,可以继续在主题文件functions.php里继续填加调用。

    然后刷新前台基本搞定。

    相关文章:translate.js:两行代码实现网页全自动多语言内容动态翻译

    现在的WordPress多语言解决方案,尤其是主流插件,确实让人又爱又恨,痛苦主要集中在以下几点:

    沉重的年度费用,如同“数字税”,像WPML、Polylang Premium这类插件,需要每年支付高昂的授权费来获得更新和支持。对于一个长期运营的网站来说,这成了一笔沉重的、持续的固定支出。网站不赚钱时,这笔钱尤其肉疼;网站赚钱了,又会觉得为什么我要一直为这个“基础设施”付钱?感觉就像被“套牢”了。

    “全家桶”式捆绑,资源浪费严重,大型插件功能大而全,但你可能只需要其中最核心的菜单和静态内容翻译功能。它却强行塞给你一整套复杂的翻译管理系统、字符串翻译、媒体翻译等。这导致插件异常臃肿,严重拖慢网站速度,为了一个“点”的需求,背上了整个“面”的负担。

    架构复杂,学习成本高,配置过程繁琐,需要在不同标签页之间来回切换,理解“字符串”、“翻译编辑器”等专业概念。对于只是想给网站加个中英文菜单的博主来说,学习成本太高,一不小心就配错了。

    与主题/插件兼容性噩梦,一旦主题更新或更换,或者安装了新的插件,兼容性问题就可能出现,导致翻译失效或页面错乱。排查问题非常困难,往往需要深度技术知识。

    机器翻译API的隐藏成本,一些方案鼓励你接入Google Translate或DeepL的API来自动翻译。初期感觉方便,但随着内容增长,API调用的费用会悄无声息地累积,成为一个不可预测的成本黑洞。

    总结来说,当下的痛苦是:我们只是想要一个“轻量、快速、便宜、能控制”的翻译方案,尤其是针对菜单和前端静态内容。但市场给出的答案往往是“沉重、昂贵、复杂、受制于人”的庞然大物。

  • translate.js:两行代码实现网页全自动多语言内容动态翻译

    translate.js:两行代码实现网页全自动多语言内容动态翻译

    在全球化日益深入的今天,为网站提供多语言支持已成为提升用户体验和扩大受众范围的关键。传统多语言解决方案通常需要复杂的配置、大量的翻译文件以及繁琐的代码修改,而translate.js的出现彻底改变了这一现状。

    寻找简单高效的网站翻译方案?translate.js 仅用两行JavaScript代码,即可为你的网站添加全自动多语言翻译功能,支持动态内容翻译,是WordPress插件和Google API的轻量级替代方案。

    什么是translate.js?

    translate.js是一款创新的开源JavaScript库,专注于网页多语言切换。它采用MIT开源协议,完全免费商用,只需两行核心代码即可实现HTML页面的全自动翻译,无需修改页面结构,无需语言配置文件,无需API Key,同时对SEO友好。

    核心优势

    1. 极简接入:无需复杂配置,快速集成
    2. 全自动翻译:智能识别页面内容并自动翻译
    3. 无侵入设计:对现有代码几乎零影响
    4. SEO友好:保持搜索引擎优化效果
    5. 开源免费:MIT协议,商业应用无忧

    translate.js是一个免费、开源的翻译工具库,支持多种语言之间的互译,如中英文、法文、日语、韩语、德语等。它避免了API调用次数的限制和费用问题,且使用方法简单,方便快捷。

    普通网页快速测试示例

    1. 随便打开一个网页
    2. F12(审查元素)
    3. 在控制台页签下粘贴入以下代码: 
      var head= document.getElementsByTagName('head')[0];
     var script= document.createElement('script');
     script.type= 'text/javascript';
     script.src= 'https://res.zvo.cn/translate/inspector_v2.js';
     head.appendChild(script);

    普通网页快速接入示例

    <script src="https://cdn.staticfile.net/translate.js/3.18.66/translate.js"></script>
    <script>
    translate.service.use('client.edge'); //设置机器翻译服务通道,相关说明参考 http://translate.zvo.cn/545867.html
    translate.listener.start(); //开启页面元素动态监控,js改变的内容也会被翻译,参考文档: http://translate.zvo.cn/4067.html
    translate.execute();//完成翻译初始化,进行翻译
    </script>

    在网页最末尾, </html> 之前,加入以下代码,一般在页面的最底部,就会出现选择语言的 select 切换标签。添加上述代码后,页面底部将自动出现语言选择下拉框,用户可以轻松切换界面语言。    详细解说

    工作原理

    translate.js的工作原理十分巧妙:

    1. 内容扫描:对页面所有DOM元素进行扫描,识别可翻译文本
    2. 文本抽离:提取需要翻译的文本内容
    3. API翻译:通过配置的翻译服务通道进行翻译
    4. 结果渲染:将翻译结果重新赋予对应元素

    整个过程自动完成,无需人工干预。

    高级功能与微调

    虽然基础使用极其简单,但translate.js提供了丰富的微调指令,满足各种复杂需求:

    语言控制

    translate.changeLanguage('english'); // 主动切换语言
    translate.language.setLocal('chinese_simplified'); // 设置本地语种
    translate.language.getCurrent(); // 获取当前显示语种

    内容过滤

    translate.ignore.text.push('你好'); // 忽略特定文本
    translate.ignore.id.push('test'); // 忽略特定ID元素
    translate.ignore.class.push('test'); // 忽略特定class元素

    高级配置

    translate.setAutoDiscriminateLocalLanguage(); // 自动识别用户语种
    translate.language.setUrlParamControl(); // URL参数控制显示语种
    translate.selectionTranslate.start(); // 启用划词翻译

    除了基础翻译功能,translate.js还提供了一系列高级特性,例如自动识别并翻译图片中的文字内容,监控AJAX请求,实时翻译动态加载的内容,自定义翻译术语,确保专业词汇准确一致,且监控翻译性能,优化用户体验。

    最佳实践建议

    1. 自托管JS文件:将translate.js下载到自己的服务器,确保稳定加载
    2. 合理配置缓存:根据业务特点设置合适的缓存策略
    3. 选择性翻译:对不需要翻译的内容进行排除,提升性能
    4. 渐进式实施:先在小范围测试,再全面推广

    translate.js重新定义了网页多语言实现的范式,将复杂的技术难题简化为几行优雅的代码。无论是个人项目还是企业级应用,它都能提供高效、稳定、易用的多语言解决方案。其开源免费的特性更是降低了技术门槛,让更多开发者能够轻松实现产品的国际化。随着人工智能技术的不断发展,translate.js也在持续进化,集成更先进的翻译引擎,提供更精准的翻译结果。未来,它将继续致力于降低多语言实现的复杂度,助力更多产品走向全球市场。


    DEMO:

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>多语言网站示例</title>
        <!-- 引入本地的 translate.js -->
        <script src="./translate.js"></script>
        <style>
            body {
                font-family: Arial, sans-serif;
                max-width: 800px;
                margin: 0 auto;
                padding: 20px;
            }
            .language-switcher {
                margin: 20px 0;
                padding: 10px;
                background: #f5f5f5;
                border-radius: 5px;
            }
            .language-btn {
                padding: 8px 16px;
                margin: 0 5px;
                border: 1px solid #ddd;
                background: white;
                cursor: pointer;
                border-radius: 3px;
            }
            .language-btn.active {
                background: #007bff;
                color: white;
                border-color: #007bff;
            }
            .content {
                margin-top: 20px;
                padding: 20px;
                border: 1px solid #eee;
                border-radius: 5px;
            }
        </style>
    </head>
    <body>
        <div class="language-switcher">
            <h3>选择语言 / Select Language:</h3>
            <button class="language-btn active" onclick="switchLanguage('chinese_simplified')">中文</button>
            <button class="language-btn" onclick="switchLanguage('english')">English</button>
            <button class="language-btn" onclick="switchLanguage('japanese')">日本語</button>
            <button class="language-btn" onclick="switchLanguage('korean')">한국어</button>
            <button class="language-btn" onclick="switchLanguage('french')">Français</button>
            <button class="language-btn" onclick="switchLanguage('german')">Deutsch</button>
        </div>
    
        <div class="content" id="translatable-content">
            <h1>欢迎来到我的多语言网站</h1>
            <p>这是一个演示如何使用 translate.js 实现多语言切换的示例。</p>
            
            <h2>功能特点</h2>
            <ul>
                <li>支持多种语言实时切换</li>
                <li>无需刷新页面</li>
                <li>自动翻译页面内容</li>
                <li>简单易用的API</li>
            </ul>
            
            <h2>联系我们</h2>
            <p>电子邮件:contact@example.com</p>
            <p>电话:+86 123-4567-8900</p>
            
            <div class="no-translate">
                <p><em>这个区域的内容不会被翻译(class="no-translate")</em></p>
            </div>
        </div>
    
        <script>
            // 页面加载完成后初始化翻译功能
            document.addEventListener('DOMContentLoaded', function() {
                // 初始化翻译配置
                translate.service.use('client.edge'); // 使用浏览器内置翻译(免费)
                // 或者使用自有翻译服务:translate.service.use('translate.service');
                
                // 设置页面默认语言
                translate.language.setLocal('chinese_simplified');
                
                // 设置忽略翻译的元素(可选)
                translate.ignore.class.push('no-translate');
                
                // 启动监听器,自动检测页面变化
                translate.listener.start();
                
                // 根据浏览器语言自动切换(可选)
                autoDetectLanguage();
                
                console.log('translate.js 初始化完成!');
            });
    
            // 语言切换函数
            function switchLanguage(lang) {
                // 更新按钮状态
                document.querySelectorAll('.language-btn').forEach(btn => {
                    btn.classList.remove('active');
                });
                event.target.classList.add('active');
                
                // 切换语言并执行翻译
                translate.changeLanguage(lang);
                translate.execute();
                
                // 保存语言偏好到本地存储
                localStorage.setItem('preferred-language', lang);
                
                console.log('切换到语言:', lang);
            }
    
            // 自动检测浏览器语言
            function autoDetectLanguage() {
                const savedLang = localStorage.getItem('preferred-language');
                if (savedLang) {
                    // 使用用户之前选择的语言
                    setActiveButton(savedLang);
                    return;
                }
                
                // 检测浏览器语言
                const browserLang = navigator.language.toLowerCase();
                let detectedLang = 'chinese_simplified'; // 默认中文
                
                if (browserLang.includes('en')) {
                    detectedLang = 'english';
                } else if (browserLang.includes('ja')) {
                    detectedLang = 'japanese';
                } else if (browserLang.includes('ko')) {
                    detectedLang = 'korean';
                } else if (browserLang.includes('fr')) {
                    detectedLang = 'french';
                } else if (browserLang.includes('de')) {
                    detectedLang = 'german';
                }
                
                // 如果检测到的语言不是中文,自动切换
                if (detectedLang !== 'chinese_simplified') {
                    setTimeout(() => {
                        switchLanguage(detectedLang);
                    }, 1000);
                }
            }
    
            // 设置活动按钮样式
            function setActiveButton(lang) {
                document.querySelectorAll('.language-btn').forEach(btn => {
                    btn.classList.remove('active');
                    if (btn.textContent.toLowerCase().includes(getLanguageText(lang).toLowerCase())) {
                        btn.classList.add('active');
                    }
                });
            }
    
            // 获取语言显示文本
            function getLanguageText(lang) {
                const langMap = {
                    'chinese_simplified': '中文',
                    'english': 'English',
                    'japanese': '日本語',
                    'korean': '한국어',
                    'french': 'Français',
                    'german': 'Deutsch'
                };
                return langMap[lang] || lang;
            }
    
            // 手动触发翻译函数(如果需要)
            function manualTranslate() {
                translate.execute();
            }
    
            // 重置翻译(恢复原始语言)
            function resetTranslation() {
                translate.reset();
            }
        </script>
    </body>
    </html>

    [members_only]

    <div style="text-align: center;">
        <span id="timeDate"></span><span id="times"></span> 
    </div>
    
    <script language="javascript"> 
    var now = new Date();
    function createtime(){
        var grt= new Date("01/01/2024 00:00:00");
        now.setTime(now.getTime()+250);
        days = (now - grt ) / 1000 / 60 / 60 / 24;
        dnum = Math.floor(days);
        hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum);
        hnum = Math.floor(hours);
        if(String(hnum).length ==1 ){hnum = "0" + hnum;}
        minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);
        mnum = Math.floor(minutes);
        if(String(mnum).length ==1 ){mnum = "0" + mnum;}
        seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
        snum = Math.round(seconds);
        if(String(snum).length ==1 ){snum = "0" + snum;}
        document.getElementById("timeDate").innerHTML = "本网站己运行"+dnum+"天";
        document.getElementById("times").innerHTML = hnum + "小时" + mnum + "分" + snum + "秒";
    }
    setInterval("createtime()",250); 
    </script>
    
    <div style="text-align: center;"><strong>
    	切换语言:</strong>
    	<a class="ignore" href="javascript:translate.changeLanguage('english');">English</a> | 
    	<a class="ignore" href="javascript:translate.changeLanguage('chinese_simplified');">简体中文</a>
    </div>
    <script src="http://naver.19901117.xyz/translate.js/translate.js"></script>
    
    <script>
    translate.selectLanguageTag.languages = 'english,chinese_simplified,japanese,spanish,deutsch,french,korean';
    translate.request.listener.delayExecuteTime = 500;
    translate.service.use('client.edge'); //设置机器翻译服务通道
    translate.listener.start(); //开启页面元素动态监控
    translate.selectLanguageTag.show = false;//false隐藏选择框,true打开
    translate.execute();//完成翻译初始化,进行翻译
    </script>

    支持的语种表 – translate.service通道

    corsican:科西嘉语
    guarani:瓜拉尼语
    kinyarwanda:卢旺达语
    hausa:豪萨语
    norwegian:挪威语
    dutch:荷兰语
    yoruba:约鲁巴语
    english:英语
    gongen:贡根语
    latin:拉丁语
    nepali:尼泊尔语
    french:法语
    czech:捷克语
    hawaiian:夏威夷语
    georgian:格鲁吉亚语
    russian:俄语
    chinese_simplified:简体中文
    persian:波斯语
    bhojpuri:博杰普尔语
    hindi:印地语
    belarusian:白俄罗斯语
    swahili:斯瓦希里语
    icelandic:冰岛语
    yiddish:意第绪语
    twi:契维语
    irish:爱尔兰语
    gujarati:古吉拉特语
    khmer:高棉语
    slovak:斯洛伐克语
    hebrew:希伯来语
    kannada:卡纳达语
    hungarian:匈牙利语
    tamil:泰米尔语
    arabic:阿拉伯语
    bengali:孟加拉语
    azerbaijani:阿塞拜疆语
    samoan:萨摩亚语
    afrikaans:南非荷兰语
    indonesian:印尼语
    danish:丹麦语
    shona:修纳语
    bambara:班巴拉语
    lithuanian:立陶宛语
    vietnamese:越南语
    maltese:马耳他语
    turkmen:土库曼语
    assamese:阿萨姆语
    catalan:加泰罗尼亚语
    singapore:僧伽罗语
    cebuano:宿务语
    scottish_gaelic:苏格兰盖尔语
    sanskrit:梵语
    polish:波兰语
    galician:加利西亚语
    latvian:拉脱维亚语
    ukrainian:乌克兰语
    tatar:鞑靼语
    welsh:威尔士语
    japanese:日语
    filipino:菲律宾语
    aymara:艾马拉语
    lao:老挝语
    telugu:泰卢固语
    romanian:罗马尼亚语
    haitian_creole:海地克里奥尔语
    dogrid:多格来语
    swedish:瑞典语
    maithili:迈蒂利语
    thai:泰语
    armenian:亚美尼亚语
    burmese:缅甸语
    pashto:普什图语
    hmong:苗语
    dhivehi:迪维希语
    chinese_traditional:繁體中文
    luxembourgish:卢森堡语
    sindhi:信德语
    kurdish:库尔德语(库尔曼吉语)
    turkish:土耳其语
    macedonian:马其顿语
    bulgarian:保加利亚语
    malay:马来语
    luganda:卢干达语
    marathi:马拉地语
    estonian:爱沙尼亚语
    malayalam:马拉雅拉姆语
    deutsch:德语
    slovene:斯洛文尼亚语
    urdu:乌尔都语
    portuguese:葡萄牙语
    igbo:伊博语
    kurdish_sorani:库尔德语(索拉尼)
    oromo:奥罗莫语
    greek:希腊语
    spanish:西班牙语
    frisian:弗里西语
    somali:索马里语
    amharic:阿姆哈拉语
    nyanja:齐切瓦语
    punjabi:旁遮普语
    basque:巴斯克语
    italian:意大利语
    albanian:阿尔巴尼亚语
    korean:韩语
    tajik:塔吉克语
    finnish:芬兰语
    kyrgyz:吉尔吉斯语
    ewe:埃维语
    croatian:克罗地亚语
    creole:克里奥尔语
    quechua:克丘亚语
    bosnian:波斯尼亚语
    maori:毛利语

    [/members_only]

    相关文章:立省万元!李哥教你如何使用translate.js实现WP菜单的JavaScript翻译

  • 数字囤积症救星!LeePoet教你用AI智能整理海量图片

    数字囤积症救星!LeePoet教你用AI智能整理海量图片

    图片太多了怎么办?LeePoet一站式智能整理方案

    💡 LeePoet技术理念:复杂的科技,应该以最简单的方式服务每个普通人。

    你是否也曾在数千张照片中翻找一张重要合影?是否因为图片太多而放弃整理?本文是数字时代每个人的“图片救星”。无论你是拥有上万张照片的摄影爱好者,还是被工作图片淹没的职场人,LeePoet将用AI技术为你提供从简单到专业的全系列解决方案。

    从人物识别到内容分类,Python自动化搞定图片管理,每个人手机里几千张照片的普遍现象,手动整理的痛苦:耗时、低效、容易遗漏,LeePoet的解决方案理念:技术让生活更简单。”隐私保护+内容管理,一键分类敏感图片”,多层级风险评估。

    包含开箱即用的Python脚本、详细配置教程和常见问题解决方案。LeePoet用实际案例证明,技术不应该高高在上,而要真正服务于生活。

    UBUNTU创建虚拟环境操作

    1.创建虚拟环境
    # 进入你的项目文件夹
    cd /path/to/your/project
    
    # 创建虚拟环境(会在当前文件夹创建 venv 目录)
    python3 -m venv myenv
    
    2.激活虚拟环境
    source myenv/bin/activate
    
    3.安装依赖
    python -m pip install opencv-python
    

    如果要使用增强版本,还需要安装:

    python -m pip install torch ultralytics
    
    4.基本完成。

    初级检测:

    创建一个名为 extract_people_images.py的文件完整代码:

    import os
    import shutil
    import cv2
    from pathlib import Path
    
    def detect_people_in_image(image_path, face_cascade=None):
        """
        检测图片中是否包含人物
        """
        if face_cascade is None:
            face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
        
        try:
            img = cv2.imread(image_path)
            if img is None:
                return False
            
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            
            faces = face_cascade.detectMultiScale(
                gray,
                scaleFactor=1.1,
                minNeighbors=5,
                minSize=(30, 30)
            )
            
            return len(faces) > 0
            
        except Exception as e:
            print(f"处理图片 {image_path} 时出错: {e}")
            return False
    
    def extract_images_with_people(source_dir, target_dir):
        """
        从源文件夹提取带人物的图片到目标文件夹
        """
        supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp']
        
        # 创建目标文件夹
        Path(target_dir).mkdir(parents=True, exist_ok=True)
        
        # 加载人脸检测器
        face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
        
        # 统计信息
        total_images = 0
        images_with_people = 0
        
        print("开始扫描图片...")
        
        for filename in os.listdir(source_dir):
            file_path = os.path.join(source_dir, filename)
            
            # 检查文件格式
            if os.path.isfile(file_path) and any(filename.lower().endswith(fmt) for fmt in supported_formats):
                total_images += 1
                print(f"处理第 {total_images} 张图片: {filename}")
                
                # 检测是否包含人物
                if detect_people_in_image(file_path, face_cascade):
                    images_with_people += 1
                    
                    # 构建目标路径
                    target_path = os.path.join(target_dir, filename)
                    
                    # 处理重名文件
                    counter = 1
                    while os.path.exists(target_path):
                        name, ext = os.path.splitext(filename)
                        target_path = os.path.join(target_dir, f"{name}_{counter}{ext}")
                        counter += 1
                    
                    # 复制文件
                    shutil.copy2(file_path, target_path)
                    print(f"✓ 检测到人物: {filename}")
                else:
                    print(f"✗ 未检测到人物: {filename}")
        
        print("\n" + "="*50)
        print("处理完成!")
        print(f"总共处理图片: {total_images}张")
        print(f"检测到包含人物的图片: {images_with_people}张")
        print(f"图片已保存到: {target_dir}")
    
    def main():
        # 设置路径
        current_dir = os.getcwd()
        target_dir = os.path.join(current_dir, "images_with_people")
        
        print(f"当前文件夹: {current_dir}")
        print(f"目标文件夹: {target_dir}")
        print("-" * 50)
        
        # 执行提取
        extract_images_with_people(current_dir, target_dir)
    
    if __name__ == "__main__":
        main()
    
    5. 运行脚本
    python extract_people_images.py
    
    6. 退出虚拟环境

    完成后,可以退出虚拟环境:

    其它说明:安装所需库(上面装完了可以不看这)
    # 升级pip(可选)
    python -m pip install --upgrade pip
    
    # 安装OpenCV(基础版本)
    python -m pip install opencv-python
    
    # 或者安装增强版本所需的库
    python -m pip install opencv-python torch ultralytics
    
    创建 requirements.txt 文件(可选)

    你可以创建一个依赖文件,方便以后重新安装:

    # 生成requirements.txt
    python -m pip freeze requirements.txt
    

    requirements.txt 内容示例:

    opencv-python==4.8.1.78
    numpy==1.24.3
    

    以后重新安装依赖:

    python -m pip install -r requirements.txt
    
    完整的项目结构建议
    your_project/
    ├── venv/                    # 虚拟环境(不要提交到版本控制)
    ├── extract_people_images.py # 主程序
    ├── requirements.txt         # 依赖列表
    └── images_with_people/      # 输出文件夹(程序自动创建)
    

    库装不上的其它操作

    python -m pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple –verbose

    中级检测:

    正常激活虚拟环境

    cd myenv  #即虚拟环境目录
    source myenv/bin/activate   # 进入虚拟环境(如果还没激活)
    pip install opencv-python    # 确保已安装所需库
    

    安装依赖的完整步骤

    # 1. 激活虚拟环境
    source myenv/bin/activate
    
    # 2. 安装依赖(如果网络慢可以使用清华镜像)
    python -m pip install torch torchvision ultralytics opencv-python
    
    # 或者使用国内镜像加速安装
    python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple torch torchvision ultralytics opencv-python
    
    # 直接使用python命令运行,不需要执行权限
    python extract_people_images.py
    
    # 给脚本执行权限:
    chmod +x extract_people_images.py
    

    ##

    一、增强检测人物图片:

    使用YOLOv8模型进行更准确的人物检测,增强版人物图片检测

    模型说明

    • yolov8n.pt:最小最快,适合快速检测
    • yolov8s.pt:平衡速度和精度
    • yolov8m.pt:中等精度
    • yolov8l.pt:高精度
    • yolov8x.pt:最高精度,最慢

    特性

    1. 更准确的人物检测:YOLO可以检测各种姿势、大小的人物
    2. 可调置信度:根据需求调整检测敏感度
    3. 检测预览:可选保存带检测框的图片
    4. 详细统计:显示检测数量、置信度、处理时间等
    5. 错误处理:完善的异常处理,不会因为单张图片失败而停止
    6. 进度显示:实时显示处理进度

    这个增强版本比基础版本准确得多,特别是对于侧面、远处、遮挡的人物检测效果更好!

    完整的Python代码

    #!/usr/bin/env python3
    """
    增强版人物图片检测程序
    使用YOLOv8模型进行更准确的人物检测
    """
    
    import os
    import shutil
    import argparse
    from pathlib import Path
    import time
    
    def setup_environment():
        """检查并导入所需的库"""
        try:
            from ultralytics import YOLO
            import cv2
            return YOLO, cv2
        except ImportError as e:
            print("错误: 缺少必要的库")
            print("请安装以下依赖:")
            print("pip install torch torchvision ultralytics opencv-python")
            print("\n如果安装缓慢,可以使用清华镜像:")
            print("pip install -i https://pypi.tuna.tsinghua.edu.cn/simple torch torchvision ultralytics opencv-python")
            return None, None
    
    def extract_images_with_people_enhanced(source_dir, target_dir, confidence_threshold=0.3, 
                                          model_size='yolov8n.pt', device='cpu', 
                                          save_detection_preview=False):
        """
        使用YOLO模型检测并提取包含人物的图片
        
        参数:
        source_dir: 源文件夹路径
        target_dir: 目标文件夹路径
        confidence_threshold: 置信度阈值(0.0-1.0),值越小检测越敏感
        model_size: 模型大小 ('yolov8n.pt', 'yolov8s.pt', 'yolov8m.pt', 'yolov8l.pt', 'yolov8x.pt')
        device: 运行设备 ('cpu' 或 'cuda')
        save_detection_preview: 是否保存带检测框的预览图
        """
        
        # 检查库是否可用
        YOLO, cv2 = setup_environment()
        if YOLO is None:
            return
        
        # 创建目标文件夹
        Path(target_dir).mkdir(parents=True, exist_ok=True)
        
        # 如果启用预览,创建预览文件夹
        preview_dir = None
        if save_detection_preview:
            preview_dir = os.path.join(target_dir, "detection_previews")
            Path(preview_dir).mkdir(parents=True, exist_ok=True)
        
        # 支持的图片格式
        supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp', '.JPG', '.JPEG', '.PNG']
        
        print("=" * 60)
        print("增强版人物图片检测程序")
        print("=" * 60)
        print(f"源文件夹: {source_dir}")
        print(f"目标文件夹: {target_dir}")
        print(f"模型: {model_size}")
        print(f"置信度阈值: {confidence_threshold}")
        print(f"设备: {device}")
        print(f"保存检测预览: {save_detection_preview}")
        print("-" * 60)
        
        try:
            # 加载YOLO模型(会自动下载如果不存在)
            print("正在加载YOLO模型...")
            start_time = time.time()
            model = YOLO(model_size)
            load_time = time.time() - start_time
            print(f"✓ 模型加载完成,耗时: {load_time:.2f}秒")
            
        except Exception as e:
            print(f"✗ 模型加载失败: {e}")
            print("请检查网络连接或手动下载模型")
            return
        
        # 统计信息
        total_images = 0
        images_with_people = 0
        processed_files = []
        detection_times = []
        
        print("\n开始扫描图片...")
        
        # 获取所有图片文件
        image_files = []
        for filename in os.listdir(source_dir):
            file_path = os.path.join(source_dir, filename)
            if os.path.isfile(file_path) and any(filename.lower().endswith(fmt) for fmt in supported_formats):
                image_files.append(filename)
        
        total_files = len(image_files)
        print(f"找到 {total_files} 张待处理图片")
        
        # 处理每张图片
        for i, filename in enumerate(image_files, 1):
            file_path = os.path.join(source_dir, filename)
            
            print(f"\n[{i}/{total_files}] 处理: {filename}")
            total_images += 1
            
            try:
                # 记录开始时间
                start_time = time.time()
                
                # 使用YOLO进行检测
                results = model(file_path, conf=confidence_threshold, device=device, verbose=False)
                detection_time = time.time() - start_time
                detection_times.append(detection_time)
                
                # 检查是否检测到人物(YOLO中person类的ID是0)
                has_people = False
                people_count = 0
                max_confidence = 0.0
                
                for result in results:
                    if result.boxes is not None and len(result.boxes) > 0:
                        for box in result.boxes:
                            class_id = int(box.cls)
                            confidence = float(box.conf)
                            
                            # class_id 0 对应 'person'
                            if class_id == 0:
                                has_people = True
                                people_count += 1
                                max_confidence = max(max_confidence, confidence)
                
                if has_people:
                    images_with_people += 1
                    
                    # 构建目标文件路径
                    target_path = os.path.join(target_dir, filename)
                    
                    # 处理重名文件
                    counter = 1
                    base_target_path = target_path
                    while os.path.exists(target_path):
                        name, ext = os.path.splitext(filename)
                        target_path = os.path.join(target_dir, f"{name}_{counter}{ext}")
                        counter += 1
                    
                    # 复制原图到目标文件夹
                    shutil.copy2(file_path, target_path)
                    
                    # 如果启用预览,保存带检测框的图片
                    if save_detection_preview and has_people:
                        try:
                            # 绘制检测结果
                            plotted_image = results[0].plot()
                            preview_filename = f"preview_{os.path.splitext(filename)[0]}.jpg"
                            preview_path = os.path.join(preview_dir, preview_filename)
                            cv2.imwrite(preview_path, plotted_image)
                        except Exception as e:
                            print(f"  警告: 无法保存检测预览图: {e}")
                    
                    print(f"  ✓ 检测到 {people_count} 个人物 (最高置信度: {max_confidence:.3f})")
                    print(f"  ✓ 检测时间: {detection_time:.2f}秒")
                    print(f"  ✓ 已复制到: {os.path.basename(target_path)}")
                    
                    processed_files.append({
                        'filename': filename,
                        'people_count': people_count,
                        'max_confidence': max_confidence,
                        'detection_time': detection_time
                    })
                    
                else:
                    print(f"  ✗ 未检测到人物 (检测时间: {detection_time:.2f}秒)")
                    
            except Exception as e:
                print(f"  ✗ 处理图片时出错: {e}")
                continue
        
        # 输出统计信息
        print("\n" + "=" * 60)
        print("处理完成!")
        print("=" * 60)
        
        if total_images > 0:
            print(f"总共处理图片: {total_images}张")
            print(f"检测到包含人物的图片: {images_with_people}张")
            print(f"检测率: {(images_with_people/total_images*100):.1f}%")
            
            if detection_times:
                avg_detection_time = sum(detection_times) / len(detection_times)
                print(f"平均检测时间: {avg_detection_time:.2f}秒/张")
                print(f"总检测时间: {sum(detection_times):.2f}秒")
            
            if images_with_people > 0:
                print(f"\n包含人物的图片已保存到: {target_dir}")
                if save_detection_preview:
                    print(f"检测预览图已保存到: {preview_dir}")
                
                # 显示检测到最多人物的前几张图片
                if processed_files:
                    processed_files.sort(key=lambda x: x['people_count'], reverse=True)
                    print(f"\n检测结果最好的图片:")
                    for i, file_info in enumerate(processed_files[:3]):
                        print(f"  {i+1}. {file_info['filename']} - {file_info['people_count']}人 "
                              f"(置信度: {file_info['max_confidence']:.3f})")
        else:
            print("未找到任何可处理的图片文件")
    
    def main():
        """主函数"""
        parser = argparse.ArgumentParser(description='增强版人物图片检测程序')
        parser.add_argument('--source', '-s', default='.', 
                           help='源文件夹路径 (默认: 当前文件夹)')
        parser.add_argument('--target', '-t', default='images_with_people',
                           help='目标文件夹路径 (默认: images_with_people)')
        parser.add_argument('--confidence', '-c', type=float, default=0.3,
                           help='检测置信度阈值 (0.0-1.0, 默认: 0.3)')
        parser.add_argument('--model', '-m', default='yolov8n.pt',
                           choices=['yolov8n.pt', 'yolov8s.pt', 'yolov8m.pt', 'yolov8l.pt', 'yolov8x.pt'],
                           help='YOLO模型大小 (默认: yolov8n.pt)')
        parser.add_argument('--device', '-d', default='cpu',
                           choices=['cpu', 'cuda'],
                           help='运行设备 (默认: cpu)')
        parser.add_argument('--preview', '-p', action='store_true',
                           help='保存带检测框的预览图')
        
        args = parser.parse_args()
        
        # 检查源文件夹是否存在
        if not os.path.exists(args.source):
            print(f"错误: 源文件夹 '{args.source}' 不存在")
            return
        
        # 运行检测程序
        extract_images_with_people_enhanced(
            source_dir=args.source,
            target_dir=args.target,
            confidence_threshold=args.confidence,
            model_size=args.model,
            device=args.device,
            save_detection_preview=args.preview
        )
    
    # 简化版本函数(不需要命令行参数)
    def simple_extract():
        """简化版本,使用默认参数"""
        source_dir = os.getcwd()  # 当前文件夹
        target_dir = os.path.join(source_dir, "images_with_people")
        
        print("使用简化模式运行...")
        extract_images_with_people_enhanced(source_dir, target_dir)
    
    if __name__ == "__main__":
        # 如果没有命令行参数,使用简化版本
        import sys
        if len(sys.argv) == 1:
            simple_extract()
        else:
            main()
    

    步骤1:保存文件

    在nano编辑器中:

    • Ctrl+X退出
    • Y确认保存
    • Enter确认文件名

    步骤2:运行程序

    python extract_people_images_enhanced_copy.py
    

    方法2:使用命令行参数

    # 基本使用
    python extract_people_images_enhanced_copy.py --source /path/to/images --target ./output
    
    # 调整检测敏感度(值越小越敏感)
    python extract_people_images_enhanced_copy.py --confidence 0.2
    
    # 使用更大的模型(更准确但更慢)
    python extract_people_images_enhanced_copy.py --model yolov8s.pt
    
    # 保存检测预览图
    python extract_people_images_enhanced_copy.py --preview
    
    # 使用GPU加速(如果有NVIDIA显卡)
    python extract_people_images_enhanced_copy.py --device cuda
    
    # 查看所有选项
    python extract_people_images_enhanced_copy.py --help
    

    如果还是有问题,使用这个简单版本:

    # 先删除所有有问题的文件
    rm -f *.py
    
    # 创建简单版本
    cat > simple_detection.py << 'EOF'
    import os
    import shutil
    import cv2
    from pathlib import Path
    
    def detect_people():
        print("开始检测人物图片...")
        
        # 检查OpenCV
        try:
            face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
        except:
            print("请先安装OpenCV: pip install opencv-python")
            return
        
        # 创建目标文件夹
        target_dir = "images_with_people"
        Path(target_dir).mkdir(exist_ok=True)
        
        # 支持的图片格式
        formats = ['.jpg', '.jpeg', '.png']
        count = 0
        
        for filename in os.listdir('.'):
            if any(filename.lower().endswith(fmt) for fmt in formats):
                print(f"处理: {filename}")
                img = cv2.imread(filename)
                if img is not None:
                    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
                    faces = face_cascade.detectMultiScale(gray, 1.1, 5)
                    if len(faces) > 0:
                        shutil.copy2(filename, os.path.join(target_dir, filename))
                        print(f"✓ 检测到人物")
                        count += 1
                    else:
                        print(f"✗ 未检测到人物")
        
        print(f"\n完成! 找到 {count} 张包含人物的图片")
    
    if __name__ == "__main__":
        detect_people()
    EOF
    
    # 运行简单版本
    python simple_detection.py
    

    请按照步骤1-4操作,应该能解决问题!

    二、增强检测人物图片(自定义文件夹):

    这个版本实现了把检测到的图片直接移动到新的文件夹而不是复制,也可以通过后面的加参数定义移动或者复制。

    主要修改 shutil.copy2()shutil.move()

    #!/usr/bin/env python3
    """
    增强版人物图片检测程序(移动版本)
    使用YOLOv8模型进行更准确的人物检测,并将图片移动到新文件夹
    """
    
    import os
    import shutil
    import argparse
    from pathlib import Path
    import time
    
    def setup_environment():
        """检查并导入所需的库"""
        try:
            from ultralytics import YOLO
            import cv2
            return YOLO, cv2
        except ImportError as e:
            print("错误: 缺少必要的库")
            print("请安装以下依赖:")
            print("pip install torch torchvision ultralytics opencv-python")
            print("\n如果安装缓慢,可以使用清华镜像:")
            print("pip install -i https://pypi.tuna.tsinghua.edu.cn/simple torch torchvision ultralytics opencv-python")
            return None, None
    
    def extract_images_with_people_enhanced(source_dir, target_dir, confidence_threshold=0.3, 
                                          model_size='yolov8n.pt', device='cpu', 
                                          save_detection_preview=False, move_instead_of_copy=True):
        """
        使用YOLO模型检测并移动包含人物的图片
        
        参数:
        source_dir: 源文件夹路径
        target_dir: 目标文件夹路径
        confidence_threshold: 置信度阈值(0.0-1.0),值越小检测越敏感
        model_size: 模型大小 ('yolov8n.pt', 'yolov8s.pt', 'yolov8m.pt', 'yolov8l.pt', 'yolov8x.pt')
        device: 运行设备 ('cpu' 或 'cuda')
        save_detection_preview: 是否保存带检测框的预览图
        move_instead_of_copy: 是否移动而不是复制图片
        """
        
        # 检查库是否可用
        YOLO, cv2 = setup_environment()
        if YOLO is None:
            return
        
        # 创建目标文件夹
        Path(target_dir).mkdir(parents=True, exist_ok=True)
        
        # 如果启用预览,创建预览文件夹
        preview_dir = None
        if save_detection_preview:
            preview_dir = os.path.join(target_dir, "detection_previews")
            Path(preview_dir).mkdir(parents=True, exist_ok=True)
        
        # 支持的图片格式
        supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp', '.JPG', '.JPEG', '.PNG']
        
        print("=" * 60)
        print("增强版人物图片检测程序(移动版本)")
        print("=" * 60)
        print(f"源文件夹: {source_dir}")
        print(f"目标文件夹: {target_dir}")
        print(f"操作模式: {'移动' if move_instead_of_copy else '复制'}")
        print(f"模型: {model_size}")
        print(f"置信度阈值: {confidence_threshold}")
        print(f"设备: {device}")
        print(f"保存检测预览: {save_detection_preview}")
        print("-" * 60)
        
        # 警告信息
        if move_instead_of_copy:
            print("⚠️  警告: 此操作将移动图片文件,原文件夹中的图片将被删除!")
            response = input("是否继续?(y/N): ")
            if response.lower() != 'y':
                print("操作已取消")
                return
        
        try:
            # 加载YOLO模型(会自动下载如果不存在)
            print("正在加载YOLO模型...")
            start_time = time.time()
            model = YOLO(model_size)
            load_time = time.time() - start_time
            print(f"✓ 模型加载完成,耗时: {load_time:.2f}秒")
            
        except Exception as e:
            print(f"✗ 模型加载失败: {e}")
            print("请检查网络连接或手动下载模型")
            return
        
        # 统计信息
        total_images = 0
        images_with_people = 0
        processed_files = []
        detection_times = []
        
        print("\n开始扫描图片...")
        
        # 获取所有图片文件
        image_files = []
        for filename in os.listdir(source_dir):
            file_path = os.path.join(source_dir, filename)
            if os.path.isfile(file_path) and any(filename.lower().endswith(fmt) for fmt in supported_formats):
                image_files.append(filename)
        
        total_files = len(image_files)
        print(f"找到 {total_files} 张待处理图片")
        
        # 处理每张图片
        for i, filename in enumerate(image_files, 1):
            file_path = os.path.join(source_dir, filename)
            
            print(f"\n[{i}/{total_files}] 处理: {filename}")
            total_images += 1
            
            try:
                # 记录开始时间
                start_time = time.time()
                
                # 使用YOLO进行检测
                results = model(file_path, conf=confidence_threshold, device=device, verbose=False)
                detection_time = time.time() - start_time
                detection_times.append(detection_time)
                
                # 检查是否检测到人物(YOLO中person类的ID是0)
                has_people = False
                people_count = 0
                max_confidence = 0.0
                
                for result in results:
                    if result.boxes is not None and len(result.boxes) > 0:
                        for box in result.boxes:
                            class_id = int(box.cls)
                            confidence = float(box.conf)
                            
                            # class_id 0 对应 'person'
                            if class_id == 0:
                                has_people = True
                                people_count += 1
                                max_confidence = max(max_confidence, confidence)
                
                if has_people:
                    images_with_people += 1
                    
                    # 构建目标文件路径
                    target_path = os.path.join(target_dir, filename)
                    
                    # 处理重名文件
                    counter = 1
                    base_target_path = target_path
                    while os.path.exists(target_path):
                        name, ext = os.path.splitext(filename)
                        target_path = os.path.join(target_dir, f"{name}_{counter}{ext}")
                        counter += 1
                    
                    # 移动或复制文件到目标文件夹
                    if move_instead_of_copy:
                        shutil.move(file_path, target_path)
                        operation_text = "移动"
                    else:
                        shutil.copy2(file_path, target_path)
                        operation_text = "复制"
                    
                    # 如果启用预览,保存带检测框的图片
                    if save_detection_preview and has_people:
                        try:
                            # 重新读取图片用于预览(如果是移动操作,需要重新加载)
                            if move_instead_of_copy:
                                preview_source_path = target_path
                            else:
                                preview_source_path = file_path
                                
                            preview_results = model(preview_source_path, conf=confidence_threshold, device=device, verbose=False)
                            plotted_image = preview_results[0].plot()
                            preview_filename = f"preview_{os.path.splitext(filename)[0]}.jpg"
                            preview_path = os.path.join(preview_dir, preview_filename)
                            cv2.imwrite(preview_path, plotted_image)
                        except Exception as e:
                            print(f"  警告: 无法保存检测预览图: {e}")
                    
                    print(f"  ✓ 检测到 {people_count} 个人物 (最高置信度: {max_confidence:.3f})")
                    print(f"  ✓ 检测时间: {detection_time:.2f}秒")
                    print(f"  ✓ 已{operation_text}到: {os.path.basename(target_path)}")
                    
                    processed_files.append({
                        'filename': filename,
                        'people_count': people_count,
                        'max_confidence': max_confidence,
                        'detection_time': detection_time,
                        'operation': operation_text
                    })
                    
                else:
                    print(f"  ✗ 未检测到人物 (检测时间: {detection_time:.2f}秒)")
                    
            except Exception as e:
                print(f"  ✗ 处理图片时出错: {e}")
                continue
        
        # 输出统计信息
        print("\n" + "=" * 60)
        print("处理完成!")
        print("=" * 60)
        
        if total_images > 0:
            print(f"总共处理图片: {total_images}张")
            print(f"检测到包含人物的图片: {images_with_people}张")
            print(f"检测率: {(images_with_people/total_images*100):.1f}%")
            
            if detection_times:
                avg_detection_time = sum(detection_times) / len(detection_times)
                print(f"平均检测时间: {avg_detection_time:.2f}秒/张")
                print(f"总检测时间: {sum(detection_times):.2f}秒")
            
            if images_with_people > 0:
                operation_mode = "移动" if move_instead_of_copy else "复制"
                print(f"\n包含人物的图片已{operation_mode}到: {target_dir}")
                if save_detection_preview:
                    print(f"检测预览图已保存到: {preview_dir}")
                
                # 显示检测到最多人物的前几张图片
                if processed_files:
                    processed_files.sort(key=lambda x: x['people_count'], reverse=True)
                    print(f"\n检测结果最好的图片:")
                    for i, file_info in enumerate(processed_files[:3]):
                        print(f"  {i+1}. {file_info['filename']} - {file_info['people_count']}人 "
                              f"(置信度: {file_info['max_confidence']:.3f})")
                    
                # 安全提示
                if move_instead_of_copy:
                    remaining_files = len([f for f in os.listdir(source_dir) 
                                         if any(f.lower().endswith(fmt) for fmt in supported_formats)])
                    print(f"\n⚠️  原文件夹剩余图片: {remaining_files}张")
                    print("⚠️  检测到的图片已被移动到目标文件夹,原文件已删除")
        else:
            print("未找到任何可处理的图片文件")
    
    def main():
        """主函数"""
        parser = argparse.ArgumentParser(description='增强版人物图片检测程序(移动版本)')
        parser.add_argument('--source', '-s', default='.', 
                           help='源文件夹路径 (默认: 当前文件夹)')
        parser.add_argument('--target', '-t', default='images_with_people',
                           help='目标文件夹路径 (默认: images_with_people)')
        parser.add_argument('--confidence', '-c', type=float, default=0.3,
                           help='检测置信度阈值 (0.0-1.0, 默认: 0.3)')
        parser.add_argument('--model', '-m', default='yolov8n.pt',
                           choices=['yolov8n.pt', 'yolov8s.pt', 'yolov8m.pt', 'yolov8l.pt', 'yolov8x.pt'],
                           help='YOLO模型大小 (默认: yolov8n.pt)')
        parser.add_argument('--device', '-d', default='cpu',
                           choices=['cpu', 'cuda'],
                           help='运行设备 (默认: cpu)')
        parser.add_argument('--preview', '-p', action='store_true',
                           help='保存带检测框的预览图')
        parser.add_argument('--copy', action='store_true',
                           help='使用复制模式而不是移动模式')
        
        args = parser.parse_args()
        
        # 检查源文件夹是否存在
        if not os.path.exists(args.source):
            print(f"错误: 源文件夹 '{args.source}' 不存在")
            return
        
        # 运行检测程序
        extract_images_with_people_enhanced(
            source_dir=args.source,
            target_dir=args.target,
            confidence_threshold=args.confidence,
            model_size=args.model,
            device=args.device,
            save_detection_preview=args.preview,
            move_instead_of_copy=not args.copy  # 如果指定--copy则使用复制模式
        )
    
    # 简化版本函数(不需要命令行参数)
    def simple_extract():
        """简化版本,使用默认参数(移动模式)"""
        source_dir = os.getcwd()  # 当前文件夹
        target_dir = os.path.join(source_dir, "images_with_people")
        
        print("使用简化模式运行(移动模式)...")
        print("此操作将把检测到人物的图片移动到新文件夹!")
        
        response = input("是否继续?(y/N): ")
        if response.lower() != 'y':
            print("操作已取消")
            return
        
        extract_images_with_people_enhanced(source_dir, target_dir, move_instead_of_copy=True)
    
    if __name__ == "__main__":
        # 如果没有命令行参数,使用简化版本
        import sys
        if len(sys.argv) == 1:
            simple_extract()
        else:
            main()
    

    主要修改内容:

    1. shutil.copy2()改为 shutil.move()
    2. 添加了移动模式的安全确认,避免误操作
    3. 增加了 move_instead_of_copy参数,可以控制是移动还是复制
    4. 添加了 --copy命令行参数,如果需要复制模式可以加上这个参数
    5. 改进了预览图生成逻辑,适应移动操作
    6. 增加了操作完成后的统计信息,显示剩余文件数量

    使用方法:

    移动模式(默认):

    # 简单使用(移动图片)
    python extract_people_images_enhanced_move.py
    
    # 带参数使用
    python extract_people_images_enhanced_move.py --source ./图片文件夹 --target ./人物图片
    

    复制模式(如果需要保留原文件):

    # 使用复制模式
    python extract_people_images_enhanced_move.py --copy
    
    # 带预览的复制模式
    python extract_people_images_enhanced_move.py --copy --preview
    

    其他参数:

    # 调整检测敏感度
    python extract_people_images_enhanced_move.py --confidence 0.2
    
    # 使用更大的模型
    python extract_people_images_enhanced_move.py --model yolov8s.pt
    
    # 保存检测预览图
    python extract_people_images_enhanced_move.py --preview
    

    安全特性:

    1. 运行前确认:移动模式会要求用户确认
    2. 进度显示:实时显示处理进度
    3. 结果统计:完成后显示移动/复制的文件数量
    4. 剩余文件提示:显示原文件夹剩余图片数量

    这样修改后,检测到人物的图片会被直接移动到目标文件夹,原文件会被删除,节省磁盘空间。如果你需要保留原文件,使用 --copy参数即可。

    高级检测:

    方案1:基于YOLO的人体部位检测

    专门检测女性人体暴露或色情内容。这里有几个不同级别的实现方案:

    #!/usr/bin/env python3
    """
    女性人体暴露/色情图片检测程序
    使用YOLO模型检测暴露的身体部位
    """
    
    import os
    import shutil
    import argparse
    from pathlib import Path
    import time
    
    def setup_environment():
        """检查并导入所需的库"""
        try:
            from ultralytics import YOLO
            import cv2
            return YOLO, cv2
        except ImportError as e:
            print("错误: 缺少必要的库")
            print("请安装以下依赖:")
            print("pip install torch torchvision ultralytics opencv-python")
            return None, None
    
    class NudityDetector:
        """暴露内容检测器"""
        
        def __init__(self, confidence_threshold=0.3):
            self.confidence_threshold = confidence_threshold
            # 定义敏感部位类别(基于COCO数据集)
            self.sensitive_parts = {
                'person': 0,      # 人物
                'face': 1,        # 脸部(某些数据集有)
            }
            
            # 定义暴露风险等级的关键词(用于文件名和路径分析)
            self.risky_keywords = [
                'nude', 'naked', 'bikini', 'swimsuit', 'lingerie', 'sexy', 'hot',
                '暴露', '性感', '内衣', '比基尼', '泳装', '裸体', '色情'
            ]
        
        def detect_exposure_level(self, results, filename=""):
            """
            检测图片的暴露等级
            返回: (暴露等级, 置信度, 检测到的部位)
            """
            exposure_level = 0  # 0: 安全, 1: 轻度, 2: 中度, 3: 高度暴露
            max_confidence = 0
            detected_parts = []
            
            for result in results:
                if result.boxes is not None and len(result.boxes) > 0:
                    for box in result.boxes:
                        class_id = int(box.cls)
                        confidence = float(box.conf)
                        
                        # 检测人物
                        if class_id == 0:  # person
                            detected_parts.append('person')
                            max_confidence = max(max_confidence, confidence)
                            
                            # 如果有高置信度的人物检测,基础暴露等级为1
                            if confidence > 0.5:
                                exposure_level = max(exposure_level, 1)
            
            # 基于文件名分析
            filename_risk = self.analyze_filename_risk(filename.lower())
            exposure_level = max(exposure_level, filename_risk)
            
            return exposure_level, max_confidence, detected_parts
        
        def analyze_filename_risk(self, filename):
            """分析文件名的风险等级"""
            risk_level = 0
            for keyword in self.risky_keywords:
                if keyword in filename:
                    if keyword in ['nude', 'naked', '裸体', '色情']:
                        risk_level = max(risk_level, 3)
                    elif keyword in ['bikini', 'swimsuit', 'lingerie', '比基尼', '泳装', '内衣']:
                        risk_level = max(risk_level, 2)
                    else:
                        risk_level = max(risk_level, 1)
            return risk_level
        
        def analyze_skin_ratio(self, image_path):
            """简单的肤色比例分析(基础版本)"""
            try:
                import cv2
                import numpy as np
                
                # 读取图片
                img = cv2.imread(image_path)
                if img is None:
                    return 0
                    
                # 转换到HSV颜色空间进行肤色检测
                hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
                
                # 定义肤色范围(需要根据实际情况调整)
                lower_skin = np.array([0, 20, 70], dtype=np.uint8)
                upper_skin = np.array([20, 255, 255], dtype=np.uint8)
                
                # 创建肤色掩码
                mask = cv2.inRange(hsv, lower_skin, upper_skin)
                
                # 计算肤色像素比例
                skin_ratio = np.sum(mask > 0) / (img.shape[0] * img.shape[1])
                
                return skin_ratio
                
            except Exception as e:
                print(f"肤色分析错误: {e}")
                return 0
    
    def extract_sensitive_images(source_dir, target_dir, confidence_threshold=0.3, 
                               model_size='yolov8n.pt', device='cpu', 
                               save_detection_preview=False, move_instead_of_copy=True,
                               min_exposure_level=1):
        """
        检测并提取敏感图片
        
        参数:
        source_dir: 源文件夹路径
        target_dir: 目标文件夹路径
        confidence_threshold: 置信度阈值
        model_size: 模型大小
        device: 运行设备
        save_detection_preview: 是否保存检测预览
        move_instead_of_copy: 是否移动文件
        min_exposure_level: 最小暴露等级 (1-3)
        """
        
        # 检查库是否可用
        YOLO, cv2 = setup_environment()
        if YOLO is None:
            return
        
        # 创建目标文件夹
        Path(target_dir).mkdir(parents=True, exist_ok=True)
        
        # 按暴露等级创建子文件夹
        level_folders = {
            1: os.path.join(target_dir, "level1_mild"),
            2: os.path.join(target_dir, "level2_moderate"),
            3: os.path.join(target_dir, "level3_high")
        }
        
        for folder in level_folders.values():
            Path(folder).mkdir(parents=True, exist_ok=True)
        
        # 如果启用预览,创建预览文件夹
        preview_dir = None
        if save_detection_preview:
            preview_dir = os.path.join(target_dir, "detection_previews")
            Path(preview_dir).mkdir(parents=True, exist_ok=True)
        
        # 支持的图片格式
        supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp']
        
        print("=" * 70)
        print("女性人体暴露/色情图片检测程序")
        print("=" * 70)
        print(f"源文件夹: {source_dir}")
        print(f"目标文件夹: {target_dir}")
        print(f"操作模式: {'移动' if move_instead_of_copy else '复制'}")
        print(f"最小暴露等级: {min_exposure_level}")
        print(f"模型: {model_size}")
        print(f"置信度阈值: {confidence_threshold}")
        print("-" * 70)
        
        # 警告信息
        if move_instead_of_copy:
            print("⚠️  警告: 此操作将移动图片文件!")
            response = input("是否继续?(y/N): ")
            if response.lower() != 'y':
                print("操作已取消")
                return
        
        # 初始化检测器
        detector = NudityDetector(confidence_threshold)
        
        try:
            # 加载YOLO模型
            print("正在加载YOLO模型...")
            start_time = time.time()
            model = YOLO(model_size)
            load_time = time.time() - start_time
            print(f"✓ 模型加载完成,耗时: {load_time:.2f}秒")
            
        except Exception as e:
            print(f"✗ 模型加载失败: {e}")
            return
        
        # 统计信息
        total_images = 0
        detected_images = 0
        level_stats = {1: 0, 2: 0, 3: 0}
        processed_files = []
        detection_times = []
        
        print("\n开始扫描图片...")
        
        # 获取所有图片文件
        image_files = []
        for filename in os.listdir(source_dir):
            file_path = os.path.join(source_dir, filename)
            if os.path.isfile(file_path) and any(filename.lower().endswith(fmt) for fmt in supported_formats):
                image_files.append(filename)
        
        total_files = len(image_files)
        print(f"找到 {total_files} 张待处理图片")
        
        # 处理每张图片
        for i, filename in enumerate(image_files, 1):
            file_path = os.path.join(source_dir, filename)
            
            print(f"\n[{i}/{total_files}] 分析: {filename}")
            total_images += 1
            
            try:
                start_time = time.time()
                
                # 使用YOLO进行检测
                results = model(file_path, conf=confidence_threshold, device=device, verbose=False)
                detection_time = time.time() - start_time
                detection_times.append(detection_time)
                
                # 检测暴露等级
                exposure_level, max_confidence, detected_parts = detector.detect_exposure_level(results, filename)
                
                # 简单的肤色比例分析
                skin_ratio = detector.analyze_skin_ratio(file_path)
                if skin_ratio > 0.3:  # 如果肤色比例较高,提高暴露等级
                    exposure_level = max(exposure_level, 2)
                
                if exposure_level >= min_exposure_level:
                    detected_images += 1
                    level_stats[exposure_level] = level_stats.get(exposure_level, 0) + 1
                    
                    # 确定目标文件夹
                    target_level_folder = level_folders.get(exposure_level, target_dir)
                    
                    # 构建目标文件路径
                    target_path = os.path.join(target_level_folder, filename)
                    
                    # 处理重名文件
                    counter = 1
                    while os.path.exists(target_path):
                        name, ext = os.path.splitext(filename)
                        target_path = os.path.join(target_level_folder, f"{name}_{counter}{ext}")
                        counter += 1
                    
                    # 移动或复制文件
                    if move_instead_of_copy:
                        shutil.move(file_path, target_path)
                        operation_text = "移动"
                    else:
                        shutil.copy2(file_path, target_path)
                        operation_text = "复制"
                    
                    # 保存检测预览
                    if save_detection_preview:
                        try:
                            preview_results = model(target_path if move_instead_of_copy else file_path, 
                                                  conf=confidence_threshold, device=device, verbose=False)
                            plotted_image = preview_results[0].plot()
                            preview_filename = f"L{exposure_level}_preview_{os.path.splitext(filename)[0]}.jpg"
                            preview_path = os.path.join(preview_dir, preview_filename)
                            cv2.imwrite(preview_path, plotted_image)
                        except Exception as e:
                            print(f"  警告: 无法保存检测预览图: {e}")
                    
                    # 暴露等级描述
                    level_descriptions = {
                        1: "轻度暴露",
                        2: "中度暴露", 
                        3: "高度暴露"
                    }
                    
                    print(f"  ✓ 检测结果: {level_descriptions.get(exposure_level, '未知')} (等级{exposure_level})")
                    print(f"  ✓ 肤色比例: {skin_ratio:.3f}")
                    print(f"  ✓ 检测部位: {', '.join(detected_parts) if detected_parts else '无'}")
                    print(f"  ✓ 检测时间: {detection_time:.2f}秒")
                    print(f"  ✓ 已{operation_text}到: level{exposure_level}/{os.path.basename(target_path)}")
                    
                    processed_files.append({
                        'filename': filename,
                        'exposure_level': exposure_level,
                        'skin_ratio': skin_ratio,
                        'detected_parts': detected_parts,
                        'detection_time': detection_time,
                        'operation': operation_text
                    })
                    
                else:
                    print(f"  ✗ 安全图片 (暴露等级: {exposure_level}, 检测时间: {detection_time:.2f}秒)")
                    
            except Exception as e:
                print(f"  ✗ 处理图片时出错: {e}")
                continue
        
        # 输出统计信息
        print("\n" + "=" * 70)
        print("检测完成!")
        print("=" * 70)
        
        if total_images > 0:
            print(f"总共处理图片: {total_images}张")
            print(f"检测到敏感图片: {detected_images}张")
            print(f"检测率: {(detected_images/total_images*100):.1f}%")
            
            print(f"\n暴露等级分布:")
            for level, count in level_stats.items():
                if count > 0:
                    level_desc = {1: "轻度暴露", 2: "中度暴露", 3: "高度暴露"}.get(level, "未知")
                    print(f"  等级{level} ({level_desc}): {count}张")
            
            if detected_images > 0:
                operation_mode = "移动" if move_instead_of_copy else "复制"
                print(f"\n敏感图片已{operation_mode}到对应等级的文件夹")
                
                # 显示检测结果
                if processed_files:
                    processed_files.sort(key=lambda x: x['exposure_level'], reverse=True)
                    print(f"\n风险最高的图片:")
                    for i, file_info in enumerate(processed_files[:5]):
                        print(f"  {i+1}. {file_info['filename']} - 等级{file_info['exposure_level']} "
                              f"(肤色比例: {file_info['skin_ratio']:.3f})")
        else:
            print("未找到任何可处理的图片文件")
    
    def main():
        """主函数"""
        parser = argparse.ArgumentParser(description='女性人体暴露/色情图片检测程序')
        parser.add_argument('--source', '-s', default='.', 
                           help='源文件夹路径 (默认: 当前文件夹)')
        parser.add_argument('--target', '-t', default='sensitive_images',
                           help='目标文件夹路径 (默认: sensitive_images)')
        parser.add_argument('--confidence', '-c', type=float, default=0.3,
                           help='检测置信度阈值 (0.0-1.0, 默认: 0.3)')
        parser.add_argument('--model', '-m', default='yolov8n.pt',
                           choices=['yolov8n.pt', 'yolov8s.pt', 'yolov8m.pt', 'yolov8l.pt', 'yolov8x.pt'],
                           help='YOLO模型大小 (默认: yolov8n.pt)')
        parser.add_argument('--device', '-d', default='cpu',
                           choices=['cpu', 'cuda'],
                           help='运行设备 (默认: cpu)')
        parser.add_argument('--preview', '-p', action='store_true',
                           help='保存带检测框的预览图')
        parser.add_argument('--copy', action='store_true',
                           help='使用复制模式而不是移动模式')
        parser.add_argument('--level', type=int, default=1, choices=[1, 2, 3],
                           help='最小暴露等级 (1:轻度, 2:中度, 3:高度, 默认: 1)')
        
        args = parser.parse_args()
        
        if not os.path.exists(args.source):
            print(f"错误: 源文件夹 '{args.source}' 不存在")
            return
        
        extract_sensitive_images(
            source_dir=args.source,
            target_dir=args.target,
            confidence_threshold=args.confidence,
            model_size=args.model,
            device=args.device,
            save_detection_preview=args.preview,
            move_instead_of_copy=not args.copy,
            min_exposure_level=args.level
        )
    
    if __name__ == "__main__":
        import sys
        if len(sys.argv) == 1:
            # 简化模式运行
            source_dir = os.getcwd()
            target_dir = os.path.join(source_dir, "sensitive_images")
            
            print("女性人体暴露图片检测程序")
            print("此操作将检测并分类暴露程度的图片!")
            
            response = input("是否继续?(y/N): ")
            if response.lower() == 'y':
                extract_sensitive_images(source_dir, target_dir, move_instead_of_copy=True)
            else:
                print("操作已取消")
        else:
            main()
    

    方案2:使用专门的NSFW检测模型

    如果需要更准确的结果,可以使用专门的NSFW检测模型:

    # 需要额外安装的库
    # pip install tensorflow keras
    
    def setup_nsfw_detector():
        """设置专门的NSFW检测器"""
        try:
            # 这里可以使用预训练的NSFW检测模型
            # 例如: https://github.com/rockyzhengwu/nsfw
            print("正在加载NSFW检测模型...")
            # 实际实现需要下载预训练模型
            return None
        except ImportError:
            print("请安装TensorFlow: pip install tensorflow")
            return None
    

    使用方法:

    # 基本使用(移动模式,检测所有暴露等级)
    python sensitive_detector.py
    
    # 只检测高度暴露的图片
    python sensitive_detector.py --level 3
    
    # 复制模式(保留原文件)
    python sensitive_detector.py --copy
    
    # 指定源文件夹和目标文件夹
    python sensitive_detector.py --source ./图片库 --target ./敏感图片
    
    # 保存检测预览
    python sensitive_detector.py --preview
    
    # 使用更准确的模型
    python sensitive_detector.py --model yolov8s.pt
    

    暴露等级说明:

    • 等级1(轻度): 检测到人物,可能有轻微暴露
    • 等级2(中度): 检测到较多肤色区域或敏感关键词
    • 等级3(高度): 高度暴露内容,包含大量肤色区域或明确敏感内容

    注意事项:

    1. 准确率限制: 这种检测方法有一定误判率
    2. 隐私保护: 请确保合法使用,尊重他人隐私
    3. 法律合规: 在不同地区使用此类工具可能受到法律限制
    4. 人工审核: 建议最终结果由人工审核确认

    这个程序会按暴露程度将图片分类到不同的文件夹,方便你进一步处理。

    正确的运行方法:

    方法1:直接运行Python脚本

    # 进入脚本所在目录
    cd /home/leepoet/Documents/env/myenv/甜心
    
    # 直接运行Python脚本
    python 女性人体暴露.py
    

    方法2:给脚本添加执行权限后直接运行

    # 进入脚本所在目录
    cd /home/leepoet/Documents/env/myenv/甜心
    
    # 给脚本添加执行权限
    chmod +x 女性人体暴露.py
    
    # 直接运行脚本
    ./女性人体暴露.py
    

    设置自定义检测路径

    你可以通过命令行参数灵活指定源文件夹和目标文件夹:

    # 检测指定文件夹,结果保存到自定义目录
    python your_script.py --source /path/to/your/images --target /path/to/output

    # 完整参数示例
    python your_script.py --source /home/user/photos --target /home/user/sorted_photos --confidence 0.5 --model yolov8s.pt --preview --copy

    4. 关键参数说明

    • --source: 指定需要检测的图片文件夹路径
    • --target: 指定结果输出文件夹路径
    • --confidence: 调整检测灵敏度(0.1-1.0)
    • --model: 选择不同的YOLO模型(影响精度和速度)
    • --preview: 保存带检测框的预览图
    • --copy: 使用复制模式(默认是移动文件)
  • CloudFlare优选Cname域名

    CloudFlare优选Cname域名

    小提示:
    公共 cname 可能会将搜索引擎蜘蛛路线解析到其他服务器来劫持蜘蛛,请使用信得过的 cname 地址。
    公共地址可能存在解析到第三方服务器的情况,请使用信得过的 cname 地址。
    公共 CNAME 域名可能存在被污染的情况,请隔段时间测试一下,及时更换掉被污染的域名。
    第三方反代 IP 也可能会导致域名被注册局禁用或被墙的情况,网站用户不建议使用反代 IP。
    CloudFlare 每隔一段时间会调整变更路由线路,因此请尽可能选择更新频率高的 cname 域名。

    [members_only]
    网站使用 CloudFlare 优选域名的教程https://www.baota.me/post-433.html

    地址名称协议版本维护周期备注说明
    *.cloudflare.182682.xyz4&615ip/15分钟泛域名解析可以解析到任意前缀,本站提供维护
    bestcf.top424HVPS789
    cdn.2020111.xyz415ip/10分钟网络收集
    cfip.cfcdn.vip46ip/1天网络收集
    cf.0sm.com4&6手动更新网络收集
    cf.090227.xyz4&6未知频率网络收集
    cf.zhetengsha.eu.org4未知频率网络收集
    cloudflare.9jy.cc4未知频率网络收集
    cf.zerone-cdn.pp.ua4未知频率网络收集
    cfip.1323123.xyz4未知频率网络收集
    cnamefuckxxs.yuchen.icu4未知频率网络收集
    cfip.xxxxxxxx.tk4未知频率OTC大佬提供维护
    cloudflare-ip.mofashi.ltd4未知频率网络收集
    115155.xyz4&618ip/1小时网络收集
    cname.xirancdn.us4&6未知频率网络收集
    f3058171cad.002404.xyz4&6未知频率网络收集
    speed.marisalnc.com41000ip/3分钟【推荐】ktff大佬提供维护
    8.889288.xyz4未知频率网络收集
    cdn.tzpro.xyz4未知频率网络收集
    cf.877771.xyz4未知频率网络收集
    xn--b6gac.eu.org4未知频率↗↘↗.eu.org
    freeyx.cloudflare88.eu.org41000ip/3分钟同speed.marisalnc.com

    原站链接:CloudFlare优选Cname域名 – 微测网

    [/members_only]

  • 设计师与开发者必备:25个免费SVG图标资源宝库

    设计师与开发者必备:25个免费SVG图标资源宝库

    开源库到商业资源,从极简风到动画图标,这份超全的SVG网站合集一定能满足你的需求。文章不仅列出链接,更附上每个网站的特点简介,干货满满。告别图标荒!我搜罗了全网最好用的25个免费SVG图标站点,无论是个人创作还是商业项目,都能轻松找到心仪之选。资源优质,大部分可直接商用,快来提升你的设计质感吧。

    1. SVG Repo
      官网链接:SVG Repo

    SVG Repo是一个庞大的图标库,包含超过400,000个完全免费的SVG矢量和图标。这些图标完全开放许可,意味着您可以在商业项目中使用它们,而无需支付版税或认证。您可以通过搜索特定关键字或浏览矢量集合来查找图标。

    1. Icons8
      官网链接:Icons8

    Icons8提供了数千个SVG图标的巨大捆绑包,并且具有易于搜索的过滤器和大量的类别选项。您可以通过搜索、图像、样式搜索等进行过滤。此外,Icons8还提供动画SVG图标,为网页设计增添活力。需要注意的是,虽然可以免费使用其图标,但必须将资源链接回Icons8,除非您支付高级计划。

    1. Bootstrap Icons
      官网链接:Bootstrap Icons

    Bootstrap Icons是Bootstrap团队推出的官方图标库,包含超过1500个SVG格式的图标。这些图标是为Bootstrap开发的,但也可以在其他框架中使用。它们可以通过npm或Composer轻松地安装到项目中。

    1. IconPacks
      官网链接:IconPacks

    IconPacks提供超过17,000个完全免费的SVG图标。虽然其搜索功能相对基础,但您可以轻松找到社交媒体图标和徽标等流行图标的SVG版本。这对于个人项目可能非常有用,但对于商业项目可能会受到限制。

    1. Reshot
      官网链接:Reshot

    Reshot提供完全免版税的图标库,您可以在商业项目中自由使用。通过搜索功能,您可以轻松找到所需的图标或图标包。如果找不到所需内容,Reshot还会提供其他搜索建议。

    1. Remix Icon
      官网链接:Remix Icon

    Remix Icon包含大量不同种类的图标,这些图标完全开源,可免费用于个人和商业用途。所有图标都是中性的,并且风格相似,非常适合需要一致风格的项目。

    1. Heroicons
      官网链接:Heroicons

    Heroicons提供近300种不同的图标,包括轮廓、实心和迷你图标。这些图标风格一致,非常适合需要活力美感的项目。它们也可以作为SVG、JSX或Vue组件库使用。

    1. Boxicons
      官网链接:Boxicons

    Boxicons包含超过1,600个不同的SVG图标,这些图标在风格上都很相似。它们分为多个类别,如电子商务、金融和音乐,便于排序和查找。每个图标都有不同的格式,可以下载SVG,也可以用作字体图标和Web组件。

    1. Iconoir
      官网链接:Iconoir

    Iconoir包含1,200多个不同的图标,并且还在不断增长。这些图标有SVG格式以及Font、React、Figma和Framer格式。您可以通过滑块轻松自定义图标的大小和笔画宽度,以及调整颜色。

    1. Freepik
      官网链接:Freepik

    Freepik拥有世界上最大的图标库之一,提供超过1000万个个人或商业用途的图标。虽然每个图标都以PNG格式免费提供,但也可以轻松集成到项目中,只需注明出处即可。

    1. Flaticon
      官网链接:Flaticon

    Flaticon提供了多种样式的图标,超过1000万个,包括PNG、SVG、EPS、PSD等格式。您还可以找到动画图标和贴纸,并使用在线编辑器更改图标资源的颜色和大小。

    1. Feather Icons
      官网链接:Feather Icons

    Feather Icons提供超过200个设计精美的图标,允许在下载之前自定义图标的大小、笔画宽度和颜色。

    1. Ionicons
      官网链接:Ionicons

    Ionicons是Ionic框架的图标集合,用于Web、移动应用或桌面应用程序。图标包含SVG和字体图标格式,有三种不同的风格:Outline、Filled、Sharp。

    1. Tabler Icons
      官网链接:Tabler Icons

    Tabler Icons提供超过1300个清晰一致的图标,并且可定制。除了SVG格式之外,还包括JSX、Data URI、React Component、Webfont、SCSS等格式。

    1. Radix Icons
      官网链接:Radix Icons

    Radix Icons包含一组具有细轮廓特征的图标,每个图标都是15×15像素,在屏幕上看起来很清晰。提供Figma、Sketch、IconJar、SVG或NPM格式。

    1. Ant Design Icons
      官网链接:Ant Design Icons

    Ant Design Icons是Ant Design的一部分,可以通过NPM将图标集合作为独立组件安装。每个图标都可以作为React.js组件使用,并将呈现为SVG。它有三种风格:Outlined、Filled、Two-tone,并且兼容轻模式和暗模式配色方案。

    1. Material Design Icons
      官网链接:Material Design Icons

    Material Design Icons是谷歌的图标集合,为Web、Android、iOS、Flutter等平台提供SVG、图片文件格式的图标。

    1. Octicons
      官网链接:Octicons

    Octicons是GitHub的图标库,这些图标是为“Primer”设计系统创建的,特别是为GitHub应用程序创建的。如果您正在构建与GitHub集成的网站或应用程序,那么它是一个完美的选择。

    1. Icons Grommet
      官网链接:Icons Grommet

    Icons Grommet提供一组React.js组件SVG图标,适合在React项目中使用。

    1. CSS.gg
      官网链接:CSS.gg

    CSS.gg提供了大约700个高质量的图标,图标集合有多种格式,包括CSS、SVG、TypeScript、Figma、Adobe XD以及API终端,适合设计人员和开发人员使用。

    1. Typicons
      官网链接:Typicons

    Typicons是一个漂亮的、外观现代的图标集,专为Web、移动应用或桌面应用程序设计。每个图标都有SVG和图标字体格式,不依赖于分辨率,使得它在不同分辨率下都看起来锐利而清晰。

    1. 即时设计资源广场
      官网链接:即时设计资源广场

    即时设计资源广场是即时设计内置的资源社区,涵盖了设计组件、界面设计、设计系统、插画和图标等多种素材。SVG图标库资源丰富多样,样式新颖,除了常见的单色和多色图标外,还包括独特的3D、毛玻璃等风格。

    1. Iconfont-阿里巴巴矢量图标库
      虽然未提供具体链接,但阿里巴巴体验团队打造的Iconfont是一个功能强大且图标内容丰富的矢量图标库,提供矢量图标下载、在线存储、格式转换等功能。
    2. Zondicons
      官网链接:Zondicons

    Zondicons是由UI设计师兼插画家Steve Schoger创作的优质SVG图标库,提供的图标可以免费用于任何数字产品的商业用途。该图标库包含超过250个SVG图标,设计上采用几何风格。

    1. Hawcons
      官网链接:Hawcons

    Hawcons拥有超过500个高质量的用户界面SVG图标,支持SVG、EPS、PNG和PDF等多种常见格式。该库提供六个不同类别的图标,包括文档、体育、天气、表情符号、手势和文件等类型。

    这些网站提供了丰富的免费SVG图标资源,无论是个人项目还是商业项目,都能找到满足需求的图标。希望这份分享对您有所帮助!

  • Clone-Wars仓库收录GitHub热门网站的开源克隆项目

    Clone-Wars仓库收录GitHub热门网站的开源克隆项目

    我们日常使用的许多热门网站和服务,如TikTok、YouTube、Amazon、Netflix、Google翻译等,其实都有开源克隆版本。今天要介绍的这个名为 Clone-Wars​ 的GitHub项目,就像一个巨大的宝藏库,精心收集了100多个此类开源项目,并获得了超过3万颗Star,深受开发者喜爱。

    项目亮点:Clone-Wars 是什么?

    • 一站式集合:Clone-Wars 将GitHub上优秀的开源克隆项目分门别类,涵盖了 Airbnb、Amazon、Instagram、Netflix、TikTok、Spotify、WhatsApp、YouTube 等众多知名平台。
    • 信息详尽:每个收录的项目不仅提供源代码仓库链接,还通常包含在线演示地址、技术栈说明和GitHub Star数量,方便开发者快速评估。
    • 两大类别:项目清单主要分为两部分:
      1. 带教程的克隆项目:适合学习者,通常配有免费视频或文章教程(如来自freeCodeCamp),可一步步跟着实现。
      2. 克隆版与开源替代品:包括用于学习的功能简化版克隆,以及功能完备、可直接部署使用的成熟开源替代软件。

    精选项目举例Clone-Wars 覆盖的范围非常广,以下列举几个有趣的开源替代品:

    1. 笔记/项目管理工具替代
      • Notion/Obsidian 替代:项目推荐了 Zettlr​ (12K Stars),一个专注于写作与出版的开源工作台;以及 Focalboard​ (25K Stars),一个可用于替代 Trello、Notion 的开源项目管理工具。
    2. 内容发布平台替代
      • Medium/WordPress 替代Ghost​ (51K Stars) 是一个强大的开源内容发布平台,支持会员订阅、付费内容和新闻通讯,非常适合独立创作者搭建内容变现网站。
    3. 云存储服务替代
      • Google Drive 替代myDrive​ (4K Stars) 是一个基于 Node.js 和 MongoDB 的开源云存储服务器,可以部署在自有服务器上,完全掌控数据隐私。
    4. 翻译服务替代
      • Google Translate 替代LibreTranslate​ (13K Stars) 是一个开源的机器翻译API,支持自行搭建服务甚至离线使用,是谷歌翻译的开源替代方案。

    此外,项目中还包含Youtube、Netflix、IMDB、Instagram等大量其他平台的克隆版本。

    Clone-Wars 受到了大量开发者的关注和喜爱。

    它把在 GitHub 上开源的热门网站克隆版收罗了起来,例如 Airbnb、Amazon、Instagram、Netflix、TikTok、Spotify、WhatsApp、YouTube 等等。

    每一个克隆项目不仅提供了源代码,还包含演示链接、技术栈说明和GitHub Star 梳理。

    01\项目简介

    看这个开源清单,主要包括两大部分:

    ① 带教程的克隆项目 这些开源项目通常配有免费的教学视频或文章,比如来自 freeCodeCamp 或 YouTube 的教程,适合初学者一步步跟着实现。

    ② 克隆或替代项目列表 其中既包括外观类似但功能可能较简单的学习型项目,也包括功能完备、可直接使用的开源替代软件。

    02\项目简介

    ① 笔记软件替代 Clone-Wars 收集了 Zettlr 和 Focalboard 作为 Notion、Obsidian 的开源替代。 Zettlr 已经在 GitHub 上获得 12K 的 Star:这是一款免费开源的「一站式写作与出版工作台」,既能帮你专注于内容创作,又能轻松处理格式导出、引用管理等问题,而且全程不用付费。

    开源地址:https://github.com/Zettlr/Zettlr

    Focalboard 已经在 GitHub 上获得 25K 的 Star: 看了下,这个其实是一个开源的项目管理工具,号称替代 Trello、Notion 和 Asana,帮个人和团队明确、整理、跟踪以及管理各类工作事项。

    开源地址:https://github.com/mattermost-community/focalboard

    ② 内容发布平台替代

    知名内容平台 Medium、Wordpress 的开源替代叫 Ghost。这个 51K 星的开源项目主要用来搭建内容发布平台,支持会员体系、订阅功能和新闻通讯,很适合需要做内容变现或精准触达读者的用户。

    对于独立创作者来说,比如科技博主、旅行作家或者生活方式 KOL,用 Ghost 建个人网站很合适。 可以把日常产出的长文、专栏整理成内容库,再通过会员体系设置不同等级 —— 比如免费用户看基础文章,付费会员解锁深度分析、独家访谈或者专属资源包,直接通过订阅功能实现变现。 另外,还能定期发新闻通讯,把新内容更新、创作思路或者生活片段推给订阅者,拉近和读者的距离,不用依赖第三方社交平台。

    开源地址:https://github.com/TryGhost/Ghost

    ③ 云盘开源替代 叫 myDrive 的开源项目有 4000 人 Star。 基于 Node.js 和 MongoDB 开发的开源云存储服务器,模仿 Google Drive 做的工具,你可以把它部署在自己的服务器或者信任的平台上,之后通过网页浏览器就能访问和管理文件。 和市面上的第三方云盘不一样,用 myDrive 的话,所有数据都在你自己手里,不用依赖别人的服务器,隐私和安全性更有保障。

    ④ 翻译开源替代 这个 13K Star 的开源项目是谷歌翻译的开源替代。 本质上一个免费开源的机器翻译 API,和谷歌翻译、微软 Azure 翻译这类商业服务不一样,它不用依赖第三方平台,翻译引擎靠的是开源的 Argos Translate 库。

    它支持自己搭建服务,还能离线使用,哪怕是新手,跟着简单步骤也能快速 setup 起来。

    谷歌翻译:https://github.com/uav4geo/LibreTranslate

    另外还有 Youtube、Netflix、IMDB、Instagram 等国外知名网站的开源平台或者克隆版本,不一一介绍了。 感兴趣的去开源地址瞧瞧。

    开源地址:https://github.com/TryGhost/Ghost

    ③ 云盘开源替代 叫 myDrive 的开源项目有 4000 人 Star。 基于 Node.js 和 MongoDB 开发的开源云存储服务器,模仿 Google Drive 做的工具,你可以把它部署在自己的服务器或者信任的平台上,之后通过网页浏览器就能访问和管理文件。 和市面上的第三方云盘不一样,用 myDrive 的话,所有数据都在你自己手里,不用依赖别人的服务器,隐私和安全性更有保障。

    开源地址:https://github.com/subnub/myDrive

    ④ 翻译开源替代 这个 13K Star 的开源项目是谷歌翻译的开源替代。 本质上一个免费开源的机器翻译 API,和谷歌翻译、微软 Azure 翻译这类商业服务不一样,它不用依赖第三方平台,翻译引擎靠的是开源的 Argos Translate 库。

    它支持自己搭建服务,还能离线使用,哪怕是新手,跟着简单步骤也能快速 setup 起来。

    谷歌翻译:https://github.com/uav4geo/LibreTranslate

    另外还有 Youtube、Netflix、IMDB、Instagram 等国外知名网站的开源平台或者克隆版本,不一一介绍了。 感兴趣的去开源地址瞧瞧。

    开源地址

    Clone-Wars 覆盖的技术栈还挺广泛的,从前端的 React、Vue、Angular,到后端的 Node.js、Django、Firebase,甚至还有移动端的 Flutter、React Native 等。 不管你是想做全栈练习、学习特定框架,还是想找一个可二次开发的开源替代品,这个项目都能提供丰富的选择。

    项目地址与总结GitHub项目地址  https://github.com/GorvGoyl/Clone-Wars
    总而言之,Clone-Wars​ 是一个极其宝贵的开发者资源库。它极大地节省了人们寻找和学习高质量克隆项目的时间,无论用于学习、练习还是实际部署,都具有很高的参考价值。强烈推荐给每一位对开发感兴趣的读者。

  • 告别付费与广告!这5款开源翻译神器,每一款都是效率法宝

    告别付费与广告!这5款开源翻译神器,每一款都是效率法宝

    查文献时,网页翻译广告满天飞;用APP,动不动就要充会员;好不容易找到个免费的,翻译结果却让人啼笑皆非,比如把 “Python decorator” 译成 “蟒蛇装饰者”…… 这种“翻译焦虑”,是时候终结了!今天为大家精选5款在GitHub上广受好评(均获5K+星标)的开源翻译工具,覆盖从命令行查词、本地神经翻译到前端国际化等不同场景,全部免费、无套路,让你彻底摆脱翻译困扰。

    Translate Shell

    详细介绍

    这是命令行里的“翻译闪电侠”,不用开浏览器、不用装APP,终端里敲个命令就能查单词、翻句子,支持50多种语言互译(中、英、日、韩全涵盖),还能听发音、查词典例句。最绝的是它轻量到离谱——安装包才几百KB,启动快到没感觉,堪称“键盘不离手星人查翻译的救命神器”。

    主要功能

    多语言互译(中英、中日、中韩等50+语言,日常和专业场景都够用);词典级解析(查单词时显示词性、常见搭配、例句,比单纯翻译更懂语法);离线支持(下载语言包后没网也能翻,出差坐飞机也能用);跨工具集成(能嵌到Vim、Emacs里,写代码时选中单词直接翻,不中断思路);语音朗读(支持听英文、日文发音,练听力也方便)。

    应用场景

    程序员看外文文档(遇到“deprecated”“dependency”这类词,终端输“trans deprecated”秒知意思,不用切窗口);学生学外语(记单词时查例句,比如“trans -d 美丽”看英文翻译和用法,比单词APP轻量);职场人写英文邮件(不确定“附件”怎么说,输“trans 附件”,连“attachment”的搭配都给你列出来);甚至看外国剧(复制台词到终端,输“trans 台词内容”,不用等字幕组更新)。

    使用方法

    # 1. 安装(Ubuntu为例,其他系统看官网)
    sudo apt install translate-shell

    # 2. 基本翻译(中英互译)
    trans "你好,世界"  # 中文转英文,输出"Hello, world"
    trans :zh "I love programming"  # 英文转中文,输出"我喜欢编程"

    # 3. 查词典(看单词用法,带例句)
    trans -d good  # 查good的含义,显示"形容词:好的",还有"good at"等搭配例句
    trans -d 编程  # 查"编程"的英文,显示"programming",附带"计算机编程"等场景用法

    # 4. 听发音(需要先装mpg123播放器)
    sudo apt install mpg123
    trans -speak "Python is easy to learn"  # 听英文发音
    trans -speak :zh "开源翻译工具真好用"  # 听中文发音

    项目对比

    比网页翻译快(不用开浏览器输网址,终端直接操作,省3步操作);比翻译APP轻量(APP占内存几百MB,它才几百KB,低配电脑也流畅);比词典工具灵活(词典APP只能查单词,它能翻句子、听发音,场景更全)。喜欢用终端、怕麻烦的人,选它准没错。

    项目地址

    https://github.com/soimort/translate-shell

    Argos Translate

    详细介绍

    这是个“能本地跑的轻量级翻译”,不用连外网、不用调用第三方API,下载语言模型后就能在自己电脑上翻译,支持中、英、法、德等10多种语言,翻译质量比普通机翻好太多,还能集成到其他软件(比如 LibreOffice)。最适合怕数据泄露的人——翻译内容不联网,查敏感文档也放心,堪称“本地翻译的小能手”。

    主要功能

    本地离线翻译(模型下到本地,不用联网,保护隐私);多语言支持(中英、英法、英德等,覆盖主流语言);轻量级部署(模型最小才几十MB,普通电脑也能装,启动快);第三方集成(能嵌到LibreOffice、Chrome插件里,用起来更方便);开源免费(无广告、无会员,所有功能全开放)。

    应用场景

    翻译敏感文档(比如公司英文合同,不想上传到网上,本地翻译更安全);没网时查资料(出差在外没网,用它翻酒店入住单、景点介绍);学生写外文作业(翻作文、论文片段,不用等在线翻译加载);甚至给老人用(简单界面,选语言输内容就出结果,比复杂APP好上手)。

    使用方法

    # 1. 用pip安装(Python 3.8+)
    pip install argostranslate

    # 2. 下载语言模型(以中英互译为例)
    argospm install translate en zh  # 安装英文→中文模型
    argospm install translate zh en  # 安装中文→英文模型

    # 3. 命令行翻译
    argostranslate translate -t zh "Hello, how are you?"  # 英文转中文,输出"你好,你怎么样?"
    argostranslate translate -t en "今天天气很好。"  # 中文转英文,输出"The weather is very nice today."

    # 4. 用GUI界面(适合不喜欢命令行的人)
    argostranslate-gui  # 启动图形界面,选语言、输内容,点翻译就出结果

    项目对比

    比DeepL免费(DeepL免费版有字符限制,付费版贵,它全免费);比Google翻译本地(Google翻译要联网且数据可能上传,它本地跑,隐私更安全);比Translate Shell翻译质量高(Translate Shell偏词典级,它是神经翻译,翻句子更通顺)。想本地翻译、怕隐私泄露的人,选它没错。

    项目地址

    https://github.com/argosopentech/argos-translate

    OpenNMT

    详细介绍

    这是个“专业级神经机器翻译框架”,适合想自己训练翻译模型的人——不管是训练“中文→小语种”模型,还是优化现有翻译(比如针对游戏、医疗领域),它都能搞定。支持TensorFlow、PyTorch,文档超详细,还有现成的预训练模型,堪称“翻译领域开发者的‘造轮子’神器”。

    主要功能

    神经机器翻译(基于Transformer架构,翻译质量比传统统计翻译好);多框架支持(兼容TensorFlow、PyTorch,开发者不用换工具);预训练模型多(提供中英、英德等现成模型,下载就能用,不用从零训);自定义训练(能喂自己的数据集,训练领域专属模型,比如“游戏术语翻译”);多语言支持(能做多语言互译,比如同时支持中英、中日)。

    应用场景

    企业做领域翻译(比如医疗公司训练“医学文献翻译”模型,翻专业术语更准);开发者做翻译工具(基于它开发专属翻译APP/API,比如针对外贸的“产品描述翻译”);研究人员做NLP(用来实验新的翻译算法,文档全,上手快);甚至高校教学(教神经机器翻译原理,用它做实验案例)。

    使用方法

    # 1. 用Docker快速体验(不用装复杂依赖)
    docker pull opennmt/opennmt-tf:latest

    # 2. 下载预训练模型(中英互译)
    wget https://s3.amazonaws.com/opennmt-models/tf/ende_wmt19.tar.gz
    tar -xzf ende_wmt19.tar.gz  # 这里是英德模型,中英模型可查官网

    # 3. 命令行翻译(用预训练模型)
    echo "Hello world" | docker run -i opennmt/opennmt-tf:latest
      translate --model ende_wmt19/model.ckpt --vocab ende_wmt19/vocab.txt
      --source_lang en --target_lang de  # 英文转德文,输出"Hallo Welt"

    # 4. 训练自己的模型(简单示例,详细看文档)
    # 准备数据集(src.txt存源语言,tgt.txt存目标语言)
    echo "我爱编程" > src.txt
    echo "I love programming" > tgt.txt

    # 开始训练(用PyTorch版本)
    pip install opennmt-py
    onmt_preprocess -train_src src.txt -train_tgt tgt.txt -save_data data
    onmt_train -data data -save_model my_model

    项目对比

    比Google Cloud Translation灵活(Google是API调用,它能自己训模型,适合定制);比Hugging Face Transformers更专注翻译(Hugging Face是通用NLP,它专门做翻译,功能更全);比传统翻译框架(如Moses)先进(基于Transformer,翻译质量更高,速度更快)。需要定制翻译模型的开发者,它是行业标准级选择。

    项目地址

    https://github.com/OpenNMT/OpenNMT-tf(TensorFlow版);https://github.com/OpenNMT/OpenNMT-py(PyTorch版)

    Lingva Translate

    详细介绍

    这是Google翻译的“开源无广告平替”,界面和Google翻译几乎一模一样,能翻文本、网页、文档,还能切换多种语言,但没有广告、不用登录,甚至能自己部署到服务器,对接Google翻译API(免费额度内)。不用再忍受Google翻译的弹窗广告,也不用怕登录后数据被跟踪,堪称“喜欢Google翻译但烦广告的救星”。

    主要功能

    Google翻译同款界面(操作逻辑一样,用惯Google的人零门槛上手);无广告无登录(打开就能用,不用点掉弹窗,不用输账号);多功能支持(文本翻译、网页翻译、文档翻译,Google有的它基本都有);自建部署(能部署到自己的服务器,避免API调用限制,更稳定);隐私保护(不收集用户翻译内容,比官方版更安全)。

    应用场景

    日常查翻译(翻句子、单词,界面干净,没有广告打扰);翻译网页(复制外文网页链接,它能整页翻译,比浏览器插件快);翻译文档(上传Word、PDF,不用转格式,直接翻内容);团队共享(部署到公司服务器,大家一起用,不用每个人申请Google API)。

    使用方法

    # 1. 用Docker部署(自己搭服务,更稳定)
    docker run -d
      --name lingva-translate
      -p 3000:3000
      -e "LINGVA_DEFAULT_SOURCE=en" 
      -e "LINGVA_DEFAULT_TARGET=zh" 
      thedaviddelta/lingva-translate:latest

    # 2. 访问使用
    打开浏览器访问http://localhost:3000→界面和Google翻译一样
    # 文本翻译:输"Hello, world",选目标语言中文,点翻译秒出结果
    # 网页翻译:在"Web"标签输https://github.com,点翻译,整页变成中文
    # 文档翻译:在"Documents"标签上传英文PDF,选中文,下载翻译后的文件

    # 3. 直接用官方演示站(不用自己部署,适合临时用)
    访问https://lingva.ml→直接用,和自己部署的功能一样

    项目对比

    比Google翻译官方版干净(无广告、无登录,体验更流畅);比其他开源翻译前端功能全(有的只支持文本,它支持网页、文档,更实用);比DeepL网页版灵活(能自建部署,避免地区限制,比如某些地区用不了DeepL)。喜欢Google翻译的界面但烦广告,选它准没错。

    项目地址

    https://github.com/thedaviddelta/lingva-translate

    i18next

    详细介绍

    这是前端开发的“国际化翻译神器”,专门解决APP/网站多语言适配的痛点——不用手动写多语言切换逻辑,它能帮你管理翻译文案、切换语言、处理复数/性别等特殊场景,支持React、Vue、Angular等所有前端框架,生态超全,堪称“前端开发者做国际化的‘扛把子’工具”。

    主要功能

    多框架支持(React、Vue、Angular、Vanilla JS全兼容,不用换工具);文案管理(把翻译文案存在JSON文件里,不用散在代码里,方便维护);特殊场景处理(支持复数、性别、日期格式化,比如英文“1 apple”“2 apples”自动切换);语言切换(一行代码切换语言,界面实时更新,不用刷新页面);插件丰富(能加翻译缓存、API对接、编辑器,功能随你扩)。

    应用场景

    前端做多语言APP(比如做一个支持中、英、日的电商APP,用它管理所有文案);网站国际化(企业官网要支持多语言,用它切换语言,不用写重复代码);小程序多语言(微信小程序、支付宝小程序,用它适配不同地区语言);甚至桌面端应用(Electron开发的桌面APP,用它做国际化,体验一致)。

    使用方法

    # 1. 安装(以React项目为例)
    npm install i18next react-i18next i18next-http-backend i18next-browser-languagedetector

    # 2. 配置i18next(src/i18n.js)
    import i18n from "i18next";
    import { initReactI18next } from "react-i18next";
    import Backend from "i18next-http-backend"; // 加载JSON文案
    import LanguageDetector from "i18next-browser-languagedetector"; // 自动检测语言

    i18n
      .use(Backend)
      .use(LanguageDetector)
      .use(initReactI18next)
      .init({
        fallbackLng: "zh", // 默认语言中文
        interpolation: { escapeValue: false }, // React已转义,这里关了
      });

    export default i18n;

    # 3. 新建翻译文案(public/locales/zh/translation.json)
    {
      "welcome": "欢迎来到我的网站!",
      "login": "登录",
      "apple": "{{count}}个苹果" // 复数场景
    }

    # 4. 在React组件中使用
    import { useTranslation } from "react-i18next";

    function App() {
      const { t, i18n } = useTranslation();

      // 切换语言到英文
      const changeToEn = () => i18n.changeLanguage("en");

      return (
        <div>
          <h1>{t("welcome")}</h1>
          <button onClick={changeToEn}>切换到英文</button>
          <p>{t("apple", { count: 2 })}</p> // 输出"2个苹果"
        </div>
      );
    }

    export default App;

    项目对比

    比React-intl生态广(React-intl只支持React,它支持所有前端框架,复用性强);比vue-i18n功能全(vue-i18n只支持Vue,它能处理更复杂的场景,比如复数、性别);比手动写多语言灵活(手动写要维护大量if-else,它用JSON管理文案,切换语言一行代码)。前端做国际化,它是行业首选工具。

    项目地址

    https://github.com/i18next/i18next


    这5个开源翻译神器是不是各有神通?我用Translate Shell看英文文档,不用切窗口秒查单词;用i18next做前端项目,多语言切换超省心!