使用几何光学实现空间相对定位--“鸿鹄“空间定位仪3.0(python+opencv)

原文链接:https://blog.csdn.net/zbp_12138/article/details/103208910

本文讲解的是基于”鸿鹄”空间定位仪第一,二代程序写的第三代程序,相较于前两代的程序,第三代的程序有比较大的改动,其程序是在第二代的基础上进行改进的.

“鸿鹄”空间定位仪1.0版本:
https://blog.csdn.net/zbp_12138/article/details/101100607

在这里插入图片描述

“鸿鹄”空间定位仪2.0版本:
https://blog.csdn.net/zbp_12138/article/details/103191129

在这里插入图片描述
不同版本有不同版本的优缺点:

  1. 在1.0版本中,程序能快速地识别目标物体,并迅速地返回对应的距离,但缺点是精确度不高,距离目标物40cm时,误差的平均值为5cm,在背景纷繁复杂时,程序不能准确识别到目标物,误差大且数值一直在变化,不稳定.即速度快,但准确度低.
  2. 在2.0版本中,我调用了百度AI的图像主体识别接口,在一定程度上能准确识别到目标物体,从而提高了识别的稳定性与准确度,但缺点是识别速度很慢,不能达到实时的效果.即速度慢,但准确度高.
  3. 在3.0版本中,我使用了多线程的方式,把1.0和2.0版本的优点结合起来,达到了速度快,且准确度高的效果,可以实现实时检测.

以下是"鸿鹄"空间定位仪3.0版本的代码讲解,首先来看一下几个必要的资源库:

import requests
import base64
import numpy as np
import cv2
import time
import multiprocessing as mp


其中multiprocessing是python内置的一个进程管理模块,我们可以通过这个模块实现多进程。进程想要执行任务就需要依赖线程。换句话说,就是进程中的最小执行单位就是线程,并且一个进程中至少有一个线程。

那什么是多线程?提到多线程这里要说两个概念,就是串行和并行,搞清楚这个,我们才能更好地理解多线程。

所谓串行,其实是相对于单条线程来执行多个任务来说的,我们就拿下载文件来举个例子:当我们下载多个文件时,在串行中它是按照一定的顺序去进行下载的,也就是说,必须等下载完第一个文件之后才能开始下载第二个文件,它们在时间上是不可能发生重叠的。

而并行就是在下载多个文件时,开启多条线程,多个文件同时进行下载,这里是严格意义上的,在同一时刻发生的,并行在时间上是重叠的。

多线程类似于同时执行多个不同程序,是为了同步完成多项任务而使用的,是为了提高资源使用效率来提高系统的效率,多线程运行有如下优点:

  1. 使用线程可以把占据时间长的程序任务放到后台去处理。
  2. 程序的运行速度可能加快。

在这里我们先举一个简单的例子:
以较为常用的Queue为例子,在父进程中创建两个子进程,一个往Queue里写数据,一个从Queue里读取数据:

import multiprocessing as mp


导入multiprocessing

#写数据进程
def write_data(q,name):
    print(name)
    for v in range(5):
        q.put(v)
        print ('把%s写入队列'%v)



第一个进程:写入数据

#读数据进程
def read_data(q,name):
    print(name)
    while True:
        value = q.get()
        print('从队列里读取到%s'%value)


第二个进程:读取数据

def run():
    name1 = "写数据进程"
    name2 = "读数据进程"
    #父进程创建queue,并传递给各个子进程:
    q = mp.Queue(1)
    #启动子进程pw,写入数据
    pw = mp.Process(target=write_data,args=(q,name1))
    pw.start()
    #启动子进程pr,读取数据
    pr = mp.Process(target=read_data, args=(q,name2))
    pr.start()
    #等待pw结束
    pw.join()
    #pr,进程里是死循环,无法等待其自动结束,所以手动结束
    pr.terminate()


控制两个进程的方法

if __name__ == '__main__':
    run()


运行程序

在这里插入图片描述

如果你已经得到了上面的结果,那么恭喜你,你已经成功一半了,接下来,看看"鸿鹄"空间定位仪3.0是怎么使用多进程的:

def image_put(q, user, pwd, ip):
    cap1 = cv2.VideoCapture("rtsp://%s:%s@%s:8554/live" % (user, pwd, ip))
    cap2 = cv2.VideoCapture("http://%s:%s@ip地址:8081"% (user, pwd))
    while (cap2.isOpened()):
        (grabbed, frame) = cap2.read()
        q.put(frame)
        q.get() if q.qsize() > 1 else time.sleep(0.01)


cap1和cap2都可以调用ip摄像头,方法不同而已

def image_get(q,camera_ip):
    while True:
        frame = q.get()
        frame_count = 1
        params = []
        params.append(1)
        cv2.imwrite("/Users/Administrator/PycharmProjects/untitled/images/video%d.jpg" % frame_count, frame, params)
        marker = find_width("/Users/Administrator/PycharmProjects/untitled/images/video%d.jpg" % frame_count)
        # frame_count = frame_count + 1
        inches = distance_to_camera(KNOWN_WIDTH, focalLength, marker[0])
        box = (marker[2],marker[1]), (marker[2] + marker[0], marker[1]), (marker[2] + marker[0], marker[1] + marker[3]),(marker[2] ,marker[1] + marker[3])
        print(box)
        box = np.int0(box)
        cv2.drawContours(frame, [box], -1, (0, 255, 0), 2)
        # inches 转换为 cm
        cv2.putText(frame, "%.2fcm" % (inches/6.6 ), (frame.shape[1] - 350, frame.shape[0] - 20),cv2.FONT_HERSHEY_SIMPLEX, 2.0, (0, 255, 0), 3) #2.54
        # show a frame
        title = 'Locator 3.0'
        gbk_title = title.encode("gbk").decode(errors="ignore")
        cv2.imshow(gbk_title, frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break



获取视频的某一帧,其中的代码详解在使用几何光学实现空间相对定位2.0(python+opencv)里有介绍

def run_single_camera():
    user_name, user_pwd, camera_ip = "admin", "admin", "ip地址"
    mp.set_start_method(method='spawn')  # init
    queue = mp.Queue(2)
    processes = [mp.Process(target=image_put, args=(queue, user_name, user_pwd, camera_ip)),
                 mp.Process(target=image_get, args=(queue, camera_ip))]
    [setattr(process, "daemon", True) for process in processes]  # process.daemon = True  # 设置进程守护
    [process.start() for process in processes]
    [process.join() for process in processes]


使用示例代码前,请记得替换其中的ip地址

if __name__ == '__main__':
    run_single_camera()


为了让三篇文章显得更具有逻辑性,我在这篇文章里就不做一些重复性的解释了,大家感兴趣的话,可以查阅我以前的文章.

总的来说,在"鸿鹄"空间定位仪3.0版本中,我使用Python3自带的多线程模块multiprocessing,创建一个队列,线程A从通过rtsp / http 协议从视频流中读取出每一帧,并放入队列中,线程B从队列中将图片取出,处理后进行显示。

之所以能加快识别的速度,是因为:

线程A如果发现队列里有两张图片,则证明线程B的读取速度跟不上线程A,那么线程A主动将队列里面的旧图片删掉,换上新图片。

通过多线程的方法:

  1. 线程A的读取速度始终不收线程B的影响,防止网络摄像头的缓存区爆满
  2. 线程A更新了队列中的图片,使线程B始终读取到最新的画面,降低了延迟


测试数据:

在这里插入图片描述

经过测试,"鸿鹄"空间定位仪在距离目标物35cm到60cm时,平均误差小于1cm,平均精确度高达98.7%

在这里插入图片描述

其中一次测试数据:实际距离为55.00cm,测量距离为:55.45cm

以下链接是“鸿鹄”空间定位仪3.0的实拍视频:
http://v.youku.com/v_show/id_XNDQ0Mzk2NDYyMA==.html?x&sharefrom=android&sharekey=fd7ac36a100eb692f3056be1ef4db6e80
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值