Я пытаюсь реализовать некоторый код, который я нашел в StackOverflow (кредит Самый эффективный способ вычисления радиального профиля ), и я нахожу несколько проблем, связанных с возвращаемой переменной. Ключевым типом данных, с которым вы работаете, является 16-разрядное целое число без знака;однако, глядя на результаты, они кажутся намного выше, чем хотелось бы. Вот мой установочный код, и я компилирую его с помощью инструментов сборки Visual Studio - лучше ли будет использовать GCC, и если да, может кто-нибудь подсказать мне советы по смене компиляторов?
Код setup.py
:
from distutils.core import setup
from Cython.Build import cythonize
import numpy
ext_options = {"compiler_directives": {"profile": True}, "annotate": True}
setup(
ext_modules = cythonize("radialAvgCython.pyx", **ext_options),
include_dirs=[numpy.get_include()]
)
Спасибо за ваше время!
РЕДАКТИРОВАТЬ 3: Я думаю, что я, возможно, нашел проблему, которая находится в одной из функций в коде Cythonic, показанном ниже:
cdef void cython_radial_profile(DTYPE_IMG_t [:, :] img_view, DTYPE_t [:] r_profile_view, int xs, int ys, int x0, int y0) nogil:
cdef int x, y, r, tmp
for x in prange(xs):
for y in range(ys):
r =<int>(sqrt((x - x0)**2 + (y - y0)**2))
tmp = img_view[x, y]
r_profile_view[r] += tmp
Я считаю, что для каждого радиуса r
значение добавляется к предыдущему значению и усреднение не происходит;Вот почему результаты, как правило, намного больше, чем ожидалось. Я попытаюсь найти способ усреднения каждого r, но я думаю, что это может быть основной проблемой, поскольку результаты существенно больше, чем другие простые азимутальные / радиальные средние коды.
РЕДАКТИРОВАТЬ 2: Воткод, используемый в radialAvgCython.pyx
, насколько я могу судить, код хорошо написан, но результаты между этим и стандартным радиальным средним значением сильно различаются:
import numpy as np
cimport numpy as np
cimport cython
from cython.parallel import prange
from libc.math cimport sqrt, ceil
DTYPE_IMG = np.uint16
ctypedef np.uint16_t DTYPE_IMG_t
DTYPE = np.int
ctypedef np.int_t DTYPE_t
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
cdef void cython_radial_profile(DTYPE_IMG_t [:, :] img_view, DTYPE_t [:] r_profile_view, int xs, int ys, int x0, int y0) nogil:
cdef int x, y, r, tmp
for x in prange(xs):
for y in range(ys):
r =<int>(sqrt((x - x0)**2 + (y - y0)**2))
tmp = img_view[x, y]
r_profile_view[r] += tmp
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.nonecheck(False)
def radial_profile(np.ndarray img, int centerX, int centerY):
# Find and define image dimensions.
cdef int xs, ys, r_max
xs, ys = img.shape[0], img.shape[1]
# Find maximum radius based on defined center and image size.
cdef int topLeft, topRight, botLeft, botRight
topLeft = <int> ceil(sqrt(centerX**2 + centerY**2))
topRight = <int> ceil(sqrt((xs - centerX)**2 + (centerY)**2))
botLeft = <int> ceil(sqrt(centerX**2 + (ys-centerY)**2))
botRight = <int> ceil(sqrt((xs-centerX)**2 + (ys-centerY)**2))
r_max = max(topLeft, topRight, botLeft, botRight)
# Create relevant variables and feed in, solve.
cdef np.ndarray[DTYPE_t, ndim=1] r_profile = np.zeros([r_max], dtype=DTYPE)
cdef DTYPE_t [:] r_profile_view = r_profile
print(r_profile)
cdef DTYPE_IMG_t [:, :] img_view = img
with nogil:
cython_radial_profile(img_view, r_profile_view, xs, ys, centerX, centerY)
# Return radial profile.
print(r_profile)
return r_profile
РЕДАКТИРОВАТЬ: я должен упомянуть, чтоЯ использую PyCharm в качестве своей IDE.