56 二值图像分析–直线拟合与极值点寻找
代码
import cv2 as cv
import numpy as np
def canny_demo(image):
t = 80
canny_output = cv.Canny(image, t, t * 2)
return canny_output
src = cv.imread("../images/twolines.png")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)
binary = canny_demo(src)
k = np.ones((3, 3), dtype=np.uint8)
binary = cv.morphologyEx(binary, cv.MORPH_DILATE, k)
cv.imshow("binary", binary)
# 轮廓发现
contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
# 直线拟合与极值点寻找
for c in range(len(contours)):
x, y, w, h = cv.boundingRect(contours[c])
m = max(w, h)
if m < 30:
continue
vx, vy, x0, y0 = cv.fitLine(contours[c], cv.DIST_L1, 0, 0.01, 0.01)
k = vy/vx
b = y0 - k*x0
maxx = 0
maxy = 0
miny = 100000
minx = 0
for pt in contours[c]:
px, py = pt[0]
if maxy < py:
maxy = py
if miny > py:
miny = py
maxx = (maxy - b) / k
minx = (miny - b) / k
cv.line(src, (np.int32(maxx), np.int32(maxy)),
(np.int32(minx), np.int32(miny)), (0, 0, 255), 2, 8, 0)
# 显示
cv.imshow("contours_analysis", src)
cv.waitKey(0)
cv.destroyAllWindows()
实验结果

解释
对轮廓进行分析,除了可以对轮廓进行椭圆或者圆的拟合之外,还可以对轮廓点集进行直线拟合,直线拟合的算法有很多,最常见的就是最小二乘法,对于多约束线性方程,最小二乘可以找好直线方程的两个参数、实现直线拟合,OpenCV中直线拟合正是基于最小二乘法实现的。OpenCV实现直线拟合的API如下:
line = cv.fitLine(points, distType, param, reps, aeps[, line])
points表示待拟合的输入点集合distType表示在拟合时候使用距离计算公式是哪一种,OpenCV支持如下六种方式:DIST_L1= 1DIST_L2= 2DIST_L12= 4DIST_FAIR= 5DIST_WELSCH= 6DIST_HUBER= 7
param对模型拟合距离计算公式需要参数C,5~7distType需要参数Creps与aeps是指对拟合结果的精度要求line在二维拟合时候输出的是vec4f类型的数据,在三维拟合的时候输出是vec6f的vector
所有内容均来源于贾志刚老师的知识星球——OpenCV研习社,本文为个人整理学习,已获得贾老师授权,有兴趣、有能力的可以加入贾老师的知识星球进行深入学习。

本文介绍了一种基于OpenCV的二值图像分析方法,通过Canny边缘检测、轮廓发现及直线拟合,实现了图像中直线的精确识别与极值点定位。此过程涉及最小二乘法原理及OpenCV的fitLine函数应用。
1万+

被折叠的 条评论
为什么被折叠?



