使用几何光学实现空间相对定位(python+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的版本:

WIN+R会出现一个小窗口,在里面输入cmd进入命令行

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 ,已知待检测目标的实际大小,在某一位置拍摄的照片里显示的目标像素大小后,变换拍摄位置,目标像素大小改变,但是这个像素大小可以通过计算机处理后得到,因此,我们可以求出拍摄的位置即距离.

相似三角形原理在“鸿鹄”空间定位仪中的应用

举个例子,假设我在离相机距离 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

KNOWN_DISTANCE =34.64

# 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摄像头的具体代码如下:

if __name__ =='__main__':

cv2.namedWindow("camera1",1)

#开启ip摄像头

    video1="http://admin:admin@192.168.1.100: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)

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


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


确保手机与被测目标是平行的
测量手机摄像头到目标A4纸的距离(1)
测量手机摄像头到目标A4纸的距离(2)
测量手机摄像头到目标A4纸的距离(3)

我为“鸿鹄”空间定位仪制作了一个短视频,感兴趣的朋友们可以进入我的QQ空间里查看:“鸿鹄”空间定位仪

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容