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

img = img(1:40,1:100)
imshow(img);
ffts = blockproc(img, [20 20], @(block_struct) fftshift(fft2(block_struct.data)));
// fft = imresize(ffts, [40 100], 'nearest');

По сути, этот код берет верхнюю левую часть изображения размером 40 x 100, а затем выполняет блочную обработку для каждой части 20 x 20 этой области, вычисляя fft2. Надеюсь, моя логика пока звучит хорошо.

Что мне интересно, так это то, есть ли способ выполнить средний fft2 из 20 x 20 частей матрицы 40 x 100 fft с помощью встроенной функциональности Matlab. Я знаю, что это можно сделать относительно легко с помощью циклов, но я хотел бы, чтобы решение в моем коде было как можно более компактным.

Я немного прочитал руководство и очевидно, что есть пара функций Matlab, которые могут это сделать; Однако я пока не совсем уверен в своей заявке. Приветствуются любые направления!

2
m.n 28 Авг 2014 в 22:57
Вы хотите вычислить средний блок 20 x 20 теперь, когда вы вычислили все 20 x 20 2D БПФ изображения?
 – 
rayryeng
28 Авг 2014 в 23:03
Да, я хотел бы вычислить средний блок 20 x 20 по всем двухмерным БПФ 20 x 20 изображения. Извините за отсутствие ясности с моей стороны.
 – 
m.n
28 Авг 2014 в 23:04
Хорошо, дам ответ. Дай мне 5 минут
 – 
rayryeng
28 Авг 2014 в 23:06

1 ответ

Лучший ответ

Это легко сделать в 3 строчки кода.


Линия 1

Сначала используйте im2col, чтобы изменить форму каждой отдельной окрестности блока 20 х 20 в один столбик. Таким образом, на выходе будет матрица 400 x N, где каждый столбец обозначает уникальную окрестность блока, которая была преобразована в столбец. В каждом столбце будет 400 строк, так как в каждой окрестности 400 элементов (20 x 20). N будет общим количеством уникальных блоков в вашем изображении 40 x 100. Это составит 10, так как мы можем уместить 2 блока по горизонтали и 5 блоков по вертикали, учитывая требование 20 x 20.

Строка # 2

Что хорошо в выводе im2col, так это то, что i th строка im2col сообщает вам i th элемент для каждого блока вашего изображения. Таким образом, все, что вам нужно сделать, это взять каждую строку и получить среднее значение по всем столбцам . На выходе будет вектор 400 x 1, который обозначает ваше среднее значение БПФ для всех блоков. Этого можно добиться, используя mean и указав, что мы хотите усреднить по второму измерению (второй параметр - 2), то есть по столбцам.

Строка № 3

Затем нам нужно преобразовать это обратно в матрицу 20 x 20, поэтому используйте reshape для этого. Мы указываем, что выходной матрицей является 20 x 20, учитывая вектор элементов 400 x 1.

Один вопрос, который вы можете задать, заключается в том, гарантирует ли это переупорядочение правильное переупорядочение нашего блока БПФ. Это гарантировано, потому что, когда im2col построил каждый блок в столбец, он продвигается в порядке основного столбца . Это означает, что для одного столбца блоков мы строим их построчно. Как только мы получаем наш набор отдельных блоков 20 x 20, эти блоки располагаются таким образом, что они выбираются в порядке возрастания столбцов. Это означает, что из одного блока 20 x 20 создается вектор-столбец 400 x 1, где столбцы блока 20 x 20 накладываются друг на друга слева направо. Следовательно, выполняя mean и reshape, пространственные положения для каждого блока действительно соответствуют друг другу и, таким образом, дадут правильный ответ.


Без лишних слов, вот код:

colBlocks = im2col(ffts, [20 20], 'distinct'); %// Line 1
meanCol = mean(colBlocks, 2); %// Line 2
fftBlockAverage = reshape(meanCol, [20 20]); %// Line 3

Незначительный побочный эффект

Поскольку БПФ является комплексным по своей природе, выполняя усреднение, вы усредняете реальную и мнимую составляющие отдельно. Вот как MATLAB обрабатывает среднее значение комплексных данных. Я не уверен, какой анализ вы будете выполнять после вычисления среднего блока 2D БПФ, но имейте это в виду, прежде чем продолжить свой анализ.


Примечание

Divakar в предыдущем ответе создал более эффективную реализацию im2col. Это особенно полезно, если у вас не установлен Image Processing Toolbox. Вы можете проверить эту реализацию здесь. Было показано, что время между этой функцией и im2col MATLAB на порядок быстрее.

Бенчмаркинг

В качестве бонуса вот тест с использованием его кода. Результаты измерения времени были получены с использованием матрицы 40 x 100, в которой встроенная функция im2col была рассчитана по времени, а пользовательская функция Divakar - после. Результаты показывают, что его метод быстрее. Это может быть очень полезно при рассмотрении изображений большего размера. Однако, если вы ищете лаконичности, используйте то, что я написал. Если вы хотите чего-то быстрого, воспользуйтесь его методом.

Код сравнения

%// Input Parameters
nrows = 20;
ncols = 20;
A = rand(40,100);

disp('------------------------- With IM2COL');
tic
B1 = im2col(A,[nrows ncols],'distinct');
toc,clear B1

disp('----------------- With CUSTOM-BUILT IM2COL');
tic
B2 = im2col_distinct(A,[nrows ncols]);
toc,clear B2

Результаты

------------------------- With IM2COL
Elapsed time is 0.026914 seconds.
----------------- With CUSTOM-BUILT IM2COL
Elapsed time is 0.004186 seconds.
2
Community 23 Май 2017 в 13:33
Если это работает для OP и если необходимо использовать im2col и если производительность во время выполнения важна, позвольте мне предложить ему альтернативу - stackoverflow.com/a/25454746/3293881, что показалось быстрее на нескольких тестах, которые мне удалось выполнить.
 – 
Divakar
28 Авг 2014 в 23:19
- Это забавно. Я на самом деле одобрил тот вопрос, на который вы ссылались, и проголосовал за вас, lol. Я должен был знать лучше. Спасибо за ссылку Дивакар!
 – 
rayryeng
28 Авг 2014 в 23:20
Думаю, я заплатил;) Что ж, теперь, когда у нас есть реальный случай, OP может протестировать его со встроенным и заказным! Хотелось бы увидеть несколько тестов от OP по этому поводу!
 – 
Divakar
28 Авг 2014 в 23:21
- хе-хе. Я не знаю, когда я это сделал, но когда я проверил ваш ответ, я уже проголосовал за него и мне понравилось. Должно быть, это было давно. С точки зрения написания кода это было бы самым коротким решением. Если требуется эффективность, ОП обязательно должен использовать ваш ответ.
 – 
rayryeng
28 Авг 2014 в 23:22
1
- Полагаю, что для небольших матриц тесты скорости будут сопоставимы. Когда матрицы будут большего размера, подозреваю, что ваш метод будет быстрее.
 – 
rayryeng
28 Авг 2014 в 23:24