Обнаружение линий в изображении
Я новичок в обработке изображений и пытался обнаружить вертикальные линии, используя этот код -
image=imread('benzene.jpg');
BW = im2bw(image);
w1=[-1 2 -1 ; -1 2 -1 ; -1 2 -1];
g=(imfilter(double(BW),w1));
g=abs(g);
T=max(g(:));
g=g>=T;
imshow(g);
Это был мой образ -

И это то, что я получил после выполнения операций-

Итак, мой вопрос в том, почему я получаю этот вывод?Существует 10 вертикальных линий, если вертикальные двойные связи считаются 2 отдельными вертикальными линиями.Кроме того, если я хочу получить горизонтальные, вертикальные, 45 и -45 все линии,как я могу использовать все 4 маски, чтобы получить одну единственную выход?
3 ответа:
У меня есть одно простое предложение-обнаружить градиент и определить ориентацию точки ребра. Имейте в виду, что ориентация находится в направлении, которое перпендикулярно краю. Поэтому, если вы хотите найти вертикальные линии, направление, перпендикулярное вертикальной линии, является горизонтальным, которое составляет либо 180 градусов, либо -180 градусов по отношению к декартовой плоскости. Таким образом, для каждой обнаруженной ориентации краевых точек, если ориентация равна либо -180 градусов, либо 180 градусов, затем установите выходное значение этого положения равным
true, иначеfalse. Для обнаружения градиентных ориентаций используйтеimgradientиз набора инструментов обработки изображений для этого. Я предполагаю, что это доступно, поскольку вы использовали обаimreadиim2bw, и они оба являются частью этого набора инструментов:im = imread('http://i.stack.imgur.com/bdNOt.png'); tol = 5; [~,ang] = imgradient(im); out = (ang >= 180 - tol | ang <= -180 + tol); imshow(out);Код использует переменную под названием
tolдля определения допуска в углах, которые вы хотите обнаружить, чтобы учесть шум или ребра, которые выглядят вертикальными, но когда угол вычисляется, может показаться, что его нет. В принципе, мы ищем любые точки, углы которых находятся в пределах 180 градусов или -180 градусов.Вот что мы получаем:
В качестве средства постобработки можно использовать
bwareaopenчтобы отфильтровать пиксельные области, площади которых падают ниже определенной величины. Воспользовавшись тем, что вертикальные линии имеют большую площадь, чем другие пиксели, вы можете сделать что-то вроде этого:out_filter = bwareaopen(out, 50);Мы получить:
Теперь, если вы хотите обнаружить горизонтальные линии, вы должны найти градиентные ориентации, которые составляют либо -90, либо 90 градусов. Это имеет смысл, потому что те линии, которые являются горизонтальными, направление, перпендикулярное горизонтальной линии, действительно вертикальное, и это либо -90, либо 90 градусов. Если вам нужны наклонные линии, если вам нужна левая наклонная линия, ищите углы 45 градусов или -135 градусов и правую наклонную линию, либо -45 градусов или 135 степени. Я позволю вам понять, почему эти углы действительно являются репрезентативными для таких линий. У вас нет горизонтальных линий на изображении, которое вы предоставили, поэтому я просто буду искать наклонные линии:Левые наклонные линии
Примечание: мне пришлось увеличить допуск из-за ошибок квантования.
im = imread('http://i.stack.imgur.com/bdNOt.png'); tol = 20; [~,ang] = imgradient(im); out = (ang >= 45 - tol & ang <= 45 + tol) | (ang >= -135 - tol & ang <= -135 + tol); out_filter = bwareaopen(out, 50); imshow(out_filter);
Правые наклонные линии:
Также пришлось увеличить допуск и здесь:
im = imread('http://i.stack.imgur.com/bdNOt.png'); tol = 20; [~,ang] = imgradient(im); out = (ang >= 135 - tol & ang <= 135 + tol) | (ang >= -45 - tol & ang <= -45 + tol); out_filter = bwareaopen(out, 50); imshow(out_filter);
Другой подход заключается в использовании того факта, что все линии, изображающие связи, имеют одинаковое соотношение сторон и площадь. после фильтрации изображения, оставляя его только с привязками, мы можем посмотреть на ориентацию или на список индексов, которые составляют их, чтобы определить, являются ли они вертикальными или что-то еще. Все это можно сделать с помощью
regionprops.image=rgb2gray(imread('benzene.png')); d=abs(255-image); % inverse the image d=im2bw(d); stat=regionprops(d,'Area', 'Orientation','PixelIdxList'); areas=[stat.Area]; hist(areas)
Проверка гистограммы показывает, где нужно вырезать линии, линии имеют меньшие площади, чем буквы, и они должны имеют примерно такую же площадь. Поэтому я вырезал для областей ниже 1000 пикселей:
idx=find(areas<1000); angs=round([stat(idx).Orientation]);Теперь вы можете использовать
angsиidx, чтобы получить, какой тип строки вы хотите. Например, давайте просто построим 30-градусные линии:d2=zeros(size(d)); d2(vertcat(stat(idx(angs==30)).PixelIdxList))=1; imagesc(d2)Обратите внимание, что в то время, когда я начал отвечать на этот вопрос, образ, который я взял, был бензолом.PNG-файл. Теперь я понимаю, что вы предоставили другой образ, чем первоначальный, так что линии, которые изображают связи, не разделены, а вы есть "кольца". Я посмотрю позже, смогу ли я обратиться и к этому, если вы этого хотите.
Редактировать:
Чтобы найти соответствующую линию для нового изображения, где у вас есть кольца, единственное отличие линий состоит в том, что они являются прямыми "линиями", а не изогнутыми. Поэтому я прибегаю к возлюбленному Hough transform , чтобы забрать их:image=imread('http://i.stack.imgur.com/bdNOt.png'); d=abs(1-image); % inverse the image BW=im2bw(d); BW = bwmorph(BW,'skel',1); [H, T, R] = hough(BW,'Theta',-90:10:80); P = houghpeaks(H, 100,'NHoodSize',[3 3],'threshold',1); lines = houghlines(BW, T, R, P, 'FillGap',5, 'MinLength', 35);Получим углы обнаруженных линий:
angs=round([lines.theta]);Вы увидите, что здесь
angsбудет генерировать значения 0, -60 или 60 градусов.Предположим, что вы хотите построить только те, которые равны 0 градусам:
p1=vertcat(lines(angs==0).point1); p2=vertcat(lines(angs==0).point2); imshow(BW, 'InitialMag',200, 'Border','tight'), hold on for k = 1:size(p1,1) line([p1(k,1) p2(k,1)],[p1(k,2) p2(k,2)], 'LineWidth',4,... 'Color',[1 0 0]); hold on end hold off
Я все еще в процессе выполнения этого. Но до сих пор у меня есть это. Я использовал не ваш фильтр, а скорее другой.
Я использовал первое изображение, которое вы предоставили. Фильтры описаны здесь: image_filters .
Вывод, который я получил, таков: как вы можете видеть, результат еще не завершен. Я могу предложить вам попробовать две вещи: использовать морфологический оператор эрозии для удаления мелких элементов. Вы также можете использовать connected компоненты, чтобы сделать это.image=imread('benzene.png'); BW = im2bw(image); w1=(1/3)*[1 0 -1;1 0 -1;1 0 -1]; g=(imfilter(double(BW),w1)); g(g<1)=0; imshow(g);А пока постарайтесь сделать то, что я предложил. Если я получу ответ, я обновлю его.








