我有如下所示的图像(图 1),我想将两个椭圆拟合到内部和外部形状。
编辑
根据 fmw42 的建议创建新代码
if img is None:
print("Failed to load the image")
exit()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
masked = cv2.inRange(gray,100,255)
ksize= 15
blurred = cv2.medianBlur(masked,ksize = ksize)
ret,thresh = cv2.threshold(blurred,100,255,cv2.THRESH_BINARY)
def detect_ellipses(img, contours):
ellipses = []
for contour in contours:
relevant_points = np.reshape(contour, (contour.shape[0], 2))
try:
ellipse = cv2.fitEllipse(relevant_points)
print(ellipse)
ellipses.append(ellipse)
except:
pass
return ellipses
# # Apply edge detection to the grayscale image with adjusted parameters
edges = cv2.Canny(thresh, 100, 255)
plt.figure()
plt.imshow(edges)
plt.show()
# # # Find the contours in the edge map
contours, hierarchy = cv2.findContours(
edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
应用 Canny 和拟合后的结果|| |我仍然遇到最终结果中不需要的轮廓的问题。不幸的是,我无法真正过滤掉它们,因为有些形状与所需的形状太接近。
我一直在使用 OpenCV,并且能够始终拟合内部椭圆。由于我无法完全消除噪音,外部一直很棘手,这会导致不理想的配件(图 2)。目前,我可以通过反复试验来拟合单个图像,但并不理想。
if img is None:
print("Failed to load the image")
exit()
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
kernel = np.ones((5,5),np.uint8)
gray = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel)
ret,thresh = cv2.threshold(gray,65,255,cv2.THRESH_BINARY)
ksize = 15
med= cv2.medianBlur(thresh, ksize = ksize)
def detect_ellipses(img, contours):
ellipses = []
for contour in contours:
relevant_points = np.reshape(contour, (contour.shape[0], 2))
try:
ellipse = cv2.fitEllipse(relevant_points)
#print(ellipse)
ellipses.append(ellipse)
except:
pass
return ellipses
# # Apply edge detection to the grayscale image with adjusted parameters
edges = cv2.Canny(med, 65, 255)
# # # Find the contours in the edge map
contours, hierarchy = cv2.findContours(
edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# plt.figure('outer')
# plt.imshow(contours)
# plt.show()
# # # Detect ellipses from the contours
ellipses = detect_ellipses(img, contours)
# # Draw the ellipses on the original image
for ellipse in ellipses:
try:
cv2.ellipse(img, ellipse, (0, 255, 0), 2)
print(ellipse)
except:
pass
# #Show the original image with the fitted ellipses
cv2.imshow('Ellipse Detection', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
I have been using OpenCV and am able to consistently fit the inner ellipse. The outer has been tricky due to the noises that I have not been able to remove completely, which cause undesired fittings (Figure 2). Currently, I am able to fit individual images through trial and error, but not ideal.
以下是使用 Python 和 OpenCV 检测图像中两个椭圆(内椭圆和外椭圆)的分步过程。该代码侧重于通过图像处理技术减少不需要的轮廓,从而实现更稳健的椭圆拟合:
1. 加载图像并预处理:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像
img = cv2.imread('image.png')
if img is None:
print("无法加载图像")
exit()
# 将图像转换为灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 应用中值滤波器以减少噪声
gray = cv2.medianBlur(gray, 5)
2. 创建二值图像:
# 通过自适应阈值处理创建清晰的边缘图
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV, 11, 2)
3. 检测和过滤轮廓:
# 查找轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 按区域过滤轮廓,保留较大的轮廓
min_area = 1000 # 根据需要调整此值
filtered_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > min_area]
4. 拟合椭圆:
# 对过滤后的轮廓拟合椭圆
ellipses = []
for cnt in filtered_contours:
if len(cnt) >= 5: # 确保至少有 5 个点进行椭圆拟合
ellipse = cv2.fitEllipse(cnt)
ellipses.append(ellipse)
5. 绘制结果:
# 在原始图像上绘制椭圆
result_image = img.copy()
for ellipse in ellipses:
cv2.ellipse(result_image, ellipse, (0, 255, 0), 2)
# 显示结果
cv2.imshow("检测到的椭圆", result_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
说明:
- 中值滤波器 有助于减少噪声,同时保留边缘。
- 自适应阈值处理 可以为具有不同照明条件的图像创建更稳健的二值图像。
- 按区域过滤轮廓 有助于消除与的目标椭圆不对应的微小噪声或不必要的细节。
-
函数
cv2.fitEllipse()
需要至少 5 个点 才能拟合椭圆。检查每个轮廓的点数可以防止运行时错误。
调整:
-
根据的图像以及噪声级别和椭圆尺寸,可能需要调整
medianBlur
中的内核大小和adaptiveThreshold
中的参数。 -
min_area
参数控制要过滤掉的轮廓的大小。根据椭圆的大小进行实验以找到合适的值。
通过仔细微调这些参数,可以提高椭圆检测算法的准确性。
标签:python,opencv,matplotlib,image-processing From: 78780193