Документация по ImageEdgeDetection.jl
Пакет Julia, содержащий ряд алгоритмов для обнаружения краев на изображениях.
Начало работы
Этот пакет является частью более широкой экосистемы обработки изображений на основе Julia. Если вы только начинаете работу, вам будет полезно прочитать о некоторых фундаментальных соглашениях, используемых в экосистеме, которые заметно отличаются от обычного представления изображений в OpenCV, MATLAB, ImageJ или Python.
В примерах использования в пакете ImageEdgeDetection.jl
предполагается, что у вас уже установлены некоторые основные пакеты. Примечательно, что в примерах предполагается, что вы можете загрузить и отобразить изображение. Загрузка изображения осуществляется с помощью пакета FileIO.jl, который использует QuartzImageIO.jl, если вы работаете в MacOS
, и ImageMagick.jl в противном случае. В зависимости от конфигурации системы вы можете столкнуться с проблемами при установке пакетов загрузки изображений. В этом случае можно обратиться к руководству по устранению неполадок.
Для отображения изображений обычно используется пакет ImageView.jl. Альтернативой могут служить различные пакеты для построения графиков, включая Makie.jl. Доступен пакет ImageShow.jl, который упрощает отображение изображений в записных книжках Jupyter
с помощью IJulia.jl. Наконец, с помощью пакета ImageInTerminal.jl вы можете предварительно просмотреть изображение в REPL. Однако этот пакет предполагает, что в терминале используется моноширинный шрифт, и, как правило, он не выводит адекватные результаты в среде Windows.
Еще один пакет, который используется для иллюстрации функциональности в ImageEdgeDetection.jl
, — это TestImages.jl, который служит репозиторием множества стандартных тестовых изображений для обработки изображений.
Базовое использование
Каждый алгоритм обнаружения краев в пакете ImageEdgeDetection.jl
представляет собой алгоритм AbstractEdgeDetectionAlgorithm
.
Предположим, необходимо пометить края на изображении. Для этого достаточно выбрать подходящий алгоритм и вызвать функции detect_edges
или detect_edges!
для изображения.
Рассмотрим простую демонстрацию, где используется известный алгоритм обнаружения краев Кэнни (Canny):
using TestImages, ImageEdgeDetection, MosaicViews
img = testimage("mandril_gray")
# Обнаружение краев в разных масштабах путем настройки параметра `spatial_scale`.
img_edges₁ = detect_edges(img, Canny(spatial_scale = 1.4))
img_edges₂ = detect_edges(img, Canny(spatial_scale = 2.8))
img_edges₃ = detect_edges(img, Canny(spatial_scale = 5.6))
demo₁ = mosaicview(img, img_edges₁, img_edges₂, img_edges₃; nrow = 2)
Вы можете управлять порогами гистерезиса Кэнни, задавая соответствующие параметры ключевых слов.
# Управление порогами гистерезиса путем задания низкого и высокого пороговых значений.
img = testimage("cameraman")
img_edges₄ = detect_edges(img, Canny(spatial_scale = 1.4, low = Percentile(5), high = Percentile(80)))
img_edges₅ = detect_edges(img, Canny(spatial_scale = 1.4, low = Percentile(60), high = Percentile(90)))
img_edges₆ = detect_edges(img, Canny(spatial_scale = 1.4, low = Percentile(70), high = Percentile(95)))
demo₂ = mosaicview(img, img_edges₄, img_edges₅, img_edges₆; nrow = 2)
Каждый алгоритм уточнения краев в пакете ImageEdgeDetection.jl
представляет собой алгоритм AbstractEdgeThinningAlgorithm
.
Предположим, что необходимо подавить типичную передачу двухкромочного фильтра обнаружения краев. Для этого достаточно выбрать подходящий алгоритм и вызвать функции thin_edges
или thin_edges!
для градиентов изображения и величин градиентов.
Например, можно подавить нежелательные многокромочные передачи, связанные с фильтром Собеля:
using TestImages, ImageEdgeDetection, MosaicViews, ImageFiltering, ImageCore
img = Gray.(testimage("lake_gray"))
# Определение градиентов изображения
g₁, g₂ = imgradients(img, KernelFactors.sobel)
# Определение величины градиента
mag = hypot.(g₁, g₂)
# Подавление немаксимальных величин градиента
nms₁ = thin_edges(mag, g₁, g₂, NonmaximaSuppression())
nms₂ = thin_edges(mag, g₁, g₂, NonmaximaSuppression(threshold = Percentile(95)))
demo₃ = mosaicview(img, Gray.(nms₂), Gray.(mag), Gray.(nms₁); nrow = 2)
Можно также определить ориентацию градиента настраиваемым образом, определив OrientationConvention
. С помощью типа OrientationConvention
можно указать направление по компасу, относительно которого вы собираетесь измерять угол, и указать, как вы будете выполнять измерение — по часовой или против часовой стрелки.
В примере ниже мы сопоставляем углы [0...360]
с единичным интервалом, чтобы визуализировать ориентацию градиента изображения, используя различные соглашения об ориентации. Обратите внимание, что угол 360
используется в качестве контрольного значения для выделения пикселей, для которых ориентация градиента не определена. Ориентация градиента считается неопределенной, если величина градиента равна нулю. Это соответствует областям постоянной интенсивности на изображении. На панели изображений первое изображение представляет собой черный круг на белом фоне. На последующих изображениях показана ориентация градиента изображения, где неопределенные ориентации градиента представлены в виде чисто белых пикселей.
using ImageEdgeDetection, MosaicViews, ImageFiltering, ImageCore
# Создание тестового изображения (черный круг на белом фоне).
a = 250
b = 250
r = 150
img = Gray.(ones(500, 500))
for i in CartesianIndices(img)
y, x = i.I
img[i] = (x-a)^2 + (y - b)^2 - r^2 < 0 ? 0.0 : 1.0
end
# Определение градиентов изображения
g₁, g₂ = imgradients(img, KernelFactors.sobel)
orientation_convention₁ = OrientationConvention(in_radians = false, compass_direction = 'S')
orientation_convention₂ = OrientationConvention(in_radians = false, compass_direction = 'N')
orientation_convention₃ = OrientationConvention(in_radians = false, compass_direction = 'E', is_clockwise = true)
angles₁ = detect_gradient_orientation(g₁, g₂, orientation_convention₁) / 360
angles₂ = detect_gradient_orientation(g₁, g₂, orientation_convention₂) / 360
angles₃ = detect_gradient_orientation(g₁, g₂, orientation_convention₃) / 360
demo₄ = mosaicview(img, Gray.(angles₁), Gray.(angles₂), Gray.(angles₃); nrow = 2)
Более сложные примеры использования приведены на странице Справочник по функциям.