Есть два способа приблизиться к этому, в зависимости от ваших предпочтений.
Метод # 1 - Использование bwareaopen
дешевый способ сделать это было бы, чтобы инвертировать изображение таким образом, чтобы объект пикселей белый вместо черного, затем выполняет морфологическое закрытие на изображении и удаления этих областей, подпадают под определенную сумму. Закрытие объединяет объединенные регионы и использует преимущества того, что присоединение к «структуре» приведет к созданию региона с большой площадью, вы можете порождать область каждого региона и исключать те регионы, которые опускаются ниже определенной суммы.
Вы можете вернуть исходное изображение, просто выполнив логический AND
с инвертированным изображением и закрытым результатом, а затем переустановив этот промежуточный результат. Эффект этого заключается в том, что мы сохраняем только пиксели, принадлежащие исходному изображению, из-за операции закрытия, искусственно создающей пиксели объекта. В частности, объединение соседних областей структуры создало бы новые пиксели объекта, и поэтому выполнение AND
обеспечит удаление этих пикселей, не совпадающих с оригиналом. Поскольку это выполняется на обратной стороне исходного результата, повторное преобразование возвращает вас к исходному домену пикселей объекта, являющемуся черным, а не белым.
Что-то вроде этого:
%// Read in image from StackOverflow
im = imread('http://i.stack.imgur.com/A7iT7.png');
%// Invert image
im = ~im;
%// Define 50 x 50 structuring element and close the image
se = strel('square', 50);
out = imclose(im, se);
%// Remove regions whose areas fall below 10000 pixels
out = bwareaopen(out, 10000);
%// Remove out extraneous closing areas by ANDing with inverted image
%// then reinvert to bring back to original label scheme
out = ~(im & out);
%// Show the image
imshow(out);
Мы получаем этот образ:
Примечание
- Функции
imclose
будет выполнять морфологическое закрытие для вас с помощью структурного элемента определяемый strel
. Я использовал квадрат 50 x 50, чтобы убедиться, что у нас есть достаточно большое окно для объединения соседних пикселей объекта.
- Функция
bwareaopen
принимает двоичное изображение и удаляет области, пиксельные области которых находятся ниже определенной величины. После закрытия вы будете иметь две связанные области - верхнюю часть изображения со структурой и нижней частью с текстом. По экспериментам 10000 пикселей удалили область внизу. Метод
# 2 - Использование regionprops
, относящиеся к методу # 1, альтернативный способ сделать это и быть порог агностик пойти с вашей оригинальной идеей. Сделайте операцию закрытия, но затем оцените области каждой из подключенных областей и выберите ту, которая имеет наибольшую площадь. В этом случае я рекомендую использовать regionprops
, что является функцией, которая специально предназначена для анализа характеристик отдельных областей изображения. Результатом будет структура элементов N
, где N
- общее количество уникальных и связанных объектов, найденных на изображении, и каждая структура содержит поля свойств, которые вы хотите измерить на изображении. В вашем случае укажите атрибуты 'Area'
и 'PixelIdxList'
, которые содержат области и основные пиксельные местоположения пикселей каждого региона.
Вы найдете максимальную площадь в целом и используете соответствующие пиксельные местоположения и задаете карту вывода, которую вы бы логили AND
.
Что-то вроде этого:
%// Read in image from StackOverflow
im = imread('http://i.stack.imgur.com/A7iT7.png');
%// Invert image
im = ~im;
%// Define 50 x 50 structuring element and close the image
se = strel('square', 50);
out = imclose(im, se);
s = regionprops(out, 'Area', 'PixelIdxList'); %// Apply regionprops
%// Find the region with the max area
[~,id] = max([s.Area]);
%// Create an output mask with the largest area
%// Make logical
out = false(size(im));
%// Set pixels from largest area
out(s(id).PixelIdxList) = true;
%// Rest of the logic from before
%// Remove out extraneous closing areas by ANDing with inverted image
%// then reinvert to bring back to original label scheme
out = ~(im & out);
%// Show the image
imshow(out);
Вы должны получить те же результаты, что и первый метод.
Вопрос может звучать глупо, но в чем разница между частями, которые вы хотите, и теми частями, которые вам не нужны? Оба являются линиями и символами. Может быть, обнаружить вертикальный зазор (использовать сумму строк) и разделить там? Может быть, использовать imerode для подключения обеих черных областей, а затем сегментировать с bwlabel? – Daniel