Я изучил ряд методов сегментации изображения и маркировки связанных компонентов, то есть процесса разделения изображения на небольшие фрагменты (называемые «компонентами»), которые не содержат других компонентов. Этот процесс можно использовать для анализа изображения в целом, что имеет значение в таких областях, как оптическое распознавание символов.

Популярный метод сегментации называется «размытие по Гауссу». Этот алгоритм работает путем попиксельного сглаживания изображений до тех пор, пока не будет достигнуто пороговое значение, после чего изображение считается сегментированным. Этот метод страдает от проблемы, называемой «обнаружение края», когда объект, который находится близко к другому объекту, будет иметь компоненты вокруг своих краев, стертые во время процесса размытия, поэтому он не будет правильно сегментирован.

Другой способ обойти эту проблему — сначала сегментировать изображение с помощью какой-либо другой техники, а затем применить размытие по Гауссу в качестве шага постобработки. Одна из проблем с размытием по Гауссу заключается в том, что оно плохо работает с изображениями, содержащими текст, потому что текст может быть искажен в процессе размытия. Чтобы исправить это, вы можете использовать метод, называемый маркировкой подключенных компонентов, который рисует линию вокруг каждого маленького компонента на изображении, чтобы определить набор V и многое другое, что мы рассмотрим в статье.

ОФТАЛЬМОСКОПИЧЕСКАЯ

Алгоритм извлечения ярких областей из входных изображений глазного дна

ПРЕДВАРИТЕЛЬНАЯ ОБРАБОТКА

Выравнивание гистограммы:

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

импорт cv2
импорт numpy как np

img = cv2.imread('two.tif')

# Преобразование в оттенки серого
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Применить выравнивание гистограммы
eq = cv2.equalizeHist(gray)

# Сложить изображения для вывода
res = np.hstack((gray,eq)) #размещение изображений рядом

# Сохранить изображение
# cv2.imshow(,res)
cv2.imshow('res.png',res)
#Ждать нажатия клавиши
cv2.waitKey(0)

#Уничтожить все окна
cv2.destroyAllWindows()

ВЫВОД:

Техника CLAHE:

Это можно решить с помощью адаптивной коррекции гистограммы с ограниченным контрастом (CLAHE). CLAHE работает аналогично обычному методу выравнивания гистограммы, но вместо перераспределения всех пикселей он перераспределяет только те, которые находятся в определенном диапазоне. Диапазон представляет собой оценку того, что считается «бликами» и «тенями». Этот диапазон можно ограничить, задав параметр контрастности, который указывает, какой процент пикселей будет перераспределяемым.

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

Если вы знакомы со статистикой, это, по сути, z-значение.

CLAHE работает следующим образом:

  • Рассчитать среднее значение и стандартное отклонение для каждого канала и каждого пикселя изображения.
  • Установите для параметра контрастности небольшое значение (я использовал 0,05).
  • Для каждого канала обрежьте оба пороговых значения по ограничениям этого канала. Итак, если минимальное значение канала равно 0, а максимальное — 255, то мы установим два пороговых значения следующим образом: —
  • Если L ‹ -(((min_channel_value — σ) / (max_channel_value — min_channel_value)) + 1), то порог равен 0 -
  • Если L › (((max_channel_value — min_channel_value) / (max_channel_value — min_channel_value)) + 1), то порог равен 255
  • Для каждого канала и каждого пикселя изображения мы вычитаем среднее значение, а затем возводим результат в квадрат. Затем мы извлекаем из этого значения квадратный корень, чтобы получить пороговые значения.
  • Рассчитайте наше выходное изображение, применив max() к значению канала каждого пикселя: — Если пиксель имеет интенсивность меньше или равную нашему первому пороговому значению, тогда он остается черным — Если его интенсивность больше нашего первого порогового значения, но меньше или равно нашему второму порогу, то он становится белым.

import cv2
import numpy as np

img = cv2.imread( 'two.tif' )

# преобразовать входное изображение в цветовое пространство LAB
lab = cv2.cvtColor( img , cv2.COLOR_BGR2LAB )

# разбить изображение на каналы L, A и B
l , a , b = cv2.split( lab )

# применяем CLAHE к каналу L
clahe = cv2.createCLAHE( clipLimit=3.0 , tileGridSize=(8 , 8))
cl = clahe.apply( l )

# объединить расширенный канал L CLAHE с исходными каналами A и B
limg = cv2.merge( (cl , a , b))

# преобразовать изображение LAB обратно в цветовое пространство RGB
final = cv2.cvtColor( limg , cv2.COLOR_LAB2BGR )

# отображаем выходное изображение
cv2.imshow( 'Enhanced Image', final )
cv2.imshow('Исходное изображение', img)
cv2.waitKey(0)

ВЫВОД:

Исходное изображение (слева) и изображение после применения CLAHE (справа). В этом случае вы можете ясно видеть, что контраст увеличивается, когда мы применяем CLAHE слева.

Обзор литературы:

Долгое время было невозможно выровнять изображения с высокой контрастностью без чрезмерного усиления контраста, тем самым уничтожая некоторые детали в сцене. Однако недавно был разработан новый алгоритм под названием Contrast Limited Adaptive Histogram Equalization (CLAHE). CLAHE — это вариант адаптивного выравнивания гистограммы (AHE), который обеспечивает чрезмерное усиление контраста. Как это достигается, объясняется в следующем разделе. CLAHE работает с небольшими областями изображения, называемыми фрагментами, а не со всем изображением. Соседние плитки затем объединяются с помощью билинейной интерполяции для удаления искусственных границ между ними. На следующем рисунке показаны два примера изображений до и после применения алгоритма CLAHE. На изображениях справа мы можем видеть, как CLAHE может улучшать детали изображения, не преувеличивая контрастность и сохраняя естественный вид сцены.

Операционный поток CLAHE приведен ниже:

1. Отсканируйте изображение с разной контрастностью и сохраните набор гистограмм для каждого уровня контрастности

2. Вычислить логарифмические гистограммы для каждой плитки, используя сохраненные гистограммы

3. Определите плитку, которая имеет максимальный контраст с соседними плитками

4. Вычислите карту адаптивного контраста, используя выбранную плитку, и билинейно интерполируйте ее, чтобы получить глобальную карту контраста.

Обзор:

Вы когда-нибудь видели изображение с большим количеством пустого пространства вокруг объекта? Как насчет сильно недоэкспонированного изображения? Скорее всего, если вы похожи на большинство людей, ваш мозг говорит: «Нет! Я не так вижу мир! Это слишком ярко! Слишком темно!" Оказывается, мы не совсем правильно видим вещи. Встроенная система человеческого зрения имеет ряд серьезных ограничений. Он был разработан для распознавания объектов в повседневной жизни, а не для захвата изображений. В результате он на самом деле не показывает нам реальный мир. Например, представьте, что вы идете по темной комнате с включенным светом. Вы не сможете увидеть все огни сразу, и вам придется брать их по одному. Если свет слишком далеко от вас, вы вообще не сможете его увидеть. То же самое верно и для вашей камеры: то, что видят ваши глаза, может не совпадать с тем, что снимает ваша камера. На самом деле, иногда это может быть совершенно иначе, как показано на изображении ниже:

Контрастное растяжение

Растягивание контраста – это простой метод улучшения изображения, который пытается повысить контрастность изображения путем "растягивания" диапазона значений интенсивности, содержащегося в нем, до требуемого диапазона значений. Например, если бы мы пытались растянуть изображение, которое содержит много темных оттенков, но очень мало светлых, мы могли бы сделать темные области светлее, а светлые — темнее, тем самым расширив диапазон имеющихся интенсивностей. Это простая концепция. Вопрос в том, может ли это действительно работать?

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

Обзор литературы:

В области цифровой обработки изображений существует множество алгоритмов для повышения контрастности. Большинство из них можно разделить на линейные и нелинейные методы. Линейные методы просты в реализации и быстры. Однако они не могут должным образом улучшить изображение, если интенсивность различных объектов на изображении сильно различается.

Самым популярным методом настройки контрастности является выравнивание гистограммы. Выравнивание гистограммы берет гистограмму исходного изображения и пытается сопоставить ее с другой предварительно определенной гистограммой. Проблема с этим подходом заключается в том, что он приводит к осветлению темных областей входного изображения и затемнению уже ярких областей. Это приводит к потере деталей в обоих случаях, что неприемлемо для многих приложений.

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

Как работает нормализация?

Нормализация – это метод обработки изображений, используемый для обеспечения надлежащей яркости и контрастности изображения. Это процесс, который включает в себя получение значений пикселей в определенном диапазоне и установку их на ноль или единицу. Нормализация может применяться как к отдельным пикселям, так и к группе пикселей.

Обзор литературы:

Нормализация часто используется для изображений, полученных с помощью цифровой камеры. При съемке при слабом освещении время экспозиции может быть увеличено, что может привести к тому, что некоторые элементы изображения будут слишком темными, а другие — слишком яркими. В таких случаях можно применить нормализацию, чтобы избавиться от этой проблемы. Различные функции, такие как тени и блики, также можно нормализовать по отдельности, чтобы каждая из них имела значение в установленных пределах.

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

=

import cv2
import numpy as np

# прочитать входное изображение
img = cv2.imread('two.tif',0)

# применение контрастного растяжения
s = np.log( img + 1)
s = s / s.max() * 255
s = s.astype(np.uint8)

# применение CLAHE
clahe = cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
cl1 = clahe.apply(img)

# применение порога Оцу
ret,thresh1 = cv2.threshold (cl1,0,255,cv2.THRESH_OTSU)

# применение обнаружения Canny Edge
edges = cv2.Canny(thresh1,100,200)

# поиск контуров
contours,hierarchy = cv2.findContours(edges,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

# найти контур с максимальной площадью и сохранить его как best_cnt
max_area = 0
для cnt в контурах:
area = cv2.contourArea(cnt)
if area › max_area:
max_area = area
best_cnt = cnt

# найти центроиды best_cnt и нарисовать там круг
M = cv2.moments(best_cnt)
cx,cy = int(M['m10'] / M['m00']),int(M['m01'] / M[ 'm00' ])
cv2.circle(img,(cx,cy),5,255,-1)

# показать входное и выходное изображение
cv2.imshow('Входное изображение',img)
cv2.imshow('Контрастное растянутое изображение', s)
cv2.imshow('CLAHE Image',cl1)
cv2.imshow('Порог Оцу',thresh1)
cv2.imshow('Обнаружение хитрых краев',края)

cv2.waitKey(0)
cv2.destroyAllWindows()

ВЫВОД:

Обнаружение осторожных краев:

Порог Оцу:

Контрастное растяжение:

КЛАШ:

Входное изображение:

Алгоритм определения местоположения диска зрительного нерва

Обзор литературы:

"Какой алгоритм лучше всего определяет расположение диска зрительного нерва на изображениях глазного дна?" Было изучено несколько различных методов, чтобы попытаться решить эту проблему, но трудно сказать, какой из них лучше, потому что это можно сделать разными способами. Цель алгоритма — взять изображение и разделить его на две части: сетчатку и все остальное. Большинство методов включают в себя различие между ними с использованием определенного типа обнаружения границ с методом пороговой обработки. Большинство существующих сегодня алгоритмов используют морфологические операции для обнаружения границ, но некоторые используют другие методы, такие как величина градиента. В большинстве методов также используется метод пороговой обработки для разделения двух частей. Это можно сделать разными способами:

Метод Оцу представляет собой адаптивный порог, при котором он анализирует все изображение и определяет, какое изменение интенсивности является наименее значительным (темнота), и устанавливает область вокруг этого пикселя как белую. Это не очень точный метод, поскольку он находит минимальное значение только локально, а не глобально.

Есть еще два популярных метода для выполнения этой задачи: пороговое определение с помощью верхней шляпы и нечеткая кластеризация c-средних.

ПОРОГ ВЕРХНЕЙ ЧАСТИ:

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

Метод заключается в определении интенсивности каждого пикселя, определении средней интенсивности всех пикселей, а затем сравнении отношения среднего значения с пороговым значением (чаще всего 0,5). Это известно как Top Hat Thresholding, потому что оно дает вам форму цилиндра, если вы рисуете пиксели со средней интенсивностью выше 0,5. Его легко реализовать, и он дает хорошие результаты, если вы позаботитесь о том, чтобы избежать шума и других артефактов, которые могут мешать.

«Когда вы выполняете офтальмологическую визуализацию и у вас есть одно или несколько изображений глазного дна, вам может быть интересно найти расположение диска зрительного нерва. В зависимости от качества изображения и других особенностей изображения ваша задача может оказаться не такой простой, как кажется. Диск зрительного нерва представляет собой небольшую темную структуру с четким центром, окруженную сетчаткой. Несмотря на то, что это выглядит как единая круговая структура, на самом деле она может иметь несколько компонентов на одном изображении в зависимости от того, как она была получена. Другими словами, диск может быть разбит на несколько частей разного цвета и формы, что затрудняет определение его истинного центра. Вы можете попробовать вручную нарисовать контуры вокруг каждой части диска, но это может стать утомительным при работе с сотнями или даже тысячами изображений».

Алгоритм отклонения выбросов (ORA)

Другим популярным методом является алгоритм отклонения выбросов (ORA), который пока не получил широкого распространения, но, как было показано, имеет лучшую точность, чем Top Hat Thresholding, при использовании на высококачественных изображениях, с одним большим предостережением: ORA удаляет много сигнала от вашего изображения. Этот алгоритм работает следующим образом: сначала изображение сглаживается с помощью фильтра скользящего среднего 3x3, чтобы избавиться от шума. Затем он находит все локальные максимумы и минимумы в пределах 1 диаметра диска вокруг этих максимумов и минимумов.

Компонентный анализ

«Компонентный анализ — это процесс, который включает в себя идентификацию различных частей изображения и их маркировку. В этом случае различными частями изображения глазного дна являются диск зрительного нерва и окружающая область. Диск зрительного нерва помечен как центр изображения, а окружающая область помечена как фон. Цель этой программы — найти диск зрительного нерва на данном изображении глазного дна и пометить его. Сначала программа загружает изображение глазного дна и преобразует его в оттенки серого. Затем он применяет к изображению порог, чтобы сделать фон черным, а диск зрительного нерва — белым. Затем он использует алгоритм анализа связанных компонентов, чтобы найти самый большой компонент в изображении, которым является диск зрительного нерва. Наконец, он помечает диск зрительного нерва кружком».

Метод порогового значения контуров:

ИСПОЛЬЗОВАНИЕ РАСШИРЕНИЯ И ЭРОЗИИ ДЛЯ УДАЛЕНИЯ НЕКОТОРЫХ ШУМОВ

Чтобы точно определить расположение диска зрительного нерва, нам нужно сначала найти контур глазного бокала. Для этого на изображении используется метод пороговой обработки, который можно выполнить двумя способами. Первый способ заключается в использовании фиксированного порогового значения и маскирующей области вокруг диска зрительного нерва. Второй способ — использование переменного порога в зависимости от яркости пикселей. Этот метод показан в первой части и будет показан более подробно во второй части в виде кода.

import cv2
import numpy as np

# Прочитать изображение
img = cv2.imread("two.tif", 0)
# Применить расширение и эрозию, чтобы убрать шум
kernel = np.ones( (3,3),np.uint8)
img_opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, ядро, итерации = 2)
# Применить порог для получения изображения только с черным и белым
ret, thresh = cv2.threshold(img_opening,210,255,cv2.THRESH_BINARY)
# Найти контуры отфильтрованного изображения
contours, Hierary = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Найти контур наибольшей площади и нарисуйте ее
cnt = max(contours, key = lambda x: cv2.contourArea(x))
x,y, w,h = cv2.boundingRect(cnt)
cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),3 )
# Показать результирующее изображение
cv2.imshow("Изображение", img)
cv2. ключ ожидания(0)

ВЫВОД:

БЕЗ ИСПОЛЬЗОВАНИЯ РАСШИРЕНИЯ И ЭРОЗИИ ДЛЯ УДАЛЕНИЯ НЕКОТОРЫХ ШУМОВ

import cv2
import numpy as np

#Прочитайте изображение
img = cv2.imread('two.tif')

#Преобразовать изображение в оттенки серого
gray = cv2.cvtColor( img,cv2.COLOR_BGR2GRAY)

#Применить пороговое значение к изображению в градациях серого для получения бинарного изображения
ret, thresh = cv2.threshold (grey,210,255,0)

#Найти контуры в бинарном изображении
contours, Hierary = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

#Найти контур максимальной площади
cnt = max(contours, key = лямбда x: cv2.contourArea(x))
x,y,w,h = cv2.boundingRect(cnt)
cv2.rectangle( img,(x,y),(x+w,y+h),(0,255,0),3)

#Нарисуйте контур на исходном изображении
cv2.drawContours(img, [cnt], 0, (0,255,0), 3)

#Показать изображение
cv2.imshow('Обнаружение диска зрительного нерва', img)

#Ждем нажатия клавиши
cv2.waitKey(0)

#Уничтожить все окна
cv2.destroyAllWindows()

ВЫВОД:

Метод сегментации подключенных компонентов контура

импортировать numpy как np
импортировать cv2

#read image
image = cv2.imread("two.tif")
#convert to Grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#применить пороговое значение
ret, thresh = cv2.threshold(gray,200,255,0)
# вычислить контуры
контуры, иерархия = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

#draw контуры
cv2.drawContours(изображение, контуры, -1, (0,255,0), 3)

#print location
для c в контурах:
M = cv2.moments(c)
if M[“m00”] != 0:
cx = int(M[“m10”] / M[“m00”])
cy = int(M[ «m01»] / M[«m00»])
print(«Координаты диска зрительного нерва: {}, {}».format(cx,cy))

#display
cv2.imshow("Контуры", изображение)
cv2.waitKey(0)
cv2.destroyAllWindows()

КООРДИНАТЫ ОПТИЧЕСКОГО ДИСКА:

Подключен к отладчику pydev (сборка 213.6777.50)

Координаты диска зрительного нерва: 435, 274

Координаты диска зрительного нерва: 449, 286

Координаты диска зрительного нерва: 428, 284

Координаты диска зрительного нерва: 435, 282

Координаты диска зрительного нерва: 415, 276

Координаты диска зрительного нерва: 451, 258

Координаты диска зрительного нерва: 439, 255

Координаты диска зрительного нерва: 434, 246

ВЫВОД:

КОНКУРЕНТНЫЙ АНАЛИЗ СПОСОБОВ ОБРАБОТКИ КОНТУРОВ С ИСПОЛЬЗОВАНИЕМ И БЕЗ ИСПОЛЬЗОВАНИЯ МЕТОДОВ РАСШИРЕНИЯ И ЭРОЗИИ ДЛЯ УДАЛЕНИЯ ШУМА-

Мы сравнили результаты двух различных методов пороговой обработки контуров — метода рисования контуров с использованием методов расширения и эрозии для удаления шума и метода рисования контуров без использования методов расширения и эрозии для удаления шума.

Мы провели конкурентный анализ различных способов рисования контуров с использованием координат (x,y) облаков точек. Методы контурирования включали:

  • - Пороговый метод
  • -Метод дилатации и эрозии
  • -Метод сегментации компонентов, связанных с контуром

Мы сравнили эти методы по нескольким критериям, включая скорость и точность.

  1. Мы обнаружили, что метод порогового определения является наиболее точным с точки зрения определения того, какие точки были частью исходного облака, а какие нет. Однако на сегодняшний день это был и самый медленный метод.
  2. Метод расширения и эрозии был довольно быстрым, но не позволял создать достаточно четкую линию для точного определения контура.
  3. Метод сегментации подключенных компонентов контура создал точную линию, но работал очень медленно. Поэтому мы пришли к выводу, что этот метод непригоден для больших наборов данных.
  • Первый метод, известный как метод определения порога итеративного расширения и эрозии контуров (CIDE), применяется к бинарным изображениям без шума. Второй метод, известный как метод определения порога контуров (CTM), применяется к бинарным изображениям с шумом.
  • Использование методов расширения и эрозии в первом методе предназначено для создания гладкой непрерывной поверхности между каждым многоугольником с пороговым значением, который был образован перекрытием или зазором в краях исходного изображения. Во втором методе не использовались методы расширения и эрозии, а это означает, что каждый край полигона резкий, что создает видимые линии между соседними порогами. Однако это может облегчить просмотр объектов, которые могут быть скрыты шумом на исходном изображении.

ОФТАЛЬМОСКОПИЧЕСКАЯ

import cv2
import numpy as np

# read image
img = cv2.imread( “two.tif”, 0 )

# применить порог
_ , thresh = cv2.threshold( img , 200 , 255 , cv2.THRESH_BINARY )

# найти контуры
contours , _ = cv2.findContours( thresh , cv2 .RETR_TREE , cv2.CHAIN_APPROX_SIMPLE )

# сортировка контуров
sorted_contours = sorted( контуры , key=lambda x : cv2.contourArea ( x ), reverse=True )

# извлечь самый большой контур
largest_contour = sorted_contours[ 0 ] < br />
# нарисовать самый большой контур на исходном изображении
cv2.drawContours( img , [large_contour] , 0 , (0 , 255 , 0) , 3 )

# отобразить результат
cv2.imshow( “FUCK YOU”, img )
cv2.imwrite("RETINAL OPTIC DISC.tif", img)
cv2.waitKey( 0 )
cv2.destroyAllWindows( )

ВЫВОД:

ОШИБКА_ПРОВЕРКА

import cv2
import numpy as np

# прочитать изображение
img = cv2.imread('two.tif')

# преобразовать в оттенки серого
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# применить пороговое значение
_, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV )

# найти контуры
контуры, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# рисовать контуры
img = cv2.drawContours(img, контуры, -1, (0, 255, 0), 2)

# вывести координаты
print(contours[0][0][0])

# показать изображение
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

# реальных координат диска зрительного нерва
x = 37
y = 37

# обнаруженные координаты диска зрительного нерва
a = контуры[0 ][0][0]

# error
error = np.sqrt((x — a[0])* *2 + (y — a[1])**2)
print(ошибка)

ВЫВОД:

C:/Users/mateeb.ce41ceme/PycharmProjects/pythonProject/venv/error.py

[0 0]

52.32590180780452

Процесс завершен с кодом выхода 0

ERROR_CHECKING.py:

импортировать csv

с помощью open('/Users/Desktop/image_file.csv', 'r') как csvfile:
reader = csv.DictReader (csvfile)
для строки в программе чтения:
x1 = float(row['x'])
y1 = float(row['y'])
x2 = float(row['x2'])
y2 = float( row['y2'])
error = ((x1-x2)**2 + (y1-y2)**2)**0,5
row['error'] = error

с open('/Users/Desktop/image_file.csv', 'w') как csvfile: >
fieldnames = ['x', 'y', 'x2', 'y2', 'error']
author = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
для строки в считывателе:
writer.writerow (строка)

НАША ТАБЛИЦА ОШИБОК:

изображение x y x2 y2 ошибка

02_test.tif 458 275 442 279 16.4924225

04_test.tif 361 275 354 280 8.602325267

06_test.tif 461 268 447 272 14.56021978

08_test.tif 485 277 472 280 13.34166406

10_left.jpeg 2439 1697 2278 1550 218.013761

10_right.jpeg 2985 1562 2905 2192 635.0590524

10_test.tif 468 278 407 367 107,8981001

12_test.tif 82 257 91 259 9.219544457

13_left.jpeg 504 832 728 664 280

13_right.jpeg 2119 852 1841 564 400,2848985

13_test.tif 486 268 390 415 175,5704987

14_test.tif 479 275 467 283 14.4222051

15_test.tif 193 282 196 283 3.16227766

16_test.tif 479 258 467 305 48.50773134

17_left.jpeg 1396 1322 1578 1230 203,931361

17_test.tif 467 267 445 264 22.20360331

18_test.tif 471 262 423 353 102,8834292

19_left.jpeg 1445 1176 1359 1096 117,4563749

19_right.jpeg 2456 1269 2383 1216 90,21086409

19_test.tif 486 275 482 281 7.211102551

20_left.jpeg 2539 1513 2657 1362 191,637679

20_right.jpeg 1293 1296 1288 1192 104.1201229

20_test.tif 482 284 433 383 110.4626634

21_left.jpeg 1724 1589 1971 1034 607,481687

21_right.jpeg 3036 1556 2926 1243 331,7664841

21_training.tif 77 257 207 150 168,3716128

22_left.jpeg 747 848 696 770 93,1933474

22_right.jpeg 1821 910 1931 856 122,5397895

22_training.tif 471 272 459 281 15

23_left.jpeg 1417 1127 1556 968 211.1918559

23_right.jpeg 2676 1242 2371 775 557,7759407

23_training.tif 428 227 438 228 10.04987562

24_training.tif 472 289 444 212 81,93289938

25_left.jpeg 2635 1455 2397 1271 300,8321791

25_right.jpeg 791 1846 1099 1552 425,7933771

25_training.tif 464 270 453 276 12,52996409

26_training.tif 80 245 91 246 11.04536102

27_training.tif 492 283 483 284 9,055385138

29_training.tif 497 271 492 279 9.433981132

30_training.tif 492 291 485 288 7,615773106

31_left.jpeg 1665 1542 1736 1031 515,9089067

31_right.jpeg 3366 1536 3358 1606 70,45565982

31_training.tif 393 250 394 252 2.236067977

32_training.tif 491 285 477 288 14.31782106

33_left.jpeg 1657 1592 1648 1577 17,49285568

33_training.tif 470 305 462 299 10

34_training.tif 388 223 278 275 121,6716894

35_training.tif 81 276 91 273 10.44030651

37_training.tif 496 292 410 200 125,9364919

38_training.tif 490 274 485 275 5.099019514

Для набора данных я буду использовать это изображение из Национальной лаборатории возобновляемых источников энергии (NREL), доступ к которому можно получить здесь:

https://drive.google.com/drive/folders/1DxmL9I2772qTCYwlbMk1KpKPtJb85o-H

БЛОК-СХЕМА

ЗАКЛЮЧИТЕЛЬНЫЕ РЕЗУЛЬТАТЫ

Выходные данные для статьи можно найти здесь:

https://drive.google.com/drive/folders/1Y6WcZUulU6R7Ro4c85IkUvBBOz2xk5-b