首页 > 编程语言 >使用几何光学实现空间相对定位(python+opencv)

使用几何光学实现空间相对定位(python+opencv)

时间:2023-03-16 19:32:49浏览次数:55  
标签:python image cv2 距离 像素 opencv 光学


我从2019年3月份开始学习python,在有一定的基础后,我看到学校有一个物理实验竞赛:北京联合大学第十二届物理实验竞赛,其中有一个题目是空间定位,即利用物理原理,自行搭建实验装置,实现物体的空间定位。

在有一定编程能力的基础之上,我在想,能不能用python写出一个程序,用来检测摄像头到目标物体的距离.我暂且把我的想法起了一个名字,叫: “鸿鹄”空间定位仪.

近年来,深度学习(DeepLearning)备受热捧,但是,在我看来,为了达到很好的精度,DeepLearning需要大数据支撑。由于深度学习中图模型的复杂化导致算法的时间复杂度急剧提升,为了保证算法的实时性,需要更高的并行编程技巧和更多更好的硬件支持,作为普通程序员,只能望而却步.

于是,我把目光转向了opencv.我的想法是:通过ip摄像头连接个人电脑,从而实现在移动端上的识别,在pc端识别该设备与某个物体的相对距离,即判断某个物体的空间位置。该实验类似于目前的倒车雷达判断距离,其区别是,目前的倒车雷达使用超声波进行回声定位,而“鸿鹄”空间定位仪则通过逐帧分析,实时判定距离,能瞬时输出检测物体的空间相对位置,且计算速度更高。

我在网上看了几篇关于摄像头标定和摄像头焦距等原理的文章,然后通过这篇文章真正启发了我:​​单目摄像机测距(python+opencv)​​主要的测距的原理是利用相似三角形计算物体到相机的距离。

在开始之前,先讲讲我遇到的问题吧,希望大家在做的时候也注意一下这个问题.我使用的环境是: Python 3.7.1+ opencv-python(3.4.7+contrib).在安装opencv库时,如果直接pip install opencv-python会出现报错的情况,这个时候,需要安装与python版本对应的库!在命令行里输入python即可查看python的版本;

使用几何光学实现空间相对定位(python+opencv)_空间定位


opencv在这个网站上下载: https://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml,那么如何找到与python版本一致的opencv版本呢?

举个例子: opencv_python‑3.4.2‑cp37‑cp37m‑win_amd64.whl(cp37指的是python的版本,win_amd64是指python是64位的,也有可能有人64位的系统装了32位的python,这时候就需要装win32的版本).下载好以后,再用pip安装这个文件即可.

除此之外,还需要安装一个小小的资源库:numpy.简单来说,这是一个处理矩阵的库.安装这个库只需要常规操作即可.

我们先导入一下两个必要的资源库,当pycharm未提示错误时,则说明这两个库已成功安装:
import numpy as np
import cv2

在编写代码前,必要的理论知识要了解一下:

我们将使用相似三角形来计算摄像头到一个已知的物体或者目标的距离。

相信大家在初高中都学过:三角分别相等,三边成比例的两个三角形叫做相似三角形.在本实验中,相似三角形就是这么一回事:假设我们有一个宽度为 W 的目标或者物体。然后我们将这个目标放在距离我们的相机为 D 的位置。我们用相机对物体进行拍照并且测量物体的像素宽度P。这样我们就得出了相机焦距的公式:F = (P x D) / W ,已知待检测目标的实际大小,在某一位置拍摄的照片里显示的目标像素大小后,变换拍摄位置,目标像素大小改变,但是这个像素大小可以通过计算机处理后得到,因此,我们可以求出拍摄的位置即距离.

使用几何光学实现空间相对定位(python+opencv)_python_02


举个例子,假设我在离相机距离 D = 24 英寸的地方放一张标准的 8.5 x 11 英寸的 A4 纸(横着放;W = 11)并且拍下一张照片。我测量出照片中 A4 纸的像素宽度为 P = 249 像素。

因此我的焦距 F 是:F = (248px x 24in) / 11in = 543.45

当我继续将我的相机移动靠近或者离远物体或者目标时,我可以用相似三角形来计算出物体离相机的距离:D’ = (W x F) / P

为了更具体,我们再举个例子,假设我将相机移到距离目标 3 英尺(或者说 36 英寸)的地方并且拍下上述的 A4 纸。通过自动的图形处理我可以获得图片中 A4 纸的像素距离为 170 像素。将这个代入公式得:D’ = (11in x 543.45) / 170 = 35 英寸或者约 36 英寸,合 3 英尺。

从以上的解释中,我们可以看到,要想得到距离,我们就要知道摄像头的焦距和目标物体的尺寸大小,这两个已知条件根据公式: D’ = (W x F) / P得出目标到摄像机的距离D,其中P是指像素距离,W是A4纸的宽度,F是摄像机焦距。

好了,那么现在我们可以开始编写代码了!在这里,为了便于初学者学习,我的注释可能会显得有些繁杂,在日常写代码时,希望大家有一个良好编程习惯:注释言简意赅就行,不必长篇大论.

# 找到目标函数
def find_marker(image):
# convert the image to grayscale, blur it, and detect edges
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # cvtcolor()函数是一个颜色空间转换函数,可以实现RGB颜色向HSV,HSI等颜色空间转换。也可以转换为灰度图。
gray = cv2.GaussianBlur(gray, (5, 5),0) # 高斯模糊滤波器.低通滤波器是在像素与周围像素的亮度差值小于一个特定值时,平滑该像素的亮度。主要用于去噪和模糊化,如高斯模糊是最常用的模糊滤波器,是一个削弱高频信号强度的低通滤波器。
edged = cv2.Canny(gray, 35, 125) # 采用 Canny 算法做边缘检测

# 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)
# 求最大面积
c = max(cnts, key=cv2.contourArea)

# compute the bounding box of the of the paper region and return it
# cv2.minAreaRect() c代表点集,返回rect[0]是最小外接矩形中心点坐标,
# rect[1][0]是width,rect[1][1]是height,rect[2]是角度
return cv2.minAreaRect(c)
# 距离计算函数
def distance_to_camera(knownWidth, focalLength, perWidth):
# compute and return the distance from the maker to the camera
return (knownWidth * focalLength) / perWidth

我们把标定好的图片与.py文件放在同一个文件夹下:

使用几何光学实现空间相对定位(python+opencv)_ide_03

KNOWN_DISTANCE = 34.64
# initialize the known object width, which in this case, the piece of
# paper is 11 inches wide
# A4纸的长和宽(单位:inches)
KNOWN_WIDTH = 11.8
KNOWN_HEIGHT = 8.27

# initialize the list of images that we'll be using
IMAGE_PATHS = ["images/88cm.jpg", "images/70cm.jpg", "images/60cm.jpg"]

# 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(IMAGE_PATHS[0]) # 使用imread()读取图像地址:从硬盘读取第一张图,——我们将用这张图来作为标定图片
marker = find_marker(image) # 计算图中 A4 纸的轮廓信息
focalLength = (marker[1][0] * KNOWN_DISTANCE) / KNOWN_WIDTH # 使用三角形相似法计算出 focalLength(焦距)
print('focalLength = ', focalLength)

为了让“鸿鹄”空间定位仪有更广的应用,我使用电脑调用IP摄像头,从而实现了可以在移动端实时检测的操作,该操作可以延伸到无人机,智能小车等需要测距和测速的领域,打开GPS即可查看经纬度信息以及速度.调用IP摄像头的具体代码如下:

import cv2
if __name__ == '__main__':
cv2.namedWindow("camera1",1)
#开启ip摄像头
video1=http://admin:[email protected]:8081
#此处@后的ipv4 地址需要修改为自己的地址
capture1 =cv2.VideoCapture(video1)
while(capture1.isOpened()):
success1,img = capture1.read()
cv2.imshow("camera1",img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
capture1.release()
cv2.destroyAllWindows("camera1")

现在到最为关键的一步了,为了保证代码的运行效果,我在测试时加了一句代码:

try:
pass
except Exception as e:
print(e)

通过这段代码,我们可以让程序在运行的过程中不报错,对于代码数量大的程序来说,是很有必要的.

使用几何光学实现空间相对定位(python+opencv)_空间定位_04


以下是我在制作“鸿鹄”空间定位仪的花絮:

使用几何光学实现空间相对定位(python+opencv)_opencv_05


使用几何光学实现空间相对定位(python+opencv)_空间定位_06


使用几何光学实现空间相对定位(python+opencv)_opencv_07


为了便于演示“鸿鹄”空间定位仪的效果,我做了一个视频,大家可以进入链接查看:​​“鸿鹄”空间定位仪​



标签:python,image,cv2,距离,像素,opencv,光学
From: https://blog.51cto.com/u_16011718/6125749

相关文章

  • 调用AI聊天机器人自动回复信息(Python)
    “人类正从IT时代走向DT时代”,随着移动互联网技术持续高速发展,海量数据计算存储、智能数据挖掘、低时延数据传送和可靠网络安全已经成为软硬件技术飞速发展的催化剂,也推......
  • 抓取王者荣耀英雄列表的爬虫笔记(python+requests)
    在开始这个内容之前,我们先来一张效果图:实现它,需要几个过程:调用王者荣耀助手的数据接口获取所有英雄的图片通过迭代,把所有图片转换成二进制数据流把这些数据导入MySQL数据库......
  • Python startswith()和endswith()方法
    startswith()方法startswith()方法用于检索字符串是否以指定字符串开头,如果是返回True;反之返回False。endswith()方法endswith()方法用于检索字符串是否以指定字符......
  • python - 面向对象编程
    一、对象与过程的概念python中的两大范式:1.面向过程2.面向对象他们两个都不是新的技术,而是一种做事的思维方式1.面向过程:根据业务逻辑从上到下写垒代码面向过程核心是......
  • Python根据图片拍摄日期等整理重命名
    关键词:exif、exifread等等。最近在整理多年拍摄的图片,希望按照拍摄时间进行排序整理制作相册。但是有的图片有水印显示拍摄日期;有的文件创建日期因为搬运创建日期和修改......
  • Python基础数据类型
    一、字符串1、字符串赋值1.1直接赋值使用'',"",''''''(单、双、三引号)和“=”赋值符号,进行字符串赋值注意:三引号形式的字符串支持换行1.2 通过input()方法 2、字......
  • Python装饰器深入理解
    在本博客的前面部分其实已经介绍过Python中装饰器的基本使用了(Python迭代器、生成器、装饰器的使用,Python@函数装饰器以及super()父类继承 ),不过还有一些深入的知识点(......
  • python并行计算demo,用于求0~n之间的素数之和
     想试试服务器的并行计算能力,就让cpu慢慢计算,计算0~n之间所有素数之和设置target为结尾,num_of_processors为进程数,即可开始跑如下所示frommultiprocessingimportP......
  • 通过Python+CRemoteAPI控制Trace32进行调试
    关键词:Python、CRemoteAPI、Trace32等等。当需要对Trace32调试进行自动化,或者提高效率时,可以通过RemoteControlAPI进行。基本的调试流程如下:Python、C等语言可以通......
  • python 类中的属性排序
    可以使用Python中的类(class)来定义一个包含姓名和年龄的类。以下是一个示例代码:classPerson:def__init__(self,name,age):self.name=namese......