opencv-python 中直线拟合函数cv.fitLine()的2D直线拟合(适合小白观看)

在提取指静脉的过程中,我们需要提取有用的ROI区域。而这时候,我们会采取将手指两边中点拟合成一条直线,求得这个直线的直线方程,然后得到旋转的角度,以便对原来的图像进行旋转操作。当我们知道如何取得手指的边缘中点后,直接用fitLine函数可以方便的按我们想要的方式得到期望 的直线。

首先是官方文档上的函数原型:

 然后我会通过实例来解释每一个参数的意义,代码十分简单:

import cv2 as cv
import numpy as np

test =[(1,2),(2,4),(3,6)]
nptest=np.array(test)
line =cv.fitLine(nptest,cv.DIST_L2,0,0.01,0.01)

 这里的line就是我们的结果了

line的形式是[[cos  a],[sin a],[point_x],[point_y]],前面两项是有关直线与Y正半轴(这里指的是屏幕坐标系)夹角a的三角函数,后面两项就是所得拟合直线上的一点的横纵坐标。我们知道一个直线的倾斜角度和它经过的一个点后就可以唯一确定一条直线。

参数列表解释:

常用的骨架快速提取算法有多种,其中一种是基于中轴线的细化算法,可以用Python实现。 1. 首先,将二值化的图像进行细化(或称为骨架化),得到中轴线。 2. 对中轴线进行拓扑分析,找到所有端点和交叉点。 3. 从任意一个端点出发,沿着中轴线向交叉点方向搜索,直到找到另一个端点为止。这一过程中,记录下搜索路径上的所有交叉点和端点,这些点就是骨架的分支点。 4. 对于每个分支点,将其周围的中轴线分成若干条子骨架,这些子骨架之间没有交叉点或端点,每个子骨架的起点是该分支点,终点是其周围的交叉点或端点。 5. 对于每个子骨架,用最小二乘法拟合一条直线,得到该子骨架的方向和长度。将所有子骨架的方向和长度记录下来,得到整个骨架的形状。 以下是一个基于OpenCVPython代码示例,实现了基于中轴线的骨架快速提取算法: ```python import cv2 import numpy as np # 读入二值化图像 img = cv2.imread("binary_image.png", cv2.IMREAD_GRAYSCALE) # 细化图像,得到中轴线 skel = cv2.ximgproc.thinning(img) # 找到所有端点和交叉点 keypoints = cv2.xfeatures2d.StarDetector_create().detect(skel) # 遍历所有端点,提取骨架 skeleton = [] for kp in keypoints: if kp.response < 100: # 筛选出较长的端点 continue path = [kp.pt] # 记录搜索路径 while True: neighbors = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3)) neighbors[1, 1] = 0 neighbor_kps = [kp for kp in cv2.KeyPoint_convert(cv2.KeyPointsFilter.filter(keypoints, neighbors))] if len(neighbor_kps) == 1: # 到达另一个端点 path.append(neighbor_kps[0]) break elif len(neighbor_kps) == 2: # 继续搜索 path.append(neighbor_kps[0]) path.append(neighbor_kps[1]) skel[int(path[-1][1]), int(path[-1][0])] = 0 # 避免重复搜索 kp = neighbor_kps[1] # 选取下一个邻居 else: # 遇到分叉点或环 break if len(path) > 2: # 筛选出较长的骨架 skeleton.append(path) # 提取骨架方向和长度 shapes = [] for path in skeleton: coords = np.array(path, np.float32) direction = cv2.fitLine(coords, cv2.DIST_L2, 0, 0.01, 0.01) length = np.linalg.norm(coords[-1] - coords[0]) shapes.append((direction, length)) # 显示骨架 display_img = cv2.cvtColor(skel, cv2.COLOR_GRAY2BGR) for shape in shapes: pt1 = tuple(np.round(shape[0][:2] - shape[0][2:] * shape[1]).astype(int)) pt2 = tuple(np.round(shape[0][:2] + shape[0][2:] * shape[1]).astype(int)) cv2.line(display_img, pt1, pt2, (0, 0, 255), 2) cv2.imshow("skeleton", display_img) cv2.waitKey() ``` 其中,使用了OpenCV的细化函数(`cv2.ximgproc.thinning`)和拟合直线函数(`cv2.fitLine`),以及Star特征检测器(`cv2.xfeatures2d.StarDetector_create`)。通过遍历所有端点,沿着中轴线搜索骨架并拟合直线,最终得到了骨架的形状。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值