如何用Python+OpenCV定位图像中书本的中心?代码异常求解
解决书本轮廓质心定位错误的问题
问题根源
- 错误选择轮廓:直接取
contours[0]大概率不是书本的轮廓,而是图像中面积更小的噪声轮廓,导致质心计算完全偏离。 - 手动计算质心不严谨:手动累加轮廓点坐标再取平均的方式,不仅效率低,还容易因轮廓点分布问题出现误差,且未处理除以0的边界情况。
修正方案
1. 筛选正确的书本轮廓
通过轮廓面积排序,取面积最大的轮廓,这才是我们需要的书本主体:
# 按轮廓面积从大到小排序,取第一个(最大的轮廓) contours = sorted(contours, key=cv2.contourArea, reverse=True) book_contour = contours[0]
2. 使用OpenCV矩函数计算质心
利用cv2.moments()计算轮廓的矩,通过矩的数学公式推导质心,精度更高且更可靠:
M = cv2.moments(book_contour) # 避免除以0的异常情况 if M["m00"] != 0: cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) else: cX, cY = 0, 0
3. 优化预处理(可选)
添加高斯模糊减少噪声,配合RETR_EXTERNAL提取最外层轮廓,进一步提升轮廓质量:
# 高斯模糊降噪 blurred = cv2.GaussianBlur(imgray, (5, 5), 0) # 二值化 ret, thresh = cv2.threshold(blurred, 127, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) # 只提取最外层轮廓 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
完整修正代码
import cv2 import numpy as np image = cv2.imread("29289.jpg") imgray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 预处理:模糊降噪+二值化 blurred = cv2.GaussianBlur(imgray, (5, 5), 0) ret, thresh = cv2.threshold(blurred, 127, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) # 提取最外层轮廓并按面积排序 contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contours = sorted(contours, key=cv2.contourArea, reverse=True) book_contour = contours[0] # 绘制书本轮廓 cv2.drawContours(image, [book_contour], -1, (0, 255, 0), 2) # 计算并绘制质心 M = cv2.moments(book_contour) if M["m00"] != 0: cX = int(M["m10"] / M["m00"]) cY = int(M["m01"] / M["m00"]) else: cX, cY = 0, 0 cv2.circle(image, (cX, cY), 5, (0, 0, 255), -1) # 显示结果 cv2.namedWindow("Result", cv2.WINDOW_NORMAL) cv2.imshow("Result", image) cv2.waitKey(0) cv2.destroyAllWindows()
关键细节说明
cv2.RETR_EXTERNAL:仅提取最外层轮廓,避免书本内部的文字、图案等小轮廓干扰。cv2.CHAIN_APPROX_SIMPLE:压缩轮廓点数量(比如把矩形的四个点保留,去掉中间冗余点),减少计算量且不影响质心精度。- 面积排序:确保我们选中的是图像中最大的物体(书本),而非噪声或其他小物体。
内容的提问来源于stack exchange,提问作者vojtam
相关产品推荐
相关产品推荐

