任务一:两个赛题数据可视化
- 难度/分值:低/1
打卡内容:
- 参赛选手名称:AppleDoctor
- 完成日期:2023.6.6
- 任务完成情况:
- 使用的编程语言:Python
- 实现的功能:
- 对赛题1的苹果病害数据进行可视化的方法:
- 加载苹果病害图像,并展示图像及其标签;
- 对赛题2的建筑物检测数据进行可视化的方法:
- 加载"吉林一号"高分辨率卫星遥感影像,展示影像;
- 可视化影像中的建筑物变化。
背景介绍
本次打卡任务是 Coggle 30 Days of ML 中的第一项任务,要求完成两个赛题的数据可视化。赛题1是苹果叶片病害识别,提供了九类自然环境下苹果叶片的病害图像数据,参赛选手需要展示图像及其标签。赛题2是建筑物变化检测,提供了"吉林一号"高分辨率卫星遥感影像作为数据集,选手需要展示影像中的建筑物变化。
数据集准备
首先报名并下载数据集,以下是实践比赛地址:
- 赛题1:苹果病害图像识别
- 赛题2:建筑物变化检测
赛题一:苹果病害图像识别
标签分布可视化
接下来,我对苹果病害数据集的标签进行了可视化和分析。首先,我计算了每个类别的数据量,并使用柱状图展示了各类别的数量分布。
root = './datasets/apple' classes_name = ['d1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9'] split = 1.0 train_path, val_path = [], [] class_counts = [] for cls in classes_name: cls_path = glob.glob(f'{root}/train/{cls}/*') class_counts.append(len(cls_path)) print(f"类别 {cls} 数量为: {len(cls_path)}") # 计算训练集和验证集的数量 num_train = int(len(cls_path) * split) num_val = len(cls_path) - num_train # 随机选取80%的数据,存储到训练集列表中 train_path.extend(random.sample(cls_path, num_train)) # 将剩余的20%的数据存储到验证集列表中 val_path.extend(list(set(cls_path) - set(train_path))) # 设置图表样式 plt.style.use('seaborn-whitegrid') # 可视化类别数量 plt.bar(classes_name, class_counts) plt.xlabel('Category') plt.ylabel('Count') plt.title('Category Count') # 在每个柱子上方添加类别数量标签 for i in range(len(class_counts)): plt.text(i, class_counts[i], class_counts[i], ha='center', va='bottom') plt.xticks(rotation=45) plt.show()
从可视化结果可以看出,苹果病害数据集的标签分布是不均衡的。其中,有3个类别的数据超过了1900个样本,而其他类别的数据量不足1000个,甚至有5个类别的数据量只有约300个左右。因此,该数据集的标签分布存在不均衡的情况。
以下是各个类别的数据量统计:
类别 d1 数量为: 292 类别 d2 数量为: 288 类别 d3 数量为: 2227 类别 d4 数量为: 238 类别 d5 数量为: 362 类别 d6 数量为: 260 类别 d7 数量为: 829 类别 d8 数量为: 1928 类别 d9 数量为: 3787
计算平均尺寸
我还计算了所有图像的平均尺寸,以了解图像的大小特征。
total_width = 0 total_height = 0 num_images = len(train_path) # 遍历训练集中的所有图像,求出它们的平均宽度和高度 for image_path in tqdm(train_path): image = Image.open(image_path) width, height = image.size total_width += width total_height += height average_width = total_width / num_images average_height = total_height / num_images print("Average Image Size:") print("Width:", average_width) print("Height:", average_height)
计算得到的平均宽度为990,平均高度为683。
Average Image Size: Width: 990.6477328371365 Height: 683.6091469983352
可视化各个类别图片
为了更好地了解各个类别的特征,我展示了每个类别的前几张图片。
num_images_per_category = 5 # 显示每个类别的前num_images_per_category张图像 for cls in classes_name: cls_path = glob.glob(f'{root}/train/{cls}/*')[:num_images_per_category] fig, axes = plt.subplots(1, num_images_per_category, figsize=(12, 2)) for i, image_path in enumerate(cls_path): image = Image.open(image_path) axes[i].imshow(image) axes[i].axis('off') plt.suptitle(f'Images for Category {cls}') plt.show()
通过以上可视化结果,我们可以观察到各个类别的特征。特别是在d2和d6类别中,它们的特征是最明显的。d2类别代表了黄叶,而d6类别的叶子则有一定程度的腐烂。
赛题二:建筑物变化检测
在建筑物变化检测数据集中,包含三个文件夹,分别是Image1、Image2和label1。
**原始影像:**双时相影像以.tif格式存储,包含R、G、B三个波段。训练集和测试集的影像尺寸均为512x512像素。
**标签数据:**标签以单通道的.png#pic_center格式存储,每个像素的标签值用一个数值表示,使用’uint8’数据类型存储。标签数值表示像素是否发生变化,其中“0”代表未变化,“1”代表变化。标签的尺寸也为512x512像素。
标签分布可视化
plt.figure(figsize=(12, 6)) bar_color = 'skyblue' # 柱状图颜色 bar_width = 0.8 # 柱状图宽度 # 绘制柱状图 bars = plt.bar(labels, counts, color=bar_color, width=bar_width) # 在每个柱状图上方显示标签的数量 for bar in bars: height = bar.get_height() plt.text(bar.get_x() + bar.get_width() / 2, height, height, ha='center', va='bottom', fontsize=8) plt.xlabel('Pixel Label') plt.ylabel('Count') plt.title('Pixel Label Distribution') plt.xticks(rotation=45, ha='right') # 旋转x轴标签 plt.tight_layout() # 调整布局以避免标签被裁剪 plt.show()
通过以上代码,可以得到标签分布的可视化结果。从图中可以看出,“0”代表未变化,“1”代表变化。可以观察到像素标签“0”的数量远大于“1”的数量。具体而言,“0”像素的数量为626,774,703,“1”像素的数量为28,585,297。每个影像的尺寸为512x512像素。
遥感图像可视化
可以看到三列,分别是Image1,Image2和label
root = 'datasets/satellite/train' image_folder1 = 'Image1' image_folder2 = 'Image2' label_folder = 'label1' folder1_path = os.path.join(root, image_folder1) folder2_path = os.path.join(root, image_folder2) label_path = os.path.join(root, label_folder) # 获取文件夹中的TIF图像文件列表 image_files1 = sorted([f for f in os.listdir(folder1_path) if f.endswith('.tif')]) image_files2 = sorted([f for f in os.listdir(folder2_path) if f.endswith('.tif')]) label_files = sorted([f for f in os.listdir(label_path) if f.endswith('.png')]) num_images = min(3, len(image_files1), len(image_files2), len(label_files)) fig, axes = plt.subplots(num_images, 3, figsize=(12, 6)) for i in range(num_images): image_path1 = os.path.join(folder1_path, image_files1[i]) image_path2 = os.path.join(folder2_path, image_files2[i]) label_image_path = os.path.join(label_path, label_files[i]) image1 = Image.open(image_path1) image2 = Image.open(image_path2) label_image = Image.open(label_image_path) axes[i, 0].imshow(image1) axes[i, 0].axis('off') axes[i, 0].set_title(f'{image_files1[i]}') axes[i, 1].imshow(image2) axes[i, 1].axis('off') axes[i, 1].set_title(f'{image_files2[i]}') axes[i, 2].imshow(label_image, cmap='gray') axes[i, 2].axis('off') axes[i, 2].set_title(f'{label_files[i]}') plt.tight_layout() plt.show()