Как отбросить непрямоугольные замкнутые области на изображении в MATLAB?
Я хочу извлечь прямоугольные формы (некоторые могут иметь треугольные расширения на одной стороне) с таким изображением;
То, что я сделал в MATLAB, это;
BW=imread('Capture2.JPG');
BW=~im2bw(BW);
SE = strel('rectangle',[1 6]);
BW = ~imclose(BW,SE);
BW2 = imfill(~BW,'holes');
figure
imshow(~BW)
figure
imshow(BW2);
s = regionprops(BW,'BoundingBox','Area','PixelIdxList');
s = s(2:end);
[lab, numberOfClosedRegions] = bwlabel(BW);
figure
imshow(BW)
for i=1:numel(s)
rec = s(i);
ratio = rec.BoundingBox(4)/rec.BoundingBox(3);%height/width
% ratio > 0.3 && ratio < 51.6 && rec.Area > 1100 && rec.Area < 22500
% if ratio > 0.16
rectangle('Position',s(i).BoundingBox,'EdgeColor','r','LineWidth',2);
text(rec.BoundingBox(1),rec.BoundingBox(2),num2str(i),'fontsize',16);
% end
end
То, что я придумал, это;
Как видно, есть области, которые можно найти как часть текста, фигуры внутри блока (индекс = 3) и неблокированные области (индекс = 11). Мне нужно отбросить внутренние регионы и неблокированные области.
Другая проблема заключается в том, что регионы определяются белыми областями, мне нужно получить черные границы блоков, чтобы я мог захватить сам блок, а не внутреннюю белую область. Как я могу решить эти проблемы?
Я оба пытался перевернуть изображение и использовать методы, но безуспешно.
РЕДАКТИРОВАТЬ: улучшение кода и дополнительное изображение
Одно из изображений может быть таким, включая непрямоугольный, но интересующий вас объект (крайний левый).
Еще одна проблема, если изображение не так хорошо, как должно быть, линия считается открытой, особенно диагональной, и шириной 1px, из-за чего регион пропускает их.
Улучшение кода;
close all;
image=imread('Capture1.JPG');
BW = image;
BW = ~im2bw(BW);
SE = strel('rectangle',[3 6]);
BW = ~imclose(BW,SE); % closes some caps to be closed region
r = regionprops(BW,'PixelIdxList');
BW(r(1).PixelIdxList) = 0; %removes outermost white space allowing to connection lines disapear
se = strel('rectangle',[6 1]);
BW = imclose(BW,se);% closes some caps to be closed region
BW = imfill(BW,'holes');
s = regionprops(BW,{'Area', 'ConvexArea', 'BoundingBox','ConvexHull','PixelIdxList'});
%mostly the area and convex area are similar but if convex area is much greater than the area itself it is a complex shape like concave intermediate sections then remove
noidx = [];
for i=1:numel(s)
rec = s(i);
if rec.Area*1.5 < rec.ConvexArea
BW(rec.PixelIdxList) = 0;
noidx(end+1)=i;
end
end
s(noidx)=[];
% нет условий для оставшихся регионов фигура imshow(BW)
for i=1:numel(s)
rec = s(i);
ratio = rec.BoundingBox(4)/rec.BoundingBox(3);%height/width
% ratio > 0.3 && ratio < 51.6 && rec.Area > 1100 && rec.Area < 22500
% if ratio > 0.16
rectangle('Position',s(i).BoundingBox,'EdgeColor','r','LineWidth',2);
text(rec.BoundingBox(1),rec.BoundingBox(2),num2str(i),'fontsize',16,'color','red');
% end
end
Результат есть;
Преимущество заключается в том, что все остальные области являются областями, если не представляют интереса никакие исключения и нет условий для ограничения области и т. Д., Поскольку размер изображения может отличаться, таким образом, площадь.
Но даже это не работает на втором изображении. Из-за текста под блоками (что всегда имеет место -> первое изображение было очищено для загрузки) и диагональные концы крайних левых блоков считаются открытыми линиями.
2 ответа
Добавив два условия, я получил несколько хороших результатов:
- Прямоугольник должен быть полностью закрыт
- Площадь должна быть больше, чем х пикселей (в данном случае 1100)
Чтобы проверить, замкнут ли прямоугольник или нет, я создал индекс для каждого многоугольника. Эти индексы имеют ту же форму, что и прямоугольники. Так что если sum(~BW(index)) == sum(index(:))
это означает, что многоугольник замкнут.
Обновленный код:
warning off
BW=imread('test.jpg');
BW=~im2bw(BW);
SE = strel('rectangle',[1 6]);
BW = ~imclose(BW,SE);
BW2 = imfill(~BW,'holes');
s = regionprops(BW,'BoundingBox','Area','PixelIdxList');
s = s(2:end);
[lab, numberOfClosedRegions] = bwlabel(BW);
figure
imshow(imread('test.jpg'))
inc = 1;
for i=1:numel(s)
rec = s(i);
s(i).BoundingBox = floor(s(i).BoundingBox + [-1,-1,2,2]);
%Creation of the index
clear ind
ind = zeros(size(BW));
y = s(i).BoundingBox(1);
x = s(i).BoundingBox(2);
h = s(i).BoundingBox(3);
w = s(i).BoundingBox(4);
ind(x:x+w,[y,y+h]) = 1;
ind([x,x+w],y:y+h) = 1;
ind = logical(ind);
if sum(~BW(ind)) == sum(ind(:)) && rec.Area > 1100
rectangle('Position',s(i).BoundingBox,'EdgeColor','r','LineWidth',1);
text(rec.BoundingBox(1),rec.BoundingBox(2),num2str(inc),'fontsize',16);
inc = inc + 1;
end
end
РЕЗУЛЬТАТ
Как вы можете отказаться от непрямоугольных областей? Ну, я уверен, что вы можете придумать некоторые математические свойства, которые довольно уникальны для прямоугольников.
Площадь является произведением ширины и высоты.
Периметр - двойная сумма ширины и высоты.
Это очевидно имеет 4 прямоугольных угла.
Я думаю, что первого свойства будет достаточно, и вы можете придумать больше правил, если вам нужно.
Вы можете избавиться от нежелательных прямоугольников и других мелких вещей с ограничением минимального размера или проверить, заключены ли они в прямоугольник.
Это должно быть довольно просто.