2d матрица для изображения конуса

avatar
Testing123
8 апреля 2018 в 00:12
811
1
3

У меня есть двумерная пустая матрица размером 512x256. Я могу легко преобразовать его в изображение с помощью PIL, scipy и т. д., но это, очевидно, дает мне форму прямоугольника размером 512x256. Мне интересно, могу ли я что-то сделать, чтобы эта матрица приняла форму конуса, как на рисунке? enter image description here

Я думаю об этом так: первый столбец матрицы будет самой левой линией конуса, а следующий столбец матрицы будет немного правее этой линии и так далее. Поскольку угол между двумя крайними точками равен 45 градусам, а у меня 256 столбцов, значит ли это, что каждая строка получает приращение угла (45/256) градусов? Это всего лишь некоторые грубые мысли, но я хотел узнать у сообщества, есть ли у них какие-либо идеи о том, как мне поступить с этим? Я представляю основное изображение черного квадрата и этот конус посередине. Любые идеи/мысли?

Источник
ahed87
8 апреля 2018 в 01:22
0

вам всегда будет нужна полная пиксельная матрица для создания изображения, поэтому, когда вы хотите преобразовать из равноудаленной декартовой системы координат, но все же сделать изображение на основе пикселей, вам придется подумать о схеме того, что поместить в пиксели, которые по определению будут быть пустым, как только вы сделали свой конус. Если вы погуглите «проекции» или «преобразования», вы должны найти то, что ищете с точки зрения изготовления конуса. Но, как уже отмечалось, у вас все еще есть «пустые» пиксели, которые вы можете заполнить по своему вкусу. А может вам повезло и кто-то сделал для этого библиотеку, если да, то я не в курсе.

ahed87
8 апреля 2018 в 01:24
0

Итак, чего вы на самом деле хотите достичь, т. е. каков более высокий уровень проблемы, на который вы смотрите? Я имею в виду, что существует множество программ, которые будут смешивать/преобразовывать векторную графику (а также пиксельную графику), но вашей отправной точкой является изображение, представленное матрицей numpy?

Marat
8 апреля 2018 в 01:42
0

в основном, вы ищете преобразование из полярных координат в линейные, где X в исходном изображении — это угол, а Y — расстояние. Это сообщение может оказаться полезным

Testing123
9 апреля 2018 в 14:26
0

@ahed87 - вы видели снимки УЗИ? Они имеют конусообразную форму. Вы правы, что моей отправной точкой была не пустая матрица, а необработанные данные чисел. Пришлось почистить и все, а потом создать несколько матриц, где каждая матрица представляет кадр. И да, Google не вернул никакой удобной библиотеки, которую я мог бы использовать для этого преобразования.

Ответы (1)

avatar
Andrey Tyukin
8 апреля 2018 в 01:43
2

Вот быстрое и грязное решение, которое сопоставляет полярные координаты в результирующем изображении с прямоугольными координатами в исходном изображении и использует interp2d на каждом канале исходного изображения:

import numpy as np
from scipy import misc
from scipy.interpolate import interp2d
from math import pi, atan2, hypot

inputImagePath = 'wherever/whateverYouWantToInterpolate.jpg'
resultWidth = 800
resultHeight = 600
centerX = resultWidth / 2
centerY = - 50.0
maxAngle =  45.0 / 2 / 180 * pi
minAngle = -maxAngle
minRadius = 100.0
maxRadius = 600.0

inputImage = misc.imread(inputImagePath)
h,w,chn = inputImage.shape
print(f"h = {h} w = {w} chn = {chn}")
channels = [inputImage[:,:,i] for i in range(3)]
interpolated = [interp2d(range(w), range(h), c) for c in channels]
resultImage = np.zeros([resultHeight, resultWidth, 3], dtype = np.uint8)

for c in range(resultWidth):
  for r in range(resultHeight):
    dx = c - centerX
    dy = r - centerY
    angle = atan2(dx, dy) # yes, dx, dy in this case!
    if angle < maxAngle and angle > minAngle:
      origCol = (angle - minAngle) / (maxAngle - minAngle) * w
      radius = hypot(dx, dy)
      if radius > minRadius and radius < maxRadius:
        origRow = (radius - minRadius) / (maxRadius - minRadius) * h
        for chn in range(3):
          resultImage[r, c, chn] = interpolated[chn](origCol, origRow)

import matplotlib.pyplot as plt
plt.imshow(resultImage)
plt.show()

Производит:

warped logo of StackOverflow

Производительность ужасная, не удосужился "векторизировать". Обновлю, когда узнаю как.

Testing123
9 апреля 2018 в 14:28
0

Привет @Андрей. Я только что увидел ваш ответ и прочитал код. Кстати, что такое «chn» в «h, w, chn = inputImage.shape»?

Andrey Tyukin
9 апреля 2018 в 14:54
0

@Testing123 количество цветов channels, обычно должно быть 3, его можно опустить. Я думаю, что если я заменю 3 в нескольких других местах на chn, это должно работать и с изображениями в градациях серого. ;; Это не код страны Китая, и код не "сделано в Китае", если вы имели в виду это... ;)

Testing123
15 апреля 2018 в 20:53
0

Ха-ха... "China Fund Inc" звучит лучше :) Кроме шуток, ваше решение работает!