Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使凹凸不平的圆圈平滑_Python_Numpy_Image Processing_Geometry_Scikit Image - Fatal编程技术网

Python 使凹凸不平的圆圈平滑

Python 使凹凸不平的圆圈平滑,python,numpy,image-processing,geometry,scikit-image,Python,Numpy,Image Processing,Geometry,Scikit Image,我检测圆形物体的边缘,并获得“凹凸”的不规则边缘。有没有办法平滑边缘,使我的形状更均匀 例如,在下面的代码中,我生成了一个“凹凸”圆(左)。是否有一种平滑或移动平均的函数可以用来获得或近似“平滑”圆(右)。最好是用一些我能控制的参数,因为我的实际图像不是完美的圆形 import numpy as np import matplotlib.pyplot as plt fig, (bumpy, smooth) = plt.subplots(ncols=2, figsize=(14, 7)) an

我检测圆形物体的边缘,并获得“凹凸”的不规则边缘。有没有办法平滑边缘,使我的形状更均匀

例如,在下面的代码中,我生成了一个“凹凸”圆(左)。是否有一种平滑或移动平均的函数可以用来获得或近似“平滑”圆(右)。最好是用一些我能控制的参数,因为我的实际图像不是完美的圆形

import numpy as np
import matplotlib.pyplot as plt

fig, (bumpy, smooth) = plt.subplots(ncols=2, figsize=(14, 7))

an = np.linspace(0, 2 * np.pi, 100) 

bumpy.plot(3 * np.cos(an) + np.random.normal(0,.03,100), 3 * np.sin(an) + np.random.normal(0,.03,100))

smooth.plot(3 * np.cos(an), 3 * np.sin(an))

我建议使用FIR滤波器。背后的想法是使用过滤点周围点的加权平均值。。。你只是做一些像

p(i) = 0.5*p(i) + 0.25*p(i-1) + 0.25*p(i+1) 
其中
p(i)
i-th
点。最好记住原始的
p(i)
,因为它用于下一次迭代(以避免移位)。可以分别执行每个轴。可以使用任何权重,但其总和应为1.0。您可以使用任意数量的邻居,而不仅仅是2个(但在这种情况下,您需要记住更多的点)。对称权重将减少移位。您可以多次应用FIR

这里有一个小的2D C++示例:

//---------------------------------------------------------------------------
常数int n=50;//要点
浮动pnt[n][2];//点x,y。。。
//---------------------------------------------------------------------------
void pnt_init()
{
int i;
浮点数a,da=2.0*MμPI/浮点数(n),r;
随机化();

对于(a=0.0,i=0;i您可以在频域中执行此操作
曲线点的坐标,并将信号构造为
信号=x+yj
,然后对该信号进行傅里叶变换。滤除高频分量,然后进行傅里叶逆变换,将得到平滑曲线。您可以通过调整截止频率来控制平滑度

下面是一个例子:

import numpy as np
from matplotlib import pyplot as plt

r = 3
theta = np.linspace(0, 2 * np.pi, 100) 
noise_level = 2
# construct the signal
x = r *  np.cos(theta) + noise_level * np.random.normal(0,.03,100)
y = r *  np.sin(theta) + noise_level * np.random.normal(0,.03,100)
signal = x + 1j*y
# FFT and frequencies
fft = np.fft.fft(signal)
freq = np.fft.fftfreq(signal.shape[-1])
# filter
cutoff = 0.1
fft[np.abs(freq) > cutoff] = 0
# IFFT
signal_filt = np.fft.ifft(fft)

plt.figure()
plt.subplot(121)
plt.axis('equal')
plt.plot(x, y, label='Noisy')
plt.subplot(122)
plt.axis('equal')
plt.plot(signal_filt.real, signal_filt.imag, label='Smooth')

如果所讨论的形状近似于椭圆,并且您希望强制它们成为实际的椭圆,您可以通过计算点集的惯性矩来轻松拟合椭圆,并从中计算椭圆的参数。代码很容易转换为Python:

import numpy as np
import matplotlib.pyplot as plt

# Some test data (from Question, but with offset added):
an = np.linspace(0, 2 * np.pi, 100) 
x = 3 * np.cos(an) + np.random.normal(0,.03,100) + 3.8
y = 3 * np.sin(an) + np.random.normal(0,.03,100) + 5.4

plt.plot(x, y)

# Approximate the ellipse:
L, V = np.linalg.eig(np.cov(x, y))
r = np.sqrt(2*L)                       # radius
cos_phi = V[0, 0]
sin_phi = V[1, 0]                      # two components of minor axis direction
m = np.array([np.mean(x), np.mean(y)]) # centroid

# Draw the ellipse:
x_approx = r[0] * np.cos(an) * cos_phi - r[1] * np.sin(an) * sin_phi + m[0];
y_approx = r[0] * np.cos(an) * sin_phi + r[1] * np.sin(an) * cos_phi + m[1];

plt.plot(x_approx, y_approx, 'r')
plt.show()


上面的质心计算是有效的,因为点均匀地分布在椭圆周围。如果不是这样,.

您期望的输入和输出是什么?图像?通过FIR滤波器平滑点(来自自身和邻域的加权平均值可能需要对中心位置和比例进行传统校正,以避免在重筛选时移动位置和改变大小)或通过数据集(与点之间的距离最小的圆等)。@DyZ输入是一个列表或数组,例如
zip(3*np.cos(an)+np.random.normal(0.03100),3*np.sin(AN)+NP.随机(正常(0,03100))输出是相似的,例如:代码> zip(3 *NP.COS(AN),3 *NP.Sin(AN))< /C> > SpktRe。我将查看FIR滤波器。@ Gyt增加了小C++示例(对不起,不是Python编码器)作为回答,我认为这里真正的技巧不是傅里叶域,更多的是在复平面上修改笛卡尔坐标。这真是个好主意。不幸的是,在我看来,这并不容易应用于高维问题(这不是问题的范围)@norok2事实上,据我所知,我是从中得出这个想法的(但它并没有超出2D),我们应该能够将其应用于光滑的高维曲面。我认为这对于高维曲线是不可能的。回答得很好。你能进一步深入了解
截止
参数吗?它的单位是什么?除了通过实验之外,你如何计算出合理的值范围根据经验?@MarkSetchell
cutoff
是一种频率。它的单位可以根据您的
信号而变化。基本上,频率是信号变化速度的指示器。如果您检查信号的频谱,高频对应于信号的快速变化分量。因此,如果您不想要频率,请如果超过某个值,您可以在信号的频域表示中删除它们,然后进行逆变换。因此,这就像一个粗糙的低通滤波器。@MarkSetchell,以及任何其他想要学习的人:fft中的Bin 0表示圆的质心。Bin 1和-1(第二个和最后一个)一起表示半径(这是一个正弦波的实部和虚部周期,具有适当的缩放和移位)。因此,使用前三个值可以对任何椭圆进行编码。Bins 2和-2一起表示下一个更高的变化模式(正弦波的两个周期),使用此功能,您可以对更复杂的平滑形状进行编码。添加的组件越多,形状的复杂度就越高。边界框缩放是平滑曲线收缩效果的巧妙解决方案。我以前没有想到过这一点。唯一的问题是,您依赖于噪声数据的最大值和最小值……如何保留曲线区域?@克里斯伦戈,你可以使用任何标准……正如我提到的质心更好,使用面积也应该更好,你只需要替换多边形区域的Box计算。@ MasStjChel-THX我用我的GIF捕捉屏幕应用程序(我的纯C++代码没有VCL第三方LIBs)来获取它,使GFX为我的答案更容易。(因为imgur只允许GIF动画)。我将fps设置为1,并通过鼠标滚轮手动应用FIR过滤器来设置动画:)…(我答案中的所有动画都是通过抓取器完成的)我觉得这应该是一个注释,除非您还为OP@HaleemurAli据我所知,答案不要求完整或包含代码——有时只需要有经验的人的洞察力。有时一个人知道一半的答案,而另一个人可以提供答案e另一半,我认为如果它不允许部分/不完整或c,那么它将是一个更贫穷的地方