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博士 在此特别鸣谢

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

    关注

    161

    文章

    4317

    浏览量

    119959
  • 函数
    +关注

    关注

    3

    文章

    4276

    浏览量

    62303
  • OpenCV
    +关注

    关注

    29

    文章

    624

    浏览量

    41206
  • python
    +关注

    关注

    55

    文章

    4765

    浏览量

    84353

原文标题:使用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次下载

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

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

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

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

    简述我们该如何使用OpenCV测量图像中物体之间的距离

    计算物体之间的距离与计算图像中物体的大小算法思路非常相似——都是参考对象开始的。我们将使用0.25美分作为我们的参考对象,它的宽度为0.955英寸。
    的头像 发表于 03-12 11:39 3831次阅读

    如何用PythonOpenCV来测量相机目标的距离

    和基于轨迹的跟踪方法来确定或者估计小球在视频帧中的位置。并且因为棒球的大小是已知的,所以我也能估计出其本垒的距离。 那是个有趣的项目,
    的头像 发表于 05-20 15:15 3911次阅读
    如何用<b class='flag-5'>Python</b>和<b class='flag-5'>OpenCV</b>来测量<b class='flag-5'>相机</b><b class='flag-5'>到</b>目标的<b class='flag-5'>距离</b>

    Linux Debian与Python、Flask和OpenCV识别面部

    电子发烧友网站提供《Linux Debian与Python、Flask和OpenCV识别面部.zip》资料免费下载
    发表于 08-24 10:16 2次下载
    Linux Debian与<b class='flag-5'>Python</b>、Flask和<b class='flag-5'>OpenCV</b>识别面部

    使用opencvpython进行智能火灾检测

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

    用于距离测量和物体检测的飞行时间系统

    飞行时间(ToF)为此变得越来越重要。使用ToF技术,光调制源(例如激光)发射,然后由传感器或相机捕获从一个或多个物体反射的光束。因此,可以通过发射光和接收反射光之间的时间延迟∆来确定距离
    的头像 发表于 11-22 14:17 701次阅读
    用于<b class='flag-5'>距离</b>测量和<b class='flag-5'>物体</b>检测的飞行时间系统

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

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

    用于距离测量和物体检测的飞行时间系统

    飞行时间(ToF)为此变得越来越重要。使用ToF技术,光调制源(例如激光)发射,然后由传感器或相机捕获从一个或多个物体反射的光束。因此,可以通过发射光和接收反射光之间的时间延迟∆来确定距离
    的头像 发表于 12-09 15:41 924次阅读
    用于<b class='flag-5'>距离</b>测量和<b class='flag-5'>物体</b>检测的飞行时间系统

    如何使用OpenCVPython图像中提取感兴趣区域

    今天我们将一起探究如何使用OpenCVPython图像中提取感兴趣区域(ROI)。 在之间的文章中,我们完成了图像边缘提取,例如从台球桌中提取桌边。使用了简单的OpenCV
    的头像 发表于 02-07 14:42 1739次阅读

    opencv-pythonopencv一样吗

    不一样。OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库,它提供了大量的图像和视频处理功能。OpenCV-Python
    的头像 发表于 07-16 10:38 853次阅读