Pull to refresh

Детектирование округлостей на изображении средствами MATLAB

Reading time 3 min
Views 30K
image
В этом топике я приведу альтернативный подход к задаче, решенной товарищем VasG тут. Как заметили в комментариях, задачу обнаружения округлостей на изображении можно было решить при помощи MATLAB Image Processing Toolbox, что я и сделал. MATLAB радует меня очень сильной документацией с большим количеством наглядных примеров; а также удобством m-языка, за счет которого сильно сокращается время реализации вычислительных решений. Конечно, есть и минусы — в частности алгоритмы работают медленно, — но для данной задачи это не существенно. Отмечу только, что из m-языка довольно просто можно получить C-код, который будет работать гораздо быстрее.

Я старался писать с нуля, исходя из формулировки задачи и не пользуясь алгоритмическими наработками VasG. Естественно, в силу простоты задачи решения очень похожи. В хелпе MATLAB'а по Image Processing Toolbox обнаружился набор демок, посвященных детектированию объектов и в частности поиску круглых форм, что мне очень помогло. Далее приводится код полученного алгоритма на m-языке:

img = imread('kkk.jpg');
grayimg = rgb2gray(img);
grayimg = imadjust(grayimg);
bw = edge(grayimg,'canny', 0.15, 2);
bw = imfill(bw,'holes');
se = strel('disk',1);
bw = imopen(bw,se);

[B,L] = bwboundaries(bw);
stats = regionprops(L,'Centroid','EquivDiameter');
figure, imshow(img)
hold on
for k = 1:length(B)
 boundary = B{k};
 radius = stats(k).EquivDiameter/2;
 xc = stats(k).Centroid(1);
 yc = stats(k).Centroid(2);
 theta = 0:0.01:2*pi;
 Xfit = radius*cos(theta) + xc;
 Yfit = radius*sin(theta) + yc;
 plot(Xfit, Yfit, 'g');
 text(boundary(1,2)-15,boundary(1,1)+15, num2str(radius,3),'Color','y',...
  'FontSize',8);
end


Заметьте, в нем всего 30 строчек. Из них половина реализует красивый вывод результата. Давайте разберем код.
img = imread('kkk.jpg'); — открываем наше изображение. Я использовал изображение из статьи VasG.
image

grayimg = rgb2gray(img); — переводим изображение в оттенки серого.
grayimg = imadjust(grayimg); — контрастируем.
image

bw = edge(grayimg,'canny', 0.15, 2); — выделяем границы методом Канни. Функция edge предлагает возможность использования алгоритмов Собеля, Робертса, Прюитта и некоторых других, но я, как и VasG, остановил свой выбор на Канни, потому что он, как мне кажется, работает лучше всего. Параметры подбирались эмпирически, чтобы выделялись границы всех объектов на изображении.
image

bw = imfill(bw,'holes'); — заливаем замкнутые области на изображении.
image

Далее необходимо избавиться от тонких линий.
se = strel('disk',1); — формируем структурный элемент, крест 3 на 3.
bw = imopen(bw,se); — морфологическое открытие, тонкие линии исчезают.
image

[B,L] = bwboundaries(bw); — данная функция выдает два результата. B — ячеечный массив размера P х 1, где P — кол-во объектов на изображении. Элементы массива B — матрицы размером Q х 2, где Q — количество пикселей, принадлежащих границе соответствующего объекта. Строки матрицы Q — координаты этих граничных пикселей. L — матрица, размер которой равен размеру изображения, содержащая неотрицательные числа, которые соответствуют замкнутым областям. Регион с номером k на матрице L обозначается элементами со значением k. Фону соответствует 0.
stats = regionprops(L,'Centroid','EquivDiameter'); — эта функция создает массив структур stats, поля элеметнов которого Centroid и EquivDiameter содержат соответственно координаты центра области и (в нашем случае) диаметр области.
Собственно задача решена. Дальше реализуется вывод результатов.
image

Результаты аналогичны тем, что были получены VasG с точностью до коэффициентов некоторых функций. Времени на реализацию было потрачено примерно столько же, сколько на оформление данной статьи, примерно около часа. VasG, насколько понятно по статье, потратил на порядок больше времени. У меня довольно большой опыт работы с MATLAB, но я считаю, даже если человек не знаком с m-языком, за рабочий день можно разобраться в системе и написать подобную реализацию. Таким образом налицо высокая скорость реализации решений прикладных задач в системе MATLAB. Советую VasG, а также другим научным сотрудникам и инженерам оценить для себя систему MATLAB в действии!

upd. Заменил пару imerode+imdilate на imopen. Спасибо ScayTrase.
Tags:
Hubs:
+45
Comments 46
Comments Comments 46

Articles