资讯详情

Python调用百度AI识别花卉,自动分类整理照片实战

📅 2026/10/7 8:43:27 | 华诺云谱 👁 阅读
Python调用百度AI识别花卉,自动分类整理照片实战
简介这是一份面向Python开发者与AI图像识别初学者的完整项目资源聚焦“识别花卉种类并自动整理分类”的真实任务。项目借助Python脚本调用百度AI开放平台的图像识别接口对花卉照片自动识别分类再结合文件操作模块将照片移动到对应目录内容覆盖图像预处理、API鉴权、结果解析与批量文件整理等关键环节。压缩包内共21个文件包含1个Python主程序、15张png效果截图和5张jpg花卉样张整体大小10.47MBpng直观展示运行过程和识别画面jpg则为待分类的花卉样例方便边看代码边对照验证。此资源发布在CSDN下载频道已有1756人学习浏览特别适合想快速上手第三方AI接口、并希望把图像识别落地到文件自动化整理的开发者。通过阅读源码与附带样例可提升Python调用API、图像数据处理、文件批量整理以及简单项目部署方面的实践能力。1. 识别花卉类型并自动整理先搞清楚这套东西能解决什么先说结论这是一个用 Python 调百度 AI 接口识花、再把同一种花的照片自动归到同一个文件夹的小工具。别人拿它整理一大堆叫不出名字的花卉照片你不用自己训练模型、不用攒数据集只要有一个百度 AI 开放平台的账号跑一个脚本就能把几十上百张图按品种分好。对经常拍花又懒得手动归档的人来说这就是个省事的东西对想学「Python 第三方 AI 接口」怎么落地的人来说它是一份很完整的参考实现涉及接口鉴权、base64 编码、JSON 解析、文件遍历和移动全是实际开发里要过的坎。下面我按自己拆包复现的顺序把这个项目从头到尾捋一遍。2. 环境与接入密钥申请、依赖安装和资源包结构2.1 先去百度 AI 开放平台创建应用拿到 AK/SK整个项目不依赖本地模型识图工作全部发生在云端所以第一步不是装深度学习框架而是先拿到调用凭证。登录百度 AI 开放平台在控制台里创建一个应用服务类型勾选「图像识别」相关的项。创建完成后控制台会给你一对字符串API Key 和 Secret Key后面所有请求都要靠它们换身份令牌。注意密文别随便贴到公开仓库里脚本里写环境变量或者单独放一个 config.py 是我习惯的做法。这一对 Key 本身不能直接调用接口它换的是 Access Token相当于临时通行证。百度返回的 token 有效期默认是 30 天也就是说你不用每次调用都换启动脚本时拿一次、存成全局变量复用就行。我见过有人每识别一张图就重新调一次 token 接口白白把 QPS 额度浪费在鉴权上完全没必要。2.2 拆开下载的 ZIP看清里面哪是代码哪是素材下载下来的压缩包解开以后文件其实分成三类。第一类是核心脚本名字就叫「Python识别花卉种类并自动整理分类.py」整个项目的逻辑都在里面。第二类是「花卉合集」这个目录里面放了一堆待识别的花卉图片是拿来演示和测试用的。第三类是一批 QQ 截图和微信图片仔细看能发现这些是作者调试脚本时留下的界面截图比如识别结果弹窗、命令行输出之类的它们不是程序运行的必要输入只是过程记录。这个区分很重要因为很多人拆包后直接把所有图片扔进脚本的输入目录结果把截图也送去识别返回一堆乱七八糟的分类。正确做法是只把真实的花卉照片放进输入目录截图留着当参照就行。我在复现时就是先在「花卉合集」里挑了几张单独测试确认接口通了再整目录跑。2.3 本地 Python 环境和第三方库这个项目对 Python 版本没有苛刻要求Python 3.8 以上跑起来都没问题。第三方库更简单核心只依赖 requests用来发 HTTP 请求os 和 shutil 是标准库负责遍历目录和移动文件base64 和 json 也都是内置的不需要额外装。如果你机器上连 requests 都没有命令行里执行下面这条就行pip install requests装完可以在 Python 里验证一下python -c import requests; print(requests.__version__)能输出版本号就说明环境没问题。别一上来就装什么 tensorflow、opencv这个项目用不到装了一堆重库反而拖慢环境搭建。等以后你想自己从零训练花卉识别模型再考虑那些也不迟。把依赖控制得越少脚本换机器跑起来越省心。2.4 写一个独立的 token 获取函数先把鉴权跑通在跑完整流程之前我建议你先单独验证一下 token 能不能拿到这样如果后面识别接口报鉴权错误能立刻定位是哪一步出了问题。下面这个函数就是从百度鉴权接口换 token 的import requests API_KEY 你的API Key SECRET_KEY 你的Secret Key def get_access_token(): 从百度AI平台获取访问令牌有效期约30天 url https://aip.baidubce.com/oauth/2.0/token params { grant_type: client_credentials, client_id: API_KEY, client_secret: SECRET_KEY } resp requests.post(url, paramsparams) result resp.json() if access_token in result: print(token获取成功) return result[access_token] else: print(鉴权失败:, result) return None token get_access_token()这段代码里需要注意两点。第一接口用的是 POST 请求但参数是放在 query string 里传的requests 的 params 参数会自动拼到 URL 后面不需要自己拼。第二如果返回结果里没有 access_token别急着改代码先看看错误信息的 error_description多半是 API Key 复制错了或者密钥之间多了空格。token 拿到以后先打印出来确认一下接下来所有识别请求都要带着它。3. 核心代码图片压缩编码、请求识别、结果解析与自动归档3.1 单张图片识别的完整函数鉴权通了以后核心问题就变成怎么把一张图片交给百度识花再拿回一个可信的分类结果。百度的图像识别接口接受 base64 编码的图像数据也就是说你得先把图片文件读出来、转成 base64 字符串然后塞进 POST 请求的 body 里。这里有一个容易被忽略的细节——图片体积。百度图像识别接口对请求图片大小有限制通常要求编码后不超过 4MB最好是压缩到 1MB 以内再传。我试过直接把手机原图发过去结果接口返回图片过大错误。所以正规一点的写法是先把图片用 PIL 或者 OpenCV 压缩一下不过为了不引入额外依赖也可以用下面这个更轻的办法先读文件如果超过阈值就直接报错提示用户。下面是单张识别的核心函数import base64 import requests ACCESS_TOKEN token # 上一步拿到的token def recognize_flower(image_path): 识别单张图片中的花卉种类返回置信度最高的结果 with open(image_path, rb) as f: image_data base64.b64encode(f.read()) url https://aip.baidubce.com/rest/2.0/image-classify/v1/plant ?access_token ACCESS_TOKEN params {image: image_data} # top_num表示返回前几个候选结果我们这里取5个用于后续比对 params[top_num] 5 headers {Content-Type: application/x-www-form-urlencoded} resp requests.post(url, dataparams, headersheaders) result resp.json() if result in result: top_result result[result][0] name top_result[name] score top_result[score] return name, score, result[result] else: print(识别失败:, result) return None这个函数做了三件事读图并转 base64、带 token 调植物识别接口、解析返回结果取最高置信度的候选。代码里用到了植物识别接口/plant它返回的 result 是一个列表每一项包含花卉名称 name 和置信度 score列表顺序按置信度从高到低排。我特意把 top_num 设成 5因为很多时候第一名不可信比如置信度只有 0.55第二名 0.44这种时候就要怀疑图片拍得不清楚或者花形不典型。3.2 遍历目录、处理同名冲突、移动文件到分类文件夹单张识别跑通之后批量整理的核心逻辑就是遍历。这里要处理的问题有两个一是图片格式不统一目录里可能有 .jpg、.png、.jpeg二是最终移动文件时可能遇到重名比如两个目录里各有一张叫 1.jpg 的图都识别成月季直接移动后一张会覆盖另一张。我一般用目标文件夹内添加时间戳的办法解决保证文件名唯一。import os import shutil from datetime import datetime def organize_photos(input_dir, output_dir, threshold0.6): 遍历输入目录识别每张图片并按结果移动到输出目录 valid_ext (.jpg, .jpeg, .png, .bmp) files [f for f in os.listdir(input_dir) if f.lower().endswith(valid_ext)] for idx, filename in enumerate(files): img_path os.path.join(input_dir, filename) print(f[{idx1}/{len(files)}] 识别: {filename}) result recognize_flower(img_path) if result is None: move_unknown(img_path, output_dir, filename) continue name, score, all_results result if score threshold: print(f 置信度不足({score:.2f})移入待人工确认文件夹) move_unknown(img_path, output_dir, filename) continue # 构建目标文件夹路径 target_dir os.path.join(output_dir, name) os.makedirs(target_dir, exist_okTrue) # 加时间戳避免同名文件覆盖 ts datetime.now().strftime(%Y%m%d%H%M%S) new_name f{ts}_{filename} target_path os.path.join(target_dir, new_name) shutil.move(img_path, target_path) print(f 移动至 {name}/{new_name}) def move_unknown(img_path, output_dir, filename): 统一处理识别失败或置信度不足的图片 unknown_dir os.path.join(output_dir, 待人工确认) os.makedirs(unknown_dir, exist_okTrue) ts datetime.now().strftime(%Y%m%d%H%M%S) new_name f{ts}_{filename} shutil.move(img_path, os.path.join(unknown_dir, new_name))这一段里两个设计值得说。第一识别失败和置信度不足走了同一个分支——都塞进「待人工确认」文件夹这个文件夹是最终整理的兜底方案宁可多人工看几张也别让分类错误越滚越大。第二文件移动前先 os.makedirs(target_dir, exist_okTrue) 创建分类目录不管分类名字多古怪都能建出来比如「波斯菊」这种带特殊名词的目录名Windows 下也没问题。3.3 组合成完整脚本跑通整个流程把上面几个函数拼到一起再加一个 main 入口一个能直接运行的脚本就成型了if __name__ __main__: # 输入目录放待整理的花卉照片输出目录按分类生成子文件夹 input_dir ./花卉合集 output_dir ./分类结果 if not os.path.exists(input_dir): print(输入目录不存在请检查路径) exit(1) os.makedirs(output_dir, exist_okTrue) # 先确保token有效 global ACCESS_TOKEN ACCESS_TOKEN get_access_token() if not ACCESS_TOKEN: print(无法获取访问令牌程序终止) exit(1) organize_photos(input_dir, output_dir, threshold0.6) print(全部处理完成)运行方式在命令行里执行python 识别花卉.py跑起来的预期效果是控制台逐条打印当前识别的图片文件名、对应花卉名和置信度「花卉合集」目录里的图片被搬空按品种分到「分类结果」下的子目录里。脚本跑完后你打开「分类结果」看到的应该是「月季」「波斯菊」「向日葵」这类目录名。如果图片本身比较杂还会有一个「待人工确认」目录里面全是置信度没过线的图。3.4 关键参数的解释与调优建议这个项目的参数不多但每个都直接影响结果质量。第一个是 top_num它的含义是返回前几个候选结果建议保持 5 或更大。第二个是 threshold也就是置信度阈值这是最需要调的参数。百度返回的置信度范围是 0 到 1但实际经验里不同花卉种类的分数分布差异很大常见花能到 0.9 以上小众花或者角度刁钻的可能才 0.5 左右。我给出的 0.6 是保守值适合第一批测试。参数推荐值说明top_num5返回候选结果数量太小会影响比对threshold0.6置信度阈值低于此值进入待确认目录输入目录./花卉合集放待整理图片的目录输出目录./分类结果自动生成分类子目录的根目录如果你发现识别结果明显不对比如把菊花识别成向日葵但置信度还挺高这时候别急着降阈值先检查图片本身——是不是把整盆花拍进去了花形太小模型看不到特征。阈值调得再低也救不回来。4. 避坑识别不准、限流、中文路径、文件覆盖四个高频踩坑记录4.1 图片主体太杂接口把花和背景一起识别现象识别出来的名称和实际花卉对不上置信度却高达 0.85。比如拍的是月季结果返回「蔷薇」或者返回一个让人摸不着头脑的品种名。原因百度识花识别的依据是整张图片的视觉特征。如果照片里月季花只占中间一小块四周全是枝叶、天空、地面模型会优先提取全局特征把整棵植物甚至场景特征也纳入判断导致结果偏向「看起来像的东西」。解决识别前先把图片裁剪到主体突出。我一般会给脚本加一个可选参数让待识别图片先经过一次「居中裁剪」只保留图片中央 70% 区域再编码发送。用 PIL 的话一行img.crop()就行。还有一个笨办法但有效——把阈值调高识别结果置信度低于 0.8 的统统丢待确认目录人眼再审一遍。4.2 一次性提交太多图片接口返回 QPS 超限错误现象跑批量整理时前几张很顺利十几张之后连续报错返回的 JSON 里带QPS或者limit字样后续图片全部识别失败。原因百度 AI 接口有并发限制免费配额通常是每秒几次请求。脚本里for循环本身很快图片转 base64 在本地瞬间完成但接口处理需要时间连续快速请求很快就触发了限流。解决在每次请求之间加延时把速率压到安全范围import time # 在organize_photos函数循环内每次识别后等待 time.sleep(1) # 每秒最多1张适配免费配额如果你有更高配额可以把 sleep 间隔缩短到 0.2 秒。这个参数没有统一标准依据你账号的实际配额来定。另外识别和移动文件的逻辑耦合在一个循环里如果中途出错文件已经移动了网络请求又失败会导致目录里文件数量对不上。我会改成先识别完所有图片、把结果存进列表、再统一执行文件移动这样即使中途断网也能从列表中恢复进度。4.3 中文目录名在 Windows 下报找不到路径现象脚本明明就放在和目标文件夹同一个目录下os.listdir也能列出来文件名但拼好路径后shutil.move报文件不存在或者识别完成后文件移到了错误的位置。原因Windows 控制台的默认编码和 Python 内部字符串编码不一致尤其是中文目录名。os.listdir返回的文件名在内存里是 Unicode打印到控制台正常但拼接路径时如果用了错误的编码格式传给文件系统的路径就乱套了。解决最省事的办法是给 Python 脚本开头加一句环境声明让运行时的标准输出用 UTF-8 编码。另外路径拼接统一用os.path.join别手动用字符串加斜杠拼。如果问题依旧就在运行前用chcp 65001把控制台切到 UTF-8 代码页。这个坑在 Windows 上几乎必踩我换了三台机器测试有两台都出现过类似的路径怪问题。4.4 目标文件夹已经有同名文件新文件覆盖了旧文件现象跑完整理后发现「月季」文件夹里图片数量比识别成功的少日志里每张图都显示移动成功但文件数对不上。原因不同来源的图片很多都叫1.jpg、2.jpg移动到同一个分类目录时shutil.move遇到目标已存在会直接覆盖后面的图把前面的同名图顶掉了。解决这个问题我在前面的代码里已经处理过了——移动前先给新文件名加时间戳或序号前缀。这里再强调一遍不只是整理花卉任何批量移动文件的脚本都必须考虑重名。如果你不想在代码里拼时间戳也可以用uuid.uuid4().hex[:8]生成随机前缀效果一样。4.5 识别结果出现多个完全不同的候选到底取哪个现象top_num 返回了 5 个候选结果第一名是「波斯菊」0.58第二名「秋英」0.41第三名「格桑花」0.39名字看起来完全不像让人怀疑接口是不是抽风了。原因这其实不是 bug而是植物命名的常见现象。波斯菊的别名就是秋英、格桑花同一个物种在不同地区叫法不同百度训练数据里这些名字对应不同的类别标签模型在特征空间里对它们的响应都很高。解决遇到这种情况处理原则是「置信度明显领先才自动归档」。我建议在代码里加一道判断第一名和第二名的差距小于 0.1说明模型自己也很犹豫直接送待确认。如果第一名领先很多就直接用那个名字哪怕它和第二名是别名关系也无所谓反正人工复核时一眼就能看出来。5. 进阶改造给整理脚本加日志、加并发、加人工复核机制这个脚本跑通只是起点真正让它在日常使用中不翻车还需要往下走三步。第一步是加日志。纸面上看每条识别结果都有 print 输出但图片一多控制台历史就滚没了。我习惯在每个识别节点追加写入一个classify_log.csv字段包括原文件名、识别名称、置信度、是否被移动、移动后路径。这个 CSV 就是你的后悔药——如果哪张图被错误归档直接按日志找到它原来的位置改回来就行。第二步是加并发。前面为了避开 QPS 限制我让脚本每次请求后 sleep 1 秒当时花 100 张图跑大概两分钟。但实际上百度接口的免费配额虽然低也没低到一次只能请求一张。可以用线程池把速率控制在三秒两请求时间能压到 40 秒左右from concurrent.futures import ThreadPoolExecutor, as_completed def process_one(img_path, output_dir): 单张图片的识别移动交给线程池执行 result recognize_flower(img_path) if result is None or result[1] 0.6: move_unknown(img_path, output_dir, os.path.basename(img_path)) else: name, score, _ result target_dir os.path.join(output_dir, name) os.makedirs(target_dir, exist_okTrue) ts datetime.now().strtime(%Y%m%d%H%M%S) new_name f{ts}_{os.path.basename(img_path)} shutil.move(img_path, os.path.join(target_dir, new_name)) return img_path, result with ThreadPoolExecutor(max_workers3) as executor: futures {executor.submit(process_one, os.path.join(input_dir, f), output_dir) for f in files} for future in as_completed(futures): img_path, result future.result() print(f完成: {img_path} - {result[0] if result else 待确认})并发这里有个边界必须说清楚max_workers3只意味着本地同时发 3 个请求接口那边的 QPS 限制依然存在。如果你账号额度只有每秒一次照样会超限。我的习惯是先在控制台看有没有 QPS 报错有就调回单线程。线程池解决的不是接口额度问题而是本地 CPU 编码和网络等待的并行利用。第三步是人工复核机制的工程化。前面已经把所有低置信度图片丢进了「待人工确认」文件夹但如果没有辅助信息人工确认就是逐张看图再手动拖到对应目录。更好的做法是输出一份未分类图片带截图缩略图的 HTML 清单或者简单点把 CSV 里置信度排名第二、第三的结果也打出来人工比对时有个参照系。你会发现很多花其实识别结果就在前三名里只是第一名的分不够高被阈值拦截了。这种图人工复核成本极低。从那以后我每次批量整理图片前都强制先跑一遍「十张测试」——抽取最多 10 张图片丢进脚本观察置信度分布和输出日志确认阈值设置合理、目录路径没问题再全量跑。这套流程在用百度接口识花时救过我一次后来做别的图像分类整理我也沿用同样的套路。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑