1. 程式人生 > >基於深度學習的CT影象肺結節自動檢測技術五—3dcnn優化模型

基於深度學習的CT影象肺結節自動檢測技術五—3dcnn優化模型

import os
import random
from keras import layers
from keras import backend as K
from keras.layers import Input, Convolution3D, MaxPooling3D, Flatten, Dropout,\
AveragePooling3D, BatchNormalization,Activation
from keras.metrics import binary_accuracy, binary_crossentropy
from keras.models import Model
from
keras.optimizers import Adam from keras.callbacks import ModelCheckpoint, History, EarlyStopping import matplotlib.pyplot as plt import numpy import cv2 K.set_image_dim_ordering("tf") CUBE_SIZE = 32 MEAN_PIXEL_VALUE = 41 BATCH_SIZE = 8
實現3dcnn的網路結構,並載入預訓練好的權重——優化模型
def get_3dnnnet(input_shape=(CUBE_SIZE,
CUBE_SIZE, CUBE_SIZE, 1), load_weight_path=None, USE_DROPOUT=True) -> Model: inputs = Input(shape=input_shape, name="input_1") x = inputs #------------------------------------------------------------- X_shortcut = x #儲存輸入值,後面將需要添加回主路徑 #-------------------------------------------------------------
x = AveragePooling3D(pool_size=(2, 1, 1), strides=(2, 1, 1), border_mode="same")(x) x = Convolution3D(64, 3, 3, 3, border_mode='same', name='conv1', subsample=(1, 1, 1))(x) x = BatchNormalization()(x) x = Activation('relu')(x) x = MaxPooling3D(pool_size=(1, 2, 2), strides=(1, 2, 2), border_mode='valid', name='pool1')(x) if USE_DROPOUT: x = Dropout(p=0.3)(x) #空間金字塔池化 ###dropout = SpatialDropout3D(rate=dropout_rate, data_format=data_format)(convolution1) # 2nd layer group x = Convolution3D(128, 3, 3, 3, border_mode='same', name='conv2', subsample=(1, 1, 1))(x) x = BatchNormalization()(x) x = Activation('relu')(x) x = MaxPooling3D(pool_size=(2, 2, 2), strides=(2, 2, 2), border_mode='valid', name='pool2')(x) if USE_DROPOUT: x = Dropout(p=0.3)(x) # 3rd layer group x = Convolution3D(256, 3, 3, 3, activation='relu', border_mode='same', name='conv3a', subsample=(1, 1, 1))(x) x = Convolution3D(256, 3, 3, 3, activation='relu', border_mode='same', name='conv3b', subsample=(1, 1, 1))(x) x = MaxPooling3D(pool_size=(2, 2, 2), strides=(2, 2, 2), border_mode='valid', name='pool3')(x) if USE_DROPOUT: x = Dropout(p=0.4)(x) # 4th layer group x = Convolution3D(512, 3, 3, 3, activation='relu', border_mode='same', name='conv4a', subsample=(1, 1, 1))(x) x = Convolution3D(512, 3, 3, 3, activation='relu', border_mode='same', name='conv4b', subsample=(1, 1, 1), )(x) x = MaxPooling3D(pool_size=(2, 2, 2), strides=(2, 2, 2), border_mode='valid', name='pool4')(x) if USE_DROPOUT: x = Dropout(p=0.5)(x) # shortcut路徑-------------------------------------------- X_shortcut = Convolution3D(512, 3, 3, 3, activation='relu', border_mode='same', name='conv4a_X', subsample=(1, 1, 1))(x) X_shortcut = Convolution3D(512, 3, 3, 3, activation='relu', border_mode='same', name='conv4b_X', subsample=(1, 1, 1))(X_shortcut) X_shortcut = MaxPooling3D(pool_size=(2, 2, 2), strides=(2, 2, 2), border_mode='valid', name='pool5')(X_shortcut) X_shortcut = BatchNormalization()(X_shortcut) # 主路徑最後部分,為主路徑新增shortcut並通過relu啟用 X = layers.add([x, X_shortcut]) #-------------------------------------------- last64 = Convolution3D(64, 2, 2, 2, activation="relu", name="last_64")(X) out_class = Convolution3D(1, 1, 1, 1, activation="sigmoid", name="out_class_last")(last64) out_class = Flatten(name="out_class")(out_class) model = Model(input=inputs, output=[out_class]) model.load_weights(load_weight_path, by_name=False) model.compile(optimizer=Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0), loss={"out_class": "binary_crossentropy"}, metrics={"out_class": [binary_accuracy, binary_crossentropy]}) return model
# 將二維影象依次疊加,轉換為三維影象
def stack_2dcube_to_3darray(src_path, rows, cols, size):
    img = cv2.imread(src_path, cv2.IMREAD_GRAYSCALE)
    # assert rows * size == cube_img.shape[0]
    # assert cols * size == cube_img.shape[1]

    res = numpy.zeros((rows * cols, size, size))

    img_height = size
    img_width = size

    for row in range(rows):
        for col in range(cols):
            src_y = row * img_height
            src_x = col * img_width
            res[row * cols + col] = img[src_y:src_y + img_height, src_x:src_x + img_width]

    return res


# 將三維的dicom影象縮放到1mm:1mm:1mm的尺度
def rescale_patient_images2(images_zyx, target_shape, verbose=False):
    if verbose:
        print("Target: ", target_shape)
        print("Shape: ", images_zyx.shape)

    # print ("Resizing dim z")
    resize_x = 1.0
    interpolation = cv2.INTER_NEAREST if False else cv2.INTER_LINEAR
    res = cv2.resize(images_zyx, dsize=(target_shape[1], target_shape[0]), interpolation=interpolation)
    # print ("Shape is now : ", res.shape)

    res = res.swapaxes(0, 2)
    res = res.swapaxes(0, 1)

    # cv2 can handle max 512 channels..
    if res.shape[2] > 512:
        res = res.swapaxes(0, 2)
        res1 = res[:256]
        res2 = res[256:]
        res1 = res1.swapaxes(0, 2)
        res2 = res2.swapaxes(0, 2)
        res1 = cv2.resize(res1, dsize=(target_shape[2], target_shape[1]), interpolation=interpolation)
        res2 = cv2.resize(res2, dsize=(target_shape[2], target_shape[1]), interpolation=interpolation)
        res1 = res1.swapaxes(0, 2)
        res2 = res2.swapaxes(0, 2)
        res = numpy.vstack([res1, res2])
        res = res.swapaxes(0, 2)
    else:
        res = cv2.resize(res, dsize=(target_shape[2], target_shape[1]), interpolation=interpolation)

    res = res.swapaxes(0, 2)
    res = res.swapaxes(2, 1)
    if verbose:
        print("Shape after: ", res.shape)
    return res


# 對即將輸入網路的cube進行預處理操作
def prepare_image_for_net3D(img, MEAN_PIXEL_VALUE):
    img = img.astype(numpy.float32)
    img -= MEAN_PIXEL_VALUE
    img /= 255.
    img = img.reshape(1, img.shape[0], img.shape[1], img.shape[2], 1)
    return img


# 自定義的資料載入器(迭代地批量加入訓練資料,其間對訓練樣本做了augmentation)
def data_generator(batch_size, record_list, train_set):
    batch_idx = 0
    means = []
    while True:
        img_list = []
        class_list = []
        if train_set:
            random.shuffle(record_list)
        CROP_SIZE = CUBE_SIZE
        # CROP_SIZE = 48
        for record_idx, record_item in enumerate(record_list):
            # rint patient_dir
            class_label = record_item[1]
            if class_label == 0:
                cube_image = stack_2dcube_to_3darray(record_item[0], 6, 8, 48)

            elif class_label == 1:
                cube_image = stack_2dcube_to_3darray(record_item[0], 8, 8, 64)
            if train_set:
                pass

            current_cube_size = cube_image.shape[0]
            indent_x = (current_cube_size - CROP_SIZE) / 2
            indent_y = (current_cube_size - CROP_SIZE) / 2
            indent_z = (current_cube_size - CROP_SIZE) / 2
            wiggle_indent = 0
            wiggle = current_cube_size - CROP_SIZE - 1
            if wiggle > (CROP_SIZE / 2):
                wiggle_indent = CROP_SIZE / 4
                wiggle = current_cube_size - CROP_SIZE - CROP_SIZE / 2 - 1

            if train_set:
                indent_x = wiggle_indent + random.randint(0, wiggle)
                indent_y = wiggle_indent + random.randint(0, wiggle)
                indent_z = wiggle_indent + random.randint(0, wiggle)

            indent_x = int(indent_x)
            indent_y = int(indent_y)
            indent_z = int(indent_z)

            cube_image = cube_image[indent_z:indent_z + CROP_SIZE, 
                                    indent_y:indent_y + CROP_SIZE,
                                    indent_x:indent_x + CROP_SIZE]

            if CROP_SIZE != CUBE_SIZE:
                cube_image = rescale_patient_images2(cube_image, (CUBE_SIZE, CUBE_SIZE, CUBE_SIZE))

            assert cube_image.shape == (CUBE_SIZE, CUBE_SIZE, CUBE_SIZE)

            if train_set:
                if random.randint(0, 100) > 50:
                    cube_image = numpy.fliplr(cube_image)
                if random.randint(0, 100) > 50:
                    cube_image = numpy.flipud(cube_image)
                if random.randint(0, 100) > 50:
                    cube_image = cube_image[:, :, ::-1]
                if random.randint(0, 100) > 50:
                    cube_image = cube_image[:, ::-1, :]

            means.append(cube_image.mean())
            img3d = prepare_image_for_net3D(cube_image, MEAN_PIXEL_VALUE)
            if train_set:
                if len(means) % 1000000 == 0:
                    print("Mean: ", sum(means) / len(means))
            img_list.append(img3d)
            class_list.append(class_label)

            batch_idx += 1
            if batch_idx >= batch_size:
                x = numpy.vstack(img_list)
                y_class = numpy.vstack(class_list)
                yield x, {"out_class": y_class}
                img_list = []
                class_list = []
                batch_idx = 0


# 三維卷積神經網路的訓練過程
def train_3dcnn(train_gen, val_gen):
    # 載入預訓練好的權重
    model = get_3dnnnet(load_weight_path='./model/3dcnn.hd5')
    history = History()
    model.summary(line_length=150)
    # 設定權重的中間儲存路徑
    checkpoint = ModelCheckpoint('./model/cpt_3dcnn_' + "{epoch:02d}-{binary_accuracy:.4f}.hd5",
                                 monitor='val_loss', verbose=1,
                                 save_best_only=True, save_weights_only=True, mode='auto', period=1)
    # 開始訓練
    hist = model.fit_generator(
        generator=train_gen, steps_per_epoch=280, epochs=10,
        verbose=2,
        callbacks=[EarlyStopping(monitor='val_loss', patience=20),
                   history, checkpoint],
        validation_data=val_gen,
        validation_steps=60)

    plt.plot(hist.history['loss'])
    plt.plot(hist.history['val_loss'])
    plt.title('model loss')
    plt.ylabel('loss')
    plt.xlabel('epoch')
    plt.legend(['train', 'validation'], loc='upper left')
    # 儲存訓練過程的學習效果曲線
    plt.savefig("./temp_dir/chapter5/learning_curve.jpg")
if __name__ == '__main__':
    img_and_labels = []
    # 正樣本集所在路徑
    source_png_positive = "./data/chapter5/train/temp_cudes_pos/"
    # 負樣本集所在路徑
    source_png_negative = "./data/chapter5/train/temp_cudes_neg/"
    
    for each_image in os.listdir(source_png_positive):
        file_path = os.path.join(source_png_positive, each_image)
        img_and_labels.append((file_path, 1))
    for each_image in os.listdir(source_png_negative):
        file_path = os.path.join(source_png_negative, each_image)
        img_and_labels.append((file_path, 0)
            
           

相關推薦

基於深度學習CT影象結節自動檢測技術3dcnn優化模型

import os import random from keras import layers from keras import backend as K from keras.layers import Input, Convolution3D, MaxP

基於深度學習CT影象結節自動檢測技術六—模型預測

#模型預測的相關功能 from chapter4 import get_unet from chapter5 import get_3dnnnet, stack_2dcube_to_3darray, prepare_image_for_net3D, MEAN_

基於深度學習CT影象結節自動檢測技術一——資料預處理(歸一化,資料增強,資料標記)

開發環境 Anaconda:jupyter notebook /pycharm pip install SimpleItk # 讀取CT醫學影象 pip install tqdm # 可擴充套件的Python進度條,封裝

基於深度學習CT影象結節自動檢測技術四—資料增強—定義神經網路並訓練

開發環境 jupyter notebook # -- coding: utf-8 -- #訓練影象分割網路(u-net)模型 import csv import glob import random import cv2 import numpy import

基於深度學習CT影象結節自動檢測技術二——訓練資料處理

開發環境 Anaconda:jupyter notebook/pycharm pip install dicom # 用於讀取 dicom 圖片(version0.9.9) pip install SimpleItk # 讀

基於深度學習CT影象結節自動檢測(系列放在一起)

PS 為了方便查詢,將SongpingWang的肺結節系列部落格放在一起。(剛好公司要我開始接手這一塊)感謝大神 具體連結: 0 :https://blog.csdn.net/wsp_1138886114/article/details/81840891 1 :https://blog.

學習筆記之——基於深度學習影象超解析度重構

       最近開展影象超解析度( Image Super Resolution)方面的研究,做了一些列的調研,並結合本人的理解總結成本博文~(本博文僅用於本人的學習筆記,不做商業用途) 本博文涉及的paper已經打包,供各位看客下載哈~h

基於深度學習影象檢索 image retrieval based on deep learning (code ,程式碼)

本次程式碼分享主要是用的caffe框架,至於caffe框架的安裝過程不再說明。程式碼修改自“cross weights”的一篇2016年的文章,但是名字忘記了,誰記得,提醒我下。 一、環境要求         1、python &nb

基於深度學習影象質量排序

國內外各大網際網路公司(比如騰訊、阿里和Yelp)的線上廣告業務都在關注展示什麼樣的影象能吸引更多點選。在美團,商家的首圖是由商家或運營人工指定的,如何選擇首圖才能更好地吸引使用者呢?影象質量排序演算法目標就是做到自動選擇更優質的首圖,以吸引使用者點選。 傳統的影象質量排序方法主要從美學角度進行

基於深度學習影象語義分割技術概述之4常用方法 5.4未來研究方向

https://blog.csdn.net/u014593748/article/details/72794459 本文為論文閱讀筆記,不當之處,敬請指正。 A Review on Deep Learning Techniques Applied to Semantic Segmen

基於深度學習影象修復—心中無碼

一、前言 影象修復在應用上非常吸引人,通常設計師需要使用 Photoshop 根據影象周圍修復空缺部分。這一過程非常耗時和細緻,因此很早就有研究嘗試使用機器學習模型自動化這一過程。 這篇文章介紹了 DeepCreamPy 專案,它可以自動修復漫畫影象中的空缺部分和馬賽克。該專案使用部分卷

基於深度學習影象語義分割演算法綜述(截止20180715)

這篇文章講述卷積神經網路在影象語義分割(semantic image segmentation)的應用。影象分割這項計算機視覺任務需要判定一張圖片中特定區域的所屬類別。 這個影象裡有什麼?它在影象中哪個位置? 更具體地說,影象語義分割的目標是將影象的每個畫素所

基於深度學習影象分割總結

一、影象分割類別 隨著深度學習的發展,在分割任務中出現了許多優秀的網路。根據實際分割應用任務的不同,可以大致將分割分為三個研究方向:語義分割、例項分割、全景分割。這三種分割在某種意義上是具有一定的聯絡的。 語義分割: 畫素級別的語義分割,對影象中的每個畫素都劃分出對應的

如何基於深度學習實現影象的智慧稽核

如何基於深度學習實現影象的智慧稽核 背景 美團每天有百萬級的圖片產生量,運營人員負責相關圖片的內容稽核,對涉及法律風險及不符合平臺規定的圖片進行刪除操作。由於圖片數量巨大,人工稽核耗時耗力且稽核能力有限。另外對於不同稽核人員來講,稽核標準難以統一且實時變化。所以有必要藉助機器實現智慧稽核

基於深度學習影象壓縮

近年來,深度學習在計算機視覺領域已經佔據主導地位,不論是在影象識別還是超分辨重現上,深度學習已成為圖片研究的重要技術,但它們的能力並不僅限於這些任務;現在深度學習技術已進入圖片壓縮領域。下面就說說神經網路在影象壓縮領域的應用。 當前主要圖片壓縮演算法 說到影象壓縮演算法,目前市面上影響力比較

乾貨 | 美團如何基於深度學習實現影象的智慧稽核?

[1]H. Chen, S. S. Tsai, G. Schroth, D. M. Chen, R. Grzeszczuk, and B. Girod. “Robust text detection in natural images with edge-enhanced maximally stable e

基於深度學習影象語義分析及其應用

本文 轉自“火光搖曳”部落格:語義分析的一些方法(三),主要論述了基於深度學習方法的影象語義分析,包括圖片分類、圖片搜尋、圖片標註(image2text、image2sentence),以及訓練深度神經網路的一些tricks,並介紹語義分析方法在騰訊廣點通上的實際應用。以下

基於深度學習影象去噪暨SRMD論文閱讀筆記

最近一直在做基於卷積神經網路的影象去噪~感覺資料比較凌亂,本博文就是整理好經典的論文材料~ 同時本博文也結合了閱讀論文《Learning a Single Convolutional Super-Resolution Network for Multiple Degradations》時的心

基於深度學習影象去噪(論文總結)

2015 深度學習、自編碼器、低照度影象增強 Lore, Kin Gwn, Adedotun Akintayo, and Soumik Sarkar. "LLNet: A Deep Autoencoder Approach to Natural Low-light Image Enhancement." ar

Amazon Rekognition常見問題_基於深度學習影象分析服務問題

問:什麼是 Amazon Rekognition? Amazon Rekognition 作為一項服務,能夠讓您輕鬆地將功能強大的視覺化分析新增到應用程式。藉助 Rekognition Image,您可以輕鬆構建功能強大的應用程式來搜尋、驗證和組織數百萬個影象