2013-10-26 2 views
0

Я хотел бы сохранить определенное количество изображений в оттенках серого (-> 2D-массивы) в виде слоев в 3D-массиве. Потому что это должно быть очень быстрым для реального времени-приложения, я хотел бы векторизации следующий код, где т число сдвигов:MATLAB: векторизация заполнения 3D-массива

for i=1:m 
    array(:,:,i)=imabsdiff(circshift(img1,[0 i-1]), img2); 
end 

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

I = speye(size(img1,2)); E = -1*I; 
ii = toeplitz(1:m,[1,size(img1,2):-1:2]); 
D = vertcat(repmat(I,1,m),E(:,ii)); 

data_c = shape(abs([double(img1),double(img2)]*D),size(data_r,1),size(data_r,2),m); 

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

+1

Каковы размеры изображения? v - вектор, поэтому в этом случае изображение должно быть строками x col x 20. Также я не думаю, что вы правильно используете circshift. В документации говорится: «shiftsize - это вектор целочисленных скаляров, где n-й элемент определяет величину сдвига для n-го измерения массива A.» Поэтому, если у вас нет 20 размеров для изображения ... – user2816823

+1

'[0 1:20]' в вашем случае не имеет смысла. Если 'image' является 2-D массивом, тогда' [0 1] 'и' [0 1: n] '(n - любое число больше 1) даст тот же результат, поскольку вы вращаете одноэлементное измерение. Если вы хотите на самом деле кругово сдвинуть изображение для создания новых изображений и поместить их в 3-D массивы (я не знаю, что эта операция означает физически), то правильное решение, используемое для циклов, является правильным. –

+0

В конце я хочу иметь массив с 20 слоями, где каждый слой содержит одно изображение, и каждое изображение должно быть сдвинуто на другую величину. Поэтому мне нужно 20 разных изображений в одном массиве. Я уже делал это с помощью цикла, но он должен был замедляться, мне нужно его для стереовидения для обнаружения препятствий в реальном времени. – Pixel

ответ

2

Вы можете сделать это:

M = 16; N = 20; img1 = randi(255,M,N);  % Create a random M x N image 
ii = toeplitz(1:N,circshift(fliplr(1:N)',1)); % Create an indexing variable 

% Create layers that are shifted copies of the image 
array = reshape(img1(:,ii),M,N,N); 

Пока ваши размеры изображения не изменяются, вы только когда-нибудь понадобится для создания переменной ii. После этого вы можете вызывать последнюю строку каждый раз при изменении вашего изображения. Я не знаю точно, что это даст вам преимущество в скорости над циклом for, но оно векторизовано, как вы просили. :)

UPDATE

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

clear all; 

% Set image sizes 
M = 360; N = 500; 

% Number of column shifts to test 
ncols = 200; 

% Create comparison matrix (see NOTE) 
I = speye(N); E = -1*I; 
ii = toeplitz([1:N],[1,N:-1:(N-ncols+2)]); 
D = vertcat(repmat(I,1,ncols),E(:,ii)); 

% Generate some test images 
img1 = randi(255,M,N); 
img2 = randi(255,M,N); 

% Compare images (vectorized) 
data_c = reshape(abs([img2,img1]*D),M,N,ncols); 

% Compare images (for loop) 
array = zeros(M,N,ncols); % <-- Pre-allocate this array! 
for i=1:ncols 
    array(:,:,i)=imabsdiff(circshift(img1,[0 i-1]),img2); 
end 

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

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

Редактировать: Я обновил код, чтобы более точно соответствовать тому, что вы, похоже, ищете. Затем я бросаю «оригинальную» для цикла реализацию, чтобы показать, что они дают тот же результат. Одна вещь, заслуживающая внимания в отношении векторизованной версии, состоит в том, что она может быть очень интенсивной в памяти. Если ncols = N, то матрица D имеет N^3 элементов. Несмотря на то, что D редки, вещи быстро разваливаются, когда вы умножаете D нерелевантными изображениями.

Также обратите внимание, что я предварительно назначил array перед циклом for. Это всегда хорошая практика в Matlab, где практически, и это почти всегда даст вам большой прирост производительности по динамическому размеру.

+3

Я ненавижу подсветку синтаксиса StackOverflow для Matlab. Кажется, иногда нет рифмы или причины. – nispio

+0

Благодарим вас за ответ. Но моя проблема в том, что я понятия не имею, как я могу использовать вектор в качестве индекса для 3D-массива без получения ошибки. – Pixel

+0

@pixel Возможно, вам следует обновить свой вопрос, так как мой ответ достигает именно того, что задает ваш вопрос. – nispio

0

Если вопрос правильно понял, я думаю, вам нужно for цикл

for v=1:1:20 
    array(:,:,v)=circshift(image,[0 v]); 
end 
Смежные вопросы