Обнаружение краев методом Кэнни
Фильтр Кэнни по-прежнему является эффективным детектором краев, хотя он был изобретен в 1986 году [1]. В этой демонстрации показано использование недавно разработанного пакета ImageEdgeDetection
на примере фильтра Кэнни.
using Images, ImageEdgeDetection, Noise
using ImageEdgeDetection: Percentile
using TestImages
В |
В JuliaImages любой объект AbstractArray
можно рассматривать как изображение. В этой демонстрации в качестве иллюстрации мы используем сгенерированное изображение.
Сначала создадим тестовое изображение.
function make_simple_image(sz)
img_gray = zeros(Gray{Float64}, sz...)
fill_region = map(x->x÷4:3x÷4, sz)
img_gray[fill_region...] .= 1
img_rot = imrotate(img_gray, pi/4)
# Исказим изображение размытостью и шумом, чтобы немного затруднить работу нашей функции
# обнаружения краев методом Кэнни, так как фильтр Кэнни основан на принципе
# нахождения градиентов.
img_gauss = imfilter(img_rot, Kernel.gaussian(2))
# Используем фильтр `salt_pepper` из `Noise.jl`. Шум соли и перца — это в общем случае
# шум, который изменяет пиксель двумя различными значениями шума.
# Здесь мы случайным образом присваиваем пикселям только белый цвет.
img_noise = salt_pepper(img_gauss, 0.05, salt_prob = 0, pepper = 0.9)
end
img = make_simple_image((200, 200))
ImageEdgeDetection
предлагает унифицированный API detect_edges(img, alg)
с различными алгоритмами. В этой демонстрации мы покажем, как использовать оператор Canny
[1]. Сначала нужно создать экземпляр алгоритма Canny
:
alg = Canny(spatial_scale=1, high=Percentile(80), low=Percentile(20))
ImageEdgeDetection.Canny{Int64, ImageEdgeDetection.Percentile{Int64}, ImageEdgeDetection.Percentile{Int64}, ImageEdgeDetection.NonmaximaSuppression{ImageEdgeDetection.Percentile{Int64}}}
spatial_scale: Int64 1
high: ImageEdgeDetection.Percentile{Int64}
low: ImageEdgeDetection.Percentile{Int64}
thinning_algorithm: ImageEdgeDetection.NonmaximaSuppression{ImageEdgeDetection.Percentile{Int64}}
а затем применить его в качестве параметров detect_edges
. Благодаря механизму множественной диспетчеризации в Julia detect_edges
определяет, какую реализацию алгоритма следует вызвать с информацией alg
.
edges = detect_edges(img, alg)
mosaicview(img, edges; nrow=1)
Теперь посмотрим, как различные параметры Кэнни изменяют результат, а также как алгоритм работает с реальными изображениями:
cameraman = testimage("cameraman")
canny(σ) = Canny(spatial_scale=σ, high=Percentile(80), low=Percentile(20))
simple_results = map(σ->detect_edges(img, canny(σ)), 1:5)
cameraman_results = map(σ->detect_edges(cameraman, canny(σ)), 1:5)
mosaicview(
mosaicview(img, cameraman),
map(mosaicview, simple_results, cameraman_results)...;
nrow=1
)
Как видите, чем больше значение spatial_scale
, тем более мелкие детали будет игнорировать оператор Кэнни, что дает «чистый» результат по краю. Нужен ли такой результат, зависит от интерпретации.
Справочные материалы
[1] J. Canny. A Computational Approach to Edge Detection. IEEE Transactions on Pattern Analysis and Machine Intelligence, vol. PAMI-8, no. 6, pp. 679—698, Nov. 1986, doi: 10.1109/TPAMI.1986.4767851.
Эта страница была создана с помощью DemoCards.jl и Literate.jl.