Подтвердить что ты не робот

Измерение средней толщины следов на изображении

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

Первое изображение - размер: 711 x 643 px

711 x 643 example image

Второе изображение - размер: 930 x 951 px

alt text

Мне нужно измерить среднюю толщину (в пикселях) трасс в изображениях. Фактически, средняя толщина следов в изображении является несколько субъективной мерой. Итак, мне нужна мера, которая имеет некоторую корреляцию с радиусом трассы, как показано на рисунке ниже:

alt text

Примечания

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

  • В трассировке могут быть пересечения.

  • Толщина следа может быть не постоянной, но средняя мера в порядке (даже максимальная толщина трассы приемлема).

  • Трассировка всегда будет намного длиннее, чем широкая.

4b9b3361

Ответ 1

Я бы предложил этот алгоритм:

  • Примените преобразование расстояния к изображению, чтобы все фоновые пиксели были установлены на 0, все пиксели переднего плана заданы на расстояние от фона.
  • Найти локальные максимумы в преобразованном на расстоянии изображении. Это точки в середине строк. Поместите их значения пикселей (то есть расстояния от фона) в список
  • Рассчитать средний или средний список.

Ответ 2

Меня поразил ответ @nikie и дал ему попробовать...

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

Программа в Mathematica:

m = Import["http://imgur.com/3Zs7m.png"]   (* Get image from web*)
s = Abs[ImageData[m] - 1];                 (* Invert colors to detect background *)
k = DistanceTransform[Image[s]]            (* White Pxs converted to distance to black*)
k // ImageAdjust                           (* Show the image *)
Max[ImageData[k]]                          (* Get the max stroke width *)

Сгенерированный результат

alt text

Численное значение (28.46 px X 2) очень хорошо подходит для моего измерения 56 px (хотя ваше значение равно 100px: *)

Изменить - реализовал полный алгоритм

Ну... вроде... вместо поиска локальных максимумов, найдя неподвижную точку преобразования расстояния. Почти, но не совсем совершенно не похоже на одно и то же:)

m = Import["http://imgur.com/3Zs7m.png"];   (*Get image from web*)
s = Abs[ImageData[m] - 1];         (*Invert colors to detect background*)
k = DistanceTransform[Image[s]];   (*White Pxs converted to distance to black*)
Print["Distance to Background*"]
k // ImageAdjust                   (*Show the image*)
Print["Local Maxima"]
weights = 
    Binarize[FixedPoint[[email protected][Image[#], .4] &,s]]  
Print["Stroke Width =", 
     2 Mean[Select[Flatten[ImageData[k]] Flatten[ImageData[weights]], # != 0 &]]]

alt text

Как вы можете видеть, результат очень похож на предыдущий, полученный с помощью упрощенного алгоритма.

Ответ 3

Из Здесь. Простой способ!

3.1 Оценка ширины пера

Толщина пера может быть легко оценена из области A и длины периметра L переднего плана

T = A/(L/2)

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

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

Поэтому мы должны вычислить площадь A и длину периметра L, используя функции, учитывающие "округлость". В MATLAB

A = bwarea(.)  
L = bwarea(bwperim(.; 8))

Поскольку у меня нет MATLAB, я сделал небольшую программу в Mathematica:

m = Binarize[Import["http://imgur.com/3Zs7m.png"]] (* Get Image *)
k = Binarize[MorphologicalPerimeter[m]]            (* Get Perimeter *)
p = N[2 Count[ImageData[m], Except[1], 2]/ 
    Count[ImageData[k], Except[0], 2]]             (* Calculate *)

Вывод 36 Px...

Изображение периметра следует за

alt text

НТН!

Ответ 4

Прошло 3 года с тех пор, как был задан вопрос:) следуя процедуре @nikie, здесь представлена ​​реализация ширины штриха в матлабе.

 clc;
 clear;
 close all;


I = imread('3Zs7m.png');
X = im2bw(I,0.8);

subplottight(2,2,1);
imshow(X);

Dist=bwdist(X);

subplottight(2,2,2);
imshow(Dist,[]);

RegionMax=imregionalmax(Dist);

[x, y] = find(RegionMax ~= 0);
subplottight(2,2,3);
imshow(RegionMax);

List(1:size(x))=0;
for i = 1:size(x) 
List(i)=Dist(x(i),y(i));
end

fprintf('Stroke Width = %u \n',mean(List));

Ответ 5

Предполагая, что трасса имеет постоянную толщину, намного длиннее ее ширины, не слишком сильно изогнута и не имеет пересечений/пересечений, я предлагаю алгоритм обнаружения края, который также определяет направление ребра, затем подъем/детектора с некоторой тригонометрией и алгоритмом минимизации. Это дает минимальную толщину относительно относительно прямой части кривой.

Я предполагаю, что ошибка будет до 25%.

Сначала используйте краевой детектор, который дает нам информацию, где находится край, и какое направление (в 45 ° или PI/4 шагах) оно имеет. Это делается путем фильтрации с помощью 4 различных матриц 3x3 (Пример).
Обычно я бы сказал, что это достаточно для сканирования изображения по горизонтали, хотя вы также можете сканировать по вертикали или по диагонали.
Предполагая пошаговое (горизонтальное) сканирование, как только мы найдем ребро, мы проверяем, если он поднимается (идет от фона к цвету трассировки) или падает (на задний план). Если направление кромки находится под прямым углом к ​​направлению сканирования, пропустите его.
Если вы нашли один подъем и одно падение с правильными направлениями и без каких-либо помех между ними, измерьте расстояние от подъема до падения. Если направление диагонально, умножьте его на квадрат 2. Сохраните эту меру вместе с данными координат.

Затем алгоритм должен искать по краю (не удается найти веб-ресурс прямо сейчас) для соседних (по их координатам) измерений. Если есть локальный минимум с отступом от 4 до 5 единиц размера с каждой стороны (значение для игры с - больше: меньше информации, меньше: больше шума), эта мера квалифицируется как кандидат. Это делается для того, чтобы не учитывать, что концы тропы или секции согнуты слишком сильно.

Минимум этого будет измерение. Проверка достоверности: если трассировка не слишком запутана, в этой области должно быть много значений.

Прошу прокомментировать, если есть больше вопросов.: -)

Ответ 6

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

Основная идея: попробуйте установить круг в черные области изображения. Если можно, попробуйте с большим кругом.

Алгоритм:

  • установить изображение фона = 0 и trace = 1
  • инициализировать результат массива []
  • set minimumExpectedWidth
  • set w = minimumExpectedWidth
  • цикл
    • set counter = 0
    • создать матрицу нулей размера w x w
    • внутри круга с диаметром w в этой матрице, поместите их
    • вычислить площадь круга (= PI * w)
    • перемещать все пиксели изображения
      • оптимизация: если текущий пиксель имеет цвет фона → цикл продолжения
      • умножить матрицу на изображение в каждом пикселе (например, фильтровать изображение с помощью этой матрицы) (вы можете сделать это, используя текущую позицию x и y и двойную для цикла от 0 до w)
      • возьмем сумму результата каждого умножения
      • если сумма равна расчетной площади круга, счетчик приращений на один
    • сохранить результат [w - minimumExpectedWidth]
    • приращение w на один
    • Оптимизация: включить алгоритм из ниже здесь
  • в то время как счетчик больше нуля

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

У меня нет MATLAB здесь для тестирования и не знаю точно о функции для обнаружения этого внезапного падения, но мы знаем, что уменьшение является непрерывным, поэтому я бы взял максимум второй производной от (нулевой) массив результатов, подобный этому

Алгоритм:

  • set maximum = 0
  • set widthFound = 0
  • установить minimumExpectedWidth, как указано выше
  • set prevvalue = result [0]
  • set index = 1
  • set prevFirstDerivative = результат [1] - prevvalue
  • пока индекс больше длины результата
    • firstDerivative = result [index] - prevvalue
    • set secondDerivative = firstDerivative - prevFirstDerivative
    • если secondDerivative > maximum или secondDerivative < максимум * -1
      • maximum = secondDerivative
      • widthFound = index + minimumExpectedWidth
    • prevFirstDerivative = firstDerivative
    • prevvalue = result [index]
    • индекс инкремента на один
  • return widthFound

Теперь widthFound - это ширина трассы, для которой (по отношению к ширине + 1) найдено гораздо больше совпадений.

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

Ответ 7

У меня есть интересное решение:

  • Обнаружение кромок для извлечения крайних пикселей.
  • Сделайте физическое моделирование - рассмотрите краевые пиксели как положительно заряженные частицы.
  • Теперь поместите некоторое количество свободных положительно заряженных частиц в область хода.
  • Рассчитать уравнения электрической силы для определения движения этих свободных частиц.
  • Имитировать движение частиц в течение некоторого времени, пока частицы не достигнут равновесия положения. (Поскольку они будут отталкиваться от обоих краев стоков через некоторое время, они останутся в средней линии стока).
  • Теперь толщина толщины /2 будет равна average distance from edge particle to nearest free particle.