一、实验原理
- 灰度转换:将彩色图像转换为灰度图像,减少计算复杂度。
- 高斯平滑:使用高斯模糊来减少图像噪声。
- canny边缘检测:检测图像中的边缘。
- 轮廓查找:使用opencv的findcontours函数检测图像中的轮廓。
- 绘制轮廓和标记:在原始图像上绘制检测到的轮廓,并标记每个轮廓的序号。
二、实验步骤
1. 图像读取与预处理
import cv2
import matplotlib.pyplot as plt
# 读取图像
image = cv2.imread('soybean.jpg')
# 转换为灰度图像
gray = cv2.cvtcolor(image, cv2.color_bgr2gray)
# 平滑处理
blurred = cv2.gaussianblur(gray, (11, 11), 0)
soybean.jpg 图片如下所示,可自取:

2. 边缘检测
- cv2.canny(blurred, 30, 150):使用canny算法进行边缘检测,参数30和150分别是低阈值和高阈值。
# 使用canny边缘检测
edges = cv2.canny(blurred, 30, 150)
3. 轮廓检测
- cv2.findcontours(edges.copy(), cv2.retr_external, cv2.chain_approx_simple):查找图像中的轮廓。retr_external表示只检测外部轮廓,chain_approx_simple表示使用简单的链式近似方法。
# 查找轮廓
contours, _ = cv2.findcontours(edges.copy(), cv2.retr_external, cv2.chain_approx_simple)
4. 标记轮廓序号
- cv2.boundingrect(contour):计算轮廓的边界框,用于确定标注位置。
- cv2.drawcontours(image, [contour], -1, (0, 255, 0), 2):绘制轮廓,绿色线条,线宽为2像素。
- cv2.puttext(image, str(i + 1), (x + w // 2, y + h // 2), cv2.font_hershey_simplex, 0.5, (255, 0, 0), 2):在每个轮廓的中心位置标注序号,红色字体,字体大小为0.5,线宽为2像素。
# 绘制轮廓并标记序号
for i, contour in enumerate(contours):
# 计算轮廓的边界框,用于确定标注位置
x, y, w, h = cv2.boundingrect(contour)
# 绘制轮廓
cv2.drawcontours(image, [contour], -1, (0, 255, 0), 2)
# 在轮廓内标注序号
cv2.puttext(image, str(i + 1), (x + w // 2, y + h // 2), cv2.font_hershey_simplex, 0.5, (255, 0, 0), 2)
三、实验结果
- plt.figure(figsize=(10, 10)):创建一个显示窗口,大小为10x10英寸。
- plt.imshow(cv2.cvtcolor(image, cv2.color_bgr2rgb)):将处理后的图像转换为rgb格式并显示。
- plt.axis(‘off’):关闭坐标轴显示。
- plt.show():显示图像。
- print(f"黄豆数量: {len(contours)}"):输出检测到的黄豆数量。
# 显示结果图像
plt.figure(figsize=(10, 10))
plt.imshow(cv2.cvtcolor(image, cv2.color_bgr2rgb))
plt.axis('off')
plt.show()
# 输出黄豆数量
print(f"黄豆数量: {len(contours)}")

实验结果表明:图像中的所有18个黄豆都被成功识别和标记,每个黄豆的轮廓被绿色线条清晰绘制,序号标记在轮廓中心位置附近。
四、完整代码
import cv2
import matplotlib.pyplot as plt
# 读取图像
image = cv2.imread('soybean.jpg')
# 转换为灰度图像
gray = cv2.cvtcolor(image, cv2.color_bgr2gray)
# 平滑处理
blurred = cv2.gaussianblur(gray, (11, 11), 0)
# 使用canny边缘检测
edges = cv2.canny(blurred, 30, 150)
# 查找轮廓
contours, _ = cv2.findcontours(edges.copy(), cv2.retr_external, cv2.chain_approx_simple)
# 绘制轮廓并标记序号
for i, contour in enumerate(contours):
# 计算轮廓的边界框,用于确定标注位置
x, y, w, h = cv2.boundingrect(contour)
# 绘制轮廓
cv2.drawcontours(image, [contour], -1, (0, 255, 0), 2)
# 在轮廓内标注序号
cv2.puttext(image, str(i + 1), (x + w // 2, y + h // 2), cv2.font_hershey_simplex, 0.5, (255, 0, 0), 2)
# 显示结果图像
plt.figure(figsize=(10, 10))
plt.imshow(cv2.cvtcolor(image, cv2.color_bgr2rgb))
plt.axis('off')
plt.show()
# 输出黄豆数量
print(f"黄豆数量: {len(contours)}")
发表评论