Я пытаюсь выполнить некоторые задачи преобразования изображений с помощью numpy в python. Идея состоит в том, что, предположим, я загрузил файл изображения в массив numpy img
, затем я создал новый массив new_img
, а также определил отображение между координатами пикселя: [x,y]
в новом изображении соответствует до [old_x,old_y]
. А затем я использую new_img[x,y] = img[old_x,old_y]
для вычисления преобразования. L oop для фактического вычисления этого преобразования выглядит примерно так: (на самом деле не работает, потому что я опустил много деталей, касающихся правила преобразования, ширины и длины изображений, проверки границ и т. Д. c., Но вы получите представление) .
def get_old_coord(y,x):
# this is the function to compute the corresponding pixel coordinates
# some computation here yields old_x and old_y
# ...
return old_x,old_y
for x in range(height_of_new_img):
for y in range(width_of_new_img):
new_img[y,x] = img[get_old_coord(x,y)]
# new_img is then as desired.
Проблема, с которой я столкнулся, заключается в том, что двойной l oop чрезвычайно трудоемкий. Для изображений размером 1000x1000 требуется одна или две минуты. С другой стороны, поскольку правило преобразования get_old_coord
может быть многим, я не думаю, что смогу улучшить это, используя некоторую встроенную функцию для арифметики массива. Как я могу сделать этот процесс более эффективным?
Обновление: для тех, кто хочет получить полный пример, вот один
import math
import torch
import torch.nn
import torchvision
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
def get_old_coord(x,y,old_h,old_w,new_h,new_w):
cent_x, cent_y = new_h/2, new_w/2
if ((x+1)%200==0 and (y+1)%new_w==0) or (x+1==new_h and (y+1)%new_w==0):
print('Progress = %.2f %%'%((x+1)/new_h*100))
rel_x, rel_y = x-cent_x, y-cent_y
#print('Doint %d,%d, center = %d,%d, rel_x, rel_y = %d,%d'%(x,y,cent_x,cent_y,rel_x,rel_y))
rho = math.sqrt(rel_x**2+rel_y**2)
rho /= (min(new_h,new_w)/2)
if rel_x==0 and rel_y>=0:
theta = math.pi/2
if rel_x==0 and rel_y<0:
theta = -1*math.pi/2
if rel_x>0:
theta = math.atan(rel_y/rel_x)
if rel_x<0:
theta = math.atan(rel_y/rel_x)+math.pi
theta = 2*math.pi-theta
rho = 1-rho
old_x = (int)(rho*old_h)
old_y = (int)(theta*old_w/(2*math.pi))%old_w
old_x = min(old_h-1,max(0,old_x))
#old_y = min(old_w-1,max(0,old_y))
#print('rho = %f, theta = %f, old_x, old_y = %d,%d'%(rho,theta,old_x,old_y))
return old_x, old_y
def transform(new_h,new_w,old_im):
old_h, old_w, _ = old_im.size()
new_im = torch.zeros(new_h,new_w,3).int()
for i in range(new_h):
for j in range(new_w):
new_im[i,j] = old_im[get_old_coord(i,j,old_h,old_w,new_h,new_w)]
return new_im
input_file_name = 'in.jpg'
output_file_name = 'out.jpg'
new_h = 800
new_w = 800
old_im = torch.tensor(plt.imread(input_file_name))
new_im = transform_radial(new_h,new_w,old_im)
new_im = Image.fromarray(np.uint8(new_im))
new_im.save(output_file_name)
По сути, это реализует преобразование полярной координаты. Извините за то, что не успел добавить комментарии в мой код. Но пробовать это на любом из ваших изображений должно быть весело. Кроме того, я на самом деле использую тензоры факелов в этом примере, но они мало чем отличаются от numpy массивов.