和上节课一样,我们也将“批量化处理”也拆分成类似的几步完成:
1. 读取所有文件
2.调用通用物体识别
3.提取图像分类信息
4.对应分类文件夹还未创建时,创建文件夹
5.移动图像到对应文件夹
不同的是,本节课的学习重点是完善前三个步骤。
1. 读取所有文件
如图所示,是铭铭文件夹img的部分展示。
我们在读取图像文件之前,需要获取该文件夹下所有文件列表。
获取所有文件
代码的作用
获取文件夹下所有的文件列表,需要先导入os模块。
将路径作为参数传入 os.listdir() 函数,就可以获得一个列表。
输出这个列表,查看文件夹中的所有文件或文件夹的名称。
代码示例:
# 使用import导入os模块
import os
# 将存储照片的文件夹路径'/Users/img'赋值给变量imgroot
imgroot = '/Users/img'
# 使用os.listdir()函数获取该路径下所有文件,并赋值给变量imglist
imglist = os.listdir(imgroot)
# 使用print函数输出变量imglist以确认列表内容
print(imglist)
分析代码:
获取所有文件
获取所有文件的名称,需要使用 os 调用 listdir()函数。
示例中, os.listdir() 就表示调用 listdir() 函数执行获取所有文件的操作。
文件夹路径
os.listdir() 函数中要求传入参数文件夹路径。
要查看文件夹中所有的文件,该文件夹的路径为imgroot ,就将该路径传入到 os.listdir() 函数中。
返回每个文件名
使用 os.listdir() 函数获取文件名后,返回一个列表,列表中的每个元素是文件夹中的每个文件。
这些非图像文件不需要识别也不需要分类,我们可以先将它们排除在外再进行识别和分类操作。
之前我们已经得到了所有的文件(夹)名称,现在使用for循环遍历列表中所有文件(夹)的名称,以便筛除非图像文件。
# 遍历目录下的所有文件名
for imgname in imglist:
# 使用print函数输出变量imgname
print(imgname)
【加入判断条件,剔除非图像文件】
系统文件
与图像文件对比,系统文件常见的名称特点是第一个字符就是"."。
我们可以使用字符串匹配出第一个字符是"."的文件名,用imgname[0] == '.'表示。
文件夹
与图像文件对比,文件夹的特点更为明显,没有后缀名也就是没有"."。
我们可以使用not in语句筛选出不包含"."的文件名,用'.' not in imgname 表示。
接下来,我们使用if判断筛除非图像文件。
1. 筛除系统文件,使用字符串匹配出第一个字符是"."的文件名;
2.筛除文件夹,使用not in语句筛选出不包含"."的文件名;
3. 使用or语句将筛除系统文件和文件夹的操作连接起来。
注意⚠️ :在这里,continue语句的作用是,只要符合以上任意一种情况就结束本次循环,进入下一次循环。
确认获取的文件全是图像文件后,我们直接用这个文件名组成路径,作为分类文件夹名。
用字符串拼接的方式拼接变量 imgroot、"/"、变量 imgname,将拼接后的字符串赋值给变量 filePath。
# 使用import导入os模块
import os
# 将存储照片的文件夹路径'/Users/img'赋值给变量imgroot
imgroot = '/Users/img'
# 使用os.listdir()函数获取该路径下所有的照片,并赋值给变量imglist
imglist = os.listdir(imgroot)
# 遍历目录下的所有文件名
for imgname in imglist:
# 使用if判断筛除非图像文件
if imgname[0] == '.' or '.' not in imgname:
# 如果符合if判断条件,跳出本次循环,进入下一次循环
continue
# 组合图像文件路径
filePath = imgroot + '/' + imgname
# 输出图像文件的旧位置
print(filePath)
2.调用通用物体识别
到这里,我们已经完成了读取所有图像文件的操作。
接下来,我们同样调用通用物体识别接口实现对图像物体的识别。
即对'/Users/img'文件夹下所有的图像文件进行识别,输出图像中是动物还是植物,是人物还是风景。
3.提取分类结果
为了解决这个问题,我们可以通过查看返回结果有无参数result来判断是否识别成功。
只需要在之前提取分类结果的代码上加一个判断条件即可。
返回指定键的值
代码的作用
get()函数用于返回指定键的值,如果键不在字典中返回默认值 None 或者设置的默认值。
第1行,定义了一个字典dict
第2行,返回指定键'root'的值
第3行,返回指定键'url'的值
'url'不在字典dict中,返回设置的默认值Nothing
第4、5行,分别输出返回值
示例代码:
dict = {'keyword': '草原', 'score': 0.790905, 'root': '自然风景-草原'}
value1 = dict.get('root')
value2 = dict.get('url', "Nothing")
print(value1)
print(value2)
分析代码:
返回指定键的值
get()函数返回指定键的值,如果键不在字典中返回默认值 空值(None)或者指定的默认值。
书写格式为:
dict.get(key, default=None)
必选参数key
参数key:字典中要查找的键
在这里,root、url都是键。
可选参数default
参数default:如果指定键不在字典中,返回默认值 None 或者指定的默认值。
在这里,url这个键不存在,所以返回了指定的默认值Nothing。
总结:
现在就能确定每个参数'root'返回的信息都包含具体类别的细分了。
但是我们不需要这些细分信息,只需要其中的上层标签即可。
每个上层标签的字符数不一样,有的2个字的,比如动物、植物,有4个字的,比如自然风景。
因此,我们需要将上层标签与具体类别进行拆解。
分隔字符串
代码的作用
要对字符串进行拆解,我们可以使用字符串的内置函数split()。
将分隔符作为参数传入到split()函数中,即可把字符串按照指定分隔符切分成多个字符串组成的列表。
# 将分类信息得到的字符串"自然风景-草原"赋值给value
value = "自然风景-草原"
# 只取分类结果value的上层标签并赋值给变量label
label = value.split("-")[0]
# 使用print()输出变量label
print(label)
分析代码:
拆分字符串
split()函数通过指定分隔符对字符串进行切片,并返回分割后的字符串列表。
其中分隔符默认为空格,但是不能为空('')。
在这里,分隔符就是短横线"-"。
选取切片
split()函数后面的[n]:表示选取第n个切片(从0开始)
在这里,选取的就是列表['自然风景','草原']中的第一个字符串
到这里,我们就完成了前三个步骤的升级。
后面的解题思路与上节课一样,一起来回顾一下吧~
1. 读取所有文件
2.调用通用物体识别
3.提取图像分类信息
4.对应分类文件夹还未创建时,创建文件夹
5.移动图像到对应文件夹
4.对应分类文件夹还未创建时,创建文件夹
1. 用字符串拼接的方式将文件夹和分类结果组成路径,作为分类文件夹名;
2. 使用 if not语句+os.path.exists()函数判断目标文件夹不存在的情况;
3. 如果目标文件夹不存在,使用os.mkdir(targetPath) 创建所有不存在的文件夹。
# 1.读取所有文件
# 使用import导入os模块
import os
# 将存储照片的文件夹路径'/Users/img'赋值给变量imgroot
imgroot = '/Users/img'
# 使用os.listdir()函数获取该路径下所有的照片,并赋值给变量imglist
imglist = os.listdir(imgroot)
# 从aip中导入AipImageClassify
from aip import AipImageClassify
# 将AppID"10252021"赋值给变量APP_ID
APP_ID = '10252021'
# 将API Key"ZHe7788sh11GEjIAdEKeY"赋值给变量API_KEY
API_KEY = 'ZHe7788sh11GEjIAdEKeY'
# 将Secret Key"JMMzHe7788BUSH1ZhEnM1YUEhh"赋值给变量SECRET_KEY
SECRET_KEY = 'JMMzHe7788BUSH1ZhEnM1YUEhh'
# 新建一个AipImageClassify,并赋值给变量client
client = AipImageClassify(APP_ID, API_KEY, SECRET_KEY)
# 遍历目录下的所有文件名
for imgname in imglist:
# 使用if判断筛除非图像文件
if imgname[0] == '.' or '.' not in imgname:
# 如果符合if判断条件,跳出本次循环,进入下一次循环
continue
# 组合图像文件路径
filePath = imgroot + '/' + imgname
# 使用with...as以rb方式,打开路径为filePath的图片并赋值给f
with open(filePath, 'rb') as f:
# 使用read()读取f,赋值给变量image
image = f.read()
# 2.调用通用物体识别
# 调用通用物体识别接口并把结果赋值给ending
ending = client.advancedGeneral(image)
# 3.提取分类结果
# 判断是否识别成功
if "result" in ending:
# 从第一个结果中提取出图像分类并赋值给变量value
# 若没有找到root信息,则分为“未分类“目录
value = ending['result'][0].get('root', '未分类')
# 只取分类结果value的上层标签并赋值给变量label
label=value.split("-")[0]
# 字符串拼接变量imgroot、"/"、变量label并将结果赋值给变量targetPath
targetPath = imgroot + '/' + label
# 4.对应分类文件夹还未创建时,创建文件夹
# 如果目标文件夹不存在
if not os.path.exists(targetPath):
# 使用os.mkdir()函数创建文件夹
os.mkdir(targetPath)
5.移动图像到对应文件夹
1. 导入 shutil 模块;
2. 使用 shutil.move() 函数将识别完成,路径为itemPath的图像移动到路径为targetPath的对应文件夹下。
# 5.移动图像到对应文件夹
# 导入shutil模块
import shutil
# 使用shutil.move()函数移动文件,将图像移动到目标文件夹中
# 将结果赋值给变量newPath
newPath = shutil.move(filePath, targetPath)
# 使用格式化输出“已经移动到:{newPath}”
print(f"已经移动到:{newPath}")
至此,我们要帮助铭铭实现"电脑图像的智能识别和自动分类" 的功能就全部完成啦。
本节课是对上节课的升级,重点是帮助大家解决实现批量化处理的过程中,在读取、识别和提取这三个环节可能会遇到的一些复杂情况。
本节课的代码在电脑上运行的效果如图所示。
可以发现,几乎是一瞬间,几百张照片就全部完成识别分类并移动到指定的文件夹中。
人工智能的便捷之处,你get ✅ 了吗~