Генерация профилей через 2D-массив под углом без изменения пикселей - PullRequest
0 голосов
/ 08 сентября 2018

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

Это массив 600x600 с максимальной интенсивностью 1 (только на один пиксель), который расположен прямо в центре в точке (300, 300). Угол поворота от оси x (который затем определяет положение большой полуоси при повороте на этот угол) составляет theta = 89.54 degrees. Я не хочу использовать scipy.ndimage.rotate, потому что он использует сплайн-интерполяцию, и я не хочу изменять какие-либо из моих значений пикселей. Но я полагаю, что метод интерполяции ближайшего соседа будет в порядке.

Я попытался сгенерировать линии, соответствующие большой и вспомогательной осям по всему изображению, но результат был совсем не правильным (пик был намного меньше 1), поэтому, возможно, я сделал что-то не так. Код для этого ниже:

import numpy as np
import matplotlib.pyplot as plt
from scipy import ndimage

def profiles_at_angle(image, axis, theta):
    theta = np.deg2rad(theta)
    if axis == 'major':
        x_0, y_0 = 0, 300-300*np.tan(theta)
        x_1, y_1 = 599, 300+300*np.tan(theta)
    elif axis=='minor':
        x_0, y_0 = 300-300*np.tan(theta), 599
        x_1, y_1 = 300+300*np.tan(theta), -599
    num = 600
    x, y = np.linspace(x_0, x_1, num), np.linspace(y_0, y_1, num)
    z = ndimage.map_coordinates(image, np.vstack((x,y)))

    fig, axes = plt.subplots(nrows=2)
    axes[0].imshow(image, cmap='gray')
    axes[0].axis('image')
    axes[1].plot(z)
    plt.xlim(250,350)
    plt.show()

profiles_at_angle(image, 'major', theta)

Я сделал что-то явно не так в моем коде выше? Или как еще я могу это сделать? Спасибо.

Редактировать: вот несколько примеров изображений. Извините за плохое качество; мой браузер зависал каждый раз, когда я пытался загрузить их в любое место, поэтому мне приходилось делать фотографии с экрана.

Рисунок 1: Это результат моего кода выше, который явно ошибочен, так как пик должен быть на 1. Я не уверен, что я сделал неправильно, хотя. Figure 1

Рисунок 2: Я сделал этот график ниже, просто проведя профили по стандартным осям x и y, игнорируя любое вращение (это выглядит хорошо только по совпадению, потому что реальный угол поворота настолько близок к 90 градусам, что я смог просто поменять метки и получить это). Я хочу, чтобы мой результат выглядел примерно так, но с учетом поправочного угла поворота. Figure 2

Редактировать: Было бы полезно запустить тесты для этого метода, используя данные, очень похожие на мои (это 2D гауссовский с почти такими же параметрами):

image =  np.random.random((600,600))

def generate(data_set):
    xvec = np.arange(0, np.shape(data_set)[1], 1)
    yvec = np.arange(0, np.shape(data_set)[0], 1)
    X, Y = np.meshgrid(xvec, yvec)
    return X, Y

def gaussian_func(xy, x0, y0, sigma_x, sigma_y, amp, theta, offset):
    x, y = xy

    a = (np.cos(theta))**2/(2*sigma_x**2) + (np.sin(theta))**2/(2*sigma_y**2)
    b = -np.sin(2*theta)/(4*sigma_x**2) + np.sin(2*theta)/(4*sigma_y**2)
    c = (np.sin(theta))**2/(2*sigma_x**2) + (np.cos(theta))**2/(2*sigma_y**2)

    inner = a * (x-x0)**2
    inner += 2*b*(x-x0)*(y-y0)
    inner += c * (y-y0)**2
    return (offset + amp * np.exp(-inner)).ravel()

xx, yy = generate(image)
image = gaussian_func((xx.ravel(), yy.ravel()), 300, 300, 5, 4, 1, 1.56, 0)
image = np.reshape(image, (600, 600))

1 Ответ

0 голосов
/ 08 сентября 2018

Это должно сделать это для вас. Вы просто не правильно рассчитали свои строки.

theta = 65
peak = np.argwhere(image==1)[0]
x = np.linspace(peak[0]-100,peak[0]+100,1000)
y = lambda x: (x-peak[1])*np.tan(np.deg2rad(theta))+peak[0]
y_maj = np.linspace(y(peak[1]-100),y(peak[1]+100),1000)
y = lambda x: -(x-peak[1])/np.tan(np.deg2rad(theta))+peak[0]
y_min = np.linspace(y(peak[1]-100),y(peak[1]+100),1000)
del y

z_min = scipy.ndimage.map_coordinates(image, np.vstack((x,y_min)))
z_maj = scipy.ndimage.map_coordinates(image, np.vstack((x,y_maj)))

fig, axes = plt.subplots(nrows=2)
axes[0].imshow(image)
axes[0].plot(x,y_maj)
axes[0].plot(x,y_min)
axes[0].axis('image')

axes[1].plot(z_min)
axes[1].plot(z_maj)

plt.show()

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...