Я думаю, что вы хотите заменить все пиксели вокруг радиуса каждого круга изображения на среднее значение пикселей этого же радиуса во входном изображении.
Я предлагаю деформировать изображение в декартовых координатах, вычислите среднее значение и затем деформируйте обратно к полярным координатам.
Я сгенерировал некоторые тестовые данные приличного размера, такие как:
#!/usr/bin/env python3
import cv2
from PIL import Image
from scipy import stats, ndimage, misc
import matplotlib.image as mpimg
from scipy import stats
import numpy as np
w, h = 600, 600
a = np.zeros((h,w),np.uint8)
# Generate some arcs
for s in range(1,6):
radius = int(s*w/14)
centre = (int(w/2), int(w/2))
axes = (radius, radius)
angle = 360
startAngle = 0
endAngle = 72*s
cv2.ellipse(a, centre, axes, angle, startAngle, endAngle, 255, 2)
Это дает это:
Image.fromarray(a.astype(np.uint8)).save('start.png')
def orig(a):
b = a.copy().flatten()
y,x = np.indices((a.shape))
center = [len(x)//2, len(y)//2]
r = np.hypot(x-center[0],y-center[1])
r = r.astype(np.int) # integer part of radii (bin size = 1)
set_r = set(r.flatten()) # get the list of r without duplication
max_r = max(set_r) # determine the maximum r
median_r = np.array([0.]*len(r.flatten())) # array of median I for each r
for j in set_r:
result = np.where(r.flatten() == j)
median_r[result[0]] = np.median(b[result[0]])
return median_r
def me(a):
h, w = a.shape
centre = (int(h/2), int(w/2))
maxRad = np.sqrt(((h/2.0)**2.0)+((w/2.0)**2.0))
pol = cv2.warpPolar(a.astype(np.float), a.shape, centre, maxRad, flags=cv2.WARP_POLAR_LINEAR+cv2.WARP_FILL_OUTLIERS)
polmed = np.median(pol,axis=0,keepdims=True)
polmed = np.broadcast_to(polmed,a.shape)
res = cv2.warpPolar(polmed, a.shape, centre, maxRad, cv2.WARP_INVERSE_MAP)
return res.astype(np.uint8)
a_med = orig(a).reshape(a.shape)
Image.fromarray(a_med.astype(np.uint8)).save('result.png')
r = me(a)
Image.fromarray(r).save('result-me.png')
Результат такой же, как у вас, т.е. он удаляет все дуги меньше 180 градусов и заполняет все дуги на 180 градусов:
Но время для меня в 10 раз быстрее:
In [58]: %timeit a_med = orig(a).reshape(a.shape)
287 ms ± 17.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [59]: %timeit r = me(a)
29.9 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Если вам трудно представить, что я получаю после warpPolar()
, это выглядит так,Затем я использую np.mean()
, чтобы вывести среднее значение по столбцам, т.е. axis=0
:
Ключевые слова : Python,радиальное среднее, радиальная медиана, декартовы координаты, полярные координаты, прямоугольные, warpPolar, linearPolar, OpenCV, изображение, обработка изображений