一、使用paddleseg套件對遙感影像預測(基礎)
目前paddleseg套件中的predict.py代碼檔案還不支持直接對遙感影像(大圖)做預測,或者說把遙感大圖直接丟進predict.py,它的預測效果非常差,
基于以上問題,本文結合paddleseg中predict.py原始碼和這篇博文代碼(遙感語意分割切圖預測之后再拼接)重新寫了predict.py代碼,希望可以幫助到使用飛槳框架做遙感影像語意分割的朋友,所以這里需要你會使用paddleseg套件或者對paddleseg原始碼有所了解,這里有位博主寫了一系列有關paddleseg原始碼的文章,值得參考學習(人工智能研習社),
重新寫的predict.py代碼主要分為四個部分
讀取和裁剪遙感大圖 → 網路模型推理預測小圖塊 → 拼接小圖塊預測結果 → 拼接結果寫入檔案
1、讀取待預測遙感大圖,將遙感大圖裁剪成小圖塊,這里裁剪的小圖塊相鄰之間不設定重疊度,小圖塊大小為256x256,
本部分代碼如下:
#讀取需要預測的遙感大圖img_lists[local_rank][local_rank] = /home/aistudio/data/data70483/img.png
ori_image=cv2.imread(img_lists[local_rank][local_rank])
h_step = ori_image.shape[0] // 256 #高度步數
w_step = ori_image.shape[1] // 256 #寬度步數
h_rest = -(ori_image.shape[0] - 256 * h_step) #剩余行數
w_rest = -(ori_image.shape[1] - 256 * w_step) #剩余列數
seg_list = [] #小圖塊的串列
predict_list = []#預測小圖塊結果的串列
# 回圈切圖
for h in range(h_step):
for w in range(w_step):
# 劃窗采樣
image_sample = ori_image[(h * 256):(h * 256 + 256),
(w * 256):(w * 256 + 256), :]
seg_list.append(image_sample)
seg_list.append(ori_image[(h * 256):(h * 256 + 256), -256:, :])
for w in range(w_step - 1):
seg_list.append(ori_image[-256:, (w * 256):(w * 256 + 256), :])
seg_list.append(ori_image[-256:, -256:, :])
2、利用網路模型推理預測小圖塊,這里的代碼改動不多,但是需要將img_lists[local_rank]引數改成存盤小圖塊的串列seg_list,其他引數的設定根據需要而定,在這里本文只對小圖塊做最普通的推理預測,既不做多尺度預測、也不做滑窗預測(多尺度和滑窗預測是原本predict.py的功能,當然在這里我們也可以用),
本部分代碼如下:
progbar_pred = progbar.Progbar(target=len(seg_list), verbose=1)
with paddle.no_grad():
for i, im in enumerate(seg_list):
ori_shape = im.shape[:2] #原始圖片形狀(h,w)
im, _ = transforms(im) #im.shape(3, 256, 256) _為None
im = im[np.newaxis, ...] #im.shape(1,3,256,256)
im = paddle.to_tensor(im)
if False:
pred = infer.aug_inference(
model,
im,
ori_shape=ori_shape,
transforms=transforms.transforms,
scales=scales,
flip_horizontal=flip_horizontal,
flip_vertical=flip_vertical,
is_slide=is_slide,
stride=None,
crop_size=None)
else:
pred = infer.inference(
model,
im,
ori_shape=ori_shape,
transforms=transforms.transforms,
is_slide=False,
stride=None,
crop_size=None)
pred = paddle.squeeze(pred) #該OP會洗掉輸入Tensor的Shape中尺寸為1的維度,查看pred的形狀 應該剩下[h,w]
pred = pred.numpy().astype('uint8')
predict_list.append(pred)
progbar_pred.update(i + 1)
3、將小圖塊的預測結果進行拼接,這里的拼接思想很簡單,就是按照裁剪的順序進行拼接,
本部分代碼如下:
count_temp = 0
tmp = np.ones([ori_image.shape[0], ori_image.shape[1]])
for h in range(h_step):
for w in range(w_step):
tmp[
h * 256:(h + 1) * 256,
w * 256:(w + 1) * 256
] = predict_list[count_temp]
count_temp += 1
tmp[h * 256:(h + 1) * 256, w_rest:] = predict_list[count_temp][:, w_rest:]
count_temp += 1
for w in range(w_step - 1):
tmp[h_rest:, (w * 256):(w * 256 + 256)] = predict_list[count_temp][h_rest:, :]
count_temp += 1
tmp[-257:-1, -257:-1] = predict_list[count_temp][:, :]
4、將拼接結果 tmp 寫入影像檔案中,這里使用了原先predict.py的寫入函式,只是將函式中pred引數改成了tmp,需要注意的是一定要將tmp變數提前轉換為uint8型別,不然程式會報錯,
本部分代碼如下:
tmp = tmp.astype('uint8')
# save added image
added_image = utils.visualize.visualize(args.image_path,tmp, weight=0.6)
added_image_path = os.path.join(added_saved_dir, im_file)
mkdir(added_image_path)
cv2.imwrite(added_image_path, added_image)
# save pseudo color prediction
pred_mask = utils.visualize.get_pseudo_color_map(tmp)
pred_saved_path = os.path.join(pred_saved_dir,
im_file.rsplit(".")[0] + ".png")
mkdir(pred_saved_path)
pred_mask.save(pred_saved_path)
到這里代碼的主體部分基本上搞定了,值得注意的是paddleseg套件中predict.py會從paddleseg.core 呼叫predict.py,而本文為了方便移植代碼,就將兩個predict.py寫成了一個predict.py,
當時寫的第一個版本predict.py將裁剪的小圖塊尺寸設定為了256,同時將inference有些引數都設定死了,所以不推薦直接copy使用,僅作為參考學習,第一個版本predict.py完整代碼如下:
import sys
import argparse
import os
import paddle
from paddleseg.cvlibs import manager, Config
from paddleseg.utils import get_sys_env, logger
import math
import cv2
import numpy as np
from paddleseg import utils
from paddleseg.core import infer
from paddleseg.utils import progbar
def mkdir(path):
sub_dir = os.path.dirname(path) #去掉檔案名,回傳目錄
if not os.path.exists(sub_dir):
os.makedirs(sub_dir)
def partition_list(arr, m):
"""split the list 'arr' into m pieces"""
n = int(math.ceil(len(arr) / float(m)))
return [arr[i:i + n] for i in range(0, len(arr), n)]
def parse_args():
parser = argparse.ArgumentParser(description='Model prediction')
# params of prediction
parser.add_argument(
"--config", dest="cfg", help="The config file.", default=None, type=str)
parser.add_argument(
'--model_path',
dest='model_path',
help='The path of model for prediction',
type=str,
default=None)
parser.add_argument(
'--image_path',
dest='image_path',
help=
'The path of image, it can be a file or a directory including images',
type=str,
default=None)
parser.add_argument(
'--save_dir',
dest='save_dir',
help='The directory for saving the predicted results',
type=str,
default='./output/result')
# augment for prediction
parser.add_argument(
'--aug_pred',
dest='aug_pred',
help='Whether to use mulit-scales and flip augment for prediction',
action='store_true')
parser.add_argument(
'--scales',
dest='scales',
nargs='+',
help='Scales for augment',
type=float,
default=1.0)
parser.add_argument(
'--flip_horizontal',
dest='flip_horizontal',
help='Whether to use flip horizontally augment',
action='store_true')
parser.add_argument(
'--flip_vertical',
dest='flip_vertical',
help='Whether to use flip vertically augment',
action='store_true')
# sliding window prediction
parser.add_argument(
'--is_slide',
dest='is_slide',
help='Whether to prediction by sliding window',
action='store_true')
parser.add_argument(
'--crop_size',
dest='crop_size',
nargs=2,
help=
'The crop size of sliding window, the first is width and the second is height.',
type=int,
default=None)
parser.add_argument(
'--stride',
dest='stride',
nargs=2,
help=
'The stride of sliding window, the first is width and the second is height.',
type=int,
default=None)
return parser.parse_args()
def get_image_list(image_path):
"""Get image list"""
valid_suffix = [
'.JPEG', '.jpeg', '.JPG', '.jpg', '.BMP', '.bmp', '.PNG', '.png' ,'.tif'
]
image_list = []
image_dir = None
if os.path.isfile(image_path):
if os.path.splitext(image_path)[-1] in valid_suffix:
image_list.append(image_path)
elif os.path.isdir(image_path):
image_dir = image_path
for root, dirs, files in os.walk(image_path): #root=image_path
for f in files:
if os.path.splitext(f)[-1] in valid_suffix:
image_list.append(os.path.join(root, f))
else:
raise FileNotFoundError(
'`--image_path` is not found. it should be an image file or a directory including images'
)
if len(image_list) == 0:
raise RuntimeError('There are not image file in `--image_path`')
return image_list, image_dir #回傳測驗檔案串列
def main(args):
env_info = get_sys_env()
place = 'gpu' if env_info['Paddle compiled with cuda'] and env_info[
'GPUs used'] else 'cpu'
paddle.set_device(place)
if not args.cfg:
raise RuntimeError('No configuration file specified.')
cfg = Config(args.cfg)
val_dataset = cfg.val_dataset
if not val_dataset:
raise RuntimeError(
'The verification dataset is not specified in the configuration file.'
)
msg = '\n---------------Config Information---------------\n'
msg += str(cfg)
msg += '------------------------------------------------'
logger.info(msg)
model = cfg.model
transforms = val_dataset.transforms
#image_list, image_dir = get_image_list('data/UAV_seg/images')
image_list, image_dir = get_image_list(args.image_path)#需要傳入args.image_path引數 這個引數可以是測驗圖片的路徑,也可以是單張圖片的路徑
model_path=args.model_path, #傳入訓練模型的路徑
save_dir=args.save_dir,
aug_pred=False,
scales=1.0,
flip_horizontal=True,
flip_vertical=False,
is_slide=False,
stride=None,
crop_size=None
para_state_dict = paddle.load(model_path[0])
model.set_dict(para_state_dict)
model.eval()
nranks = paddle.distributed.get_world_size()
local_rank = paddle.distributed.get_rank()
if nranks > 1:
img_lists = partition_list(image_list, nranks)
else:
img_lists = [image_list] #串列的串列 img_lists[0] ->串列
added_saved_dir = os.path.join(save_dir[0], 'added_prediction') #偽彩色和原圖疊加
pred_saved_dir = os.path.join(save_dir[0], 'pseudo_color_prediction') #偽彩色預測結果
logger.info("Start to predict...")
############################## 1、裁剪遙感大圖 ########################
#讀取需要預測的遙感大圖img_lists[local_rank][local_rank] = /home/aistudio/data/data70483/img.png
ori_image=cv2.imread(img_lists[local_rank][local_rank])
h_step = ori_image.shape[0] // 256 #高度步數
w_step = ori_image.shape[1] // 256 #寬度步數
h_rest = -(ori_image.shape[0] - 256 * h_step) #剩余行數
w_rest = -(ori_image.shape[1] - 256 * w_step) #剩余列數
seg_list = [] #由遙感大圖裁剪成小圖塊的串列
predict_list = []#預測小圖塊結果的串列
# 回圈切圖
for h in range(h_step):
for w in range(w_step):
# 劃窗采樣
image_sample = ori_image[(h * 256):(h * 256 + 256),
(w * 256):(w * 256 + 256), :]
seg_list.append(image_sample)
seg_list.append(ori_image[(h * 256):(h * 256 + 256), -256:, :])
for w in range(w_step - 1):
seg_list.append(ori_image[-256:, (w * 256):(w * 256 + 256), :])
seg_list.append(ori_image[-256:, -256:, :])
##############################裁剪結束########################
############################## 2、利用網路模型推理小圖塊 ########################
progbar_pred = progbar.Progbar(target=len(seg_list), verbose=1)
with paddle.no_grad():
for i, im in enumerate(seg_list):
ori_shape = im.shape[:2] #原始圖片形狀(h,w)
im, _ = transforms(im) #im.shape(3, 256, 256) _為None
im = im[np.newaxis, ...] #im.shape(1,3,256,256)
im = paddle.to_tensor(im)
if False:
pred = infer.aug_inference(
model,
im,
ori_shape=ori_shape,
transforms=transforms.transforms,
scales=scales,
flip_horizontal=flip_horizontal,
flip_vertical=flip_vertical,
is_slide=is_slide,
stride=None,
crop_size=None)
else:
pred = infer.inference(
model,
im,
ori_shape=ori_shape,
transforms=transforms.transforms,
is_slide=False,
stride=None,
crop_size=None)
pred = paddle.squeeze(pred) #該OP會洗掉輸入Tensor的Shape中尺寸為1的維度,查看pred的形狀 應該剩下[h,w]
pred = pred.numpy().astype('uint8')
predict_list.append(pred)
progbar_pred.update(i + 1)
##############################推理結束########################
############# 3、將預測后的影像塊再拼接起來 ########################
count_temp = 0
tmp = np.ones([ori_image.shape[0], ori_image.shape[1]])
for h in range(h_step):
for w in range(w_step):
tmp[
h * 256:(h + 1) * 256,
w * 256:(w + 1) * 256
] = predict_list[count_temp]
count_temp += 1
tmp[h * 256:(h + 1) * 256, w_rest:] = predict_list[count_temp][:, w_rest:]
count_temp += 1
for w in range(w_step - 1):
tmp[h_rest:, (w * 256):(w * 256 + 256)] = predict_list[count_temp][h_rest:, :]
count_temp += 1
tmp[-257:-1, -257:-1] = predict_list[count_temp][:, :]
##################拼接結束########################
#獲取需要保存的圖片名稱,去掉前面的路徑
# get the saved name
if image_dir is not None:
pass
#im_file = im_path.replace(image_dir, '') #例:將PaddleSeg/data/optic_disc_seg/JPEGImages/P0011.jpg替換為/P0011.jpg
else:
im_file = os.path.basename(img_lists[local_rank][local_rank]) #帶后綴名
if im_file[0] == '/': #去掉/
im_file = im_file[1:]
#############
tmp = tmp.astype('uint8')
# save added image
added_image = utils.visualize.visualize(args.image_path,tmp, weight=0.6)
added_image_path = os.path.join(added_saved_dir, im_file)
mkdir(added_image_path)
cv2.imwrite(added_image_path, added_image)
# save pseudo color prediction
pred_mask = utils.visualize.get_pseudo_color_map(tmp)
pred_saved_path = os.path.join(pred_saved_dir,
im_file.rsplit(".")[0] + ".png")
mkdir(pred_saved_path)
pred_mask.save(pred_saved_path)
# pred_im = utils.visualize(im_path, pred, weight=0.0)
# pred_saved_path = os.path.join(pred_saved_dir, im_file)
# mkdir(pred_saved_path)
# cv2.imwrite(pred_saved_path, pred_im)
#progbar_pred.update(i + 1)
if __name__ == '__main__':
args = parse_args()
main(args)
第二個版本的predict.py將“裁剪遙感大圖”和“拼接小圖塊的預測結果”封裝成了函式,分別為CropBigImage(ImagePath,CropScale) 和 PinJie(predict_list , CropScale , ori_image , h_step , w_step , h_rest , w_rest) ,CropBigImage函式可以將遙感大圖裁剪成任意尺寸的小圖塊,第二個版本的predict.py完整代碼如下:
import sys
import argparse
import os
import paddle
from paddleseg.cvlibs import manager, Config
from paddleseg.utils import get_sys_env, logger
import math
import cv2
import numpy as np
from paddleseg import utils
from paddleseg.core import infer
from paddleseg.utils import progbar
def mkdir(path):
sub_dir = os.path.dirname(path) #去掉檔案名,回傳目錄
if not os.path.exists(sub_dir):
os.makedirs(sub_dir)
def partition_list(arr, m):
"""split the list 'arr' into m pieces"""
n = int(math.ceil(len(arr) / float(m)))
return [arr[i:i + n] for i in range(0, len(arr), n)]
def parse_args():
parser = argparse.ArgumentParser(description='Model prediction')
# params of prediction
parser.add_argument(
"--config", dest="cfg", help="The config file.", default=None, type=str)
parser.add_argument(
'--model_path',
dest='model_path',
help='The path of model for prediction',
type=str,
default=None)
parser.add_argument(
'--image_path',
dest='image_path',
help=
'The path of image, it can be a file or a directory including images',
type=str,
default=None)
parser.add_argument(
'--save_dir',
dest='save_dir',
help='The directory for saving the predicted results',
type=str,
default='./output/result')
# augment for prediction
parser.add_argument(
'--aug_pred',
dest='aug_pred',
help='Whether to use mulit-scales and flip augment for prediction',
action='store_true')
parser.add_argument(
'--scales',
dest='scales',
nargs='+',
help='Scales for augment',
type=float,
default=1.0)
parser.add_argument(
'--flip_horizontal',
dest='flip_horizontal',
help='Whether to use flip horizontally augment',
action='store_true')
parser.add_argument(
'--flip_vertical',
dest='flip_vertical',
help='Whether to use flip vertically augment',
action='store_true')
# sliding window prediction
parser.add_argument(
'--is_slide',
dest='is_slide',
help='Whether to prediction by sliding window',
action='store_true')
parser.add_argument(
'--crop_size',
dest='crop_size',
nargs=2,
help=
'The crop size of sliding window, the first is width and the second is height.',
type=int,
default=None)
parser.add_argument(
'--stride',
dest='stride',
nargs=2,
help=
'The stride of sliding window, the first is width and the second is height.',
type=int,
default=None)
return parser.parse_args()
def get_image_list(image_path):
"""Get image list"""
valid_suffix = [
'.JPEG', '.jpeg', '.JPG', '.jpg', '.BMP', '.bmp', '.PNG', '.png' ,'.tif'
]
image_list = []
image_dir = None
if os.path.isfile(image_path):
if os.path.splitext(image_path)[-1] in valid_suffix:
image_list.append(image_path)
elif os.path.isdir(image_path):
image_dir = image_path
for root, dirs, files in os.walk(image_path): #root=image_path
for f in files:
if os.path.splitext(f)[-1] in valid_suffix:
image_list.append(os.path.join(root, f))
else:
raise FileNotFoundError(
'`--image_path` is not found. it should be an image file or a directory including images'
)
if len(image_list) == 0:
raise RuntimeError('There are not image file in `--image_path`')
return image_list, image_dir #回傳測驗檔案串列
def CropBigImage(ImagePath,CropScale):
ImagePath = ImagePath
CropScale = CropScale
seg_list = []#存盤分割的圖塊
ori_image=cv2.imread(ImagePath)##
h_step = ori_image.shape[0] // CropScale
w_step = ori_image.shape[1] // CropScale
h_rest = -(ori_image.shape[0] - CropScale * h_step)
w_rest = -(ori_image.shape[1] - CropScale * w_step)
# 回圈切圖
for h in range(h_step):
for w in range(w_step):
# 劃窗采樣
image_sample = ori_image[(h * CropScale):(h * CropScale + CropScale),
(w * CropScale):(w * CropScale + CropScale), :]
seg_list.append(image_sample)
seg_list.append(ori_image[(h * CropScale):(h * CropScale + CropScale), -CropScale:, :])
for w in range(w_step - 1):
seg_list.append(ori_image[-CropScale:, (w * CropScale):(w * CropScale + CropScale), :])
seg_list.append(ori_image[-CropScale:, -CropScale:, :])
return seg_list , ori_image , h_step , w_step , h_rest , w_rest
def PinJie(predict_list , CropScale , ori_image , h_step , w_step , h_rest , w_rest):
# 將預測后的影像塊再拼接起來
count_temp = 0
tmp = np.ones([ori_image.shape[0], ori_image.shape[1]])
for h in range(h_step):
for w in range(w_step):
tmp[
h * CropScale:(h + 1) * CropScale,
w * CropScale:(w + 1) * CropScale
] = predict_list[count_temp]
count_temp += 1
tmp[h * CropScale:(h + 1) * CropScale, w_rest:] = predict_list[count_temp][:, w_rest:]
count_temp += 1
for w in range(w_step - 1):
tmp[h_rest:, (w * CropScale):(w * CropScale + CropScale)] = predict_list[count_temp][h_rest:, :]
count_temp += 1
tmp[-(CropScale+1):-1, -(CropScale+1):-1] = predict_list[count_temp][:, :]
return tmp.astype('uint8')
def main(args):
env_info = get_sys_env()
place = 'gpu' if env_info['Paddle compiled with cuda'] and env_info[
'GPUs used'] else 'cpu'
paddle.set_device(place)
if not args.cfg:
raise RuntimeError('No configuration file specified.')
cfg = Config(args.cfg)
val_dataset = cfg.val_dataset #用val_dataset?
if not val_dataset:
raise RuntimeError(
'The verification dataset is not specified in the configuration file.'
)
msg = '\n---------------Config Information---------------\n'
msg += str(cfg)
msg += '------------------------------------------------'
logger.info(msg)
model = cfg.model
transforms = val_dataset.transforms
#image_list, image_dir = get_image_list('data/UAV_seg/images')
image_list, image_dir = get_image_list(args.image_path)#需要傳入args.image_path引數 這個引數可以是測驗圖片的路徑,也可以是單張圖片的路徑
model_path=args.model_path #傳入訓練模型的路徑
save_dir=args.save_dir
aug_pred=args.aug_pred
scales=args.scales
flip_horizontal=args.flip_horizontal
flip_vertical=args.flip_vertical
is_slide=args.is_slide
crop_size=args.crop_size
stride=args.stride
para_state_dict = paddle.load(model_path)
model.set_dict(para_state_dict)
model.eval()
nranks = paddle.distributed.get_world_size()
local_rank = paddle.distributed.get_rank()
if nranks > 1:
img_lists = partition_list(image_list, nranks)
else:
img_lists = [image_list] #是串列還是串列的串列,等待測驗 img_lists[0] ->串列的串列
added_saved_dir = os.path.join(save_dir, 'added_prediction') #偽彩色和原圖疊加
pred_saved_dir = os.path.join(save_dir, 'pseudo_color_prediction') #偽彩色預測結果
#主要將遙感大圖裁剪成固定尺寸的圖塊,生成圖塊串列
ImagePath = img_lists[local_rank][local_rank]
CropScale = 256
seg_list , ori_image , h_step , w_step , h_rest , w_rest = CropBigImage(ImagePath,CropScale)
predict_list = []
progbar_pred = progbar.Progbar(target=len(seg_list), verbose=1)
logger.info("Start to predict...")
with paddle.no_grad():
for i, im in enumerate(seg_list):
ori_shape = im.shape[:2] #原始圖片形狀(h,w)
im, _ = transforms(im) #im.shape(3, 512, 512) _為None
im = im[np.newaxis, ...] #im.shape(1,3,512,512)
im = paddle.to_tensor(im)
if aug_pred:
pred = infer.aug_inference(
model,
im,
ori_shape=ori_shape,
transforms=transforms.transforms,
scales=scales,
flip_horizontal=flip_horizontal,
flip_vertical=flip_vertical,
is_slide=is_slide,
stride=stride,
crop_size=crop_size)
else:
pred = infer.inference(
model,
im,
ori_shape=ori_shape,
transforms=transforms.transforms,
is_slide=is_slide,
stride=stride,
crop_size=crop_size)
pred = paddle.squeeze(pred) #該OP會洗掉輸入Tensor的Shape中尺寸為1的維度,查看pred的形狀 應該剩下[h,w]
pred = pred.numpy().astype('uint8')
predict_list.append(pred)
progbar_pred.update(i + 1)
#主要將圖塊的預測結果拼接成大圖
tmp = PinJie(predict_list , CropScale , ori_image , h_step , w_step , h_rest , w_rest)
#############
#獲取需要保存的圖片名稱,去掉前面的路徑
# get the saved name
if image_dir is not None:
pass
#im_file = im_path.replace(image_dir, '') #例:將PaddleSeg/data/optic_disc_seg/JPEGImages/P0011.jpg替換為/P0011.jpg
else:
im_file = os.path.basename(img_lists[local_rank][local_rank]) #帶后綴名
if im_file[0] == '/': #去掉/
im_file = im_file[1:]
# save added image
added_image = utils.visualize.visualize(args.image_path,tmp, weight=0.6)
added_image_path = os.path.join(added_saved_dir, im_file)
mkdir(added_image_path)
cv2.imwrite(added_image_path, added_image)
# save pseudo color prediction
pred_mask = utils.visualize.get_pseudo_color_map(tmp)
pred_saved_path = os.path.join(pred_saved_dir,
im_file.rsplit(".")[0] + ".png")
mkdir(pred_saved_path)
pred_mask.save(pred_saved_path)
logger.info("-"*30+"END"+"-"*30)
if __name__ == '__main__':
args = parse_args()
main(args)
改寫了predict.py原始碼檔案,就要測驗下它的效果,本文用了一張無人機遙感影像,目的是作物分類,如下圖:

為了減輕邊緣效應和拼接痕跡,這里使用重疊度為50%的裁剪方式將原圖裁剪成7000多張256x256的資料集,利用Unet網路對資料集進行訓練,利用本文改寫的predict.py對原圖進行預測,運行predict.py代碼參考如下:!python predict.py --config unet-uav.yml --model_path output/best_model/model.pdparams --image_path /home/aistudio/data/data70483/img.png,其中 –config , –model_path , –image_path 都是需要傳入的引數,有這些引數但不僅限這些引數,預測結果圖如下:


從語意分割的結果來看,感徑訓不錯,不過這里我的訓練集和測驗集是同一個資料集,所以并不能說明網路模型的泛化能力,只能說明網路模型的擬合能力還可以,但是本文目的已經達到了,就是對遙感影像(大圖)預測,
各位小伙伴有任何問題可以在評論中留言,下一篇博文的內容依然是使用paddleseg套件對遙感影像預測,不過下篇博文的方法和以上代碼有所差別,主要是做有重疊度裁剪待預測遙感大圖和忽略相鄰圖塊重疊部分做拼接,目的是為了減輕邊緣效應和拼接痕跡,這對語意分割來說十分重要,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/258732.html
標籤:python
