Matlab: 256 бинарных матриц для одного 256-уровневого изображения в градациях серого - PullRequest
0 голосов
/ 03 июня 2011

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

Вот код:

so = imread('bio_sd.bmp');
co = rgb2gray(so);

for l = 1:256
    bw = (co == l); %         Binary image from level l of original image
    be = ordfilt2(bw, 1, ones(3, 3)); %  Convolution filter
    bl(int16(l)) = {bwlabel(be, 8)}; %   Component labelling
end

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

т. двоичное изображение bl {12} содержит 1 с, где исходное изображение имеет пиксели с уровнем 12.

Я хотел бы создать новое изображение, объединив 256 двоичных матриц обратно в изображение в градациях серого.

Но я очень плохо знаком с Matlab, и мне интересно, может ли кто-нибудь помочь мне его кодировать:)

пс: я использую Matlab R2010a для студенческого издания.

Ответы [ 3 ]

3 голосов
/ 03 июня 2011

весь этот ответ относится только к оригинальной форме вопроса .

Предположим, что вы можете собрать все свои двоичные матрицы в большую матрицу размером n × m на 256 binaryimage(x,y,greyvalue). Тогда вы можете рассчитать ваше окончательное изображение как

newimage=sum(bsxfun(@times,binaryimage,reshape(0:255,1,1,[])),3)

Волшебство здесь выполняется bsxfun, который умножает двоичное изображение 3D (n x m x 256) на вектор 1 x 1 x 256, содержащий значения серого 0 ... 255. Это создает трехмерное изображение, где для фиксированных x и y вектор (y, x, :) содержит много нулей и (для одного значения серого G, где двоичное изображение содержит 1) он содержит значение G. Так что теперь вам нужно только сложить по этому третьему измерению, чтобы получить n x m изображение.

Обновление

Чтобы проверить, что это работает правильно, давайте сначала пойдем другим путем:

fullimage=floor(rand(100,200)*256);
figure;imshow(fullimage,[0 255]);

- случайное изображение в оттенках серого. Вы можете вычислить 256 двоичных матриц следующим образом:

binaryimage=false([size(fullimage) 256]);
for i=1:size(fullimage,1)
   for j=1:size(fullimage,2)
      binaryimage(i,j,fullimage(i,j)+1)=true;
   end
end

Теперь мы можем применить решение, которое я дал выше

newimage=sum(bsxfun(@times,binaryimage,reshape(0:255,1,1,[])),3);

и убедитесь, что я возвращаю исходное изображение:

all(newimage(:)==fullimage(:))

, что дает 1 (true): -).

Обновление 2

Теперь вы упоминаете, что ваши двоичные изображения находятся в массиве ячеек, я полагаю binimg{1:256}, где каждая ячейка содержит двоичный массив n x m. Если вы можете, возможно, имеет смысл изменить код, который генерирует эти данные, для создания трехмерного двоичного массива, который я использую выше - ячейки в основном полезны, если разные ячейки содержат данные разных типов, форм или размеров.

Если есть веские причины придерживаться массива ячеек, вы можете преобразовать его в 3D-массив, используя

binaryimage = reshape(cell2mat(reshape(binimg,1,256)),n,m,256);

с n и m, как указано выше. Внутренняя форма не нужна, если у вас уже есть size(binimg)==[1 256]. Итак, чтобы подвести итог, вам нужно использовать массив ячеек binimg для вычисления двоичного изображения трехмерной матрицы, которое затем вы можете использовать для вычисления newimage, которое вас интересует, используя код в самом начале моего ответа.

Надеюсь, это поможет ...

2 голосов
/ 03 июня 2011

Что делает ваш код ...

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

  • bw = (co == l);

    Это просто создает двоичную матрицу bw с матрицами, где ваше изображение в градациях серого co имеет интенсивность пикселей, равную значению цикла l. Я заметил, что у вас цикл от 1 до 256, и это кажется мне странным. Как правило, изображения, загруженные в MATLAB , будут представлять собой 8-разрядное целое число без знака , означающее, что значения оттенков серого будут охватывать диапазон от 0 до 255. В таком случае последняя двоичная матрица bw, который вы вычисляете, когда l = 256 всегда будет содержать все нули. Кроме того, вы не выполняете какую-либо обработку для пикселей с уровнем оттенков серого, равным 0. Из вашей последующей обработки, я предполагаю, что вы намеренно хотите игнорировать значения в оттенках серого, равные 0, и в этом случае вам, вероятно, потребуется только цикл от 1 до 255. .

  • be = ordfilt2(bw, 1, ones(3, 3));

    То, что вы в основном делаете здесь с ORDFILT2 , выполняет операцию двоичной эрозии . Любые значения 1 в bw, которые имеют 0 в качестве одного из своих 8 соседей, будут установлены в 0, что приведет к разрушению островков единиц (то есть уменьшится в размере). Маленькие островки исчезнут, оставив только более крупные скопления смежных пикселей с тем же уровнем оттенков серого.

  • bl(int16(l)) = {bwlabel(be, 8)};

    Вот здесь у вас могут быть некоторые недоразумения. Во-первых, матрицы в bl не являются логическими матрицами . В вашем примере функция BWLABEL найдет кластеры из 8 подключенных. Первый найденный кластер будет иметь свои элементы, помеченные как 1 на выходном изображении, второй найденный кластер будет иметь свои элементы, помеченные как 2, и т. Д. Поэтому матрицы будут содержать положительные целочисленные значения, где 0 представляет фон.

    Во-вторых, собираетесь ли вы использовать эти помеченные кластеры для чего-либо? Возможно, вам потребуется дополнительная обработка, для которой вам нужно идентифицировать отдельные кластеры с заданным уровнем интенсивности оттенков серого, но в отношении создания изображения в оттенках серого из элементов в bl специальная метка значение не требуется , Вам нужно только идентифицировать ноль против ненулевых значений, поэтому, если вы не используете bl для чего-либо еще, я бы предложил вам просто сохранить отдельные значения be в массиве ячеек и использовать их для воссоздания градаций серого. изображение.

Теперь на ответ ...

Очень простое решение состоит в том, чтобы объединить массив ячеек изображений в трехмерную матрицу с помощью функции CAT , а затем использовать функцию MAX , чтобы найти индексы, где Нулевые значения встречаются вдоль третьего измерения (что соответствует значению серой шкалы исходного изображения). Для данного пикселя, если в третьем измерении не найдено ненулевого значения (т. Е. Это все нули), мы можем предположить, что значение пикселя должно быть 0. Однако индекс для этого пикселя, возвращаемый MAX * По умолчанию для 1063 * установлено значение 1, поэтому необходимо использовать максимальное значение в качестве логического индекса, чтобы установить для пикселя значение 0:

[maxValue,grayImage] = max(cat(3,bl{:}),[],3);
grayImage(~maxValue) = 0;

Обратите внимание, что в целях отображения или сохранения изображения вы можете изменить тип полученного изображения grayImage на 8-разрядный целочисленный тип без знака, например так:

grayImage = uint8(grayImage);
1 голос
/ 03 июня 2011

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

...