#arrays #image #matlab #image-processing
#массивы #изображение #matlab #обработка изображений
Вопрос:
Я пытаюсь добиться очень простой вещи в MATLAB. У меня есть последовательность изображений в массиве 4D в следующем формате: (номер кадра, высота, ширина, RGB).
Мой стек довольно маленький, его размер: 99 480 640 3
Чего я пытаюсь добиться, так это определить, произошло ли изменение в движении между n последовательными изображениями (изображениями, сделанными с помощью фиксированной камеры о движущихся объектах).
Для этого моя самая очевидная идея — вычесть разные изображения в стеке и сохранить их в другом стеке.
Вот очень простой код, который я пытался запустить:
vec = 1:size(stack,1)-5
dif = uint8(squeeze(abs(stack(vec,:,:,:) - stack(vec 5,:,:,:))));
Однако это выдает ошибку нехватки памяти.
Error using -
Out of memory. Type HELP MEMORY for your options.
Если я не использую сжатие (нужно ли мне использовать сжатие здесь?) Я даже получаю системную ошибку Windows о нехватке памяти.
В качестве запасного варианта я написал цикл for, который, похоже, работает, но только если я использую приведение uint8. Если нет, у него заканчивается память и выдает системную ошибку Windows.
for i = 1:size(stack,1)-5
dif(i,:,:,:) = uint8(abs(stack(i,:,:,:) - stack(i 5,:,:,:)));
end
Кроме того, для обработки этого небольшого набора данных (всего 99 кадров) требуется 20 секунд.
Можете ли вы сказать мне, как мне написать функцию, которая не пытается сохранить все в памяти?Для этой команды должно потребоваться очень мало памяти для 2 сравниваемых изображений, однако MATLAB по какой-то причине пытается выполнить все операции в памяти. Весь набор данных должен занимать 91 МБ в памяти, поэтому это явно не должно быть проблемой.
Кроме того, можете ли вы объяснить, нужно ли мне использовать сжатие или нет?Когда я пытаюсь получить одно изображение, то
dif = stack(1,:,:,:) - stack(5,:,:,:);
создает массив 4D, в то время как
dif = squeeze(stack(1,:,:,:) - stack(5,:,:,:));
создает формат изображения. Но в цикле for выше он дает одинаковые результаты как с squeeze, так и без него. Почему это происходит?
Комментарии:
1. если вы используете
double
type, ваш стек изображений не такой маленький:(99*480*640*3)*8 = 729907200 bytes
(то есть вам требуется около 700 МБ непрерывной памяти для каждой копии матрицы 4D)2. Хорошо, я изменил свой код, чтобы использовать uint8, так что теперь он использует меньше памяти. Но все же, почему векторизованная функция использует так много памяти?
3. Я попытался ответить на некоторые из ваших вопросов, пожалуйста, смотрите Мой пост ниже
4. Хорошо, спасибо, все понятно.
Ответ №1:
Что касается сжатия, stack
это 4D-матрица, так dif = stack(1,:,:,:) - stack(5,:,:,:);
же как и 4D-матрица, но первое измерение является одноэлементным. Поэтому, когда вы присваиваете результат существующей матрице (с индексацией), элементы заполняются по порядку, и любые одноэлементные измерения не имеют никакого эффекта. Однако, помещая результат в новую переменную, форма матрицы 4D сохраняется…
Вы должны знать о своих типах данных, если все значения являются целыми числами в диапазоне [0,255], затем для начала приведите весь стек изображений к UINT8. Как я упоминал в комментариях, для 4D-двойной матрицы таких размеров потребуется около 700 МБ непрерывной памяти.
Теперь в цикле for вы должны предварительно dif
выделить матрицу:
dif = zeros([99-5 480 640 3],'uint8');
for i = 1:size(stack,1)-5
dif(i,:,:,:) = abs( stack(i,:,:,:) - stack(i 5,:,:,:) );
end
Наконец, несмотря на то, что векторизованные вызовы могут быть быстрее, им требуется больше памяти, поскольку они пытаются выделить все необходимое пространство за один раз (в отличие от использования цикла, которому требуется место только для одновременного хранения одного изображения)
Комментарии:
1. Спасибо. Благодаря uint8 и предварительному распределению это занимает 4 секунды по сравнению с исходными 20!