Это не простая задача, которую вы не должны пытаться выполнить на базе R, если у вас нет сильного желания заново изобретать много колес!
К счастью, есть несколько пакетов, которые могут помочь. Поскольку ваша задача аналогична той, с которой сталкиваются при анализе микроскопических c изображений клеток, хорошее место для начала - на странице просмотра медицинской визуализации CRAN
Здесь вы найдете ссылки к некоторым полезным пакетам, включая EBImage
, который размещен на Bioconductor, а не на CRAN, поэтому вам придется установить его, используя:
install.packages("BiocManager")
BiocManager::install("EBImage")
Я адаптировал примеры, приведенные во введении EBImage стр. здесь.
Сначала мы загрузим пакет и убедимся, что можем прочитать ваше изображение:
library(EBImage)
dots <- readImage("~/blue_dots.png")
display(dots, method = "raster")
Смотрит хорошо. Теперь, поскольку точки имеют зеленовато-синий цвет, а остальная часть изображения - белый, канал с самой высокой контрастностью будет красным каналом. Давайте подтвердим это визуально:
par(mfrow = c(2, 2))
plot(dots)
text(140, 140, "All", cex = 3)
plot(getFrame(dots, 1))
text(140, 140, "Red", cex = 3, col = "red")
plot(getFrame(dots, 2))
text(140, 140, "Green", cex = 3, col = "green")
plot(getFrame(dots, 3))
text(140, 140, "Blue", cex = 3, col = "blue")
par(mfrow = c(1, 1))
Все каналы выглядят сильно коррелированными (на самом деле, если вы регрессируете зеленый канал на красный канал, вы получите скорректированный R в квадрате> 0,9).
Поэтому мы просто используем красный канал, чтобы найти точки. Мы извлекаем красный канал с помощью getFrame
и находим оптимальное пороговое значение с помощью otsu
:
dots <- getFrame(dots, 1)
threshold <- otsu(dots)
thresh_dots <- dots < threshold
Теперь мы убедились, что этот порог правильно выбрал наши точки:
display(thresh_dots)
Опять же, это выглядит довольно хорошо. Теперь мы можем попытаться посчитать точки, попросив пакет дать каждому отдельному региону свой номер. Мы можем убедиться, что это сработало визуально, выделив разные цвета для всех неподключенных областей:
nmask <- watershed( distmap(thresh_dots), 5)
display(colorLabels(nmask))
Довольно! И довольно хорошо согласно случайному осмотру. Вы можете увидеть сложность определения того, что такое точка, если вы посмотрите на большое «брызги» в нижней части изображения. Наш алгоритм назвал эти две точки, хотя можно утверждать, что это три или даже четыре точки (и мы могли бы изменить параметр водораздела, чтобы изменить это, если это было важно).
Теперь мы можем посчитать количество неподключенных областей, чтобы дать нам количество точек на странице:
length(table(bwlabel(thresh_dots)))
#> [1] 1576
И мы можем получить пропорцию нашего изображения, которая выше порогового значения, как это:
length(which(nmask > 0.5))/length(nmask)
#> [1] 0.134278
Таким образом, количество синих точек на изображении составляет около 1576, а процентное соотношение изображения, покрытого синими точками, составляет 13,43%.
Создано в 2020-02-28 с помощью представьте пакет (v0.3.0)