图像分割的必比赛,发现比赛的时候已经只剩一个多星期了,最后初赛勉强排在120名,做一下记录。
数据
训练:4716150141,7747046050
测试:3724119903,2593628832
首先训练要对训练集进行切割,在预测的时候要先切割再预测,再合并。训练集切割和测试集切割不一样,训练集切割的图像可以有交集,如果测试集图像有交集切割不太方便合并,故分为两部分代码。
代码都是由参加比赛的大神们写的,只是做了简单修改,侵删。
训练集切割代码:
import os
from tqdm import tqdm
import openslide
import numpy as np
# import matplotlib.pyplot as plt
from PIL import Image
# from itertools import groupby
# from skimage import measure
from matplotlib import image
# %matplotlib inline
def get_label(mask):
"""通过传入的mask判断所属类别"""
"""可能同时存在三种类别,所以定义返回值为list"""
return [label for label in [1,2,3] if mask[mask==label].size > 0 ]
def convert(slide_image,slide_mask,img_dir,mask_dir,root_img_name,stride=350,img_size=400):
"""
:param slide_image :the big root_image
:param slide_mask :the big root_mask
:param img_dir :crop_train_img_dataset_dir
:param mask_dir :crop_train_mask_dataset_dir
:param root_img_name:原卫星图片的名字
:param stride :滑动步长
:param img_size :剪切图片大小
"""
width,height = slide_image.dimensions
root_img_name = root_img_name.split('.')[0] # 去除.png后缀
for w_s in tqdm(range(0,width,stride)):
for h_s in range(0,height,stride):
img = np.array(slide_image.read_region((w_s,h_s), 0, (img_size,img_size) ))[:,:,:3]
if len(np.flatnonzero(img))/(img_size*img_size) < 0.75: # 图像占比0.75才保存图像
continue
image_name = root_img_name + "_" +str(w_s) + "_" + str(h_s)
if slide_mask:
mask_label = np.array(slide_mask.read_region((w_s,h_s), 0, (img_size,img_size) ))[:,:,:3]
label_list = get_label(mask_label[:,:,:1])
if not label_list: # 如果该mask中没有标签,则跳过
continue
#mask_label = np.squeeze(mask_label)# 降维
image.imsave(os.path.join(mask_dir, image_name+".png"), mask_label)
# 保存切片图像
image.imsave(os.path.join(img_dir, image_name+".png"), img)
def creat_dataset(root_dir,root_img_name,root_mask_name,img_dir_save,mask_dir_save):
"""
:param root_dir :图片数据与mask数据的根目录
:param root_img_name :原卫星图片的名字
:param root_mask_name:原卫星mask图片的名字,测试集没有为False
:param img_dir_save :切片图片保存的路径
:param mask_dir_save :切片mask图片保存的路径,测试集没有为False
"""
slide_image = openslide.open_slide(os.path.join(root_dir, root_img_name)) # image_1.png
slide_mask = False
if root_mask_name:
slide_mask = openslide.open_slide(os.path.join(root_dir, root_mask_name)) # image_1_label.png
convert(slide_image,slide_mask,img_dir_save,mask_dir_save,root_img_name)
if __name__ == "__main__":
Image.MAX_IMAGE_PIXELS = 4000000000
train_dir = './data/jingwei_round1_train_20190619/'
img_train_dir_save = "./data/unet_train_400/image/"
mask_train_dir_save = "./data/unet_train_400/label/"
test_dir = './data/jingwei_round1_test_a_20190619/'
img_test_dir_save = "./data/unet_test_513/image/"
# 创建保存目录
for file_dir in [img_train_dir_save,mask_train_dir_save,img_test_dir_save]:
if not os.path.exists(file_dir): os.makedirs(file_dir)
train_imge_list = os.listdir(train_dir)
test_imge_list = os.listdir(test_dir)
for img_index in range(0,len(train_imge_list),2):
'''train_dataset'''
img_name = train_imge_list[img_index]
mask_name = train_imge_list[img_index+1]
creat_dataset(train_dir,img_name,mask_name,img_train_dir_save,mask_train_dir_save)
#'''test_dataset'''
#img_name = test_imge_list[img_index]
#mask_name= False
#mask_test_dir_save=False
#creat_dataset(test_dir,img_name,mask_name,img_test_dir_save,mask_test_dir_save)
测试集切割代码:
# 分割遥感图片
from osgeo import gdal
import numpy as np
import cv2
import os
np.set_printoptions(threshold=np.inf) #print not show ...
# 要拆分的图片大小
split_width = 400
split_height = 400
# 图片所在路径
data_dir = "./data/jingwei_round1_test_a_20190619"
files = os.listdir(data_dir)
# 图片保存路径
save_path = "./data/crop"
if not os.path.exists(save_path):
os.mkdir(save_path)
for img_file in files:
# 去掉图片的后缀名作为图片保存的文件夹
file_base = img_file[0:len(img_file)-4]
save_file_dir = os.path.join(save_path, file_base)
if not os.path.exists(save_file_dir):
os.mkdir(save_file_dir)
file_path = os.path.join(data_dir, img_file)
dataset = gdal.Open(file_path)
rows = dataset.RasterXSize
cols = dataset.RasterYSize
description = dataset.GetDescription()
raster_count = dataset.RasterCount
print("file name = {}, description = {}, raster count = {}, cols = {}, rows = {}".format(file_path, description, raster_count, cols, rows))
split_row_count = int(rows/split_width) + 1
split_col_count = int(cols/split_height) + 1
# 获取RGBA通道,因为A通道都是255感觉没用,所以不保存A通道
print("row = {}, row count = {}".format(rows, split_row_count))
band_r = dataset.GetRasterBand(3)
band_g = dataset.GetRasterBand(2)
band_b = dataset.GetRasterBand(1)
for i in range(split_row_count):
print("row index = {}, count = {}".format(i, split_row_count))
for j in range(split_col_count):
xoffset = i * split_width
yoffset = j * split_height
width = split_width
height = split_height
if i == split_row_count - 1:
width = rows - xoffset
if j == split_col_count - 1:
height = cols - yoffset
print("column index = {}, count = {}, x offset = {}, yoffset = {}, width = {}, height = {}".format(j, split_col_count, xoffset, yoffset, width, height))
r = band_r.ReadAsArray(xoffset, yoffset, width, height)
g = band_g.ReadAsArray(xoffset, yoffset, width, height)
b = band_b.ReadAsArray(xoffset, yoffset, width, height)
img = cv2.merge([r, g, b])
file_save_path = os.path.join(save_file_dir, "{}_{}_{}.png".format(file_base[len("image_"):], i, j))
cv2.imwrite(file_save_path, img)
测试集合并代码
# 合并label
import PIL.Image as Image
import os
import cv2
import numpy as np
Image.MAX_IMAGE_PIXELS = None
# 将要合并的label图片的大小
WIDTH = 513
HEIGHT = 513
def merge(index):
# label保存的路径,比如我保存的文件夹名称时label_3,label_4
IMAGES_PATH = 'label_{}'.format(index)
SAVE_DIR = 'prediction'
IMAGE_SAVE_PATH = '{}/image_{}_predict.png'.format(SAVE_DIR, index)
image_files = os.listdir(IMAGES_PATH)
if not os.path.exists(SAVE_DIR):
os.mkdir(SAVE_DIR)
max_row = 0
max_col = 0
row_pixels = 0
col_pixels = 0
# 获取行列信息,我的label命名是按 col_row.png命名的,如12_34.png代表这个是12列,34行的label
print("get image info...")
for image_file in image_files:
image_path = os.path.join(IMAGES_PATH, image_file)
result = image_file.split('_')
col = int(result[0])
row = int(result[1].split('.')[0])
if row > max_row:
max_row = row
if col > max_col:
max_col = col
size = Image.open(image_path).size
width = size[0]
height = size[1]
if row == 0:
row_pixels += width
if col == 0:
col_pixels += height
max_row += 1
max_col += 1
print("new image...")
to_image = Image.new('L', (row_pixels, col_pixels))
for col in range(max_col):
for row in range(max_row):
sub_image_path = os.path.join(IMAGES_PATH, "{}_{}.png".format(col, row))
sub_image = Image.open(sub_image_path)
size = sub_image.size
left = col * WIDTH
right = left + size[0]
top = row * HEIGHT
bottom = top + size[1]
print("col = {}, row = {}, left = {}, top = {}, right = {}, bottom = {}, height = {}".format(col, row, left, top, right, bottom, size[1]))
to_image.paste(sub_image, (left, top, right, bottom))
print("saving image...")
to_image.save(IMAGE_SAVE_PATH)
if __name__ == "__main__":
indexs = [3,4]
for index in indexs:
print("index = {}".format(index))
merge(index)
用tensorflow开源的deeplabv3+训练
具体过程看这篇文章就可以了 https://blog.csdn.net/qq_38109843/article/details/90944940