#python #arrays #matlab #image-processing
#python #массивы #matlab #обработка изображений
Вопрос:
Мне нужно преобразовать приведенный ниже блок кода в Python. Я создал два массива с именами u
и v
отдельно и поместил их в цикл for в диапазоне от 0 до M-1, и я знаю find
, что работает аналогично условию if. У меня проблема, поскольку оба idx
и u
являются массивами.
Код MATLAB — это:
u = 0:(M-1);
v = 0:(N-1);
idx = find(u > M/2);
u(idx) = u(idx) - M; #I have a problem here
idy = find(v > N/2);
v(idy) = v(idy) - N;
В основном, что я делал в Python, пока не добрался до этой проблемной строки:
input_image = Image.open('./....image....')
input_image=np.array(input_image)
M,N = input_image.shape[0],input_image.shape[1]
FT_img = fftpack.fftshift(fftpack.fft2(input_image))
# Assign the order value
n = 2; # one can change this value accordingly
# Assign Cut-off Frequency
D0 = 60; # one can change this value accordingly
# Designing filter
u=[]
v=[]
for i in range(M-1):
u.append(i)
for i in range(N-1):
v.append(i)
Комментарии:
1. Вы ищете Numpy. Я думаю, вам следует прочитать несколько руководств по Python. 1 , 2 . В последнем есть глава, посвященная Numpy.
2. Спасибо @Cris, я только что отредактировал свой пост.
3. Очевидно, что сценарий Matlab — это ваш ввод, а сценарий Python — ваш вывод. Пожалуйста, разместите скрипты Matlab и Python в виде двух отдельных блоков кода. В настоящее время у вас есть *** Matlab *** и Python , объединенные в один блок кода. Разделите два блока кода внутри вашего сообщения stack overflow знаками pound.
### Original Matlab (input) ###
и### Attempted Python (output) ###
4. @Samuel, просто отредактировал мой пост так, как вы упомянули.
5. По-видимому, имеющийся у вас код MATLAB вычисляет нечто, известное как частоты дискретизации » Дискретного преобразования Фурье «. Дискретные преобразования Фурье хорошо изучены. Вам не нужно писать свой собственный код для вычисления частот дискретизации дискретного преобразования Фурье. Если человек, написавший код MATLAB, не смог написать комментарий, объясняющий, что они вычисляли, то этот человек был очень плохим программистом. Почти невозможно сказать, что должен делать код без комментариев. Почему бы просто не иметь функцию с именем что-то вроде
get_fft_frequencies()
?
Ответ №1:
Что u = 0:(M-1)
делает Matlab и как мы можем сделать то же самое в Python?
Ниже приведен один отрывок из вашего исходного кода Matlab:
% BEGIN MATLAB %
u = 0:(M-1);
% END MATLAB %
Что делает код?
Предположим, что M = 7
. Тогда код Matlab упрощает:
u = 0:6;
Результатом является массив u
, начинающийся 0
и заканчивающийся 6
:
u = [0 1 2 3 4 5 6]
По сути, вы инициализируете массив последовательных целых чисел.
Существуют различные способы выполнить что-то подобное в Python:
# Begin Python
M = 7
u = list(range(0, M))
# End python
Обратите внимание, что это range(0, 7)
выглядит как [0, ..., 5, 6]
, не [0, ..., 6, 7]
range
Функция Python автоматически вычитается 1
из верхнего предела
Если вы действительно занимаетесь материалами типа Matlab, то numpy
какую библиотеку вы хотите использовать в Python:
import numpy as np
u = np.array(range(0, 7))
Индексация, начинающаяся с 0, по сравнению с индексацией, начинающейся с 1
Обратите внимание, что индексация Matlab начинается с 1
.
Индексация Python начинается с 0
.
ARRAY = ["red", "blue", "white", "green"]
-------------- ------- -------- --------- ---------
| ARRAY | "red" | "blue" | "white" | "green" |
-------------- ------- -------- --------- ---------
| PYTHON INDEX | 0 | 1 | 2 | 3 |
| MATLAB INDEX | 1 | 2 | 3 | 4 |
-------------- ------- -------- --------- ---------
Понимание find
функции
Перевод find
с Matlab на английский
Рассмотрим find
функцию из Matlab:
idx = find(u > M/2); % this is matlab-code
Вызов функции find(u)
будет искать по всему массиву u
что-либо строго большее, чем M/2
. find(u)
затем вернет список всех индексов для объектов, превышающих M/2
Рассмотрим следующий пример find
функции:
u = [98 00 00 87 49 50 51 00 85];
% 1 2 3 4 5 6 7 8 9 .....ARRAY INDICIES
idx = find(u > 50);
disp(idx)
% displays .... 1 4 7 9
find(u > 50)
найдет индексы каждого элемента u
, превышающие или равные 51
Рассмотрим код u(idx) = 22;
У нас есть следующие результаты:
--------------------- ------ ----- ----- ------ ----- ----- ------ ----- ------
| MATLAB INDICIES | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
--------------------- ------ ----- ----- ------ ----- ----- ------ ----- ------
| print(u) | 99 | 00 | 00 | 99 | 49 | 50 | 51 | 00 | 99 |
--------------------- ------ ----- ----- ------ ----- ----- ------ ----- ------
| % u > 50? | %yes | %no | %no | %yes | %no | %no | %yes | %no | %yes |
--------------------- ------ ----- ----- ------ ----- ----- ------ ----- ------
| idx = find(u > 50); | | | | | | | | | |
| u(idx) = 22; | | | | | | | | | |
--------------------- ------ ----- ----- ------ ----- ----- ------ ----- ------
| print(u) | 22 | 0 | 0 | 22 | 49 | 50 | 22 | 0 | 22 |
--------------------- ------ ----- ----- ------ ----- ----- ------ ----- ------
Все, что внутри массива u
больше или равно 51
, было заменено на 22
Перевод find
с английского на Python
Предположим, что у вас есть массив u
в Python.
Вы хотите заменить каждое целое число, большее или равное на 51
22
Вы можете сделать это на Python, используя numpy
библиотеку:
# This is Python (not matlab)
import numpy as np
u = [98 00 00 87 49 50 51 00 85];
u = np.array(u)
u[u > 50] = 22
# THIS IS PYTHON CODE (not matlab)
Обратите внимание, что u[u > 50] = 22
это то же самое, что и следующее:
# THIS IS PYTHON CODE (not matlab)
indicies = type(u).__gt__(u, 50)
u.__setitem__(indicies, 22)
# THIS IS PYTHON CODE (not matlab)
Перевод find
с Matlab на Python
Если вы переведете часть своего исходного кода из Matlab в Python, это будет выглядеть следующим образом:
ВВОД MATLAB:
M = 7
u = 0:(M-1);
idx = find(u > M/2);
u(idx) = u(idx) - M;
ВЫВОД PYTHON:
# THIS IS PYTHON CODE (not matlab)
import numpy as np
M = 7
u = np.array(range(0, M))
idx = u > M/2
u[idx] = u[idx] - M
# THIS IS PYTHON CODE (not matlab)
Перевод всего ВСЕГО кода Matlab на английский и математический языки
В начале поста я объяснил, что делают несколько отдельных фрагментов вашего кода Matlab.
Теперь давайте переведем весь скрипт Matlab на английский и математический языки.
*** ЧТО-ТО ПОХОЖЕЕ НА ВАШ ОРИГИНАЛЬНЫЙ / СТАРЫЙ MATLAB НИЖЕ ***
function u = GenerateArray(M)
u = 0:(M-1);
idx = find(u > M/2);
u(idx) = u(idx) - M;
end
M = 7;
u = GenerateArray(M);
N = 9;
v = GenerateArray(N);
*** ПОВЕДЕНИЕ В ВИДЕ ТАБЛИЦЫ***
Я думаю, что код Matlab легче понять как таблицу, чем как код:
-------------- ---------------------------
| WHOLE NUMBER | ARRAY |
| `M` | `u` |
-------------- ---------------------------
| 4 | 0 1 2 -1 |
| 5 | 0 1 2 -2 -1 |
| 6 | 0 1 2 3 -2 -1 |
| 7 | 0 1 2 3 -3 -2 -1 |
-------------- ---------------------------
Для M > 7
:
- левая половина массива:
[0, 1 , 2, 3, [...], floor(M/2)]
- правая половина массива:
lang-none [(-1)*(x-0), (-1)*(x-1), (-1)*(x-2), [...], -3, -2, -1]
где x равноfloor((M-1)/2)
Перевод всего кода Matlab в Python
Следующий скрипт Python имеет тот же результат, что и скрипт Matlab:
import numpy as np
import itertools as itts
def generate_data(array_size : int) -> type(np.array(range(0, 1))):
"""
-------------- ---------------------------
| INPUT | OUTPUT |
-------------- ---------------------------
| 4 | 0 1 2 -1 |
| 5 | 0 1 2 -2 -1 |
| 6 | 0 1 2 3 -2 -1 |
| 7 | 0 1 2 3 -3 -2 -1 |
-------------- ---------------------------
* the left side of the array:
starts at:
zero
ends at:
floor(M/2)
counts by:
1
looks like:
[0, 1 , 2, 3, [...], floor(M/2)]
* the right side of the array...
starts at
(-1) * floor((M-1)/2)
ends at:
-1
counts by:
-1
looks like:
[
(-1) * floor((M-1)/2),
(-1) * (floor((M-1)/2) - 1),
(-1) * (floor((M-1)/2) - 2),
[...],
-3,
-2,
-1
]
"""
# clean_input = int(dirty_input)
n = int(array_size)
# make the first element of the left side of the array be zero.
# left_side_first = 0
lsf = 0
# left_side_last = clean_input // 2
lsl = n // 2
# left_side_iterator = range(left_side_first, 1 left_side_last)
lsit = range(lsf, 1 lsl)
# `list` stands for "left side iterator"
right_side_first = (-1) * ((n - 1) // 2)
right_side_last = -1
right_side_iterator = range(right_side_first, 1 right_side_last)
# merged_iterator = chain(left_side_iterator, right_side_iterator)
merged_iterator = itts.chain(lsit, right_side_iterator)
output = np.array(list(merged_iterator))
# We convert the iterator to a `list` because the following
# direct use of the iterator does not work:
#
# output = np.array(merged_iterator)
return output
Мы можем вызвать функцию Python следующим образом:
arr = generate_data(14)
print(arr)
Вывод для ввода 14
показан ниже:
[ 0 1 2 3 4 5 6 7 -6 -5 -4 -3 -2 -1]
Ответ №2:
Ваш код MATLAB
u = 0:(M-1);
idx = find(u > M/2);
u(idx) = u(idx) - M;
может быть более эффективно реализовано путем исключения find
:
u = 0:(M-1);
idx = u > M/2;
u(idx) = u(idx) - M;
Эта форма тривиально переводится на Python с помощью NumPy:
u = np.arange(0, M)
idx = u > M/2
u[idx] = u[idx] - M
Комментарии:
1. Предположим на мгновение, что
M/2
это число34
. Обратите внимание, что у>
оператора есть специальное определение для массивов numpy . Когдаu
массив numpyu > 34
, массив поиска кодаu
для каждого отдельного элемента больше34
. Мы заранее знаем, чтоu
это массив[0, 1, 2, 3, 4, 5, ...]
Элементыu
уже отсортированы и пронумерованы последовательно. Искать по всему массивуu
элементы больше, чем пустая трата времени34
. Для повышения эффективности во время выполнения вы могли бы написатьidx = range(1 M/2, M)
илиidx = range(1 len(u)/2, len(u))
2. @SamuelMuldoon: Я согласен. Вы также можете объединить два половинных массива и избежать вычитания. И еще проще просто позвонить
fftfreq
.