基于yolov5的目标检测和双目测距

目录

一.简介

1.双目视觉

2 YOLOv5

二.双目准备

1双目矫正

2.测距部分代码和函数

三.yolov5部分代码代码展示


效果展示

一.简介

1.双目视觉

双目视觉是通过两个摄像机同时拍摄同一场景,通过计算两幅图像的差异来获取深度信息的一种计算机视觉技术。在双目视觉中,两个摄像机的成像位置和角度是预先确定的,它们之间的距离被称为基线,通过计算两个相机拍摄的图像中对应像素点的视差,可以计算出每个像素点的深度。

双目视觉的主要优势在于其可以通过将两个视角的信息进行比较,来消除图像中的噪声和误差,从而获得更准确的深度信息。此外,在近距离测量和物体检测等领域中都有广泛的应用。

双目视觉的基本流程包括以下几个步骤:

  1. 相机标定:确定相机的内外参数,包括焦距、畸变系数、旋转和平移矩阵等,以及两个摄像机之间的基线长度和相对位置关系。

  2. 图像获取:使用两个摄像机同时拍摄同一个场景,获取两幅图像。

  3. 特征提取:从两幅图像中提取特征点或者特征区域,例如SIFT或SURF算法,生成特征点集合。

  4. 特征匹配:通过比较两个图像中的特征点集合,找出相同的特征,建立对应关系。

  5. 视差计算:根据特征点间的视差大小,结合相机标定参数,计算出每个像素点的深度值。

  6. 深度图生成:将深度信息转换为灰度图像,生成深度图。

虽然双目视觉技术能够提供准确的深度信息,并可以运用在机器人导航、三维重建等领域,但是该技术还面临一些挑战,例如光照变化、遮挡和反射等问题,这些问题可能会影响特征提取和匹配,从而影响深度信息的准确性。

2 YOLOv5

YOLOv5是一种目标检测算法,由美国加州大学伯克利分校的研究团队开发。与其前身YOLOv4相比,YOLOv5在速度和检测精度方面有了非常显著的提升。

YOLOv5的全称是You Only Look Once version 5,意为“你只需要看一次”即可完成目标检测任务。它采用深度神经网络架构,在单张图像上进行物体检测,可以同时检测出多个物体,并得到它们的位置、类别和置信度等信息,具有高效、准确的特点。

YOLOv5的主要优势包括:

1. 高速度:相较于其前身YOLOv4,YOLOv5平均检测速度提高了65%,同时还具有更小的模型尺寸和更少的计算量。

2. 高检测精度:通过采用新的网络架构和数据增强技术,YOLOv5在检测精度方面取得了突破性的进展。

3. 简单易用:相对于其他目标检测算法,YOLOv5的代码量较小,易于实现和调试,能够应用于多种不同的应用场景。

目前,YOLOv5已经被广泛应用于自动驾驶、智能安防、工业自动化等领域,在实时物体检测和跟踪任务中具有广泛的应用前景。

二.双目准备

原理参考:双目标定之张正友标定法数学原理详解matlab版-CSDN博客

棋盘格图片自提

链接:https://pan.baidu.com/s/1W31fTtr6db8qgTevulWeMA 
提取码:ybca

二.双目准备

1双目矫正

打开Matlab 上方的工具栏APP,找到图像处理和计算机视觉下的Stereo Camera Calibration工具,打开并将分割后的图片导入

 设置参数,对于一般的相机选择2 Coefficients选项即可,对于大视场相机则选择3 Coefficients选项。拉线删除误差较大的画面:

获取参数

在matlab控制台分别输入 stereoParams.CameraParameters1.IntrinsicMatrix 和stereoParams.CameraParameters2.IntrinsicMatrix 获得左右相机的参数,下边填写时请注意进行矩阵的转置

为了获取左相机的畸变系数:[k1, k2, p1, p2, k3],我们需要分别输入stereoParams.CameraParameters1.RadialDistortion 和 stereoParams.CameraParameters1.TangentialDistortion

分别输入 stereoParams.RotationOfCamera2 和 stereoParams 来获取双目的旋转矩阵和平移矩阵

将以上参数填写进stereoconfig.py文件里,注意转置

import numpy as np# 双目相机参数
class stereoCamera(object):def __init__(self):# 左相机内参self.cam_matrix_left = np.array([   [479.6018,   -0.0769,  652.6060],[       0,  478.0229,  352.3870],[       0,         0,         1]])# 右相机内参self.cam_matrix_right = np.array([  [489.9354,   0.2789,  641.6219],[       0,  487.9356,  354.5612],[       0,         0,         1]])# 左右相机畸变系数:[k1, k2, p1, p2, k3]self.distortion_l = np.array([[-0.0791, 0.0309, -0.0009, -0.0004, -0.0091]])self.distortion_r = np.array([[-0.1153, 0.1021, -0.0011,  -0.0005,  -0.0459]])# 旋转矩阵self.R = np.array([ [1.0000,  0.0005, -0.0184],[-0.0005,  1.0000, 0.0001],[ 0.0184,  -0.0001,  1.0000]   ])# 平移矩阵self.T = np.array([[121.4655], [0.2118], [0.5950]])# 焦距self.focal_length = 749.402 # 默认值,一般取立体校正后的重投影矩阵Q中的 Q[2,3]# 基线距离self.baseline = 121.4655 # 单位:mm, 为平移向量的第一个参数(取绝对值)

2.测距部分代码和函数

import sys
import cv2
import numpy as np
import stereoconfig# 预处理
def preprocess(img1, img2):# 彩色图->灰度图if (img1.ndim == 3):  # 判断是否为三维数组img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)  # 通过OpenCV加载的图像通道顺序是BGRif (img2.ndim == 3):img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)# 直方图均衡img1 = cv2.equalizeHist(img1)img2 = cv2.equalizeHist(img2)return img1, img2# 消除畸变
def undistortion(image, camera_matrix, dist_coeff):undistortion_image = cv2.undistort(image, camera_matrix, dist_coeff)return undistortion_image# 获取畸变校正和立体校正的映射变换矩阵、重投影矩阵
# @param:config是一个类,存储着双目标定的参数:config = stereoconfig.stereoCamera()
def getRectifyTransform(height, width, config):# 读取内参和外参left_K = config.cam_matrix_leftright_K = config.cam_matrix_rightleft_distortion = config.distortion_lright_distortion = config.distortion_rR = config.RT = config.T# 计算校正变换R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(left_K, left_distortion, right_K, right_distortion,(width, height), R, T, alpha=0)map1x, map1y = cv2.initUndistortRectifyMap(left_K, left_distortion, R1, P1, (width, height), cv2.CV_32FC1)map2x, map2y = cv2.initUndistortRectifyMap(right_K, right_distortion, R2, P2, (width, height), cv2.CV_32FC1)return map1x, map1y, map2x, map2y, Q# 畸变校正和立体校正
def rectifyImage(image1, image2, map1x, map1y, map2x, map2y):rectifyed_img1 = cv2.remap(image1, map1x, map1y, cv2.INTER_AREA)rectifyed_img2 = cv2.remap(image2, map2x, map2y, cv2.INTER_AREA)return rectifyed_img1, rectifyed_img2# 立体校正检验----画线
def draw_line(image1, image2):# 建立输出图像height = max(image1.shape[0], image2.shape[0])width = image1.shape[1] + image2.shape[1]output = np.zeros((height, width, 3), dtype=np.uint8)output[0:image1.shape[0], 0:image1.shape[1]] = image1output[0:image2.shape[0], image1.shape[1]:] = image2# 绘制等间距平行线line_interval = 50  # 直线间隔:50for k in range(height // line_interval):cv2.line(output, (0, line_interval * (k + 1)), (2 * width, line_interval * (k + 1)), (0, 255, 0), thickness=2,lineType=cv2.LINE_AA)return output# 视差计算
def stereoMatchSGBM(left_image, right_image, down_scale=False):# SGBM匹配参数设置if left_image.ndim == 2:img_channels = 1else:img_channels = 3blockSize = 3paraml = {'minDisparity': 0,'numDisparities': 64,'blockSize': blockSize,'P1': 8 * img_channels * blockSize ** 2,'P2': 32 * img_channels * blockSize ** 2,'disp12MaxDiff': 1,'preFilterCap': 63,'uniquenessRatio': 15,'speckleWindowSize': 100,'speckleRange': 1,'mode': cv2.STEREO_SGBM_MODE_SGBM_3WAY}# 构建SGBM对象left_matcher = cv2.StereoSGBM_create(**paraml)paramr = paramlparamr['minDisparity'] = -paraml['numDisparities']right_matcher = cv2.StereoSGBM_create(**paramr)# 计算视差图size = (left_image.shape[1], left_image.shape[0])if down_scale == False:disparity_left = left_matcher.compute(left_image, right_image)disparity_right = right_matcher.compute(right_image, left_image)else:left_image_down = cv2.pyrDown(left_image)right_image_down = cv2.pyrDown(right_image)factor = left_image.shape[1] / left_image_down.shape[1]disparity_left_half = left_matcher.compute(left_image_down, right_image_down)disparity_right_half = right_matcher.compute(right_image_down, left_image_down)disparity_left = cv2.resize(disparity_left_half, size, interpolation=cv2.INTER_AREA)disparity_right = cv2.resize(disparity_right_half, size, interpolation=cv2.INTER_AREA)disparity_left = factor * disparity_leftdisparity_right = factor * disparity_right# 真实视差(因为SGBM算法得到的视差是×16的)trueDisp_left = disparity_left.astype(np.float32) / 16.trueDisp_right = disparity_right.astype(np.float32) / 16.return trueDisp_left, trueDisp_rightdef getDepthMapWithQ(disparityMap: np.ndarray, Q: np.ndarray) -> np.ndarray:points_3d = cv2.reprojectImageTo3D(disparityMap, Q)  # points_3d 是一个三维的数组,前面两个是宽和高,第三维是一个(x,y,z)的坐标points = points_3d[:, :, 0:3]depthMap = points_3d[:, :, 2]  # 索引三维数组的最后一维,就是深度信息reset_index = np.where(np.logical_or(depthMap < 0.0, depthMap > 65535.0))depthMap[reset_index] = 0return depthMap.astype(np.float32)if __name__ == '__main__':# 读取图片cap = cv2.VideoCapture(0)cap.set(3, 1280)cap.set(4, 480)  # 打开并设置摄像头while True:ret, frame = cap.read()iml = frame[0:480, 0:640]imr = frame[0:480, 640:1280]  # 分割双目图像if (iml is None) or (imr is None):print("Error: Images are empty, please check your image's path!")sys.exit(0)height, width = iml.shape[0:2]    # 对图像进行切片操作,前面两位是高和宽iml_, imr_ = preprocess(iml, imr)  # 预处理,一般可以削弱光照不均的影响,不做也可以# 读取相机内参和外参# 使用之前先将标定得到的内外参数填写到stereoconfig.py中的StereoCamera类中config = stereoconfig.stereoCamera()# print(config.cam_matrix_left)# 立体校正map1x, map1y, map2x, map2y, Q = getRectifyTransform(height, width, config)  # 获取用于畸变校正和立体校正的映射矩阵以及用于计算像素空间坐标的重投影矩阵iml_rectified, imr_rectified = rectifyImage(iml, imr, map1x, map1y, map2x, map2y)# print(Q)# 绘制等间距平行线,检查立体校正的效果line = draw_line(iml_rectified, imr_rectified)cv2.imwrite('check_rectification.png', line)# 立体匹配disp, _ = stereoMatchSGBM(iml_rectified, imr_rectified, False)  # 这里传入的是经立体校正的图像cv2.imwrite('disaprity.png', disp * 4)# fx = config.cam_matrix_left[0, 0]# fy = fx# cx = config.cam_matrix_left[0, 2]# cy = config.cam_matrix_left[1, 2]# print(fx, fy, cx, cy)# 计算像素点的3D坐标(左相机坐标系下)points_3d = cv2.reprojectImageTo3D(disp, Q)  # 参数中的Q就是由getRectifyTransform()函数得到的重投影矩阵# 设置想要检测的像素点坐标(x,y)x = 120y = 360cv2.circle(iml, (x, y), 5, (0, 0, 255), -1)# x1 = points_3d[y, x]   # 索引 (y, x) 对应的是三维坐标 (x1, y1, z1)# print(x1)print('x:', points_3d[int(y), int(x), 0], 'y:', points_3d[int(y), int(x), 1], 'z:',points_3d[int(y), int(x), 2])  # 得出像素点的三维坐标,单位mmprint('distance:', (points_3d[int(y), int(x), 0] ** 2 + points_3d[int(y), int(x), 1] ** 2 + points_3d[int(y), int(x), 2] ** 2) ** 0.5)  # 计算距离,单位mmcv2.namedWindow("disparity", 0)cv2.imshow("disparity", iml)# cv2.setMouseCallback("disparity", onMouse,  0)# 等待用户按键,如果按下 'q' 键或者 Esc 键,则退出循环c = cv2.waitKey(1) & 0xFFif c == 27 or c == ord('q'):break# 释放视频对象并关闭窗口cap.release()cv2.destroyAllWindows()

三.yolov5部分代码代码展示

# 读取相机内参和外参config = stereoconfig_040_2.stereoCamera()# 立体校正map1x, map1y, map2x, map2y, Q = getRectifyTransform(720, 1280, config)  # 获取用于畸变校正和立体校正的映射矩阵以及用于计算像素空间坐标的重投影矩阵for path, img, im0s, vid_cap in dataset:img = torch.from_numpy(img).to(device)img = img.half() if half else img.float()  # uint8 to fp16/32img /= 255.0  # 0 - 255 to 0.0 - 1.0if img.ndimension() == 3:img = img.unsqueeze(0)# Inferencet1 = time_synchronized()pred = model(img, augment=opt.augment)[0]# Apply NMSpred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms)t2 = time_synchronized()# Apply Classifierif classify:pred = apply_classifier(pred, modelc, img, im0s)# Process detectionsfor i, det in enumerate(pred):  # detections per imageif webcam:  # batch_size >= 1p, s, im0, frame = path[i], '%g: ' % i, im0s[i].copy(), dataset.countelse:p, s, im0, frame = path, '', im0s, getattr(dataset, 'frame', 0)################################stereo codefps_set = 10 #setting the frameif(accel_frame % fps_set == 0):#t3 = time.time() # stereo time start 0.510s#string = ''#thread = threading.Thread(target = mythread,args = ((config,im0,map1x, map1y, map2x, map2y,Q)) )thread= MyThread(stereo_threading,args = (config,im0,map1x, map1y, map2x, map2y,Q))thread.start()#if(accel_frame % fps_set == 0):#    thread.join()#points_3d = thread.get_result()print()print(threading.active_count())                              #获取已激活的线程数print(threading.enumerate())    # see the thread list,查看所有线程信息,一个<_MainThread(...)> 带多个 <Thread(...)>print()print("############## Frame is %d !##################" %accel_frame)p = Path(p)  # to Pathif webcam:save_stream_path = str(save_stream_dir / "stream0.mp4")  # save streams pathelse:   save_path = str(save_dir / p.name)  # img.jpgtxt_path = str(save_dir / 'labels' / p.stem) + ('' if dataset.mode == 'image' else f'_{frame}')  # img.txts += '%gx%g ' % img.shape[2:]  # print string#print("txt_path is %s"%txt_path)gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwhif len(det):# Rescale boxes from img_size to im0 sizedet[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()# Print resultsfor c in det[:, -1].unique():n = (det[:, -1] == c).sum()  # detections per classs += f"{n} {names[int(c)]} {'s' * (n > 1)} , "  # add to string

本项目不开源,需要的私聊 ,谢谢

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/113700.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博客系统中的加盐算法

目录 一、为什么要对密码进行加盐加密&#xff1f; 1、明文 2、传统的 MD5 二、加盐加密 1、加盐算法实现思路 2、加盐算法解密思路 3、加盐算法代码实现 三、使用 Spring Security 加盐 1、引入 Spring Security 框架 2、排除 Spring Security 的自动加载 3、调用 S…

CSS常见的预处理器有哪些?

CSS常见的预处理器有以下几种&#xff1a; 1&#xff1a;Sass&#xff08;Syntactically Awesome Style Sheets&#xff09;&#xff1a;Sass是一种成熟且广泛使用的CSS预处理器。它提供了许多功能&#xff0c;如变量、嵌套规则、混合&#xff08;Mixins&#xff09;、继承&am…

EF执行迁移时提示provider: SSL Provider, error: 0 - 证书链是由不受信任的颁发机构颁发的

ef在执行时提示provider: SSL Provider, error: 0 - 证书链是由不受信任的颁发机构颁发的。 只需要在数据库链接字符串后增加EncryptTrue;TrustServerCertificateTrue;即可 再次执行

Qt第六十六章:展示数据的标签

目录 一、效果图 二、qtDesigner ①拖出一个frame作为组容器并贴上背景样式 ②拖出主要的三个控件&#xff1a;frame、line、frame、label*2 ③固定大小并设置字体、布局一下 ④拷贝三份并水平布局一下 ⑤设置样式 ⑥调整布局 三、ui文件 四、代码 一、效果图 二、qtD…

【Java 进阶篇】深入了解 Bootstrap 全局 CSS 样式

Bootstrap 是一个流行的前端框架&#xff0c;以其强大的全局 CSS 样式而闻名。这些样式能够帮助开发者快速创建漂亮的、响应式的网页&#xff0c;而无需从头编写复杂的 CSS。在本文中&#xff0c;我们将深入探讨 Bootstrap 的全局 CSS 样式&#xff0c;适合初学者&#xff0c;帮…

C#通过Entity Framework实体对数据表增删改查

目录 一、创建实体数据模型 1.建立数据库连接 2.建立EF实体模型 二.设计窗体和EF应用 1.窗体设计 2.应用程序设计 3.源码 4.生成效果 &#xff08;1&#xff09;查询 &#xff08;2&#xff09;修改 &#xff08;3&#xff09;删除 &#xff08;4&#xff09;增加 …

[AUTOSAR][诊断管理][$11] 复位服务

文章目录 一、简介(1) 应用场景&#xff08;2&#xff09; 请求格式&#xff08;3&#xff09; 重启类型 二、示例代码(1) 11_ecu_reset.c 一、简介 ECU复位服务就是可以此诊断指令来命令ECU执行自复位&#xff0c;复位有多种形式&#xff0c;依据子功能参数来区分&#xff08…

Excel函数中单元格的引用方式

如下图在D列第一行输入sum(A1:C1)&#xff1b; 回车之后结果如下&#xff1b;先要输入等号&#xff0c;然后输入sum&#xff0c;以及左括号&#xff0c;这是调用了sum求和函数&#xff1b; A1表示A列第一行&#xff0c;C1表示C列第一行&#xff1b; A1:C1&#xff0c;中间是冒号…

数字图像处理实验记录五(图像的空间域增强-锐化处理)

前言&#xff1a; 文章目录 一、基础知识1&#xff0c;什么是锐化&#xff1f;2&#xff0c;为什么要锐化&#xff1f;3&#xff0c;怎么进行锐化&#xff1f; 二、实验要求任务1&#xff1a;任务2&#xff1a;任务3&#xff1a; 三、实验记录&#xff1a;任务1&#xff1a;任…

一步一步分析ChatGPT,1 粘性,2 传染性, 3 双边网络效应

请按照以下三个维度一步一步分析ChatGPT&#xff0c;1 粘性&#xff0c;2 传染性&#xff0c; 3 双边网络效应&#xff0c;比如亚马逊的买家和商家的关系 ChatGPT的分析 1.1. 粘性 (Stickiness) 定义&#xff1a; 粘性是指产品或服务对用户的吸引力&#xff0c;即用户在使用…

【Java 进阶篇】深入了解 Bootstrap 组件

Bootstrap 是一个流行的前端框架&#xff0c;提供了丰富的组件&#xff0c;用于创建各种网页元素和交互效果。这些组件可以帮助开发者轻松构建漂亮、响应式的网页&#xff0c;而无需深入的前端开发知识。在本文中&#xff0c;我们将深入探讨 Bootstrap 中一些常用的组件&#x…

自然语言处理---Transformer机制详解之ELMo模型介绍

1 ELMo简介 ELMo是2018年3月由华盛顿大学提出的一种预训练模型. ELMo的全称是Embeddings from Language Models.ELMo模型的提出源于论文<< Deep Contextualized Word Representations >>.ELMo模型提出的动机源于研究人员认为一个好的预训练语言模型应该能够包含丰…

DataX-web安装部署和使用

DataX-web的环境准备 MySQL (5.5) 必选&#xff0c;对应客户端可以选装, Linux服务上若安装mysql的客户端可以通过部署脚本快速初始化数据库 JDK (1.8.0_xxx) 必选 DataX 必选 Python (2.x) (支持Python3需要修改替换datax/bin下面的三个python文件&#xff0c;替换文件在do…

飞书-多维文档-计算时间差

1. 选择字段类型 如图所示&#xff0c;字段类型选择 公式 2. 编辑公式 单击 公式编辑器 在弹出的公式编辑框中输入公式 TEXT([终结时间]-[开始时间],"HH:MM") [终结时间] 和 [开始时间] 请替换成你的表格中对应的字段名称HH:MM 表示输出的时间格式为 时:分其中 “…

黑豹程序员-架构师学习路线图-百科:Maven

文章目录 1、什么是maven官网下载地址 2、发展历史3、Maven的伟大发明 1、什么是maven Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project’s build, reporting and…

【算法挨揍日记】day16——525. 连续数组、1314. 矩阵区域和

525. 连续数组 525. 连续数组 题目描述&#xff1a; 给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组&#xff0c;并返回该子数组的长度。 解题思路&#xff1a; 本题的元素只有0和1&#xff0c;根据题目意思&#xff0c;我们可以把题目看成找一段最…

通讯网关软件028——利用CommGate X2Modbus实现Modbus RTU访问PI服务器

本文介绍利用CommGate X2Modbus实现Modbus RTU访问PI数据库。CommGate X2MODBUS是宁波科安网信开发的网关软件&#xff0c;软件可以登录到网信智汇(http://wangxinzhihui.com)下载。 【案例】如下图所示&#xff0c;实现上位机通过Modbus RTU来获取PI数据库的数据。 【解决方案…

YOLOv8改进实战 | 更换主干网络Backbone(二)之轻量化模型GhostnetV2

前言 轻量化网络设计是一种针对移动设备等资源受限环境的深度学习模型设计方法。下面是一些常见的轻量化网络设计方法: 网络剪枝:移除神经网络中冗余的连接和参数,以达到模型压缩和加速的目的。分组卷积:将卷积操作分解为若干个较小的卷积操作,并将它们分别作用于输入的不…

基于nodejs+vue语言的酒店管理系统

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Visual Components软件有哪些用途 衡祖仿真

Visual Components是一款用于制造业虚拟仿真的软件&#xff0c;主要用于工业自动化和制造领域。我们一起来看一下该软件有哪些功能吧&#xff01; 1、工厂仿真 Visual Components可以建立虚拟的工厂环境&#xff0c;模拟和优化生产流程。用户可以创建工厂布局、定义设备和机器人…