用opencv python写一个对一个灰度图像的牛顿环进行椭圆拟合的代码
时间: 2023-06-03 08:06:09 浏览: 149
好的,请稍等一下,我会提供相应的代码。以下是代码:
```
import cv2
import numpy as np
def newton_raphson(f, df, x, eps=1e-5, max_iter=100):
for i in range(max_iter):
delta_x = -f(x) / df(x)
x += delta_x
if abs(delta_x) < eps:
break
return x
def fit_ellipse_newton(image):
contours, _ = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
def error(a, b):
return np.sum(((np.matmul(a, b.T) - 1) ** 2))
def jacobian(a, b):
a_b = np.matmul(a, b.T)
j = np.zeros((6,))
j[0] = 2 * (a_b[0, 0] * b[0, 0] + a_b[0, 1] * b[0, 1] + a_b[1, 0] * b[1, 0] + a_b[1, 1] * b[1, 1])
j[1] = 2 * (a_b[0, 0] * b[0, 1] - a_b[0, 1] * b[0, 0])
j[2] = 2 * (a_b[1, 0] * b[1, 1] - a_b[1, 1] * b[1, 0])
j[3] = 2 * (a_b[0, 0] * a[0, 0] + a_b[0, 1] * a[1, 0])
j[4] = 2 * (a_b[0, 0] * a[0, 1] + a_b[0, 1] * a[1, 1])
j[5] = 2 * (a_b[1, 0] * a[1, 1] + a_b[1, 1] * a[0, 1])
return j
best_a, best_b = None, None
best_err = float('inf')
for cnt in contours:
if cnt.shape[0] < 5:
continue
cnt = cnt[:, 0, :]
x, y = cnt[:, 0], cnt[:, 1]
xy = np.vstack((x * x, x * y, y * y, x, y)).T
a = np.ones((len(cnt), 6))
a[:, :3] = xy
_, s, vh = np.linalg.svd(a, full_matrices=False)
lsq_b = np.matmul(vh.T, np.matmul(np.diag(s ** -1), np.matmul(a.T, np.ones((len(cnt),))))).flatten()
b = np.array([[lsq_b[0], lsq_b[1]], [lsq_b[1], lsq_b[2]]])
a = np.array([[lsq_b[3], lsq_b[4]], [lsq_b[4], lsq_b[5]]])
center, eigen_values, eigen_vectors = cv2.eigen(b)
if eigen_values[0] < 1e-5 or eigen_values[1] < 1e-5 or any(np.isnan(center)):
continue
a = np.matmul(np.linalg.inv(eigen_vectors), a)
a = np.matmul(a, eigen_vectors)
b = np.eye(2)
b[0, 0] = eigen_values[0] ** 0.5
b[1, 1] = eigen_values[1] ** 0.5
def f(x):
return error(np.matmul(a + x[0] * b, (a + x[0] * b).T), b)
def df(x):
return jacobian(a + x[0] * b, np.linalg.inv(b))
x0 = np.zeros((1,))
res = newton_raphson(f, df, x0)
b = a + res[0] * b
center = np.matmul(eigen_vectors, center)
err = error(a, b)
if err < best_err:
best_err = err
best_a, best_b = a, b
return cv2.Ellipse2D(center, best_b[0, 0], best_b[1, 1], np.arctan2(eigen_vectors[1, 0], eigen_vectors[0, 0]), cv2.ellipse2Poly(center, (int(best_b[0, 0]), int(best_b[1, 1])), int(np.arctan2(eigen_vectors[1, 0], eigen_vectors[0, 0]))))
# Load the image
img = cv2.imread('newtons_rings.jpg', cv2.IMREAD_GRAYSCALE)
# Perform binary thresholding
_, thresh = cv2.threshold(img, 50, 255, cv2.THRESH_BINARY_INV)
# Fit an ellipse to the thresholded image
ellipse = fit_ellipse_newton(thresh)
# Draw the ellipse on the original image
img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
cv2.ellipse(img, ellipse.center, (int(ellipse.major_axis), int(ellipse.minor_axis)), ellipse.angle, 0, 360, (0, 255, 0), thickness=2)
# Show the result
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
请注意,这只是一个示例代码,假设您已经拥有了一个新ton环的图像。实际应用中,您需要根据您的数据进行修改。
阅读全文