毕业设计 基于双目立体视觉的图像匹配与测距


0 项目说明

基于双目立体视觉的图像匹配与测距

提示:适合用于课程设计或毕业设计,工作量达标,源码开放


1 研究目的

双目立体视觉是计算机视觉范畴的核心之一,它利用双目相机来获得目标物体的图像,经过物体图像处理之后得到目标物体所在场景环境的三维信息,最终实现非接触条件下测距,简单便捷。

本次毕业设计主要内容为研究基于双目立体视觉平台上的图像匹配以及目标物体的距离测量技术,图像特征提取部分研究了 SIFT 算法和 SURF 算法,特征匹配部分研究了 BF 法和 FLANN 法,距离测量研究主要通过视差深度的计算,结合视觉坐标系的转换实现三维位置的定位与测量。

2 研究方法

(1)在对相机成像和坐标系原理研究的基础上,依托维视双目立体视觉测量平台 MV-VS220 实现了双目相机标定,以及目标物体图像数据采集。

(2)在灰度化、二值化以及加噪等必要图像预处理的基础上,研究 SIFT、SURF 特征点提取与匹配算法,进行实验并显示提取和匹配效果;研究测距模型和视差深度计算目标物体的深度信息,进行实验并获取测量结果,对测量误差进行分析与讨论。

(3)基于维视双目立体视觉测量平台 MV-VS220,采用 Python+OpenCV 开发工具,设计实现了一个双目立体视觉图像匹配与测距原型系统,可实现对关键环节的过程与结果的演示,以及不同算法的性能比较

3 研究结论

系统可实现对关键环节的过程与结果的演示,以及不同算法的性能比较。系统测试表明,所开发的原型演示系统从界面、功能与性能方面均达到了设计的要求。
在这里插入图片描述

4 项目源码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'mainimagewidget.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from MVGigE import *
import os
import shutil
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout, QPushButton, QMessageBox, QLabel, QFileDialog, QScrollArea, QComboBox, QLineEdit, QSlider, QGridLayout, QGroupBox, QCheckBox
from PyQt5.QtGui import QPixmap, QPalette, QImage, QIcon
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form_Image(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(800, 600)
        self.btnStartGrab = QtWidgets.QPushButton(Form)
        self.btnStartGrab.setGeometry(QtCore.QRect(210, 70, 100, 35))
        self.btnStartGrab.setStyleSheet("font: bold 14pt \"汉仪喵魂体W\";\n"
"color: rgb(255, 255, 255);\n"
"border:2px solid;\n"
"border-color: rgb(255, 255, 255);\n"
"background-color: rgb(242, 216, 121);")
        self.btnStartGrab.setObjectName("btnStartGrab")
        self.btnStopGrab = QtWidgets.QPushButton(Form)
        self.btnStopGrab.setGeometry(QtCore.QRect(350, 70, 100, 35))
        self.btnStopGrab.setStyleSheet("font: bold 14pt \"汉仪喵魂体W\";\n"
"color: rgb(255, 255, 255);\n"
"border:2px solid;\n"
"border-color: rgb(255, 255, 255);\n"
"background-color: rgb(242, 216, 121);")
        self.btnStopGrab.setObjectName("btnStopGrab")
        self.ResultLabel = QtWidgets.QLabel(Form)
        self.ResultLabel.setGeometry(QtCore.QRect(70, 485, 660, 70))
        self.ResultLabel.setStyleSheet("font: 12pt \"汉仪喵魂体W\";\n"
"color: rgb(0, 0, 0);\n"
"border:2px solid;\n"
"border-color: rgb(255, 255, 255);\n"
"background-color: rgb(242, 216, 121);")
        self.ResultLabel.setObjectName("ResultLabel")
        self.frame = QtWidgets.QFrame(Form)
        self.frame.setGeometry(QtCore.QRect(0, 0, 800, 600))
        self.frame.setStyleSheet("border-image: url(:/newPrefix/img/background.jpg);")
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.btnSaveImage = QtWidgets.QPushButton(Form)
        self.btnSaveImage.setGeometry(QtCore.QRect(490, 70, 100, 35))
        self.btnSaveImage.setStyleSheet("font: bold 14pt \"汉仪喵魂体W\";\n"
"color: rgb(255, 255, 255);\n"
"border:2px solid;\n"
"border-color: rgb(255, 255, 255);\n"
"background-color: rgb(242, 216, 121);")
        self.btnSaveImage.setObjectName("btnSaveImage")
        self.btnCloseCam = QtWidgets.QPushButton(Form)
        self.btnCloseCam.setGeometry(QtCore.QRect(630, 70, 100, 35))
        self.btnCloseCam.setStyleSheet("font: bold 14pt \"汉仪喵魂体W\";\n"
"color: rgb(255, 255, 255);\n"
"border:2px solid;\n"
"border-color: rgb(255, 255, 255);\n"
"background-color: rgb(242, 216, 121);")
        self.btnCloseCam.setObjectName("btnCloseCam")
        self.RLabel = QtWidgets.QLabel(Form)
        self.RLabel.setGeometry(QtCore.QRect(405, 135, 325, 331))
        self.RLabel.setStyleSheet("font: 14pt \"汉仪喵魂体W\";\n"
"color: rgb(255, 255, 255);\n"
"border:2px;\n"
"border-style:dotted;\n"
"border-color: rgb(242, 216, 121);")
        self.RLabel.setObjectName("RLabel")
        self.LLabel = QtWidgets.QLabel(Form)
        self.LLabel.setGeometry(QtCore.QRect(70, 135, 325, 331))
        self.LLabel.setStyleSheet("font: 14pt \"汉仪喵魂体W\";\n"
"color: rgb(255, 255, 255);\n"
"border:2px;\n"
"border-style:dotted;\n"
"border-color: rgb(242, 216, 121);")
        self.LLabel.setObjectName("LLabel")
        self.btnOpenCam = QtWidgets.QPushButton(Form)
        self.btnOpenCam.setGeometry(QtCore.QRect(70, 70, 100, 35))
        self.btnOpenCam.setStyleSheet("font: bold 14pt \"汉仪喵魂体W\";\n"
"color: rgb(255, 255, 255);\n"
"border:2px solid;\n"
"border-color: rgb(255, 255, 255);\n"
"background-color: rgb(242, 216, 121);")
        self.btnOpenCam.setObjectName("btnOpenCam")
        self.frame.raise_()
        self.btnStartGrab.raise_()
        self.btnStopGrab.raise_()
        self.ResultLabel.raise_()
        self.btnSaveImage.raise_()
        self.btnCloseCam.raise_()
        self.RLabel.raise_()
        self.LLabel.raise_()
        self.btnOpenCam.raise_()

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.btnStartGrab.setText(_translate("Form", "采集图像"))
        self.btnStopGrab.setText(_translate("Form", "停止采集"))
        self.ResultLabel.setText(_translate("Form", "结果显示区域"))
        self.btnSaveImage.setText(_translate("Form", "保存图像"))
        self.btnCloseCam.setText(_translate("Form", "关闭相机"))
        self.RLabel.setText(_translate("Form", "右图像区域"))
        self.LLabel.setText(_translate("Form", "左图像区域"))
        self.btnOpenCam.setText(_translate("Form", "启动相机"))

# -------------------------设置按钮点击事件-------------------------------------
        self.btnOpenCam.clicked.connect(self.openCam)
        self.btnStartGrab.clicked.connect(self.startGrab)
        self.btnStopGrab.clicked.connect(self.stopGrab)
        self.btnCloseCam.clicked.connect(self.closeCam)
        self.btnSaveImage.clicked.connect(self.saveImage)

    # 点击启动相机按钮,开始打开左右相机
    def openCam(self):
        r = MVInitLib()  # 初始化函数库
        if (r != MVSTATUS_CODES.MVST_SUCCESS):
            msgBox = QMessageBox(QMessageBox.Warning, '提示', '函数库初始化失败!')
            msgBox.exec()
            return
        r = MVUpdateCameraList()  # 查找连接到计算机上的相机
        if (r != MVSTATUS_CODES.MVST_SUCCESS):
            msgBox = QMessageBox(QMessageBox.Warning, '提示', '查找连接计算机失败!')
            msgBox.exec()
            return
        nCams = MVGetNumOfCameras()  # 获取相机数量
        if (nCams.status != MVSTATUS_CODES.MVST_SUCCESS):
            msgBox = QMessageBox(QMessageBox.Warning, '提示', nCams.status)
            msgBox.exec()
            return
        if (nCams.num == 0):
            msgBox = QMessageBox(QMessageBox.Warning, '提示', '没有找到相机,请确认连接和相机IP设置!')
            msgBox.exec()
            return

        # 左相机
        hCam = MVOpenCamByIndex(0)  # 根据相机的索引返回相机句柄
        if (hCam.hCam == 0):
            if (hCam.status == MVSTATUS_CODES.MVST_ACCESS_DENIED):
                msgBox = QMessageBox(QMessageBox.Warning, '提示', '无法打开相机,可能正被别的软件控制!')
                msgBox.exec()
                return
            else:
                msgBox = QMessageBox(QMessageBox.Warning, '提示', '无法打开相机!')
                msgBox.exec()
                return
        w = MVGetWidth(hCam.hCam)  # 获取图像宽度
        h = MVGetHeight(hCam.hCam)  # 获取图像高度
        pf = MVGetPixelFormat(hCam.hCam)  # 获取图像格式
        self.hCam = hCam.hCam
        self.width = w.width
        self.height = h.height
        self.pixelFormat = pf.pixelFormat
        if (self.pixelFormat == MV_PixelFormatEnums.PixelFormat_Mono8):
            self.himage = MVImageCreate(self.width, self.height, 8).himage  # 创建图像句柄
        else:
            self.himage = MVImageCreate(self.width, self.height, 24).himage  # 创建图像句柄
        # self.LLImage.resize(self.width * 0.25, self.height * 0.25)
        self.LLabel.resize(self.width * 0.25, self.height * 0.35)
        self.LLabel.setText("左相机检测正常!")
        # self.ResultLlabel.setText("左相机检测正常!")

        # 右相机
        hCam2 = MVOpenCamByIndex(1)  # 根据相机的索引返回相机句柄
        if (hCam2.hCam == 0):
            if (hCam2.status == MVSTATUS_CODES.MVST_ACCESS_DENIED):
                msgBox = QMessageBox(QMessageBox.Warning, '提示', '无法打开相机,可能正被别的软件控制!')
                msgBox.exec()
                return
            else:
                msgBox = QMessageBox(QMessageBox.Warning, '提示', '无法打开相机!')
                msgBox.exec()
                return
        w2 = MVGetWidth(hCam2.hCam)  # 获取图像宽度
        h2 = MVGetHeight(hCam2.hCam)  # 获取图像高度
        pf2 = MVGetPixelFormat(hCam2.hCam)  # 获取图像格式
        self.hCam2 = hCam2.hCam
        self.width2 = w2.width
        self.height2 = h2.height
        self.pixelFormat2 = pf2.pixelFormat
        if (self.pixelFormat2 == MV_PixelFormatEnums.PixelFormat_Mono8):
            self.himage2 = MVImageCreate(self.width2, self.height2, 8).himage  # 创建图像句柄
        else:
            self.himage2 = MVImageCreate(self.width2, self.height2, 24).himage  # 创建图像句柄
        # self.LRImage.resize(self.width2 * 0.25, self.height2 * 0.25)
        self.RLabel.resize(self.width * 0.25, self.height * 0.35)
        self.RLabel.setText("右相机检测正常!")
        # self.ResultLlabel.setText("右相机检测正常!")

        self.ResultLabel.setText("相机启动正常!")

    # 点击采集图像按钮,相机开始采集执行本函数
    def startGrab(self):
        self.winid = self.LLabel.winId()  # 获取label对象的句柄
        mode = MVGetTriggerMode(self.hCam)  # 获取当前相机采集模式
        source = MVGetTriggerSource(self.hCam)  # 获取当前相机信号源
        self.winid2 = self.RLabel.winId()  # 获取label对象的句柄
        mode2 = MVGetTriggerMode(self.hCam2)  # 获取当前相机采集模式
        source2 = MVGetTriggerSource(self.hCam2)  # 获取当前相机信号源
        if (self.btnStartGrab.text() == '采集图像'):
            if ((mode.pMode == TriggerModeEnums.TriggerMode_Off) & (mode2.pMode == TriggerModeEnums.TriggerMode_Off)):  # 当触发模式关闭的时候,界面的行为
                # self.btnStartGrab.setText('停止采集')
                MVStartGrabWindow(self.hCam, self.winid)  # 将采集的图像传输到指定窗口
                MVStartGrabWindow(self.hCam2, self.winid2)  # 将采集的图像传输到指定窗口
            else:
                if ((source.source == TriggerSourceEnums.TriggerSource_Software) & (source2.source == TriggerSourceEnums.TriggerSource_Software)):  # 当触发模式打开且为软触发的时候,界面的行为
                    MVStartGrabWindow(self.hCam, self.winid)  # 将采集的图像传输到指定窗口
                    MVStartGrabWindow(self.hCam2, self.winid2)  # 将采集的图像传输到指定窗口
                    MVTriggerSoftware(self.hCam)
                    MVTriggerSoftware(self.hCam2)
                else:  # 当触发模式打开且为外触发的时候,界面的行为
                    MVStartGrabWindow(self.hCam, self.winid)  # 将采集的图像传输到指定窗口
                    MVStartGrabWindow(self.hCam2, self.winid2)  # 将采集的图像传输到指定窗口
            self.ResultLabel.setText("图像采集开始!")
        # else:
        #     self.btnStartGrab.setText('开始采集')
        #     MVStopGrabWindow(self.hCam)  # 停止采集
        #     MVStopGrabWindow(self.hCam2)  # 停止采集
        #     self.btnStopGrab.setEnabled(False)
        #     self.ResultLabel.setText("图像采集停止!")

    # 暂停或者继续执行本函数
    def stopGrab(self):
        if (self.btnStopGrab.text() == '继续采集'):
            self.btnStopGrab.setText('暂停采集')
            MVFreezeGrabWindow(self.hCam, False)  # 恢复图像传输到左窗口
            MVFreezeGrabWindow(self.hCam2, False)  # 恢复将图像传输到右窗口
            self.ResultLabel.setText("图像采集继续!")
        else:
            self.btnStopGrab.setText('继续采集')
            MVFreezeGrabWindow(self.hCam, True)  # 暂停将图像传输到左窗口
            MVFreezeGrabWindow(self.hCam2, True)  # 暂停将图像传输到右窗口
            self.ResultLabel.setText("图像采集暂停!")


    # 保存图片执行本函数,在非触发模式时,只有采集暂停是才可以保存
    def saveImage(self):

        idn = MVGetSampleGrab(self.hCam, self.himage)
        print("01")
        fname = QFileDialog.getSaveFileName(
            self, '打开文件', './Images' + str(idn.idn) + '.bmp', ("Images (*.bmp *.jpg *.tif *.raw)"))
        print("02")
        filename = os.path.basename(fname[0])  # 获取到需要存储的文件名
        pathname = os.path.join(os.getcwd(), filename)  # 获取带有文件名的文件路径
        newfile = '\\'.join(fname[0].split('/')[:-1])  # 需要存储到的新文件夹
        print("03")
        MVImageSave(self.himage, filename.encode('utf-8'))  # 将图片保存下来
        print("04")
        if (newfile != os.getcwd()):  # 将图片移动到指定文件夹下
            try:
                shutil.move(pathname, newfile)
            except:
                os.unlink(os.path.join(newfile, filename))
                shutil.move(pathname, newfile)
        image = QImage(newfile + '\\' + filename)
        self.label.setPixmap(QPixmap.fromImage(image))  # 加载图片
        mode = MVGetTriggerMode(self.hCam)  # 获取当前相机采集模式

        #保存左图像
        # idn = MVGetSampleGrab(self.hCam, self.himage)
        # fname = QFileDialog.getSaveFileName(
        #     self, '打开文件', './Images' + str(idn.idn) + '.bmp', ("Images (*.bmp *.jpg *.tif *.raw)"))
        # filename = os.path.basename(fname[0])  # 获取到需要存储的文件名
        # pathname = os.path.join(os.getcwd(), filename)  # 获取带有文件名的文件路径
        # newfile = '\\'.join(fname[0].split('/')[:-1])  # 需要存储到的新文件夹
        # MVImageSave(self.himage, filename.encode('utf-8'))  # 将图片保存下来
        # if (newfile != os.getcwd()):  # 将图片移动到指定文件夹下
        #     try:
        #         shutil.move(pathname, newfile)
        #     except:
        #         os.unlink(os.path.join(newfile, filename))
        #         shutil.move(pathname, newfile)
        # image = QImage(newfile + '\\' + filename)
        # self.LLabel.setPixmap(QPixmap.fromImage(image))  # 加载图片

        #保存右图像
        # idn = MVGetSampleGrab(self.hCam2, self.himage2)
        # fname = QFileDialog.getSaveFileName(
        #     self, '打开文件', './Images' + str(idn.idn) + '.bmp', ("Images (*.bmp *.jpg *.tif *.raw)"))
        # filename = os.path.basename(fname[0])  # 获取到需要存储的文件名
        # pathname = os.path.join(os.getcwd(), filename)  # 获取带有文件名的文件路径
        # newfile = '\\'.join(fname[0].split('/')[:-1])  # 需要存储到的新文件夹
        # MVImageSave(self.himage2, filename.encode('utf-8'))  # 将图片保存下来
        # if (newfile != os.getcwd()):  # 将图片移动到指定文件夹下
        #     try:
        #         shutil.move(pathname, newfile)
        #     except:
        #         os.unlink(os.path.join(newfile, filename))
        #         shutil.move(pathname, newfile)
        # image2 = QImage(newfile + '\\' + filename)
        # self.RLabel.setPixmap(QPixmap.fromImage(image2))  # 加载图片

        self.ResultLabel.setText("图像保存正常!")

    # 点击关闭相机按钮,开始关闭相机
    def closeCam(self):
        result = MVCloseCam(self.hCam)# 关闭左相机
        result2 = MVCloseCam(self.hCam2)# 关闭右相机
        if (result.status != MVSTATUS_CODES.MVST_SUCCESS):
            msgBox = QMessageBox(QMessageBox.Warning, '提示', result.status)
            msgBox.exec()
        if (result2.status != MVSTATUS_CODES.MVST_SUCCESS):
            msgBox = QMessageBox(QMessageBox.Warning, '提示', result.status)
            msgBox.exec()

        self.ResultLabel.setText("相机关闭成功!")
import img

import sys
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Ui_Form_Image()
    # 显示
    window.show()
    sys.exit(app.exec_())

5 最后

**项目分享: ** https://gitee.com/asoonis/htw

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MATLAB基于双目立体视觉测距系统设计,可以实现通过双目摄像头获取图像信息,通过图像处理算法计算目标物体的距离。 首先,通过MATLAB中的图像处理工具箱,读取双目摄像头获取的图像数据。双目摄像头提供了左右两个摄像头的图像,通过对这两幅图像进行处理,可以得到立体视觉效果。 接下来,使用MATLAB中的立体视觉工具箱,对左右两幅图像进行匹配和校正处理。这一步可以通过计算两幅图像之间的视差信息来确定目标物体在图像中的位置。 然后,根据视差信息和双目横向基线长度,通过三角测距原理计算目标物体的距离。三角测距原理是利用两个不同位置的摄像头对同一目标物体进行观察,根据两个观察点之间的视差以及相机参数,计算目标物体的距离。 最后,通过MATLAB绘图工具箱实现结果的可视化。可以将测得的距离值显示在屏幕上,同时绘制出目标物体在图像中的位置,以便用户观察和分析。 在系统设计中,还可以通过降噪、滤波等图像处理技术进一步优化图像质量,提高系统测距的准确性和稳定性。 总之,MATLAB基于双目立体视觉测距系统设计可以实现通过双目摄像头获取图像信息,并通过图像处理和视差计算来实现目标物体的测距功能。这个系统可以在机器人导航、智能驾驶、机器视觉等领域得到广泛的应用。 ### 回答2: MATLAB是一种功能强大的科学计算软件,可用于开发基于双目立体视觉测距系统。在这个系统设计中,我们利用双目立体视觉原理来计算物体与相机之间的距离。 首先,我们需要使用两个摄像头来模拟双目视觉系统。每个摄像头分别捕捉场景的实时图像。然后,我们使用MATLAB中的图像处理工具箱来对这些图像进行预处理。例如,我们可以对图像进行去噪、增强和校正等处理,以提高图像质量和准确度。 接下来,我们需要对预处理后的图像进行特征提取。特征可以是物体的边缘、角点或其他可区分性强的信息。我们可以使用MATLAB中的计算机视觉工具箱来实现这一步骤。特征提取后,我们可以计算相机对应特征点之间的视差。 视差是指同一物体在两个图像中对应特征点的像素差。通过计算视差,我们可以获得物体在图像中的位置差异,从而推断出物体与相机之间的距离。这个过程可以使用MATLAB中的视差计算算法来实现。 最后,我们可以使用计算得到的视差与已知的相机参数进行距离计算。相机参数包括摄像头之间的距离、焦距和像素大小等。通过将这些参数与视差的像素值进行比例运算,我们可以得到物体与相机之间的实际距离。 在MATLAB中,我们可以使用图形用户界面(GUI)来设计这个测距系统。通过GUI,用户可以实时查看摄像头捕获的图像,并将计算得到的距离显示在屏幕上。此外,我们还可以加入实时图像标定和目标跟踪等功能,以增强这个测距系统的实用性和可扩展性。 综上所述,MATLAB基于双目立体视觉测距系统设计可以通过预处理、特征提取、视差计算和距离计算等步骤来实现。这个系统可以帮助我们准确测量物体与相机之间的距离,并具有较高的实时性和可扩展性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值