0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

使用Python和OpenCV查找从相机到物体/标记的距离

新机器视觉 来源: 程序员阿德 作者: 程序员阿德 2022-11-29 17:44 次阅读

摄像头测距就是计算照片中的目标物体到相机的距离。可以使用相似三角形(triangle similarity)方法实现,或者使用更复杂但更准确的相机模型的内参来实现这个功能。

使用相似三角形计算物体到相机的距离

假设物体的宽度为 W,将其放到离相机距离为 D 的位置,然后对物体进行拍照。在照片上量出物体的像素宽度 P,于是可以得出计算相机焦距 F 的公式: dceaa3a8-6d8f-11ed-8abf-dac502259ad0.svg

比如我在相机前 24 英寸距离(D=24 inches)的位置横着放了一张 8.5 x 11 英寸(W=11 inches)的纸,拍照后通过图像处理得出照片上纸的像素宽度 P=248 pixels。所以焦距 F 等于:

dd0636cc-6d8f-11ed-8abf-dac502259ad0.svg

此时移动相机离物体更近或者更远,我们可以应用相似三角形得到计算物体到相机的距离的公式: dd1d3886-6d8f-11ed-8abf-dac502259ad0.svg

原理大概就是这样,接下来使用 OpenCV 来实现。

获取目标轮廓

# import the necessary packages
from imutils import paths
import numpy as np
import imutils
import cv2
def find_marker(image):
    # convert the image to grayscale, blur it, and detect edges
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gray = cv2.GaussianBlur(gray, (5, 5), 0)
    edged = cv2.Canny(gray, 35, 125)
    # find the contours in the edged image and keep the largest one;
    # we'll assume that this is our piece of paper in the image
    cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    c = max(cnts, key = cv2.contourArea)
    # compute the bounding box of the of the paper region and return it
    return cv2.minAreaRect(c)

定义一个 find_marker 函数,接收一个参数 iamge,用来找到要计算距离的物体。这里我们用一张 8.5 x 11 英寸的纸作为目标物体。第一个任务是在图片中找到目标物体。

下面这三行是先将图片转换为灰度图,并进行轻微模糊处理以去除高频噪声,然后进行边缘检测

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(gray, 35, 125)

做了这几步后图片看起来是这样的:

dd2de104-6d8f-11ed-8abf-dac502259ad0.png

现在已经可以清晰地看到这张纸的边缘,接下来需要做的是找出这张纸的轮廓。

cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = max(cnts, key = cv2.contourArea)

用 cv2.findContours 函数找到图片中的众多轮廓,然后获取其中面积最大的轮廓,并假设这是目标物体的轮廓。

这种假设只适用于我们这个场景,在实际使用时,在图片中找出目标物体的方法与应用场景有很大关系。

我们这个场景用简单的边缘检测并找出最大的轮廓就可以了。当然为了使程序更具有鲁棒性,也可以用轮廓近似,并剔除不是四个点的轮廓(纸张是一个有四个点的矩形),然后再找出面积最大,具有四个点的轮廓。

注意: 关于这个方法,详情可以查看这篇文章,用于构建一个移动文本扫描工具。

我们也可以根据颜色特征在图片中找到目标物体,因为目标物体和背景的颜色有着很明显的不同。还可以应用关键点检测(keypoint detection),局部不变性描述子(local invariant descriptors)和关键点匹配(keypoint matching)来寻找目标。但是这些方法不在本文的讨论范围内,而且高度依赖具体场景。

我们现在得到目标物体的轮廓了,find_marker 函数最后返回的是包含轮廓 (x, y) 坐标、像素长度和像素宽度的边框,

计算距离

接下来该使用相似三角形计算目标到相机的距离。

def distance_to_camera(knownWidth, focalLength, perWidth):
    # compute and return the distance from the maker to the camera
    return (knownWidth * focalLength) / perWidth

distance_to_camera 函数传入目标的实际宽度,计算得到的焦距和图片上目标的像素宽度,就可以通过相似三角形公式计算目标到相机的距离了。

下面是调用 distance_to_camera 函数之前的准备:

# initialize the known distance from the camera to the object, which
# in this case is 24 inches
KNOWN_DISTANCE = 24.0


# initialize the known object width, which in this case, the piece of
# paper is 12 inches wide
KNOWN_WIDTH = 11.0


# load the furst image that contains an object that is KNOWN TO BE 2 feet
# from our camera, then find the paper marker in the image, and initialize
# the focal length
image = cv2.imread("images/2ft.jpg")
marker = find_marker(image)
focalLength = (marker[1][0] * KNOWN_DISTANCE) / KNOWN_WIDTH

首先是测量目标物体的宽度,和目标物体到相机的距离,并根据上面介绍的方法计算相机的焦距。其实这些并不是真正的摄像机标定。真正的摄像机标定包括摄像机的内参,相关知识可以可以查看这里。

使用 cv2.imread 函数从磁盘加载图片,然后通过 find_marker 函数得到图片中目标物体的坐标和长宽信息,最后根据相似三角形计算出相机的焦距。

现在有了相机的焦距,就可以计算目标物体到相机的距离了。

# loop over the images
for imagePath in sorted(paths.list_images("images")):
    # load the image, find the marker in the image, then compute the
    # distance to the marker from the camera
    image = cv2.imread(imagePath)
    marker = find_marker(image)
    inches = distance_to_camera(KNOWN_WIDTH, focalLength, marker[1][0])


    # draw a bounding box around the image and display it
    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)

使用 for 循环遍历每个图片,计算每张图片中目标对象到相机的距离。在结果中,我们根据得到的轮廓信息将方框画了出来,并显示出了距离。下面是得到的几个结果图:

dd3e0cb4-6d8f-11ed-8abf-dac502259ad0.png

dd4f0a00-6d8f-11ed-8abf-dac502259ad0.png

总结

通过这篇文章,我们学会了使用相似三角形计算图片中一个已知物体到相机的距离。

需要先测量出目标物体的实际宽度和目标物体到相机的距离,然后使用图像处理的方法自动计算图片中目标物体的像素宽度,并使用相似三角形计算出相机的焦距。

根据相机的焦距就可以计算图片中的目标物体到相机的距离。

原文作者Adrian Rosebrock博士 在此特别鸣谢

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 机器视觉
    +关注

    关注

    160

    文章

    4031

    浏览量

    118242
  • 函数
    +关注

    关注

    3

    文章

    3859

    浏览量

    61296
  • OpenCV
    +关注

    关注

    29

    文章

    611

    浏览量

    40758
  • python
    +关注

    关注

    51

    文章

    4667

    浏览量

    83440

原文标题:使用OpenCV实现摄像头测距

文章出处:【微信号:vision263com,微信公众号:新机器视觉】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    【芯灵思A83T试用申请】嵌入式视觉--远距离物体跟踪与定位

    OpenCV环境,连接工业相机3)物体跟踪与定位算法的实现4)结项与项目演示具体描述:本方案拟以嵌入式开发为基础,基于CMOS相机和数字图像处理技术的远
    发表于 04-27 14:18

    LabVIEW+Python+openCV

    的,动态链接库也需要配置,还需要知道各个参数含义和类型,这里提供另外一种方法,那就是PythonopenCV工具包,绝对开源和免费,LabVIEW可以利用Python节点调用Python
    发表于 12-07 20:59

    如何使用Python中的OpenCV模块检测颜色

    的HSV颜色贴图获得较低和较高的 HSV 值。在 OpenCV 中,色调的值0180,饱和度的值0255。因此,
    发表于 02-09 16:31

    OpenCV-Python-Toturial-中文版

    python编写opencv的入门资料,介绍了python的各个函数的应用
    发表于 03-23 14:55 0次下载

    轮廓查找基础_《OpenCV3编程入门》书本配套源代码

    OpenCV3编程入门》书本配套源代码:轮廓查找基础
    发表于 06-06 15:39 4次下载

    Python下使用OpenCV的技巧教程与典型应用案例

    Python下使用OpenCV教程,本篇将介绍和深度学习数据处理阶段最相关的基础使用,并完成4个有趣实用的小例子: - 延时摄影小程序 - 视频中截屏采样的小程序 - 图片数据增加(data augmentation)的小工具 -
    发表于 11-15 18:43 1.1w次阅读

    python图像处理opencv步骤是怎么样的

    越来越觉得python是一强大的工具,处理样本确实不错。最近因项目需要涉及到图片处理,所以开始用python调用opencv,再次觉得python真乃神器也!
    发表于 12-04 15:29 4231次阅读

    使用opencvpython进行智能火灾检测

    电子发烧友网站提供《使用opencvpython进行智能火灾检测.zip》资料免费下载
    发表于 11-02 15:08 0次下载
    使用<b class='flag-5'>opencv</b>和<b class='flag-5'>python</b>进行智能火灾检测

    OpenCV如何帮助相机自动化视觉跟踪

    OpenCV对学术用途和商业用途都免费。它有C++、C、Python和Java的接口,并且支持Windows、Linux、MacOS、iOS和Android系统。在我的OpenCV教程系列中,我们将专注于使用树莓派(当然,操作系
    发表于 11-29 10:36 606次阅读

    使用OpenCV实现目标物体相机距离测量

    假设物体的宽度为 W,将其放到离相机距离为 D 的位置,然后对物体进行拍照。在照片上量出物体的像素宽度 P,于是可以得出计算
    的头像 发表于 11-29 14:47 1636次阅读

    OpenCV常用的 7 个示例(Python版)1

    OpenCV是计算机视觉领域最流行的库之一。它最初是用 C 和 C++ 编写的。现在也可以在 Python 中使用。它最初是由英特尔开发的。该库是一个跨平台的开源库。免费使用。OpenCV 库是一个高度优化的库,其主要重点是实时
    的头像 发表于 02-07 16:23 968次阅读

    OpenCV常用的 7 个示例(Python版)2

    OpenCV是计算机视觉领域最流行的库之一。它最初是用 C 和 C++ 编写的。现在也可以在 Python 中使用。它最初是由英特尔开发的。该库是一个跨平台的开源库。免费使用。OpenCV 库是一个高度优化的库,其主要重点是实时
    的头像 发表于 02-07 16:23 838次阅读

    OpenCV常用的 7 个示例(Python版)3

    OpenCV是计算机视觉领域最流行的库之一。它最初是用 C 和 C++ 编写的。现在也可以在 Python 中使用。它最初是由英特尔开发的。该库是一个跨平台的开源库。免费使用。OpenCV 库是一个高度优化的库,其主要重点是实时
    的头像 发表于 02-07 16:23 784次阅读

    Python实现OpenCV的安装与使用

      本文实例讲述了 Python 实现 OpenCV 的安装与使用。分享给大家供 大家参考,具体如下:  由于下一步要开始研究下深度学习,而深度学习领域很多的算法和应 用都是用 Python 来实现
    发表于 07-20 11:46 7次下载

    Vulture 可在Python程序中查找未使用的代码

    Vulture 可以在Python程序中查找未使用的代码。这对于清理和查找大型项目(代码库)中的错误非常有用。 不过由于Python的动态特性,像 Vulture 这样的静态代码分析器
    的头像 发表于 10-21 10:28 215次阅读