Распределение функции по одному измерению массива в MATLAB? - PullRequest
7 голосов
/ 01 июня 2010

Мне часто хочется свернуть n-мерную матрицу в одном измерении с помощью пользовательской функции, и я не могу понять, есть ли в ней краткое заклинание, которое я могу использовать для этого.

Например, при разборе изображения я часто хочу сделать что-то подобное. (Примечание! Только для иллюстрации. Я знаю о rgb2gray для этого конкретного случая.)

img = imread('whatever.jpg');
s = size(img);
for i=1:s(1)
  for j=1:s(2)
    bw_img(i,j) = mean(img(i,j,:));
  end
end

Я бы хотел выразить это как-то так:

bw = on(color, 3, @mean);

или

bw(:,:,1) = mean(color);

Есть ли короткий способ сделать это?


РЕДАКТИРОВАТЬ: Очевидно, mean уже делает это; Я хочу быть в состоянии сделать это для любой функции, которую я написал. Например.,
...
  filtered_img(i,j) = reddish_tint(img(i,j,:));
...

, где

function out = reddish_tint(in)
  out = in(1) * 0.5 + in(2) * 0.25 + in(3) * 0.25;
end

Ответы [ 5 ]

7 голосов
/ 01 июня 2010

Многие основные функции MATLAB, такие как MEAN , MAX , MIN , SUM и т. Д., Предназначены для работы через удельный размер:

bw = mean(img,3);  %# Mean across dimension 3

Вы также можете воспользоваться тем, что арифметические операторы MATLAB предназначены для поэлементной работы с матрицами. Например, операция в вашей функции reddish_tint может быть применена ко всем пикселям вашего изображения с помощью одной строки:

filtered_img = 0.5.*img(:,:,1)+0.25.*img(:,:,2)+0.25.*img(:,:,3);

Чтобы обработать более общий случай, когда вы хотите применить функцию к произвольному измерению N-мерной матрицы, вы, вероятно, захотите написать свою функцию так, чтобы она принимала дополнительный входной аргумент, для которого измерение должно работать ( как и вышеупомянутые функции MATLAB), а затем использует некоторую простую логику (то есть операторы if-else) и поэлементные матричные операции, чтобы применить свои вычисления к надлежащему измерению матрицы.

Хотя я бы не советовал использовать его, - это быстрое и грязное решение, но оно довольно уродливо и вычислительно дороже. Вы можете использовать функцию NUM2CELL для сбора значений по измерению вашего массива в ячейки массива ячеек, а затем применить свою функцию к каждой ячейке, используя функцию CELLFUN :

cellArray = num2cell(img,3);  %# Collect values in dimension 3 into cells
filtered_img = cellfun(@reddish_tint,cellArray);  %# Apply function to each cell
6 голосов
/ 27 сентября 2012

Я написал вспомогательную функцию vecfun, которая может быть полезна для этого, если это то, чего вы пытаетесь достичь?

ссылка

4 голосов
/ 01 июня 2010

Вы можете использовать BSXFUN хотя бы для некоторых своих задач. Он выполняет поэлементную операцию среди двух массивов, расширяя размер 1 - размеры, чтобы соответствовать размеру другого массива. Функция «красноватый оттенок» станет

reddish_image = bsxfun(@times,img,cat(3,0.5,0.25,0.25));
filtered_img = sum(reddish_image,3);

Для выполнения вышеприведенного утверждения требуется, чтобы третье измерение img имело размер 1 или 3. Число и размер других измерений можно выбирать свободно.

3 голосов
/ 01 июня 2010

Если вы последовательно пытаетесь применить функцию к вектору, состоящему из 3-х измерений в блоке изображений, я рекомендую использовать пару перестановок, например:

Img = rand(480,640,3);

sz = size(Img);
output = reshape(myFavoriteFunction(reshape(Img,[prod(sz(1:2)),sz(3)])'),sz);

Таким образом, вы можете поменять местами любую функцию, которая работает с матрицами вдоль их первого измерения.

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

function o = nLayerImage2MatrixOfPixels(i)
%function o = nLayerImage2MatrixOfPixels(i)
s = size(i);
if(length(s) == 2)
  s3 = 1;
else
  s3 = s(3);
end
o = reshape(i,[s(1)*s(2),s(3)])';
2 голосов
/ 01 июня 2010

Что ж, если вас интересует только умножение векторов вместе, вы можете просто использовать скалярное произведение, например:

bw(:,:,1)*[0.3;0.2;0.5]

, следя за тем, чтобы формы ваших векторов соответствовали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...