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

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

3天内不再提示

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

jt_rfid5 来源:今日光电 作者:今日光电 2022-11-29 14:47 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

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

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

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

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

b8fb5fc2-6f0c-11ed-8abf-dac502259ad0.svg

此时移动相机离物体更近或者更远,我们可以应用相似三角形得到计算物体到相机的距离的公式:
b90c7cbc-6f0c-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)

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

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

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 循环遍历每个图片,计算每张图片中目标对象到相机的距离。在结果中,我们根据得到的轮廓信息将方框画了出来,并显示出了距离。

总结

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

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

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

审核编辑:郭婷

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

    关注

    61

    文章

    5063

    浏览量

    102554
  • 相机
    +关注

    关注

    5

    文章

    1542

    浏览量

    55448

原文标题:【光电智造】使用OpenCV实现摄像头测距

文章出处:【微信号:今日光电,微信公众号:今日光电】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    目标追踪的简易实现:模板匹配

    的信息在视频的每一帧图象中进行搜寻,获取每一帧中目标的大小和坐标。对视频流作目标追踪的好处是,我们不仅可以动态地对物体进行定位,还可以由此分析出被追踪物体的速度、加速度等参数,如下面这
    发表于 10-28 07:21

    【上海晶珩睿莓1开发板试用体验】TensorFlow-Lite物体归类(classify)

    用。 OpenCV库编译成功之后,就可以新建一个线程进行TensorFlow-Lite物体归类了,这里我直接使用现成的pb和pbtxt文件,具体内容不赘述,来看看识别效果:
    发表于 09-12 22:43

    【开发实例】基于GM-3568JHF开发板安装OpenCV并使用视频目标跟踪 ( CamShift)

    在计算机视觉领域,视频目标跟踪是一个非常重要的任务。视频目标跟踪广泛应用于监控、自动驾驶、人机交互等多个领域。OpenCV提供了多种目标跟踪算法,其中MeanShift和CamShif
    的头像 发表于 09-02 08:04 489次阅读
    【开发实例】基于GM-3568JHF开发板安装<b class='flag-5'>OpenCV</b>并使用视频<b class='flag-5'>目标</b>跟踪 ( CamShift)

    零成本钢铁侠手套!树莓派+OpenCV 秒变手势遥控器!

    使用树莓派和OpenCV实时扫描并存储二维码使用树莓派和OpenCV实现物体与动物识别使用树莓派、摄像头和OpenCV进行速度检测用树莓派+
    的头像 发表于 08-16 16:16 919次阅读
    零成本钢铁侠手套!树莓派+<b class='flag-5'>OpenCV</b> 秒变手势遥控器!

    如何使用树莓派与OpenCV实现面部和运动追踪的云台系统?

    使用树莓派和OpenCV实时扫描并存储二维码使用树莓派和OpenCV实现物体与动物识别使用树莓派、摄像头和OpenCV进行速度检测用树莓派+
    的头像 发表于 08-14 17:45 1003次阅读
    如何使用树莓派与<b class='flag-5'>OpenCV</b><b class='flag-5'>实现</b>面部和运动追踪的云台系统?

    如何使用树莓派+OpenCV实现姿态估计和面部特征点追踪?

    使用树莓派和OpenCV实时扫描并存储二维码使用树莓派和OpenCV实现物体与动物识别使用树莓派、摄像头和OpenCV进行速度检测今天是第一
    的头像 发表于 08-13 17:44 1012次阅读
    如何使用树莓派+<b class='flag-5'>OpenCV</b><b class='flag-5'>实现</b>姿态估计和面部特征点追踪?

    【GM-3568JHF开发板免费体验】OpenCV 视频目标跟踪 ( CamShift)

    目标区域的质心。 3)移动窗口:将窗口中心移动到质心位置。 4)调整窗口大小和方向:根据目标的尺寸和方向调整窗口。 5)迭代:重复步骤 2 4,直到窗口中心不再变化或达到最大迭代次数。 O
    发表于 08-09 13:19

    基于凌智视觉识别模块的基于单目视觉的目标测量装置

    1.视觉测量整体方案本视觉测量系统采用单目视觉技术实现目标距离
    的头像 发表于 07-31 15:35 761次阅读
    基于凌智视觉识别模块的基于单目视觉的<b class='flag-5'>目标</b>物<b class='flag-5'>测量</b>装置

    【Milk-V Duo S 开发板免费体验】SDK编译、人脸检测、OpenCV测试

    -mobile-test ./opencv-mobile-test 生成 200x200 尺寸的 out.jpg 图像,即实现图片压缩。 该测试工程可结合物体识别模型,实现输入图像
    发表于 07-11 13:48

    为何激光三维扫描无需喷粉也能精准测量高反光物体?—— 基于光学抗反射技术的突破

    喷粉也能实现高反光物体的精准测量,为该领域带来新突破。 传统高反光物体测量的困境与技术瓶颈 传统激光三维扫描基于三角测距原理,高反光
    的头像 发表于 06-27 09:58 396次阅读
    为何激光三维扫描无需喷粉也能精准<b class='flag-5'>测量</b>高反光<b class='flag-5'>物体</b>?—— 基于光学抗反射技术的突破

    给予多路复用器的多目标阻抗测量,测不准

    我设计了一个arduino控制ADG32多路复用器进行目标切换的电路,用来切换不同的测量目标,现在发现,当所有测量目标都接上的时候,阻抗会降
    发表于 06-11 15:50

    基于LockAI视觉识别模块:C++目标检测

    的基本概念,并提供了详细的API文档说明,帮助开发者理解和实现目标检测与可视化功能。通过上述流程,可以构建高效的实时目标检测系统,满足多种应用场景的需求。
    发表于 06-06 14:43

    如何用OpenCV相机捕捉视频进行人脸检测--基于米尔NXP i.MX93开发板

    本文将介绍基于米尔电子MYD-LMX93开发板(米尔基于NXPi.MX93开发板)的基于OpenCV的人脸检测方案测试。OpenCV提供了一个非常简单的接口,用于相机捕捉一个视频(我用的电脑内置
    的头像 发表于 04-15 11:51 668次阅读
    如何用<b class='flag-5'>OpenCV</b>的<b class='flag-5'>相机</b>捕捉视频进行人脸检测--基于米尔NXP i.MX93开发板

    在ALC SDK中使用大恒相机不使用Point Grey的相机时需要做哪些修改呢?

    编译吗? 另外,3D Scanner的 config里有opencv相机type,但是选了这个也不行,TIDA-00254:这份文档对opencv的部分也没做详细的介绍,用这个会不会更方便呢?
    发表于 03-03 08:03

    为什么由相机和投影仪构建三维测量系统时,相机的分辨率要是DMD分辨率的4倍? DLPDLCR3310最近工作距离是多少?

    工程师您好,有以下问题希望得到您的回复: 为什么由相机和投影仪构建三维测量系统时,相机的分辨率要是DMD分辨率的4倍? DLPDLCR3310的最近工作距离是多少?在实际投影时,在2
    发表于 02-18 08:33