精华内容
下载资源
问答
  • 这是五篇关于遥感影像分割分类识别的比较新的文献资料,里面很详述的讲解了一些分割与分类的实用方法与实验结果,希望对大家有用!
  • 行业分类-物理装置-模型训练、医学影像分割方法装置.zip
  • 采用多尺度分割的面向对象分类技术,提出采用"对象完整面积个数最多法"的分割方法,研究得出道路、农田、居民地、裸地、水域的最优分割尺度分别为20、30、50、80100,采用成员函数法对分割后的影像进行分类,并将分类...
  • 针对噪声导致高分辨遥感影像分割存在过分割或者欠分割的问题, 提出结合相位一致分水岭变换的高分辨率影像分割方法。该方法首先采用基于光谱相似性的相位一致的模型方法来获得边缘响应幅度, 再采用自动标记分水岭...
  • 遥感影像分割

    2017-03-14 13:01:05
    文档简单介绍遥感影像尺度分割参数设置
  • 影像分割精度评价方法初探,张世富,,影像分割是基于对象影像分析工作流程的第一个环节,影像的分割精度对影像分类以及分类结果的精度有决定性的影响。目前,影像分割
  • 遥感影像分割成多幅小图像方法

    千次阅读 热门讨论 2020-05-01 21:52:15
    遥感影像分割成多幅小图像方法

    目的

    本人需要将一幅Landsat8影像,切割成多幅256 * 256的小幅影像,用于深度学习相关处理。
    经过在envi中的可视化的裁剪,得到了一幅5130 * 5230的影像,我经过计算,发现可以横向切出
    256 * 20,纵向同样切出256*20 =5120, 共计400幅影像。

    方法

    利用python

    • gdal模块读取影像并存入numpy数组
    • 利用循环和opencv进行写入(实际用的时候要用gdal,可关注我后面有关landsat8处理小工具的博文)
      https://blog.csdn.net/RSstudent/article/details/108724556?spm=1001.2014.3001.5501
      其中代码的329-378行就是所需内容,还附带了地理编码和投影,地理信息不会丢失,可在实际中使用。
    • 利用os模块得到路径

    代码

    import numpy as np
    from osgeo import gdal
    from osgeo import gdal_array
    import cv2
    import os
    
    filename = 'tiffbigcut.tif'
    dataset = gdal.Open(filename)
    
    datatype = dataset.GetRasterBand(1).DataType
    rows = dataset.RasterYSize
    columns = dataset.RasterXSize
    bands = dataset.RasterCount
    image = np.zeros((rows, columns, bands), 
    				dtype = gdal_array.GDALTypeCodeToNumericTypeCode(datatype))
    
    for b in range(bands):
        band = dataset.GetRasterBand(b+1)
        image[:, :, b] = band.ReadAsArray()
    
    image_cut = image[:5120, :5120, :]
    
    for i in range(19):
        for j in range(19):
            image_save = image_cut[i*256:(i+1)*256, j*256:(j+1)*256, :]
            base_dir = os.getcwd()
            dir_name = 'images'
            dir = os.path.join(base_dir, dir_name)
            filename = str(i) + str(j) + '.png'
            path = os.path.join(dir, filename)
            cv2.imwrite(path, image_save)
    

    结果展示

    缩略图没经过2%linear拉伸,颜色显示较差
    在这里插入图片描述

    展开全文
  • 将基于像素MRF分割方法拓展到基于地物目标几何约束的区域MRF分割,提出了一种基于区域统计的纹理影像分割方法,其基本思想是利用Voronoi划分技术将影像域划分为若干子区域。在此基础上,采用二值高斯马尔科夫随机...
  • 针对高分辨率遥感影像中同物异谱同谱异物导致的分割困难问题,提出一种层次高斯混合模型(HGMM)快速遥感影像分割算法.首先采用HGMM构建影像的统计模型,其具有准确建模像素强度统计分布呈现的非对称、重尾多峰等...
  • 医学影像分割是计算机视觉在医学影像处理中的一个重要应用领域,其目标是从医学影像中分割出目标区域,为后续的疾病诊断治疗提供有效的帮助。
  • 首先,通过像素光谱测度定义多种统计特征,根据定义的各个特征提取特征影像并分别实现影像分割,利用其结果构建模糊决策矩阵;然后,基于像素定义特征间的模糊偏好关系矩阵,计算不同特征对最终分割决策的权重,并对模糊...
  • 遥感影像分割方法研究,孔令然,曾繁慧,图像分割是数字图像处理中的一项关键技术,它使得其后的图像分析,识别等高级处理阶段所要处理的数据量大大减少,同时又保留有关
  • MeanShift算法广泛应用于自然场景图像和医学图像分割中,针对MeanShift算法分割遥感图像的边界模糊精度不高的问题,文中提出一种全新...实验结果表明:本方法相比传统的MeanShift遥感影像分割方法能得到更好的分割效果。
  • 行业分类-物理装置-一种通用的基于遥感影像分割单元的地形校正优化方法.zip
  • 本文提出了一种将多尺度分割和支持向量机结合的图像分类算法。该方法可保留的图像光谱信息图像分割几何信息。信息;第二步,使用多尺度分割分割图像进行合并对象,结合图论,考虑了对象的异质性。最后,在分割...
  • 这是一个用于进行SRM影像分割代码,可自己通过设定不同的阈值实现不同尺度的分割。名为SRM_new的M文件为主函数文件。
  • 这篇文章的核心:基于匹配的特征点分割的单元,以配准误差为缓冲半径进行相关运算,并提出了双向相关方法来抑制影像分割不一致对变化检测结果的影响。

    这篇文章的核心:基于匹配的特征点和分割的单元,以配准误差为缓冲半径进行相关运算,并提出了双向相关方法来抑制影像分割不一致对变化检测结果的影响。

    影像配准与分割: (缺乏算法之间的实验对比)
    影像配准:
    影像配准:寻求两幅或多幅影像的像素点对应关系的过程。
    配准的方法:1:基于影像灰度的配准方法;2:基于影像特征的配准方法。

    基于影像灰度的配准方法(被淘汰)
    定义:首先从参考图像中提取目标区作为配准的模板,然后用该模板在待配准图像中滑动,通过相似性度量(如相关系数法、差的平方和法、差的绝对值法、协方差法)来寻找最佳匹配点。
    原因:由于无人机影像的倾角(上下)过大,会使得基于影像灰度的配准方法并不适用。

    基于影像特征的配准方法:
    定义:以图像中某些显著特征(点、线、区域)为配准基元,算法过程分为两步:特征提取和特征匹配。首先从两幅图像中提取灰度变化明显的点、线、区域等特征形成特征集。然后在两幅图像对应的特征集中利用特征匹配算法尽可能地将存在对应关系的特征对选择出来。对于非特征像素点利用插值等方法作处理推算出对应匹配关系,从而实现两幅图像之间逐像素的配准。
    方法分类:
    1:Harris;
    2:SIFT;
    3:加速鲁棒性特征(SURF)算子;

    SIFT特征:
    定义:局部纹理信息的一种稳健的表达方式;
    特点:在影像旋转、缩放、灰度变化时有较好的稳定性;

    配准过程:
    第一次配准:
    Step1:提取SIFT特征
    Step2:初匹配(欧氏距离);
    Step3:去除误匹配点[随机抽样一致性(RANSAC)];
    Step4:利用正确的匹配点对,以第一幅影像为基准,对第二幅影像进行射影变换,并 重采样实现影像配准;
    第二次配准:
    重复第一次配准过程的前三步;

    注:此次配准后的SIFT点在理论上,应该是一一对应的,依据此次匹配的同名点的点位残差,粗略估算影像配准的精度(目的:为配准的容差性提供依据)
    点位残差:指实际观察值与估计值之间的差

    影像分割:
    定义:根据灰度、颜色、纹理和形状等特征把图像划分成若干互不交迭的区域,并使这些特征在同一区域内呈现出相似性,而在不同区域间呈现出明显的差异性
    现状:变化检测的虚检多发生在边缘部分而影像分割能很好地将地物边缘信息提取出来形成一个对象
    本文影像分割:
    采取的分割方法:过分割;
    途径:均值漂移算法
    均值漂移算法的定义:一种基于非参数概率密度估计的统计迭代算法,它能将相同区域内所有点都快速收敛到聚类中心,从而完成影像分割。
    注:均值漂移算法的带宽直接决定着分割区域所得到的最小区域。
    带宽越大,越达不到分割效果;
    带宽越小,越会产生很多细碎的分割区域,进而,越会增加后续变化检测的复杂度和计算量;

    展开全文
  • 基于云模型,图论互信息的遥感影像分割方法
  • SRM影像分割算法的matlab程序,主函数SRM_new
  • 遥感影像分割边界平滑方法研究 硕士毕业论文,很好的文章
  • 基于BP神经网络的遥感影像分割,王旭,曾繁慧,?遥感影像分割是数字图像处理中的一项重要技术,降低了遥感影像的分析、识别等高级处理步骤所涉及的数据量,同时最大限度的保留�
  • 在Meyer算法的基础上,提出一种改进的标记分水岭遥感影像分割方法,该方法针对高空间分辨率遥感影像的特点,依据梯度影像的分布特征自动提取合适的标记影像。浸没过程中,非标记像素按照梯度值由小到大进行处理,并...
  • 结合相位一致性局部均匀性的高分辨率遥感影像分割
  • 基于改进的RIU-LBPSRM的高分辨率遥感影像分割
  • 高分辨率遥感影像(如IKONOS 影像)海量数据、复杂细节的特点决定了高分辨率遥感影像分割的技术难点,提出了基于同质性梯度特征、分水岭算法最小代价合并的快速分割方法。首先对于原始图像进行同质梯度计算得到同质...
  • 基于像素模糊?? 均值算法(FCM) 及其改进算法难以解决高分辨率遥感影像中地物目标光谱测度相似性减弱... 实验结果表明, 与基于像素的FCM增强FCM方法相比, 所提出方法可以更加精确地实现高分辨率遥感影像分割.</p>
  • 记录遥感影像分割

    千次阅读 多人点赞 2019-08-19 20:43:33
    这两周数据挖掘课期末project我们组选的课题也是遥感图像的语义分割,所以刚好又把前段时间做的成果重新整理加强了一下,故写了这篇文章,记录一下用深度学习做遥感图像语义分割的完整流程以及一些好的思路技巧...

    原文地址https://www.sohu.com/a/218292615_642762

     

    上两个月参加了个比赛,做的是对遥感高清图像做语义分割,美其名曰“天空之眼”。这两周数据挖掘课期末project我们组选的课题也是遥感图像的语义分割,所以刚好又把前段时间做的成果重新整理和加强了一下,故写了这篇文章,记录一下用深度学习做遥感图像语义分割的完整流程以及一些好的思路和技巧。

    数据集

    首先介绍一下数据,我们这次采用的数据集是CCF大数据比赛提供的数据(2015年中国南方某城市的高清遥感图像),这是一个小数据集,里面包含了5张带标注的大尺寸RGB遥感图像(尺寸范围从3000×3000到6000×6000),里面一共标注了4类物体,植被(标记1)、建筑(标记2)、水体(标记3)、道路(标记4)以及其他(标记0)。其中,耕地、林地、草地均归为植被类,为了更好地观察标注情况,我们将其中三幅训练图片可视化如下:蓝色-水体,黄色-房屋,绿色-植被,棕色-马路。更多数据介绍可以参看这里。

    现在说一说我们的数据处理的步骤。我们现在拥有的是5张大尺寸的遥感图像,我们不能直接把这些图像送入网络进行训练,因为内存承受不了而且他们的尺寸也各不相同。因此,我们首先将他们做随机切割,即随机生成x,y坐标,然后抠出该坐标下256*256的小图,并做以下数据增强操作:

    1. 原图和label图都需要旋转:90度,180度,270度
    2. 原图和label图都需要做沿y轴的镜像操作
    3. 原图做模糊操作
    4. 原图做光照调整操作
    5. 原图做增加噪声操作(高斯噪声,椒盐噪声)

    这里我没有采用Keras自带的数据增广函数,而是自己使用opencv编写了相应的增强函数。

    img_w = 256 img_h = 256 image_sets = ['1.png','2.png','3.png','4.png','5.png']defgamma_transform(img, gamma): gamma_table = [np.power(x / 255.0, gamma) * 255.0 forx inrange(256)] gamma_table = np.round(np.array(gamma_table)).astype(np.uint8) returncv2.LUT(img, gamma_table)defrandom_gamma_transform(img, gamma_vari): log_gamma_vari = np.log(gamma_vari) alpha = np.random.uniform(-log_gamma_vari, log_gamma_vari) gamma = np.exp(alpha) returngamma_transform(img, gamma) defrotate(xb,yb,angle): M_rotate = cv2.getRotationMatrix2D((img_w/2, img_h/2), angle, 1) xb = cv2.warpAffine(xb, M_rotate, (img_w, img_h)) yb = cv2.warpAffine(yb, M_rotate, (img_w, img_h)) returnxb,yb defblur(img): img = cv2.blur(img, (3, 3)); returnimgdefadd_noise(img): fori inrange(200): #添加点噪声temp_x = np.random.randint(0,img.shape[0]) temp_y = np.random.randint(0,img.shape[1]) img[temp_x][temp_y] = 255 returnimg defdata_augment(xb,yb): ifnp.random.random() < 0.25: xb,yb = rotate(xb,yb,90)

    ifnp.random.random() < 0.25: xb,yb = rotate(xb,yb,180)

    ifnp.random.random() < 0.25: xb,yb = rotate(xb,yb,270)

    ifnp.random.random() < 0.25: xb = cv2.flip(xb, 1)

    # flipcode > 0:沿y轴翻转yb = cv2.flip(yb, 1) ifnp.random.random() < 0.25: xb = random_gamma_transform(xb,1.0) ifnp.random.random() < 0.25: xb = blur(xb) ifnp.random.random() < 0.2: xb = add_noise(xb) returnxb,ybdefcreat_dataset(image_num = 100000, mode = 'original'): print('creating dataset...') image_each = image_num / len(image_sets) g_count = 0 fori intqdm(range(len(image_sets))): count = 0 src_img = cv2.imread('./data/src/'+ image_sets[i])

    # 3 channelslabel_img = cv2.imread('./data/label/'+ image_sets[i],cv2.IMREAD_GRAYSCALE)

    # single channelX_height,X_width,_ = src_img.shape

    whilecount < image_each: random_width = random.randint(0, X_width - img_w - 1) random_height = random.randint(0, X_height - img_h - 1) src_roi = src_img[random_height: random_height + img_h, random_width: random_width + img_w,:] label_roi = label_img[random_height: random_height + img_h, random_width: random_width + img_w]

    ifmode == 'augment': src_roi,label_roi = data_augment(src_roi,label_roi) visualize = np.zeros((256,256)).astype(np.uint8) visualize = label_roi *50 cv2.imwrite(('./aug/train/visualize/%d.png'% g_count),visualize) cv2.imwrite(('./aug/train/src/%d.png'% g_count),src_roi) cv2.imwrite(('./aug/train/label/%d.png'% g_count),label_roi) count += 1 g_count += 1

    经过上面数据增强操作后,我们得到了较大的训练集:100000张256*256的图片。

    卷积神经网络

    面对这类图像语义分割的任务,我们可以选取的经典网络有很多,比如FCN,U-Net,SegNet,DeepLab,RefineNet,Mask Rcnn,Hed Net这些都是非常经典而且在很多比赛都广泛采用的网络架构。所以我们就可以从中选取一两个经典网络作为我们这个分割任务的解决方案。我们根据我们小组的情况,选取了U-Net和SegNet作为我们的主体网络进行实验。

    SegNet

    SegNet已经出来好几年了,这不是一个最新、效果最好的语义分割网络,但是它胜在网络结构清晰易懂,训练快速坑少,所以我们也采取它来做同样的任务。SegNet网络结构是编码器-解码器的结构,非常优雅,值得注意的是,SegNet做语义分割时通常在末端加入CRF模块做后处理,旨在进一步精修边缘的分割结果。有兴趣深究的可以看看这里

    现在讲解代码部分,首先我们先定义好SegNet的网络结构。

    defSegNet(): model = Sequential() #encoder model.add(Conv2D(64,(3,3),strides=(1,1),input_shape=(3,img_w,img_h),padding='same',activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(64,(3,3),strides=(1,1),padding='same',activation='relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2,2))) #(128,128) model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2, 2))) #(64,64) model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2, 2))) #(32,32) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2, 2))) #(16,16) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(MaxPooling2D(pool_size=(2, 2))) #(8,8) #decoder model.add(UpSampling2D(size=(2,2))) #(16,16) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(UpSampling2D(size=(2, 2))) #(32,32) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(512, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(UpSampling2D(size=(2, 2))) #(64,64) model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(256, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(UpSampling2D(size=(2, 2))) #(128,128) model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(128, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(UpSampling2D(size=(2, 2))) #(256,256) model.add(Conv2D(64, (3, 3), strides=(1, 1), input_shape=(3,img_w, img_h), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(64, (3, 3), strides=(1, 1), padding='same', activation='relu')) model.add(BatchNormalization()) model.add(Conv2D(n_label, (1, 1), strides=(1, 1), padding='same')) model.add(Reshape((n_label,img_w*img_h))) #axis=1和axis=2互换位置,等同于np.swapaxes(layer,1,2) model.add(Permute((2,1))) model.add(Activation('softmax')) model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy']) model.summary() returnmodel

    然后需要读入数据集。这里我们选择的验证集大小是训练集的0.25。

    defget_train_val(val_rate = 0.25): train_url = [] train_set = [] val_set = []

    forpic inos.listdir(filepath + 'src'): train_url.append(pic) random.shuffle(train_url) total_num = len(train_url) val_num = int(val_rate * total_num)

    fori inrange(len(train_url)):

    ifi < val_num: val_set.append(train_url[i]) else: train_set.append(train_url[i])

    returntrain_set,val_set

    # data for training

    defgenerateData(batch_size,data=[]): #print 'generateData...'whileTrue: train_data = [] train_label = [] batch = 0 fori in(range(len(data))): url = data[i] batch += 1 #print (filepath + 'src/' + url)#img = load_img(filepath + 'src/' + url, target_size=(img_w, img_h)) img = load_img(filepath + 'src/'+ url) img = img_to_array(img) # print img# print img.shape train_data.append(img) #label = load_img(filepath + 'label/' + url, target_size=(img_w, img_h),grayscale=True)label = load_img(filepath + 'label/'+ url, grayscale=True) label = img_to_array(label).reshape((img_w * img_h,)) # print label.shape train_label.append(label) ifbatch % batch_size==0: #print 'get enough bacth!n'train_data = np.array(train_data) train_label = np.array(train_label).flatten() train_label = labelencoder.transform(train_label) train_label = to_categorical(train_label, num_classes=n_label) train_label = train_label.reshape((batch_size,img_w * img_h,n_label)) yield(train_data,train_label) train_data = [] train_label = [] batch = 0

    # data for validation

    defgenerateValidData(batch_size,data=[]): #print 'generateValidData...'whileTrue: valid_data = [] valid_label = [] batch = 0 fori in(range(len(data))): url = data[i] batch += 1 #img = load_img(filepath + 'src/' + url, target_size=(img_w, img_h))img = load_img(filepath + 'src/'+ url) #print img#print (filepath + 'src/' + url)img = img_to_array(img) # print img.shape valid_data.append(img) #label = load_img(filepath + 'label/' + url, target_size=(img_w, img_h),grayscale=True)label = load_img(filepath + 'label/'+ url, grayscale=True) label = img_to_array(label).reshape((img_w * img_h,)) # print label.shape valid_label.append(label) ifbatch % batch_size==0: valid_data = np.array(valid_data) valid_label = np.array(valid_label).flatten() valid_label = labelencoder.transform(valid_label) valid_label = to_categorical(valid_label, num_classes=n_label) valid_label = valid_label.reshape((batch_size,img_w * img_h,n_label)) yield(valid_data,valid_label) valid_data = [] valid_label = [] batch = 0

    然后定义一下我们训练的过程,在这个任务上,我们把batch size定为16,epoch定为30,每次都存储最佳model(save_best_only=True),并且在训练结束时绘制loss/acc曲线,并存储起来。

    deftrain(args): EPOCHS = 30 BS = 16 model = SegNet() modelcheck = ModelCheckpoint(args['model'],monitor='val_acc',save_best_only=True,mode='max') callable = [modelcheck] train_set,val_set = get_train_val() train_numb = len(train_set) valid_numb = len(val_set) print("the number of train data is",train_numb) print("the number of val data is",valid_numb) H = model.fit_generator(generator=generateData(BS,train_set),steps_per_epoch=train_numb//BS,epochs=EPOCHS,verbose=1, validation_data=generateValidData(BS,val_set),validation_steps=valid_numb//BS,callbacks=callable,max_q_size=1) # plot the training loss and accuracyplt.style.use("ggplot") plt.figure() N = EPOCHS plt.plot(np.arange(0, N), H.history["loss"], label="train_loss") plt.plot(np.arange(0, N), H.history["val_loss"], label="val_loss") plt.plot(np.arange(0, N), H.history["acc"], label="train_acc") plt.plot(np.arange(0, N), H.history["val_acc"], label="val_acc") plt.title("Training Loss and Accuracy on SegNet Satellite Seg") plt.xlabel("Epoch #") plt.ylabel("Loss/Accuracy") plt.legend(loc="lower left") plt.savefig(args["plot"])

    然后开始漫长的训练,训练时间接近3天,绘制出的loss/acc图如下:

    训练loss降到0.1左右,acc可以去到0.9,但是验证集的loss和acc都没那么好,貌似存在点问题。

    先不管了,先看看预测结果吧。

    这里需要思考一下怎么预测整张遥感图像。我们知道,我们训练模型时选择的图片输入是256×256,所以我们预测时也要采用256×256的图片尺寸送进模型预测。现在我们要考虑一个问题,我们该怎么将这些预测好的小图重新拼接成一个大图呢?这里给出一个最基础的方案:先给大图做padding 0操作,得到一副padding过的大图,同时我们也生成一个与该图一样大的全0图A,把图像的尺寸补齐为256的倍数,然后以256为步长切割大图,依次将小图送进模型预测,预测好的小图则放在A的相应位置上,依次进行,最终得到预测好的整张大图(即A),再做图像切割,切割成原先图片的尺寸,完成整个预测流程。

    defpredict(args): # load the trained convolutional neural networkprint("[INFO] loading network...") model = load_model(args["model"]) stride = args['stride']

    forn inrange(len(TEST_SET)): path = TEST_SET[n]

    #load the imageimage = cv2.imread('./test/'+ path)

    # pre-process the image for classification#image = image.astype("float") / 255.0#image = img_to_array(image)h,w,_ = image.shape padding_h = (h//stride + 1) * stride padding_w = (w//stride + 1) * stridepadding_img = np.zeros((padding_h,padding_w,3),dtype=np.uint8) padding_img[0:h,0:w,:] = image[:,:,:] padding_img = padding_img.astype("float") / 255.0 padding_img = img_to_array(padding_img)

    print'src:',padding_img.shape mask_whole = np.zeros((padding_h,padding_w),dtype=np.uint8)

    fori inrange(padding_h//stride):

    forj inrange(padding_w//stride): crop = padding_img[:3,i*stride:i*stride+image_size,j*stride:j*stride+image_size] _,ch,cw = crop.shape

    ifch != 256 orcw != 256:

    print'invalid size!'continuecrop = np.expand_dims(crop, axis=0) #print 'crop:',crop.shapepred = model.predict_classes(crop,verbose=2) pred = labelencoder.inverse_transform(pred[0]) #print (np.unique(pred)) pred = pred.reshape((256,256)).astype(np.uint8) #print 'pred:',pred.shapemask_whole[i*stride:i*stride+image_size,j*stride:j*stride+image_size] = pred[:,:] cv2.imwrite('./predict/pre'+str(n+1)+'.png',mask_whole[0:h,0:w])

    预测的效果图如下:

    一眼看去,效果真的不错,但是仔细看一下,就会发现有个很大的问题:拼接痕迹过于明显了!那怎么解决这类边缘问题呢?很直接的想法就是缩小切割时的滑动步伐,比如我们把切割步伐改为128,那么拼接时就会有一般的图像发生重叠,这样做可以尽可能地减少拼接痕迹。

    U-Net

    对于这个语义分割任务,我们毫不犹豫地选择了U-Net作为我们的方案,原因很简单,我们参考很多类似的遥感图像分割比赛的资料,绝大多数获奖的选手使用的都是U-Net模型。在这么多的好评下,我们选择U-Net也就毫无疑问了。

    U-Net有很多优点,最大卖点就是它可以在小数据集上也能train出一个好的模型,这个优点对于我们这个任务来说真的非常适合。而且,U-Net在训练速度上也是非常快的,这对于需要短时间就得出结果的期末project来说也是非常合适。U-Net在网络架构上还是非常优雅的,整个呈现U形,故起名U-Net。这里不打算详细介绍U-Net结构,有兴趣的深究的可以看看论文。

    现在开始谈谈代码细节。首先我们定义一下U-Net的网络结构,这里用的deep learning框架还是Keras。

    注意到,我们这里训练的模型是一个多分类模型,其实更好的做法是,训练一个二分类模型(使用二分类的标签),对每一类物体进行预测,得到4张预测图,再做预测图叠加,合并成一张完整的包含4类的预测图,这个策略在效果上肯定好于一个直接4分类的模型。所以,U-Net这边我们采取的思路就是对于每一类的分类都训练一个二分类模型,最后再将每一类的预测结果组合成一个四分类的结果。

    定义U-Net结构,注意了,这里的loss function我们选了binary_crossentropy,因为我们要训练的是二分类模型。

    defunet(): inputs = Input((3, img_w, img_h)) conv1 = Conv2D(32, (3, 3), activation="relu", padding="same")(inputs) conv1 = Conv2D(32, (3, 3), activation="relu", padding="same")(conv1) pool1 = MaxPooling2D(pool_size=(2, 2))(conv1)conv2 = Conv2D(64, (3, 3), activation="relu", padding="same")(pool1) conv2 = Conv2D(64, (3, 3), activation="relu", padding="same")(conv2) pool2 = MaxPooling2D(pool_size=(2, 2))(conv2) conv3 = Conv2D(128, (3, 3), activation="relu", padding="same")(pool2) conv3 = Conv2D(128, (3, 3), activation="relu", padding="same")(conv3) pool3 = MaxPooling2D(pool_size=(2, 2))(conv3) conv4 = Conv2D(256, (3, 3), activation="relu", padding="same")(pool3) conv4 = Conv2D(256, (3, 3), activation="relu", padding="same")(conv4) pool4 = MaxPooling2D(pool_size=(2, 2))(conv4)conv5 = Conv2D(512, (3, 3), activation="relu", padding="same")(pool4) conv5 = Conv2D(512, (3, 3), activation="relu", padding="same")(conv5) up6 = concatenate([UpSampling2D(size=(2, 2))(conv5), conv4], axis=1) conv6 = Conv2D(256, (3, 3), activation="relu", padding="same")(up6) conv6 = Conv2D(256, (3, 3), activation="relu", padding="same")(conv6) up7 = concatenate([UpSampling2D(size=(2, 2))(conv6), conv3], axis=1) conv7 = Conv2D(128, (3, 3), activation="relu", padding="same")(up7) conv7 = Conv2D(128, (3, 3), activation="relu", padding="same")(conv7) up8 = concatenate([UpSampling2D(size=(2, 2))(conv7), conv2], axis=1) conv8 = Conv2D(64, (3, 3), activation="relu", padding="same")(up8) conv8 = Conv2D(64, (3, 3), activation="relu", padding="same")(conv8) up9 = concatenate([UpSampling2D(size=(2, 2))(conv8), conv1], axis=1) conv9 = Conv2D(32, (3, 3), activation="relu", padding="same")(up9) conv9 = Conv2D(32, (3, 3), activation="relu", padding="same")(conv9) conv10 = Conv2D(n_label, (1, 1), activation="sigmoid")(conv9) #conv10 = Conv2D(n_label, (1, 1), activation="softmax")(conv9)model = Model(inputs=inputs, outputs=conv10) model.compile(optimizer='Adam', loss='binary_crossentropy', metrics=['accuracy'])

    returnmodel

    读取数据的组织方式有一些改动。

    # data for training

    defgenerateData(batch_size,data=[]): #print 'generateData...'whileTrue: train_data = [] train_label = [] batch = 0 fori in(range(len(data))): url = data[i] batch += 1 img = load_img(filepath + 'src/'+ url) img = img_to_array(img) train_data.append(img) label = load_img(filepath + 'label/'+ url, grayscale=True) label = img_to_array(label)

    #print label.shape train_label.append(label) ifbatch % batch_size==0: #print 'get enough bacth!n'train_data = np.array(train_data) train_label = np.array(train_label) yield(train_data,train_label) train_data = [] train_label = [] batch = 0

    # data for validation

    defgenerateValidData(batch_size,data=[]): #print 'generateValidData...'whileTrue: valid_data = [] valid_label = [] batch = 0 fori in(range(len(data))): url = data[i] batch += 1 img = load_img(filepath + 'src/'+ url) #print imgimg = img_to_array(img) # print img.shape valid_data.append(img) label = load_img(filepath + 'label/'+ url, grayscale=True) valid_label.append(label) ifbatch % batch_size==0: valid_data = np.array(valid_data) valid_label = np.array(valid_label) yield(valid_data,valid_label) valid_data = [] valid_label = [] batch = 0

    训练:指定输出model名字和训练集位置

    python unet.py --model unet_buildings20.h5 -- data./unet_train/buildings/

    预测单张遥感图像时我们分别使用4个模型做预测,那我们就会得到4张mask(比如下图就是我们用训练好的buildings模型预测的结果),我们现在要将这4张mask合并成1张,那么怎么合并会比较好呢?我思路是,通过观察每一类的预测结果,我们可以从直观上知道哪些类的预测比较准确,那么我们就可以给这些mask图排优先级了,比如:priority:building>water>road>vegetation,那么当遇到一个像素点,4个mask图都说是属于自己类别的标签时,我们就可以根据先前定义好的优先级,把该像素的标签定为优先级最高的标签。代码思路可以参照下面的代码:

    defcombind_all_mask(): formask_num intqdm(range(3)):

    ifmask_num == 0: final_mask = np.zeros((5142,5664),np.uint8)

    #生成一个全黑全0图像,图片尺寸与原图相同elifmask_num == 1: final_mask = np.zeros((2470,4011),np.uint8) elifmask_num == 2: final_mask = np.zeros((6116,3356),np.uint8) #final_mask = cv2.imread('final_1_8bits_predict.png',0)ifmask_num == 0: mask_pool = mask1_pool

    elifmask_num == 1: mask_pool = mask2_pool

    elifmask_num == 2: mask_pool = mask3_pool final_name = img_sets[mask_num]

    foridx,name inenumerate(mask_pool): img = cv2.imread('./predict_mask/'+name,0) height,width = img.shape label_value = idx+1 #coressponding labels valuefori intqdm(range(height)): #priority:building>water>road>vegetationforj inrange(width):

    ifimg[i,j] == 255:

    iflabel_value == 2: final_mask[i,j] = label_value eliflabel_value == 3

    andfinal_mask[i,j] != 2: final_mask[i,j] = label_value eliflabel_value == 4

    andfinal_mask[i,j] != 2

    andfinal_mask[i,j] != 3: final_mask[i,j] = label_value eliflabel_value == 1

    andfinal_mask[i,j] == 0: final_mask[i,j] = label_value cv2.imwrite('./final_result/'+final_name,final_mask) print'combinding mask...'combind_all_mask() 模型融合

    集成学习的方法在这类比赛中经常使用,要想获得好成绩集成学习必须做得好。在这里简单谈谈思路,我们使用了两个模型,我们模型也会采取不同参数去训练和预测,那么我们就会得到很多预测MASK图,此时 我们可以采取模型融合的思路,对每张结果图的每个像素点采取投票表决的思路,对每张图相应位置的像素点的类别进行预测,票数最多的类别即为该像素点的类别。正所谓“三个臭皮匠,胜过诸葛亮”,我们这种ensemble的思路,可以很好地去掉一些明显分类错误的像素点,很大程度上改善模型的预测能力。

    少数服从多数的投票表决策略代码:

    importnumpy asnpimportcv2importargparseRESULT_PREFIXX = ['./result1/','./result2/','./result3/']

    # each mask has 5 classes: 0~4

    defvote_per_image(image_id): result_list = []

    forj inrange(len(RESULT_PREFIXX)): im = cv2.imread(RESULT_PREFIXX[j]+str(image_id)+'.png',0) result_list.append(im) # each pixelheight,width = result_list[0].shape vote_mask = np.zeros((height,width))

    forh inrange(height):

    forw inrange(width): record = np.zeros((1,5))

    forn inrange(len(result_list)): mask = result_list[n] pixel = mask[h,w] #print('pix:',pixel)record[0,pixel]+=1 label = record.argmax()

    #print(label)vote_mask[h,w] = label cv2.imwrite('vote_mask'+str(image_id)+'.png',vote_mask)vote_per_image(3)

    模型融合后的预测结果:

    可以看出,模型融合后的预测效果确实有较大提升,明显错误分类的像素点消失了。

    额外的思路:GAN

    我们对数据方面思考得更多一些,我们针对数据集小的问题,我们有个想法:使用生成对抗网络去生成虚假的卫星地图,旨在进一步扩大数据集。我们的想法就是,使用这些虚假+真实的数据集去训练网络,网络的泛化能力肯定有更大的提升。我们的想法是根据这篇论文(pix2pix)来展开的,这是一篇很有意思的论文,它主要讲的是用图像生成图像的方法。里面提到了用标注好的卫星地图生成虚假的卫星地图的想法,真的让人耳目一新,我们也想根据该思路,生成属于我们的虚假卫星地图数据集。 Map to Aerial的效果是多么的震撼。

    但是我们自己实现起来的效果却不容乐观(如下图所示,右面那幅就是我们生成的假图),效果不好的原因有很多,标注的问题最大,因为生成的虚假卫星地图质量不好,所以该想法以失败告终,生成的假图也没有拿去做训练。但感觉思路还是可行的,如果给的标注合适的话,还是可以生成非常像的虚假地图。

    总结

    对于这类遥感图像的语义分割,思路还有很多,最容易想到的思路就是,将各种语义分割经典网络都实现以下,看看哪个效果最好,再做模型融合,只要集成学习做得好,效果一般都会很不错的。我们仅靠上面那个简单思路(数据增强,经典模型搭建,集成学习),就已经可以获得比赛的TOP 1%了,当然还有一些tricks可以使效果更进一步提升,这里就不细说了,总的建模思路掌握就行。完整的代码可以在我的github获取。

    Github:https://github.com/AstarLight/Satellite-Segmentation

    原文:http://www.cnblogs.com/skyfsm/p/8330882.html返回搜狐,查看更多

    展开全文
  • 行业分类-物理装置-基于生物医学影像的生物组织的分割方法通信终端.zip
  • 医学影像分割

    千次阅读 2019-04-30 10:31:58
    % title('(a) 原图图像及种子质量'); I=double(I); markerim=I==I(seedy(1),seedx(1)); for i=2:length(seedx) markerim=markerim | (I==I(seedy(i),seedx(i))); end thresh=[15, 10, 15]; maskim=zeros(size(I)); ...

    1.迭代阈值法

    %迭代阈值法
    clc;clear all;close all
    I=imread('spine.tif');
    % I=dicomread('CT-MONO2-16-ankle.dcm');
    % I=rgb2gray(I);
    subplot(1,2,1);imshow(I);title('(a) 原图');
    I=double(I);T=(min(I(:))+max(I(:)))/2;
    d=false;i=0;
    while ~ d
        u1=find(I<=T);
        u2=find(I>T);
        Tn=(mean(I(u1))+mean(I(u2)))/2;
        d=abs(Tn-T)<1;
        T=Tn;
        i=i+1;
    end
    I(u1)=0;I(u2)=1;
    subplot(1,2,2);imshow(I);title('(b) 处理结果');

    2.分水岭法

    %分水岭法
    clc;clear all;close all
    I=imread('mri.tif');
    %I=dicomread('C:\MR-MONO2-12-angio-an1\MR-MONO2-12-angio-an1');
    %I=dicomread('C:\MR-MONO2-16-knee\MR-MONO2-16-knee');
    % I=rgb2gray(I);
    subplot(2,2,1);imshow(I);title('(a) 原图');
    I=double(I);hv=fspecial('prewitt');hh=hv.'
    gv=abs(imfilter(I,hv,'replicate'));
    gh=abs(imfilter(I,hh,'replicate'));
    g=sqrt(gv.^2+gh.^2);
    L=watershed(g);wr=L==0;
    subplot(2,2,2);imshow(wr);title('(b) 分水岭');
    I(wr)=255;
    subplot(2,2,3);imshow(uint8(I));title('(c) 分割结果');
    rm=imregionalmin(g);
    subplot(2,2,4);imshow(rm);title('(d) 局部极小值');

    3.边缘探测法

    %边缘探测法
    clc;clear all;close all
    % I=imread('mri.tif');
    I=dicomread('C:\MR-MONO2-12-angio-an1\MR-MONO2-12-angio-an1');
    % I=dicomread('C:\MR-MONO2-16-knee\MR-MONO2-16-knee');
    % I=rgb2gray(I);
    figure;subplot(2,3,1);imshow(I);title('(a) 原图');
    I1=im2bw(I);
    subplot(2,3,2);imshow(I1);title('(b) 二值图像');
    I2=edge(I,'roberts');
    subplot(2,3,3);imshow(I2);title('(c) roberts算子分割');
    I3=edge(I,'sobel');
    subplot(2,3,4);imshow(I3);title('(d) sobel算子分割');
    I4=edge(I,'Prewitt');
    subplot(2,3,5);imshow(I4);title('(e) Prewitt算子分割');
    subplot(2,3,6);imhist(I);title('(f) 直方图');

    4.区域生长法

    %区域生长法
    clc;clear all;close all
    %I=imread('mri.tif');
    I=dicomread('C:\MR-MONO2-12-angio-an1\MR-MONO2-12-angio-an1');
    %I=dicomread('C:\MR-MONO2-16-knee\MR-MONO2-16-knee');
    % I=rgb2gray(I);
    figure;
    % seedx=[256, 128, 480];
    % seedy=[128, 256, 384];
    seedx=[128, 64, 255];
    seedy=[64, 128, 192];
    hold on
    plot(seedx,seedy,'gs','linewidth',1);title('(a) 原图图像及种子质量');
    figure;subplot(1,2,1);imshow(I);title('(a) 原图');
    % seedx=[256, 128, 480];
    % seedy=[128, 256, 384];
    % hold on
    % plot(seedx,seedy,'gs','linewidth',1);
    % title('(a) 原图图像及种子质量');
    I=double(I);
    markerim=I==I(seedy(1),seedx(1));
    for i=2:length(seedx)
        markerim=markerim | (I==I(seedy(i),seedx(i)));
    end
    thresh=[15, 10, 15];
    maskim=zeros(size(I));
    for i=1:length(seedx)
        g=abs(I-I(seedy(i), seedx(i)))<=thresh(i);
        maskim=maskim | g;
    end
    [g, nr]=bwlabel(imreconstruct(markerim, maskim),8);
    g=mat2gray(g);
    subplot(1,2,2);imshow(g)title('(b) 三个种子点区域生长结果');

    5.直方图阈值分割法

    % 直方图阈值分割法
    clc;clear all;close all
    I=imread('cell.tif');
    % I=rgb2gray(I);
    figure;subplot(1,3,1);imshow(I);title('(a) 原图');
    subplot(1,3,2);imhist(I);title('(b) 直方图');
    [m, n]=size(I);
    for i=1:m
        for j=1:n
            if I(i,j)>140    %阈值根据实际情况设置
                I(i,j)=255;
            end
        end
    end
    subplot(1,3,3);imshow(I);title('(c) 分割结果');
    

    6.Otsu分割法

    % Otsu分割法
    clc;clear all;close all
    I=imread('cell.tif');
    % I=rgb2gray(I);
    figure;subplot(1,2,1);imshow(I);title('(a) 原图');
    count=imhist(I);
    [r,t]=size(I);
    N=r*t;
    L=256;
    count=count/N;
    for i=2:L
        if count(i)~=0
            st=i-1;
            break
        end
    end
    for i=L:-1:1
        if count(i)~=0
            nd=i-1;
            break
        end
    end
    f=count(st+1:nd+1);
    p=st;
    q=nd-st;
    u=0;
    for i=1:q
        u=u+f(i)*(p+i-1);
        ua(i)=u;
    end
    for i=1:q
        w(i)=sum(f(1:i));
    end
    d=(u*w-ua).^2/(w.*(1-w));
    [y,tp]=max(d);
    th=tp+p;
    if th<=140
        th=tp+p;
    else
        th=140;
    end
    y1=zeros(r,t);
    for i=1:r
        for j=1:t
            x1(i,j)=double(I(i,j));
        end
    end
    for i=1:r
        for j=1:t
            if x1(i,j)>=th
                y1(i,j)=x1(i,j);
            else
                y1(i,j)=0;
            end
        end
    end
    subplot(1,2,2);imshow(y1);title('(b) 分割结果');
    

     

    展开全文
  • 为了获得更精细的边缘分类结果, 考虑像素之间的空间相关性, 采用均值漂移聚类分割获取像素的空间关系, 通过统计聚类区域像素概率的最大、方差最小的方法确定该区域对象的类别;选取典型地区的影像进行分类实验, 并...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,943
精华内容 6,377
关键字:

影像分割和影像分类