遥感图像语义分割——从原始图像开始制作⾃⼰的数据集(以⾼分⼆号为例)遥感图像语义分割——从原始图像开始制作⾃⼰的数据集(以⾼分⼆号为例)
⽂章⽬录
这篇⽂章分享⼀下遥感影像语义分割数据集的制作。从原始图像开始,经过影像融合等⼀系列步骤,⽣成⾃⼰的原图+标签形式的数据集。
1.遥感影像获取
本⽂中数据下载⾃中(本⽂的⾼分数据不共享),⽹站内含有付费和部分免费的数据共⼤家下载,具有⾼分系列卫星、资源系列卫星等遥感影像数据。
2.遥感数据预处理(影像融合)
以⾼分系列为例,影像数据压缩包内有⾼分辨率影像和多光谱影像。可以融合形成⾼分辨率多光谱的影像。具有较⾼的空间分辨率也具有多光谱的特征。利⽤ENVI进⾏图像融合的⽅法如下所⽰:
融合⽅法适⽤范围
IHS 变换纹理改善,空间保持较好。光谱信息损失较⼤⼤,受波段限制。
Brovey
变换
光谱信息保持较好,受波段限制。
乘积运算对⼤的地貌类型效果好,同时可⽤于多光谱与⾼光谱的融合。
PCA 变
换
⽆波段限制,光谱保持好。第⼀主成分信息⾼度集中,⾊调发⽣较⼤变化。
GS 改进了 PCA 中信息过分集中的问题,不受波段限制,较好的保持空间纹理信息,尤其能⾼保真保持光谱特征。专为最新⾼空间分辨率影像设
计,能较好保持影像的纹理和光谱信息。
具体⽅法:
1. 在ENVI的Toolbox中打开Image Sharpening/Gram-Schmidt Pan Sharpening,选择⾃⼰的⾼分辨率影像和低分辨率影像(多光
谱),单击OK。
2. 在 Pan Sharpening Parameters ⾯板中,选择传感器类型(Sensor):Unknown,重采样⽅法(Resampling):Cubic
Convolution,以及输出格式。
3.遥感影像批量裁剪
在制作遥感影像数据集中,必不可少的就是遥感影像的批量裁剪到统⼀的尺⼨。本⽂中的⽅法是从栅格影像(tif格式)的裁剪具体代码如下:
import gdal
import os
def read_img(filename):
dataset = gdal.Open(filename)# 打开⽂件
im_width = dataset.RasterXSize # 栅格矩阵的列数
im_height = dataset.RasterYSize # 栅格矩阵的⾏数
im_geotrans = dataset.GetGeoTransform()# 仿射矩阵
im_proj = dataset.GetProjection()# 地图投影信息
im_data = dataset.ReadAsArray(0,0, im_width, im_height)# 将数据写成数组,对应栅格矩阵
del dataset
return im_proj, im_geotrans, im_data
def write_img(filename, im_geotrans, im_data):
# gdal数据类型包括
# gdal.GDT_Byte,
# gdal .GDT_UInt16, gdal.GDT_Int16, gdal.GDT_UInt32, gdal.GDT_Int32,
# gdal.GDT_Float32, gdal.GDT_Float64
# 判断栅格数据的数据类型
if'int8'in im_data.dtype.name:
datatype = gdal.GDT_Byte
elif'int16'in im_data.dtype.name:
datatype = gdal.GDT_UInt16
else:
datatype = gdal.GDT_Float32
# 判读数组维数
if len(im_data.shape)==3:
im_bands, im_height, im_width = im_data.shape
else:
im_bands,(im_height, im_width)=1, im_data.shape
# 创建⽂件
driver = gdal.GetDriverByName("GTiff")# 数据类型必须有,因为要计算需要多⼤内存空间
dataset = driver.Create(filename, im_width, im_height, im_bands, datatype)
dataset.SetGeoTransform(im_geotrans)# 写⼊仿射变换参数
if im_bands ==1:
dataset.GetRasterBand(1).WriteArray(im_data)# 写⼊数组数据
else:
for i in range(im_bands):
dataset.GetRasterBand(i +1).WriteArray(im_data[i])
del dataset
# 有两个⽂件夹bj-5 bj-dx
# 每个⽂件夹下有4副影像
# 遍历每个影像
# 按需修改
area_list =['bj-5','bj-dx']
index_list =['01','02','03','04']
for m in area_list:
for k in index_list:
#图⽚的路径
p ="/home/kun/tif/"+ m +"/"+ k +".tif"
#读取图⽚
im_proj,im_geotrans,im_data = read_img(p)
#获取图⽚的宽、⾼、通道
channel,width,height = im_data.shape
for i in range(width//451):#451修改为⾃⼰需要的宽
for j in range(height//451):#451修改为⾃⼰需要的⾼
cur_img = im_data[:,i*451:(i+1)*451,j*451:(j+1)*451]
#保存图⽚的命名格式(可以⾃⼰修改
write_img('/home/kun/cup-end/{}/{}_{}_{}.tif'.format(m,k,i,j), im_geotrans, cur_img)
4.栅格格式影像转JPG格式
裁剪完的影像格式仍为栅格格式,语义分割需要的是JPG格式的图像。具体的转换代码如下:
import numpy as np
import os
from PIL import Image
from PIL import Image
from osgeo import gdal
def readTif(imgPath, bandsOrder=[3,2,1]):
"""
读取GEO tif影像的前三个波段值,并按照R.G.B顺序存储到形状为【原长*原宽*3】的数组中
:param imgPath: 图像存储全路径
:param bandsOrder: RGB对应的波段顺序,如⾼分⼆号多光谱包含蓝,绿,红,近红外四个波段,RGB对应的波段为3,2,1 :return: R.G.B三维数组
"""
dataset = gdal.Open(imgPath, gdal.GA_ReadOnly)
cols = dataset.RasterXSize
rows = dataset.RasterYSize
data = np.empty([rows, cols,3], dtype=float)
for i in range(3):
band = dataset.GetRasterBand(bandsOrder[i])
oneband_data = band.ReadAsArray()
data[:,:, i]= oneband_data
return data
def stretchImg(imgPath, resultPath, lower_percent=0.5, higher_percent=99.5):
"""
#将光谱DN值映射⾄0-255,并保存
:param imgPath: 需要转换的tif影像路径(***.tif)
:param resultPath: 转换后的⽂件存储路径(***.jpg)
:param lower_percent: 低值拉伸⽐率
:param higher_percent: ⾼值拉伸⽐率
:return: ⽆返回参数,直接输出图⽚
"""
RGB_Array = readTif(imgPath)
band_Num = RGB_Array.shape[2]
JPG_Array = np.zeros_like(RGB_Array, dtype=np.uint8)
for i in range(band_Num):
minValue =0
maxValue =255
# 获取数组RGB_Array某个百分⽐分位上的值
low_value = np.percentile(RGB_Array[:,:, i], lower_percent)
high_value = np.percentile(RGB_Array[:,:, i], higher_percent)
temp_value = minValue +(RGB_Array[:,:, i]- low_value)*(maxValue - minValue)/(high_value - low_value)
temp_value[temp_value < minValue]= minValue
temp_value[temp_value > maxValue]= maxValue
JPG_Array[:,:, i]= temp_value
outputImg = Image.fromarray(np.uint8(JPG_Array))
outputImg.save(resultPath)
def Batch_Convert_tif_to_jpg(imgdir, savedir):
# 获取⽂件夹下所有tif⽂件名称,并存⼊列表
file_name_list = os.listdir(imgdir)
for name in file_name_list:
# 获取图⽚⽂件全路径
img_path = os.path.join(imgdir, name)
# 获取⽂件名,不包含扩展名
filename = os.path.splitext(name)[0]
savefilename = filename +".jpg"
# ⽂件存储全路径
savepath = os.path.join(savedir, savefilename)
stretchImg(img_path, savepath)
print("图⽚:【", filename,"】完成转换")
print("完成所有图⽚转换!")
# 主函数,⾸先调⽤
if __name__ =='__main__':
area_list =['bj-5','bj-dx','pds-and-jn']
for i in area_list:
for i in area_list:
imgdir =r"/home/kun/cup-end/"+ i # tif⽂件所在的【⽂件夹】
savedir =r"/home/kun/cup-end-jpg/"+ i # 转为jpg后存储的【⽂件夹】
Batch_Convert_tif_to_jpg(imgdir, savedir)
5.⽤labelme制作图像标签
众所周知,应⽤很⼴泛的⼀所标注⼯具叫做labelme,接下来介绍labelme环境搭建以及labelme的使⽤。⾸先需要安装并配置好anaconda。打开anaconda prompt(Anaconda命令⾏)。输⼊以下指令:conda create -n labelme python=3.6
待创建完成后,激活labelme环境
conda activate labelme
安装labelme环境
pip install labelme
安装完成后,在labelme环境下输⼊
labelme
即可打开labelme标注⼯具。具体的标注、json格式⽂件的转换等操作参考:。
6.制作txt⽂档(统计训练集、验证集的图⽚名)
批量修改图⽚的⽂件名
具体修改代码如下:
import os
import re
import sys
# 图⽚的路径
file_list = os.listdir('/home/qun/json_jpg')
#⽤于命名
k=0
currentpath = os.getcwd()
os.chdir('/home/qun/json_jpg')
for i in range(0,len(file_list)):
if(file_list[i][-4:]=='json'):
last_name = file_list[i]
# 千张图⽚%04 万张图⽚%05....
for k in range(0,len(file_list)):
if((file_list[k][-3:]=='jpg')&(file_list[k][0:-4]== last_name[0:-5])):
print(file_list[k]+'finsh')
print(file_list[i]+'finsh')
os.chdir(currentpath)
sys.stdin.flush()
读取⽂件名到txt⽂档
import os
# 图⽚的路径
file_path ='/home/qun/torch-deeplabv3/pytorch-deeplab-xception-master/Waste2021/JPEGImages'
list= os.listdir(file_path)
path_name =[]
for i in list:
path_name.append(i.split('.')[0])
for j in range(0,len(path_name)):
getsavefilename
# txt⽂档的路径
with open('/home/qun/torch-deeplabv3/pytorch-deeplab-xception-master/Waste2021/ImageSets/','a')as f: f.write(path_name[j]+'\n')
print(path_name[j])
f.close()
到此为⽌,制作数据集⼤概步骤以及相关的python代码已经展⽰完毕。希望对⼤家有帮助
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论