使用Python,OpenCV检测摄像机到标记对象的距离


这篇博客将介绍如何确定图像中已知物体到相机的距离, 确定从相机到标记物体的距离是计算机视觉/图像处理领域中一个非常好的研究课题。有俩种实现方式:

  1. 使用非常简单明了的技术——三角形相似性;
  2. 使用相机模型的固有参数,虽然复杂但更准确;

本文将介绍第一种方法。

1. 效果图

测距效果图1
在这里插入图片描述
边缘检测图
在这里插入图片描述测距效果图2
在这里插入图片描述
效果图3:
在这里插入图片描述

2. 三角形相似性是什么?

三角形相似性是假设我们有一个标记或对象,宽度称为W 。然后,我们将此标记放置在距相机一定距离D处。我们使用相机拍摄物体的图片,然后以像素P为单位测量其宽度。这使我们能够得出摄像机的可感知焦距F:

F =(P x D)/ W

当继续将相机移近或远离物体/标记时,可以应用三角形相似度来确定物体到相机的距离:

D’=(宽x F)/ P

3. 三角形相似性检测距离原理

原理是参照物

利用三角形相似度,需要在应用算法之前了解两个重要参数:

  1. 用作标记的对象在某种距离度量(例如英寸或米)中的宽度(或高度)。
  2. 相机摄像头到标记对象的距离(以英寸或米为单位)。
  3. 使用计算机视觉和图像处理算法来自动确定对象的感知宽度/高度(以像素为单位),并完成三角形相似度并为我们提供焦距。
  4. 在后续图像中,找到其余的标记/对象​​并利用计算出的焦距来确定距相机到对象的距离。

4. 使用Python,OpenCV检测标记对象

  1. 转换灰度图
  2. 高斯模糊消除高频噪音
  3. 寻找边缘
  4. 检测轮廓,根据原始图像的特征保留相应的标记

在图像中找到标记的其他替代方法是利用颜色,假使标记的颜色与图像中其余场景的颜色不同。您还可以应用诸如关键点检测,局部不变描述符和关键点匹配之类的方法来查找标记。

5. 源码

# 使用Pthon,OpenCV检测标记对象到摄像头的距离
# USAGE
# python distance_to_camera.py


# 导入必要的包
from imutils import paths
import numpy as np
import imutils
import cv2


# 函数接受单个参数,image:源输入图像
# 查找我们要计算距离的对象
def find_marker(image):
	# 转换为灰度图,高斯模糊,检测边缘
	# 高斯模糊以消除高频噪声
	gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
	gray = cv2.GaussianBlur(gray, (5, 5), 0)
	edged = cv2.Canny(gray, 35, 125)

	# 从边缘图像中检测轮廓,并保留最大的轮廓
	# 假设最大轮廓是我们的纸
	cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
	cnts = imutils.grab_contours(cnts)
	c = max(cnts, key = cv2.contourArea)

	# 返回纸区域的最小面积轮廓
	return cv2.minAreaRect(c)


# 使用三角形相似度计算距离
# knownWidth 已知宽度
# focalLength 标记宽度
# perWidth 感知宽度
def distance_to_camera(knownWidth, focalLength, perWidth):
	# 计算并返回到摄像机的距离
	return (knownWidth * focalLength) / perWidth

# 找到与图像中的对象或标记的距离的第一步是校准和计算焦距。为此,我们需要知道:
# 初始化已知物体到摄像头的距离
KNOWN_DISTANCE = 24.0

# 初始化已知物体的宽度
KNOWN_WIDTH = 11.0

# 进行简单的校准
# 加载图像,寻找到纸的轮廓,计算感知焦距
image = cv2.imread("images/2ft.png")
marker = find_marker(image)
focalLength = (marker[1][0] * KNOWN_DISTANCE) / KNOWN_WIDTH

# 有了感知焦距,可以很容易地计算出相机到后续图像中标记的距离。
# 遍历图像
for imagePath in sorted(paths.list_images("images")):
	# 加载图像,寻找图像中的标记,计算标记到摄像头的距离
	image = cv2.imread(imagePath)
	marker = find_marker(image)
	inches = distance_to_camera(KNOWN_WIDTH, focalLength, marker[1][0])

	# 绘制边界框并展示在图像上,同时显示距离
	box = cv2.cv.BoxPoints(marker) if imutils.is_cv2() else cv2.boxPoints(marker)
	box = np.int0(box)
	cv2.drawContours(image, [box], -1, (0, 255, 0), 2)
	cv2.putText(image, "%.2fft" % (inches / 12),
		(image.shape[1] - 200, image.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX,
		2.0, (0, 255, 0), 3)
	cv2.imshow("image", image)
	cv2.waitKey(0)

参考

猜你喜欢

转载自blog.csdn.net/qq_40985985/article/details/112225289