opencv 卡尺法 测量边缘距离

opencv 卡尺法 测量边缘距离

参考来源 :https://github.com/crackwitz/metrology-demo



前言

halcon中有按照直线找边缘测量距离的工具,但是opencv中没有类似的工具可以直接实现该测量方式,参考网上的实现方式,可以实现。


测量的效果贴图
在这里插入图片描述

一、测量方法

根据测量线的两个端点,获取直线的像素,然后进行滤波过滤噪点,计算跳变幅度,获取最大最小值的位置,计算距离

二、测量步骤

1.获取直线的像素

将直线的通过仿射变换转成1D的图像,可以采用亚像素的算法,先获取仿射变换的矩阵

代码如下(示例):

def build_transform(p0, p1, stride=None, nsamples=None):
	"builds an affine transform with x+ along defined line"
	# use one of stride (in pixels) or nsamples (absolute value)
	(x0, y0) = p0
	(x1, y1) = p1
	dx = x1 - x0
	dy = y1 - y0
	length = np.hypot(dx, dy)
	if nsamples is not None:
		#stride = length / nsamples
		factor = 1 / nsamples
	else:
		if stride is None:
			stride = 1.0
		factor = stride / length
		nsamples = int(round(length / stride))
	# map: src <- dst (use WARP_INVERSE_MAP flag for warpAffine)
	H = np.eye(3, dtype=np.float64) # homography
	H[0:2, 0] = (dx, dy) # x unit vector
	H[0:2, 1] = (-dy, dx) # y unit vector is x rotated by 90 degrees
	x=H[0:2, 0:2]
	H[0:2, 0:2] *= factor
	H[0:2, 2] = (x0, y0) # translate onto starting point
	# take affine part of homography
	assert np.isclose(a=H[2], b=(0,0,1)).all() # we didn't touch those but let's better check
	A = H[0:2, :]
	return (nsamples, A)

然后再采用变换的方法获取图像的像素值

def sample_opencv(im, M, nsamples):
	# use transform to get samples
	# available: INTER_{NEAREST,LINEAR,AREA,CUBIC,LANCOS4)
	samples = cv.warpAffine(im, M=M, dsize=(nsamples, 1), flags=cv.WARP_INVERSE_MAP | cv.INTER_CUBIC )
	# flatten row vector
	samples.shape = (-1,)
	# INTER_CUBIC seems to break down beyond 1/32 sampling (discretizes).
	# there might be fixed point algorithms at work
	return samples

2.高斯滤波平滑曲线

samples = scipy.ndimage.gaussian_filter1d(samples, sigma=args.sigma / args.stride)

3.计算跳变幅度值

# off-by-half in position because for values [0,1,1,0] this returns [+1,0,-1]
gradient = np.diff(samples) / args.stride

4.计算距离值

	i_falling = np.argmin(gradient) # in samples
	i_rising = np.argmax(gradient) # in samples
	distance = np.abs(i_rising - i_falling) * args.stride # in pixels

5.显示和保存图片

	if args.display or args.saveplot:
		gradient *= 255 / np.abs(gradient).max()
		# plot signal
		plot = cv.plot.Plot2d_create(np.arange(nsamples, dtype=np.float64), samples.astype(np.float64))
		plot.setMinY(256+32)
		plot.setMaxY(-32)
		plot.setMinX(0)
		plot.setMaxX(nsamples)
		plot.setGridLinesNumber(5)
		plot.setShowText(False) # callout for specific point, setPointIdxToPrint(index)
		plot.setPlotGridColor((64,)*3)
		canvas1 = plot.render()
		# plot gradient
		plot = cv.plot.Plot2d_create(np.arange(nsamples-1) + 0.5, gradient.astype(np.float64))
		plot.setMinY(256+64)
		plot.setMaxY(-256-64)
		plot.setMinX(0)
		plot.setMaxX(nsamples)
		plot.setGridLinesNumber(5)
		plot.setShowText(False) # callout for specific point, setPointIdxToPrint(index)
		plot.setPlotGridColor((64,)*3)
		canvas2 = plot.render()
		# arrange vertically
		canvas = np.vstack([canvas1, canvas2]) # 600 wide, 800 tall
		# draw lines at edges (largest gradients)
		# plots are 600x400 pixels... and there's no way to plot multiple or plot lines in "plot space"
		px_falling = int(600 * (i_falling+0.5) / nsamples)
		px_rising = int(600 * (i_rising+0.5) / nsamples)
		cv.line(canvas, (px_falling, 0), (px_falling, 400*2), color=(255,0,0))
		cv.line(canvas, (px_rising, 0), (px_rising, 400*2), color=(255,0,0))
		# some text to describe the picture
		cv.putText(canvas, f"{nsamples*args.stride:.0f} px, {p0} -> {p1}",
			(10, 350), cv.FONT_HERSHEY_SIMPLEX, 0.75, (255,255,255), thickness=1, lineType=cv.LINE_AA)
		cv.putText(canvas, f"stride {args.stride} px, {nsamples} samples, sigma {args.sigma}",
			(10, 350+35), cv.FONT_HERSHEY_SIMPLEX, 0.75, (255,255,255), thickness=1, lineType=cv.LINE_AA)
		cv.putText(canvas, f"distance: {distance:.{stride_decimals}f} px",
			(10, 350+70), cv.FONT_HERSHEY_SIMPLEX, 0.75, (255,255,255), thickness=1, lineType=cv.LINE_AA)
		# save for posterity
		if args.saveplot:
			cv.imwrite(args.saveplot, canvas)
		if args.display:
			cv.imshow("plot", canvas)
			cv.line(im_disp,p0,p1,(0,255,0),3)
			# cv.imshow("src", im_disp)
			cv.imwrite('result.jpg',im_disp)
			if args.verbose:
				print("press Ctrl+C in the terminal, or press any key while the imshow() window is focused")
			while True:
				keycode = cv.waitKey(100)
				if keycode == -1:
					continue
				# some key...
				if args.verbose:
					print(f"keycode: {keycode}")
				cv.destroyAllWindows()
				break

总结

提示:显示的程序包含了opencv pilo,这个需要引入opencv-contrib-python模块:

  • 3
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV是一个流行的计算机视觉库,它提供了用于图像处理和计算机视觉任务的各种功能和算。要测量物体的偏移量,可以使用以下步骤: 1. 图像预处理:从摄像机获取图像后,首先需要对图像进行预处理,以便提高后续处理的精度和效果。预处理步骤可以包括图像去噪、图像增强、图像平滑等。 2. 物体检测和跟踪:使用物体检测算(如Haar分类器、HOG+SVM分类器或深度学习模型)来检测图像中的物体。一旦物体被检测到,就可以使用物体跟踪算(如卡尔曼滤波器、基于Kalman滤波的MeanShift算等)跟踪物体的运动。 3. 物体偏移计算:一旦物体被跟踪,可以使用相邻图像帧之间的物体位置信息来计算物体的偏移量。这可以通过计算物体在图像中的中心坐标的差异来实现。实际上,可以根据应用需求计算物体在水平方向和垂直方向上的偏移量。 4. 偏移量分析和应用:计算得到的偏移量可以用来分析物体的运动趋势和速度,也可以用于控制其他设备或系统。例如,偏移量可以用于机器人导航,自动驾驶车辆的跟踪和避障等。 总结来说,通过在OpenCV中使用物体检测和跟踪算,以及计算图像帧之间物体位置信息的差异,就可以实现物体偏移的测量。这种算对于各种应用领域,如计算机视觉、自动化和机器人等都有广泛的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值