首先级数的概念简单理解一下,就下面的公式:
5.247382 = 5 + 0.2 + 0.04 + 0.007 + 0.0003 + 0.00008 + 0.000002
想得到左边这个数,我每一次拿一部分去累加,越往后这一部分越小。生活中其实也有很多这样的例子,比如打高尔夫,先大力挥杆(5),然后再不断地用更小的力气去使球逐渐接近洞(0.2, 0.04, 0.007…)。
傅里叶描述器,就是类似这种方式,通过傅里叶级数逼近的方式,去近似得到图像轮廓的表示。
关键的输入是contours,图像轮廓,可以通过opencv的函数实现。
im = cv.cvtColor(input_imgs, cv.COLOR_BGR2GRAY)
_, thresh = cv.threshold(im, 254, 255, cv.THRESH_BINARY) #get binary
contours, hierarchy = cv.findContours(thresh,cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE )
图像轮廓的获取方式如上述代码,一般是先转灰度,再获取binary,再送到findContours函数中。
返回的contours一般是一个四维的向量,分别表示【轮廓个数,该轮廓的轮廓点个数,1, 坐标x和y】。
对于每一个轮廓,可以使用傅里叶描述器。
#!pip install pyefd
from pyefd import elliptic_fourier_descriptors, plot_efd, normalize_efd, reconstruct_contour
coeffs = []
for j in contours:
coeffs.append(elliptic_fourier_descriptors(np.squeeze(j, axis=1), order=10, normalize=True))
每一个轮廓的维度是【长度,1,2】,而elliptic_fourier_descriptors只能处理【长度,2】这样的数据,所以用np.squeeze()。
想要查看学到的轮廓,可以用plot_pyefd
plot_efd(coeffs[0])
order的含义是级数到达第几个order,比如我文章最开始那个公式就是用7个项得到了等号左边的数,那他的order就是7。当画图的时候,他代表图像个数,也是coeffs[0]的长度,而其对应宽度永远是4(大概是用四个点画曲线)。
上面这张图跟我写的5.247382 = 5 + 0.2 + 0.04 + 0.007 + 0.0003 + 0.00008 + 0.000002就是同一个意思,随着我不断累加,等号左右两边的数会越来越接近。所以当你画图时,左上角第一个order永远是个圆,而随着项数增多,曲线会越来越接近原图像。
如果想要重建轮廓点:
points = reconstruct_contour(coeffs)