赛题地址:零基础入门语义分割-地表建筑物识别
Datawhale地址:零基础入门语义分割-地表建筑物识别 专题
一、解题思路
- 先用一个基础模型跑通训练过程。搭建好基础框架。
- 在基础模型的基础上,进行数据增广,扩充数据量。划分出验证集,用于训练过程中调参等等。
- 使用更强大的模型进行训练。
- 将多个模型训练的结果进行集成。
二、数据集理解
(一)、RLE 编码与解码
rle是一种有效的二值存储格式,用不同码字来表示连续的黑、白像素数,可以简单有效的对mask进行压缩和解压。
- 编码解码代码如下:
import numpy as np
import warnings
warnings.filterwarnings('ignore')
def rle_encode(im):
'''image to rel
im: numpy array,binary code, 1 - mask, 0 - background
Returns run length as string formated
'''
pixels = im.flatten(order = 'F')
pixels = np.concatenate([[0], pixels, [0]])
runs = np.where(pixels[1:] != pixels[:-1])[0] + 1
runs[1::2] -= runs[::2]
return ' '.join(str(x) for x in runs)
def rle_decode(mask_rle, shape=(512, 512)):
'''rel to image
mask_rle: run-length as string formated (start length)
shape: (height,width) of array to return
Returns numpy array,binary code, 1 - mask, 0 - background
'''
s = mask_rle.split()
starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]
starts -= 1
ends = starts + lengths
img = np.zeros(shape[0]*shape[1], dtype=np.uint8)
for lo, hi in zip(starts, ends):
img[lo:hi] = 1
return img.reshape(shape, order='F')
代码解析:RLE编码解码
2. 测试RLE编码解码,并显示图片
from common_tools.rel_with_image import rle_encode,rle_decode
import pandas as pd
import cv2
from matplotlib import pyplot as plt
if __name__ == "__main__":
train_mask = pd.read_csv('../dataset/train_mask.csv/train_mask.csv', sep='\t', names=['name', 'mask']) # 读取mask数据:(路径,分割符,列名)
# 将训练数据与其mask关联,定位到图片所在物理位置
train_mask['name'] = train_mask['name'].apply(lambda x: '../dataset/train/' + x) # apply会将train_mask的name列字段的图片名传递给x
for i in range(4):
print(train_mask.iloc[i]) # 按行读取
print(train_mask['name'].iloc[i])
print("-" * 20)
# 判断rle编码解码正确性
mask = rle_decode(train_mask['mask'].iloc[40]) # rle编码解析为0和1的二进制mask
print(rle_encode(mask) == train_mask['mask'].iloc[40]) # 将二进制mask用rle编码再判断
print(train_mask.iloc[40]) # 按行读取
print(train_mask['name'].iloc[40])
# 有建筑物测试
img = cv2.imread(train_mask['name'].iloc[40]) # 读取图片
image, mask = img, rle_decode(train_mask['mask'].iloc[40])
plt.subplot(121)
plt.imshow(mask, cmap='gray') # 显示mask
plt.subplot(122)
plt.imshow(image) # 显示图片
plt.show()
# 没有建筑物测试
img = cv2.imread(train_mask['name'].iloc[1]) # 读取图片
image, mask = img, rle_decode(train_mask['mask'].fillna('').iloc[1])
plt.subplot(121)
plt.imshow(mask, cmap='gray') # 显示mask
plt.subplot(122)
plt.imshow(image) # 显示图片
plt.show()
显示图片结果:
(1) 有建筑物
(2)没有建筑物
三、训练模型
根据提供的baseline提供的代码走就可以。如果需要代码,可以评论留言。
四、测试模型
同上。
五、可视化测试的结果
- 代码
from PIL import Image
import pandas as pd
import numpy as np
from common_tools.rel_with_image import rle_encode,rle_decode
from matplotlib import pyplot as plt
subm = pd.read_csv("./tmp.csv",sep="\t",names=["name","mask"])
def show_predict_pic(num=0):
plt.figure(figsize=(16,8))
plt.subplot(121)
plt.imshow(rle_decode(subm.fillna('').iloc[num,1]), cmap='gray')
plt.subplot(122)
plt.imshow(np.array(Image.open('../dataset/test_a/' + subm.iloc[num,0])))
plt.show()
if __name__ == '__main__':
show_predict_pic(num=100)
show_predict_pic(num=1)
- 结果
第100张
第2张
六、作业分析
- 统计所有图片整图中没有任何建筑物像素占所有训练集图片的比例?
分析:根据mask是二值化的数据,只有黑(0)和白(1),黑色表示背景,1表示标注的建筑物。没有任何建筑物则表示其mask的值全为0,mask可视化显示后是一种黑色的背景图片,他们的mask用RLE编码之后是空值。比如train_mask.csv
文件里的DKI3X4VFD3.jpg
- 统计所有图片中建筑物像素占所有像素的比例?
各位看官,如果看到对这个问题进行详细解释的好博客,可以留言推荐,谢谢! - 统计所有图片中建筑物区域平均区域大小?
同上。