OpenCV:适合检测到的边缘
OpenCV: fit the detected edges
我使用 Canny 边缘检测来检测水波的边缘。但是,我想为这条边拟合一条曲线。这在 OpenCV 中可能吗?
这是边缘检测之前的图像:
这是边缘检测操作的结果:
代码复制自 OpenCV 教程中的示例:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('BW.JPG',0)
edges = cv2.Canny(img,100,200)
plt.plot(1),plt.imshow(edges,cmap = 'gray')
plt.title('WAVE')
plt.show()
波非常简单,因此我们将多项式曲线拟合到由 cv2
的输出定义的主边缘。首先,我们要获得 of 那个主边的点。假设您的原点与图像上的一样,位于左上角。查看原始图像,我认为如果我们只取 (750, 1500) 范围内最大 y
的点,我们将对我们的兴趣点有一个很好的近似。
import cv2
import numpy as np
from matplotlib import pyplot as plt
from numba import jit
# Show plot
img = cv2.imread('wave.jpg',0)
edges = cv2.Canny(img,100,200)
#
# Get index of matching value.
@jit(nopython=True)
def find_first(item, vec):
"""return the index of the first occurence of item in vec"""
for i in range(len(vec)):
if item == vec[i]:
return i
return -1
bounds = [750, 1500]
# Now the points we want are the lowest-index 255 in each row
window = edges[bounds[1]:bounds[0]:-1].transpose()
xy = []
for i in range(len(window)):
col = window[i]
j = find_first(255, col)
if j != -1:
xy.extend((i, j))
# Reshape into [[x1, y1],...]
data = np.array(xy).reshape((-1, 2))
# Translate points back to original positions.
data[:, 1] = bounds[1] - data[:, 1]
如果我们绘制这些点,我们可以看到它们非常接近我们的目标。
plt.figure(1, figsize=(8, 16))
ax1 = plt.subplot(211)
ax1.imshow(edges,cmap = 'gray')
ax2 = plt.subplot(212)
ax2.axis([0, edges.shape[1], edges.shape[0], 0])
ax2.plot(data[:,1])
plt.show()
现在我们已经有了一个坐标对数组,我们可以使用 numpy.polyfit
to generate the coefficients for a best-fit polynomial, and numpy.poly1d
从这些系数生成函数。
xdata = data[:,0]
ydata = data[:,1]
z = np.polyfit(xdata, ydata, 5)
f = np.poly1d(z)
然后绘图验证
t = np.arange(0, edges.shape[1], 1)
plt.figure(2, figsize=(8, 16))
ax1 = plt.subplot(211)
ax1.imshow(edges,cmap = 'gray')
ax2 = plt.subplot(212)
ax2.axis([0, edges.shape[1], edges.shape[0], 0])
ax2.plot(t, f(t))
plt.show()
我使用 Canny 边缘检测来检测水波的边缘。但是,我想为这条边拟合一条曲线。这在 OpenCV 中可能吗?
这是边缘检测之前的图像:
这是边缘检测操作的结果:
代码复制自 OpenCV 教程中的示例:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('BW.JPG',0)
edges = cv2.Canny(img,100,200)
plt.plot(1),plt.imshow(edges,cmap = 'gray')
plt.title('WAVE')
plt.show()
波非常简单,因此我们将多项式曲线拟合到由 cv2
的输出定义的主边缘。首先,我们要获得 of 那个主边的点。假设您的原点与图像上的一样,位于左上角。查看原始图像,我认为如果我们只取 (750, 1500) 范围内最大 y
的点,我们将对我们的兴趣点有一个很好的近似。
import cv2
import numpy as np
from matplotlib import pyplot as plt
from numba import jit
# Show plot
img = cv2.imread('wave.jpg',0)
edges = cv2.Canny(img,100,200)
#
# Get index of matching value.
@jit(nopython=True)
def find_first(item, vec):
"""return the index of the first occurence of item in vec"""
for i in range(len(vec)):
if item == vec[i]:
return i
return -1
bounds = [750, 1500]
# Now the points we want are the lowest-index 255 in each row
window = edges[bounds[1]:bounds[0]:-1].transpose()
xy = []
for i in range(len(window)):
col = window[i]
j = find_first(255, col)
if j != -1:
xy.extend((i, j))
# Reshape into [[x1, y1],...]
data = np.array(xy).reshape((-1, 2))
# Translate points back to original positions.
data[:, 1] = bounds[1] - data[:, 1]
如果我们绘制这些点,我们可以看到它们非常接近我们的目标。
plt.figure(1, figsize=(8, 16))
ax1 = plt.subplot(211)
ax1.imshow(edges,cmap = 'gray')
ax2 = plt.subplot(212)
ax2.axis([0, edges.shape[1], edges.shape[0], 0])
ax2.plot(data[:,1])
plt.show()
现在我们已经有了一个坐标对数组,我们可以使用 numpy.polyfit
to generate the coefficients for a best-fit polynomial, and numpy.poly1d
从这些系数生成函数。
xdata = data[:,0]
ydata = data[:,1]
z = np.polyfit(xdata, ydata, 5)
f = np.poly1d(z)
然后绘图验证
t = np.arange(0, edges.shape[1], 1)
plt.figure(2, figsize=(8, 16))
ax1 = plt.subplot(211)
ax1.imshow(edges,cmap = 'gray')
ax2 = plt.subplot(212)
ax2.axis([0, edges.shape[1], edges.shape[0], 0])
ax2.plot(t, f(t))
plt.show()