首页 > 分享 > 基于Python的图像分类 项目实践——图像分类项目

基于Python的图像分类 项目实践——图像分类项目

指导文档:https://blog.csdn.net/aiqq136/article/details/114596795

相关资料免费下载:https://download.csdn.net/download/aiqq136/15926986

图像分类项目

我们有了几十张宠物的图像,这些图像的种类都在ImageNet数据集中出现过,我们需要通过CNN模型来帮我们筛选比较一遍,顺便也对模型的识别结果和识别效率进行比较。

需要做的事情:

利用 Python 技能以及调用PaddlePaddle的CNN模型判断哪个图像分类算法最适合将图像分类为“小狗”和“非小狗”图像。需要确定最合适的分类算法在识别小狗品种时的准确率。每个图片名字使用当前认知的小狗的品种进行标记。程序只需将照片的文件名(包含品种信息)与分类算法返回的品种进行对比。找到信息一致或者不一致的小狗是哪些。最后,对于计算任务,通常需要在准确率和运行时之间做出权衡。算法的准确率越高,更有可能需要更长的运行时间和更多的计算资源。所以需要综合比较三种模型的运行时间和准确率。对于每个函数,可以想象为一个功能模块,在这个阶段,学会做系统的模块结构图,以及每个模块的流程图

注意,某些小狗品种看起来非常相似,这些算法区分两个品种的能力只与数据集 (ImageNet) 和算法相当。也就是说,算法从越多的两种外观相似的小狗品种图像中学习规律,就越能够区分这两个品种。对于人类也一样,你看到两个相似品种的小狗图像越多,发现真正的区别,就越能够区分这两种小狗。我们发现以下品种看起来很相似:大白熊犬和白警犬、德牧和玛伦牧羊犬、比格犬和步行猎犬 等等。

最后注意,格雷伊猎犬和澳洲牧羊犬在 ImageNet 中没有图像。因此算法将始终无法正确分类这两个品种,因为之前从未见过这两个品种。算法只能做到将这些图像分类为 ImageNet 中存在图像的相似小狗品种。因此如果需要自己找到图片来测试算法,需要将仅使用 ImageNet 中存在的小狗品种。

主要目标

注意:在线环境如果有不明白的地方,使用https://ai.baidu.com/ai-doc/AISTUDIO/sk3e2z8sb 完成内容后,注意保存自己的项目内容,生成新的版本。

正确标识哪些宠物图像是小狗图像(即使品种分类错误),哪些宠物图像不是小狗图像(无论图像是否分类正确)。针对小狗图像正确判断小狗品种。判断哪个 CNN 模型架构(ResNet、AlexNet 或 VGG)“最适合”实现目标1和2。思考最能实现目标 1和2所需的时间,并判断对于每个算法运行所花费的时间,是否有替代解决方案能够实现更好的效果

任务1:计算代码运行时间

我们的任务的主体代码是在check_images模块里,第一个任务是:添加计算程序运行时间的相应代码(也就是标记为TODO1的地方)。

编写完毕后,该代码将计算程序的总运行时间。后续该代码将衡量三个算法中的每个算法对 pet_images 文件夹中的所有图像进行分类所需的时间。

编写完运行时间计算的代码后,通过使用sleep()函数测试计算运行时间的代码是否运行正确。时间模块的测试包括以下内容:在 sleep() 函数中设置不同的值(秒),检查时长和时间格式。

from time import time, sleep

from os import listdir

start_time = time()

classify_dir='pet_image/'

arch='vgg'

dogfile='dognames.txt'

answers_dic = get_pet_labels()

results_dic = classify_images(classify_dir, answers_dic, arch)

adjust_results4_isadog(results_dic, dogfile)

results_stats_dic = calculates_results_stats(results_dic)

print_results(results_dic, results_stats, arch, True, True)

end_time = time()

run_time = int(end_time-start_time)

hh = run_time // 3600

mm = (run_time % 3600)//60

ss = run_time % 60

print("Run time: {:0>2d}:{:0>2d}:{:0>2d}.".format(hh, mm, ss))

check_time = time()

sleep(1)

if 0.9 < time()-check_time < 1.1:

print("Time module run successfully.")

else:

print("Time module run failed.")

'

运行结果:

[ INFO] - 38 pretrained paramaters loaded by PaddleHub

# Model: vgg

# Total images: 40

# Dog images: 12

# Not dog images: 28

@ Accuracy of Dog: 83.3%

@ Accuracy of Breed: 83.3%

@ Accuracy of Not Dog: 89.3%

@ Accuracy of Prediction: 55.0%

------------------------------Incorrect Dogs------------------------------

| 01. Poodle_07956.jpg

| 02. Poodle_07927.jpg

--------------------------------------------------------------------------

------------------------------Incorrect Breed-----------------------------

| 01. Poodle_07956.jpg

| 02. Poodle_07927.jpg

--------------------------------------------------------------------------

Run time: 00:00:29.

Time module run successfully.

任务2:创建图像标签

任务2(TODO 2)的主要内容需要编写未定义函数get_pet_labels。 在这个函数里函数,需要使用 pet_images 文件夹中的宠物图像的文件名为宠物图像创建标签。这些宠物图像标签标示宠物图像中的动物品种;因此,它们代表了图像分类“真实结果”的标签。

编写完毕后,函数将返回一个字典,字典里包含了pet_image 文件夹中的所有40个宠物图像的键值对:键是宠物图像文件名,值是宠物图像标签。

然后回到调用模块,调用get_pet_labels

测试内容

添加一个临时输出语句,输出 get_pet_labels 函数返回的字典的前 10 个键值对,并输出该字典的长度。字典包含 40 个键值对(例如字典长度为 40)。宠物图像标签全小写,多个单词构成的宠物标签用一个空格区分每个单词,并且正确地标识了文件名。

def get_pet_labels():

pic_repo_addr = "/home/aistudio/pet_image/"

pic_repo = listdir(pic_repo_addr)

dataset = dict()

for pic in pic_repo:

pet_name = pic[:pic.rfind("_")].lower()

dataset[pic] = pet_name

return dataset

'

 测试(不要用)

def get_pet_labels():

"""

这个函数需要最终返回一个基于狗狗图像文件名字的字典。

需要将宠物图像文件名读取后并提取当前宠物图像类别标签。

这个标签最后的作用是用于和我们网络分类结果进行比较,并确定网络分类的正确率。

函数参数Parameters:

image_dir - 完整的文件夹路径,文件夹内存放的所有的待CNN模型识别的狗狗的图像。

函数返回值Returns:

petlabels_dic - 一个存储了图片文件名作为字典KEY,和宠物当前文件名标签作为Value的字典。

"""

from os import listdir

filename_list = listdir("pet_image/")

values=list()

for id in range(0,len(filename_list),1):

pet_image = filename_list[id]

low_pet_image = pet_image.lower()

word_list_pet_image = low_pet_image.split("_")

pet_name =""

for word in word_list_pet_image:

if word.isalpha() :

pet_name += word + ""

pet_name = pet_name.strip()

values.append(pet_name)

pet_dic = dict()

for idx in range(0, len(filename_list),1):

if filename_list[idx] not in pet_dic:

pet_dic[filename_list[idx]] = values[idx]

else:

print("** Warning: Key=", filename_list[idx],"already exists in pet_dic with value =", pet_dic[filename_list[idx]])

for i, (k, v) in enumerate(pet_dic.items()):

if i in range(0, 10):

print("Key=",k," Value=", v)

items_in_dic = len(pet_dic)

print(items_in_dic)

return pet_dic

pass

'

任务3 :使用模型输出的内容为图像进行分类

这个任务需要完成两部分的内容

创建classifier函数,在该函数里调用CNN模型在classify_images函数里使用classifier函数为宠物图像创建标签。

此外,还需要将分类器计算的标签与原始的宠物图像标签进行比较(判断图像标识符是否正确)。

最后,还需要使用 classify_images 返回数据结构存储宠物图像标签、分类器生成的标签和标签比较结果(列表字典结构)。 这个列表字典结构:键是宠物图像文件名,每个值是针对 pet_image 文件夹中所有 40 张宠物图像的列表。这个列表将包含以下条目:宠物图像标签(索引 0)、分类器标签(索引 1),以及标签比较结果(索引 2)。

测试内容

添加输出语句,使用 classify_images 返回的字典输出分类器标签和宠物标签匹配(也就是索引2处值为1的情况)的所有情形。此外,添加另一个输出语句,使用 classify_images 返回的字典输出分类器标签和宠物标签不匹配(也就是索引2处值为0)的所有情形。

建议遍历字典两次,用两个不同的群组输出匹配和不匹配的情形,这样检查起来更简单。

需要检查以下内容:

分类器和宠物图像标签匹配的情形的确匹配分类器和宠物图像标签不匹配的情形的确不匹配匹配数和不匹配数加起来为 40,正好等于 pet_images 文件夹中的图像总数 40。

import paddlehub as hub

resnet_v2_50_imagenet = hub.Module("resnet_v2_50_imagenet")

alexnet_imagenet = hub.Module("alexnet_imagenet")

vgg19_imagenet = hub.Module("vgg19_imagenet")

models = {'resnet': resnet_v2_50_imagenet, 'alexnet': alexnet_imagenet, 'vgg': vgg19_imagenet}

def classifier(image_path, model):

"""

该函数通过加载Paddlehub的预训练模型,调用模型的classification函数,并得到图片的分类结果。

参数:

image_path - 需要识别的图片的完整路径

model -使用这个参数指定预训练的模型,模型值为以下三种: resnet alexnet vgg (string)

返回值:

result - 该图片分类结果label

"""

model = models[model]

res = model.classification(data={"image":[image_path]})

return list(res[0][0].keys())[0].lower().replace(" ", "_")

运行结果:

[2021-03-18 20:41:31,195] [ INFO] - Installing resnet_v2_50_imagenet module

[2021-03-18 20:41:31,306] [ INFO] - Module resnet_v2_50_imagenet already installed in /home/aistudio/.paddlehub/modules/resnet_v2_50_imagenet

[2021-03-18 20:41:31,553] [ INFO] - Installing alexnet_imagenet module

[2021-03-18 20:41:31,571] [ INFO] - Module alexnet_imagenet already installed in /home/aistudio/.paddlehub/modules/alexnet_imagenet

[2021-03-18 20:41:31,713] [ INFO] - Installing vgg19_imagenet module

[2021-03-18 20:41:31,731] [ INFO] - Module vgg19_imagenet already installed in /home/aistudio/.paddlehub/modules/vgg19_imagenet

def classify_images(images_dir, petlabel_dic, model):

"""

使用classifier函数得到40张图片的分类器分类结果,并和前面的图片label进行比较,

最后创建一个字典包含所有的labels以及比较的结果,并将该字典结果返回。

参数:

images_dir - 完整的文件夹路径

petlabel_dic - 包含了宠物图片label的字典,它的key是宠物文件名,它的值是宠物图片label。

model - 使用的模型名称: resnet alexnet vgg (string)

返回值:

results_dic - 本函数生成的新的字典,key是宠物文件名字,值是一个列表

(index)idx 0 = 宠物图片label (string)

idx 1 = 分类器label (string)

idx 2 = 1/0 (int) 1 =两个label一致 and 0 = 两个label不一致

"""

results_dic = dict()

for image in listdir(images_dir):

pred = classifier(images_dir+image, model)

res = [petlabel_dic[image], pred, petlabel_dic[image]==pred]

results_dic[image] = res

return results_dic

'

 

任务4:通过标签识别为小狗或者非小狗

任务4的内容将要编写TODO4处的adjust_results4_isadog函数。

此函数首先读取dognames.txt 文件,然后创建一个数据结构(字典)来存储从文件中获取的有效的小狗名称,将小狗名称与任务3返回的字典 (resutlts_dic)中的分类器标签和宠物图像标签同时进行比较,然后调整结果字典,需要计算出这张图像是“小狗”或“非小狗”。

**注意,adjust_results4_isadog 函数需要更改结果字典(results_dic),results_dic已在项目主体部分定义,但是因为字典可变的,因此函数无需返回此字典。

results_dic,将键设为宠物图像文件名,值设为 pet_image 文件夹中的所有40个宠物图像的列表。每个键列表现在将包含另外两项:宠物图像标签是小狗(索引 3)和分类器标签是小狗(索引 4),详细设置见函数说明。

测试内容

添加输出语句,使用 adjust_results4_isadog 返回的字典输出分类器标签和宠物图像标签匹配的情形。此外,添加其他临时输出语句,使用 adjust_results4_isadog 返回的字典输出分类器标签和宠物标签不匹配的所有情形。

建议遍历字典两次,用两个不同的群组输出匹配和不匹配的情形,这样检查起来更简单。

检查结果应该为:

分类器标签和宠物图像标签匹配的情形都将两种标签相应地分类为“小狗”或“非小狗”分类器标签和宠物图像标签不匹配的情形分别将每个标签正确地分类为“小狗”或“非小狗”匹配数和不匹配数加起来为 40,正好等于 pet_images 文件夹中的图像总数 40。

def adjust_results4_isadog(results_dic, dogsfile):

"""

调整结果字典results_dic的内容,通过和dognames.txt的内容进行比较,找到哪些图片是小狗,哪些图片不是,并标记出来

为后面的统计数据做准备

参数:

results_dic - 结果字典,键key是图片文件名,值是一个列表:

(index)idx 0 = 宠物的图片Label (string)

idx 1 = 分类器给出的label(string)

idx 2 = 1/0 (int) 1 :图片label和分类器label相等 0 = 两个label不相等

--- idx 3 & idx 4 是本函数增加的内容 ---

idx 3 = 1/0 (int) 1 = 图片label是小狗 0 = 图片label不是小狗

idx 4 = 1/0 (int) 1 = 分类器label是小狗 0 = 分类器label不是小狗

dogsfile - 一个包含1000种label的txt文件,里面包含了ImageNet数据集中所有出现过的狗狗种类。

这个文件里每行都有一个小狗种类.

返回值:

None

"""

with open(dogsfile, "r") as f:

dogs = [dog.lower() for dog in f.read().split()]

for image in results_dic:

label, pred, idx2 = results_dic[image]

results_dic[image] = [label, pred, idx2, label in dogs, pred in dogs]

return

results_dic = classify_images(image_dir, get_pet_labels(), "resnet")

adjust_results4_isadog(results_dic, "dognames.txt")

模块5:统计狗狗图像情况

这个任务将会涉及各项百分比计算结果。 即将编写的模块函数是:calculates_results_stats。对于此函数,接收的输入为results_dic(来自 adjust_results4_isadog 的列表字典),然后创建结果统计信息字典 (results_stats)。此结果字典将仅包含统计量的名称作为键,值将为统计量的数字值。

建议:在函数的第一行创建此字典,并在函数的最后一行返回值。

这段任务将能够提供前面我们需要统计内容的计数和百分比值。统计的内容包括:哪些是小狗图像,哪些不是小狗图像,同时针对小狗图像,能够分辨其品种,我们的程序的准确率应该是多少?

results_stats 最后的格式为:

键 = 统计量的名称(例如 n_correct_dogs、pct_correct_dogs、n_correct_breed、pct_correct_breed) 值 = 统计量的值(例如 30、100%、24、80%) 例如:example_dictionary = {'n_correct_dogs': 30, 'pct_correct_dogs': 100.0, 'n_correct_breed': 24, 'pct_correct_breed': 80.0}

在这个过程中,需要统计的量有:

Z 图像数量:这是results_dic 的长度,因为文件名 = 键A 小狗匹配正确的数量:两个标签都是小狗:results_dic[key][3] = 1 及 results_dic[key][4] = 1B 小狗图像的数量:宠物标签是小狗:results_dic[key][3] = 1C 正确非小狗匹配项的数量 两个标签都不是小狗:results_dic[key][3] = 0 及 results_dic[key][4] = 0D 非小狗图像的数量 图像数量减去小狗图像数量 或者宠物标签不是小狗:results_dic[key][3] = 0E 正确品种匹配项的数量 宠物标签是小狗并且标签匹配:results_dic[key][3] = 1 及 results_dic[key][2] = 1Y 标签匹配项的数量 标签匹配:results_dic[key][2] = 1

另外需要计算的百分比有(对应前面统计量的字母标号来看):

正确分类的小狗图像所占百分比 A:正确分类的小狗图像数量B:小狗图像数量正确分类为小狗的图像所占百分比:A/B * 100正确分类的非小狗图像所占百分比 C:正确分类的非小狗图像数量。D:非小狗图像数量正确分类为非小狗的图像所占百分比:C/D * 100正确分类的小狗品种所占百分比 E:正确分类为特定品种的_小狗_图像数量。B:_小狗_图像数量正确分类的_小狗_品种图像所占百分比:E/B * 100百分比标签匹配数(无论是否为小狗) Y:标签匹配数量Z:图像数量正确匹配的图像所占百分比(无论是否为小狗):Y/Z * 100

测试内容

检查模块5的计算结果是否正确。

def calculates_results_stats(results_dic):

"""

这个函数用于对results_dic中的数据进行统计。

参数:

results_dic - 结果字典,键key是图片文件名,值是一个列表:

(index)idx 0 = 宠物的图片Label (string)

idx 1 = 分类器给出的label(string)

idx 2 = 1/0 (int) 1 :图片label和分类器label相等 0 = 两个label不相等

--- idx 3 & idx 4 是本函数增加的内容 ---

idx 3 = 1/0 (int) 1 = 图片label是小狗 0 = 图片label不是小狗

idx 4 = 1/0 (int) 1 = 分类器label是小狗 0 = 分类器label不是小狗

返回值:

results_stats - 统计结果字典,键是统计的类型,值是统计的结果。

"""

A = 0

B = 0

C = 0

D = 0

E = 0

Y = 0

Z = 0

for image in results_dic:

Z += 1

result = results_dic[image]

if result[3] and result[4]:

A += 1

if result[3]:

B += 1

if not result[3] and not result[4]:

C += 1

if not result[3]:

D += 1

if result[3] and result[2]:

E += 1

if result[2]:

Y += 1

results_stats = {"n_images": Z, "n_correct_dogs": A, "n_dogs": B, "pct_correct_dogs": A/B*100, "n_correct_not_dogs": C, "n_not_dogs": D,

"pct_correct_not_dogs": C/D*100, "n_correct_breed": E, "pct_correct_breed": E/B*100, "n_correct_pred": Y, "pct_correct_pred": Y/Z*100}

return results_stats

results_stats = calculates_results_stats(results_dic)

print(results_stats)

运行结果:

{'n_images': 40, 'n_correct_dogs': 10, 'n_dogs': 12, 'pct_correct_dogs': 83.33333333333334, 'n_correct_not_dogs': 25, 'n_not_dogs': 28, 'pct_correct_not_dogs': 89.28571428571429, 'n_correct_breed': 10, 'pct_correct_breed': 83.33333333333334, 'n_correct_pred': 22, 'pct_correct_pred': 55.00000000000001}

任务6:比较模型输出并显示结果

最后一个任务需要编写函数 print_results。此函数将输出 results_dic (adjust_results4_isadog 中的列表字典)和结果统计字典(来自 calculates_results_stats 的 results_stats)。

首先要输出语句,表示针对三个CNN模型架构中的哪个架构以及传入的哪个输入参数 model。 接着,需要针对三个 CNN 模型架构都输出以下三项的计数。

图像数量小狗图像数量非小狗图像数量

最后,遍历 results_stats 字典并输出统计量的名称和所有百分比的值(例如以字母“p”开头的键)。

百分比计算结果:

正确的小狗图像所占百分比正确的品种图像所占百分比正确的非小狗图像所占百分比匹配项所占百分比(可选 - 包括小狗图像和非小狗图像)(可选)输出分类错误的项

可选功能旨在改善代码的调试性能。此外,可以使我们能够判断是否存在一些每种算法都很难判断的小狗品种。

(选作部分):

选择自己有兴趣的宠物图片,增加到pet_image中(注意本项目刚开始的提示)参考PaddleHub中其他预训练模型的文档,增加比较的模型种类。

测试

这个任务不需要流程图,但是需要检查:

运行程序后,正确地输出了统计量和计数并且设定了正确的格式。计算结果的代码检查部分的结果应该与6个统计量输出的结果匹配。在函数调用中保留两个默认参数,不输出分类错误的结果在函数调用中为两个默认参数添加值 True,输出分类错误的结果(预期的行为)

def print_results(results_dic, result_stats, model, print_incorrect_dogs, print_incorrect_breed):

"""

展示我们前面工作的结论

参数:

results_dic - 结果字典,键key是图片文件名,值是一个列表:

(index)idx 0 = 宠物的图片Label (string)

idx 1 = 分类器给出的label(string)

idx 2 = 1/0 (int) 1 :图片label和分类器label相等 0 = 两个label不相等

--- idx 3 & idx 4 是本函数增加的内容 ---

idx 3 = 1/0 (int) 1 = 图片label是小狗 0 = 图片label不是小狗

idx 4 = 1/0 (int) 1 = 分类器label是小狗 0 = 分类器label不是小狗

results_stats - 统计结果字典,键是统计的类型,值是统计的结果。

model - 预训练模型名称: resnet alexnet vgg (string)

print_incorrect_dogs - True- 展示没有正确分类的图片名字 False - 不做展示(bool)

print_incorrect_breed - True- 展示没有正确分类的狗狗品种 False - 不做展示 (bool)

返回值:

None - 没有返回值,本函数用于打印最终的统计展示.

"""

print("# Model: ", model)

print("# Total images: ", results_stats["n_images"])

print("# Dog images: ", result_stats["n_dogs"])

print("# Not dog images: ", result_stats["n_not_dogs"])

print("@ Accuracy of Dog: %.1f%%" % result_stats["pct_correct_dogs"])

print("@ Accuracy of Breed: %.1f%%" % result_stats["pct_correct_breed"])

print("@ Accuracy of Not Dog: %.1f%%" % result_stats["pct_correct_not_dogs"])

print("@ Accuracy of Prediction: %.1f%%" % result_stats["pct_correct_pred"])

if print_incorrect_dogs:

count = 1

print("-"*30+"Incorrect Dogs"+"-"*30+"n")

for image in results_dic:

if results_dic[image][3] and not results_dic[image][2]:

print("| {:0>2d}. {}".format(count, image))

count += 1

print("-"*74)

if print_incorrect_breed:

count = 1

print("-"*30+"Incorrect Breed"+"-"*29+"n")

for image in results_dic:

if results_dic[image][3] and not results_dic[image][2]:

print("| {:0>2d}. {}".format(count, image))

count += 1

print("-"*74)

print_results(results_dic, results_stats, "resnet", True, True)

运行结果:

# Model: resnet

# Total images: 40

# Dog images: 12

# Not dog images: 28

@ Accuracy of Dog: 83.3%

@ Accuracy of Breed: 83.3%

@ Accuracy of Not Dog: 89.3%

@ Accuracy of Prediction: 55.0%

------------------------------Incorrect Dogs------------------------------

| 01. Poodle_07956.jpg

| 02. Poodle_07927.jpg

--------------------------------------------------------------------------

------------------------------Incorrect Breed-----------------------------

| 01. Poodle_07956.jpg

| 02. Poodle_07927.jpg

项目报告

所有任务完成后,需要以小组为单位完成这个项目的报告,报告包括:

任务的分析任务的模块组成每个任务的流程图每个模块的具体实现(含核心代码)实现效果截图以及模型的比较结果对于任务过程中出现问题的解决方案实验心得和改进建议

相关知识

基于Python的图像分类 项目实践——图像分类项目
基于CNN的狗叫,猫叫语音分类
一种基于深度残差网络的宠物图像情绪识别方法
一种基于图像的宠物行为检测方法与流程
基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的鸟类识别系统(Python+PySide6界面+训练代码)
PyTorch 11—简单图像定位
FastAI 课程学习笔记 lesson 1:宠物图片分类
[附开题]flask框架宠物领养系统tusw9(源码+论文+python)
[附开题]flask框架宠物交流平台1n2n3(源码+论文+python)
宠物领养信息平台小程序源码+项目说明.zip资源

网址: 基于Python的图像分类 项目实践——图像分类项目 https://m.mcbbbk.com/newsview171062.html

所属分类:萌宠日常
上一篇: 宠物猫的品种与图片大全
下一篇: CNN简单实战:PyTorch搭