Обзор:

Оптическая когерентная томография (ОКТ):

Оптическая когерентная томография (ОКТ) - это метод визуализации, который использует когерентный свет для получения изображений биологических тканей с высоким разрешением. ОКТ широко используется офтальмологами для получения изображений сетчатки глаза с высоким разрешением. Сетчатка глаза больше похожа на пленку в фотоаппарате. ОКТ-изображения можно использовать для диагностики многих заболеваний глаз, связанных с сетчаткой.

На следующем рисунке показана анатомия глаза:

О наборе данных:

Этот набор данных содержит четыре категории (NORMAL, CNV, DME, DRUSEN). Он разделен на 3 папки (train, test, val) и содержит подпапки для каждой категории изображений (NORMAL, CNV, DME, DRUSEN). Папки «test» и «val» содержат очень небольшое количество изображений. Папка «поезд» содержит 83484 изображений.

Три - это четыре класса в изображениях rerinal oct. Они перечислены ниже.

  1. Неоваскуляризация хориоидеи (CNV): Неоваскуляризация хориоидеи (CNV) - это образование новых кровеносных сосудов в хориоидальном слое глаза. Неоваскуляризация хориоидеи является частой причиной неоваскулярной дегенеративной макулопатии (т. Е. «Влажной» дегенерации желтого пятна) [1], которая обычно усугубляется крайней миопией, злокачественной миопической дегенерацией или возрастными изменениями.

Https://en.wikipedia.org/wiki/Choroidal_neovascularization

2. Диабетический макулярный отек (DME):

DME - это осложнение диабета, вызванное скоплением жидкости в желтом пятне, которое может повлиять на ямку. Макула - это центральная часть сетчатки, которая находится в задней части глаза и где зрение является наиболее резким. Потеря зрения из-за DME может прогрессировать в течение нескольких месяцев и сделать невозможным четкую фокусировку.

На следующем рисунке показано ОКТ-изображение с заболеванием ДМО.

3. Друсен (DRUSEN):

Друзы - это желтые отложения под сетчаткой. Друзы состоят из липидов, жирного белка. Друзы, скорее всего, не вызывают возрастной дегенерации желтого пятна (ВМД). Но употребление друзов увеличивает риск развития ВМД.

Есть разные виды друзов. «Жесткие» друзы маленькие, отчетливые и далеко друг от друга. Этот вид друзы может не вызывать проблем со зрением долгое время, если вообще.

«Мягкие» друзы большие и сгруппированы ближе друг к другу. Их края не так четко очерчены, как твердые друзы. Этот мягкий вид друзы увеличивает риск ВМД.

В этой статье мы узнаем о заболевании, которым страдает изображение, полученное с помощью оптической когерентной томографии (ОКТ) сетчатки. Оптическая когерентная томография сетчатки (ОКТ) - это метод визуализации, используемый для получения поперечных срезов сетчатки живых пациентов с высоким разрешением.

На следующем изображении показано ОКТ-изображение болезни Друзена.

4. НОРМАЛЬНАЯ или нормальная сетчатка глаза:

Нормальное зрение возникает, когда свет фокусируется непосредственно на сетчатке, а не впереди или позади нее. Человек с нормальным зрением может ясно видеть предметы вблизи и вдалеке.

На следующем изображении показано, что изображение OCT имеет нормальное изображение.

Как это работает?

  1. Разберитесь в данных изображения.
  2. Увеличение изображения.
  3. Применяйте модели глубокого обучения.

Понять данные изображения

Нам нужно проверить, сколько изображений у нас в папке «поезд».

normal_len = len(os.listdir("../input/oct2017/OCT2017 /train/NORMAL"))
drusen_len = len(os.listdir("../input/oct2017/OCT2017 /train/DRUSEN"))
cnv_len = len(os.listdir("../input/oct2017/OCT2017 /train/CNV"))
dme_len = len(os.listdir("../input/oct2017/OCT2017 /train/DME"))
print("length of normal images = ",normal_len)
print("length of images with disease drusen = ",drusen_len)
print("length of images with disease cnv = ",cnv_len)
print("length of images with disease dme = ",dme_len)

Выход-

length of normal images =  26315
length of images with disease drusen =  8616
length of images with disease cnv =  37205
length of images with disease dme =  11348

Как видим, в папке «поезд» 83484 изображения. Мы разделим эти данные на тренировку и тест с соотношением 80:20.

Также важно, чтобы у нас были изображения одинаковой формы. Мы проверим, одинаковой ли формы изображения. В противном случае мы приведем все изображения в одинаковую форму.

files = os.listdir("../input/oct2017/OCT2017 /train/NORMAL/")
size = []
for i in tqdm(range(len(files))):
    img = cv2.imread("../input/oct2017/OCT2017 /train/NORMAL/"+files[i])
    #print("image size = ",img.shape)
    size.append(img.shape)
print("There are different sizes of DRUSEN images, they are = ",set(size))

выход -

There are different sizes of DRUSEN images, they are =  {(496, 1024, 3), (496, 1536, 3), (496, 768, 3), (496, 512, 3), (496, 384, 3), (512, 512, 3)}

Точно так же мы можем найти формы изображений, принадлежащих каждому классу. Мы видим, что они бывают разных форм.

Мы также можем увидеть, что изображения имеют три канала, посмотрев на их формы. Мы можем показать, что некоторые изображения принадлежат каждому классу с их отдельным каналом.

# https://stackoverflow.com/questions/37431599/how-to-slice-an-#image-into-red-green-and-blue-channels-with-misc-imread
files = os.listdir("../input/oct2017/OCT2017 /train/NORMAL/")
titles = ['', 'Red channel', 'Green channel', 'Blue channel']
cmaps = [None, plt.cm.Reds_r, plt.cm.Greens_r, plt.cm.Blues_r]
print('Five images from class - NORMAL')
for i in range(5):
    image = cv2.imread("../input/oct2017/OCT2017 /train/NORMAL/"+random.choice(files))
    
    fig, axes = plt.subplots(1, 4, figsize=(13,3))
    objs = zip(axes, (image, *image.transpose(2,0,1)), titles, cmaps)
    
    for ax, channel, title, cmap in objs:
        ax.imshow(channel, cmap=cmap)
        ax.set_title(title)
        ax.set_xticks(())
        ax.set_yticks(())

выход -

Five images from class - NORMAL

# https://stackoverflow.com/questions/37431599/how-to-slice-an-#image-into-red-green-and-blue-channels-with-misc-imread
files = os.listdir("../input/oct2017/OCT2017 /train/DRUSEN/")
titles = ['', 'Red channel', 'Green channel', 'Blue channel']
cmaps = [None, plt.cm.Reds_r, plt.cm.Greens_r, plt.cm.Blues_r]
print('Five images from class - DRUSEN')
for i in range(5):
    image = cv2.imread("../input/oct2017/OCT2017 /train/DRUSEN/"+random.choice(files))
    
    fig, axes = plt.subplots(1, 4, figsize=(13,3))
    objs = zip(axes, (image, *image.transpose(2,0,1)), titles, cmaps)
    
    for ax, channel, title, cmap in objs:
        ax.imshow(channel, cmap=cmap)
        ax.set_title(title)
        ax.set_xticks(())
        ax.set_yticks(())

выход -

Five images from class - DRUSEN

Аналогичным образом мы можем показать образец изображения остальных двух классов.

Увеличение изображения

  1. Стандартизация функций: - Мы можем стандартизировать значения пикселей для всего набора данных. Мы можем сделать это, установив аргументы featurewise_center и featurewise_std_normalization в классе ImageDataGenerator.

2. Случайное отражение: - Мы можем применить переворачивание к нашим данным изображения. Для этого мы можем установить аргументы vertical_flip и horizontal_flip в классе ImageDataGenerator.

3. Случайный сдвиг: - объекты на изображении не всегда могут быть центрированы. Чтобы обучить модель так, чтобы она могла найти смещенный по центру объект на изображении, мы можем создать смещенную версию наших обучающих данных. Для этого мы можем установить аргументы width_shift_range и height_shift_range в ImageDataGenerator.

  1. Разделение проверки: - мы можем разделить данные на обучение и проверку. Для этого мы должны установить аргумент validation_split в ImageDataGenerator.
train_datagen = ImageDataGenerator(samplewise_center=True, 
                              samplewise_std_normalization=True, 
                              horizontal_flip = True, 
                              vertical_flip = False, 
                              height_shift_range= 0.05, 
                              width_shift_range=0.1, 
                              rotation_range=15, 
                              zoom_range=0.15,
                                   validation_split=0.2)

Теперь с помощью метода flow_from_directory мы можем генерировать пакеты расширенных данных. Мы можем указать путь к каталогу, целевой размер изображения. Поскольку мы устанавливаем аргумент validation_split в классе ImageDataGenerator, мы будем использовать аргумент подмножества в методе flow_from_directory для получения данных обучения или данных проверки. Примечательно одно: каталог данных изображений должен содержать папки, содержащие изображения этого конкретного класса.

IMG_SIZE = 224
train_data_dir = '../input/oct2017/OCT2017 /train'
validation_data_dir = '../input/oct2017/OCT2017 /val'
train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(IMG_SIZE , IMG_SIZE),
    batch_size=16,
    subset='training',
    class_mode='categorical')

Модели глубокого обучения:

Прежде чем применять модели, давайте рассмотрим основное определение точности и отзывчивости.

Точность: - из всех точек, которые, по прогнозам модели, относятся к классу x, какой процент из них на самом деле относится к классу x.

Напомним: - из всех точек, которые фактически относятся к классу x, какой процент из них прогнозируется как класс x.

  1. Простая модель с пятью сверточными слоями: -

У нас будет простая модель с пятью сверточными слоями, двумя плотными слоями и последним плотным слоем с 4 узлами (поскольку у нас есть 4 класса) и функцией активации softmax. Мы использовали оптимизатор Адама и функцию потерь categoryorical_crossentropy, а затем обучили модель.

Вы можете найти код здесь - https://github.com/anshuak100/Retinal-OCT-Images

Мы получили точность_score со значением 0,78825. Здесь мы получили матрицу точности и отзыва -

2. Модель DenseNet: -

Применение модели DenseNet с удалением трех полностью связанных слоев из верхней части сети и инициализацией предварительно обученного веса в наборе данных imagenet. Добавляем плотный слой с четырьмя узлами с функцией активации softmax. Теперь обучите модель с помощью оптимизатора adam и функции потерь categoryorical_crossentropy.

Вы можете найти код здесь - https://github.com/anshuak100/Retinal-OCT-Images

# defining densenet model
def densenet_model():
    img_in = Input(t_x.shape[1:])              
    model = DenseNet121(include_top= False , 
                weights='imagenet',      # pre train weight 
                input_tensor= img_in, 
                input_shape= t_x.shape[1:],
                pooling ='avg') 
    x = model.output  
    predictions=Dense(4,activation="softmax", name="predictions")(x)    
    model = Model(inputs=img_in, outputs=predictions)
    return model

Мы получили точность_score со значением 0,9355. Здесь мы получили матрицу точности и отзыва -

3. Модель ResNet: -

Применим модель ResNet. Мы берем то же самое, что и в DenseNet, например, удалили верхний слой и добавили плотный слой с четырьмя единицами и функцией активации softmax. А затем обучите модель с помощью оптимизатора Адама и функции потерь categoryorical_crossentropy.

# Defining ResNet model
def resnet_model():
    img_in = Input(t_x.shape[1:])              
    model = ResNet50(include_top= False , 
                weights='imagenet',      
                input_tensor= img_in, 
                input_shape= t_x.shape[1:],
                pooling ='avg') 
    x = model.output  
    predictions=Dense(4,activation="softmax", name="predictions")(x)    
    model = Model(inputs=img_in, outputs=predictions)
    return model

Вы можете найти код здесь - https://github.com/anshuak100/Retinal-OCT-Images

Мы получили точность_score со значением 0,914375. Здесь мы получили матрицу точности и отзыва -

4. Модель InceptionNet: -

Мы делаем то же самое, что делали в DenseNet и ResNet, только изменение касается InceptionNet вместо DenseNet или ResNet.

# defining inceptionnet model
def inception_v3():
    img_in = Input(t_x.shape[1:])              
    model =  InceptionV3(include_top= False , 
                weights='imagenet',      
                input_tensor= img_in, 
                input_shape= t_x.shape[1:],
                pooling ='avg') 
    x = model.output  
    predictions=Dense(4,activation="softmax", name="predictions")(x)    
    model = Model(inputs=img_in, outputs=predictions)
    return model

Вы можете найти код здесь - https://github.com/anshuak100/Retinal-OCT-Images

Мы получили точность_score со значением 0,927375. Здесь мы получили матрицу точности и отзыва -

код здесь: https://github.com/anshuak100/Retinal-OCT-Images

Вывод:

  1. Трансферное обучение дает лучшую точность, чем сеть, созданная вручную.
  2. Если мы сравним матрицу отзыва для всех, мы увидим, что метка 2 неверно классифицирована больше. Матрица отзыва InceptionNet лучше других.
  3. Модель InceptionNet пытается сбалансировать все эти классы. Мы можем выбрать ее как лучшую модель.

Использованная литература :

  1. Https://www.appliedaicourse.com

2. https://www.kaggle.com/paultimothymooney/kermany2018/homehttp:

3. https://machinelearningmastery.com/image-augmentation-deep-learning-keras/

4. https://becominghuman.ai/image-data-pre-processing-for-neural-networks-498289068258?gi=b3755339c2de

5. https://www.preventblindness.org/diabetic-macular-edema-dme

6. https://www.aao.org/eye-health/diseases/what-are-drusen