精华内容
下载资源
问答
  • 双目测距

    2012-11-29 18:59:00
  • 前言在上一章我们介绍了《双目摄像头测量距离》,在这个基础上,我们来了解如何在Android上使用双目测距算法。通过本教程,你不仅掌握如何在Android中使用SBM等双目测距算法,顺便也了解到如何在Android Studio配置...

    cc9ecd68132abf7b4278dc779999a7bd.png

    前言

    在上一章我们介绍了《双目摄像头测量距离》,在这个基础上,我们来了解如何在Android上使用双目测距算法。通过本教程,你不仅掌握如何在Android中使用SBM等双目测距算法,顺便也了解到如何在Android Studio配置OpenCV,通过使用OpenCV可以在Android中实现很多图像处理的功能。

    配置OpenCV

    下载OpenCV的Android版本源码,官网下载地址:https://opencv.org/releases/,如果读者无法下载,笔者也提供的源码下载,版本是3.4.1的,下载地址:https://resource.doiduoyi.com/#736y3wk。

    1、创建一个Android项目,解压源码压缩包,在Android Studio中点击File--->Import Model,然后浏览解压后的sdk/java添加,如下图所示,如何正常的话会显示OpenCV的版本。

    e292117b00f7e31c63f5fc14f9290418.png

    2、复制OpenCV的动态库到app/libs目录下。

    3、修改OpenCVLibrary的build.gradle的内容,这些内容全都都是app/build.gradle的内容,主要把applicationId去掉。

    apply plugin: 'com.android.library'
    android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
    minSdkVersion 22
    targetSdkVersion 29
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}
    buildTypes {
    release {
    minifyEnabled false
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}}

    4、修改OpenCVLibrary的AndroidManifest.xml,内容大概如下,其中版本号对应自己导入的OpenCV的版本。

    <?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"package="org.opencv"
    android:versionCode="3410"
    android:versionName="3.4.1"></manifest>

    5、最后修改app/build.gradle的内容。

    // 在android下添加以下代码
    sourceSets {
    main {
    jniLibs.srcDirs = ['libs']}}// 在dependencies添加一下代码,根据情况修改版本号
    implementation project(path: ':openCVLibrary341')

    6、测试OpenCV,在应用中执行以下代码,如果初始化OpenCv成功,那配置OpenCV就已经成功了。

    if (OpenCVLoader.initDebug()) {
    Log.d(TAG, "OpenCVLoader初始化成功");}

    双目测距

    创建一个StereoBMUtil.java的java工具类,通过这类可以方便其他程序调用。在构造方法中配置StereoBM算法的一下参数,有些参数是相机标定的参数,具体用法参考《双目摄像头测量距离》这篇文章。更加这篇教程,完成修改StereoBM算的相机标定的参数。

        public StereoBMUtil() {
    Mat cameraMatrixL = new Mat(3, 3, CvType.CV_64F);
    Mat distCoeffL = new Mat(5, 1, CvType.CV_64F);
    Mat cameraMatrixR = new Mat(3, 3, CvType.CV_64F);
    Mat distCoeffR = new Mat(5, 1, CvType.CV_64F);
    Mat T = new Mat(3, 1, CvType.CV_64F);
    Mat rec = new Mat(3, 1, CvType.CV_64F);// 【需要根据摄像头修改参数】左目相机标定参数 fc_left_x 0 cc_left_x 0 fc_left_y cc_left_y 0 0 1
    cameraMatrixL.put(0, 0, 849.38718, 0, 720.28472, 0, 850.60613, 373.88887, 0, 0, 1);//【需要根据摄像头修改参数】左目相机标定参数 kc_left_01, kc_left_02, kc_left_03, kc_left_04, kc_left_05
    distCoeffL.put(0, 0, 0.01053, 0.02881, 0.00144, 0.00192, 0.00000);//【需要根据摄像头修改参数】右目相机标定参数 fc_right_x 0 cc_right_x 0 fc_right_y cc_right_y 0 0 1
    cameraMatrixR.put(0, 0, 847.54814, 0, 664.36648, 0, 847.75828, 368.46946, 0, 0, 1);//【需要根据摄像头修改参数】右目相机标定参数 kc_right_01, kc_right_02, kc_right_03, kc_right_04, kc_right_05
    distCoeffR.put(0, 0, 0.00905, 0.02094, 0.00082, 0.00183, 0.00000);//【需要根据摄像头修改参数】T平移向量
    T.put(0, 0, -59.32102, 0.27563, -0.79807);// 【需要根据摄像头修改参数】rec旋转向量
    rec.put(0, 0, -0.00927, -0.00228, -0.00070);
    Size imageSize = new Size(imageWidth, imageHeight);
    Mat R = new Mat();
    Mat Rl = new Mat();
    Mat Rr = new Mat();
    Mat Pl = new Mat();
    Mat Pr = new Mat();
    Rect validROIL = new Rect();
    Rect validROIR = new Rect();
    Calib3d.Rodrigues(rec, R); //Rodrigues变换//图像校正之后,会对图像进行裁剪,这里的validROI就是指裁剪之后的区域
    Calib3d.stereoRectify(cameraMatrixL, distCoeffL, cameraMatrixR, distCoeffR, imageSize, R, T, Rl, Rr, Pl, Pr, Q, Calib3d.CALIB_ZERO_DISPARITY,0, imageSize, validROIL, validROIR);
    Imgproc.initUndistortRectifyMap(cameraMatrixL, distCoeffL, Rl, Pl, imageSize, CvType.CV_32FC1, mapLx, mapLy);
    Imgproc.initUndistortRectifyMap(cameraMatrixR, distCoeffR, Rr, Pr, imageSize, CvType.CV_32FC1, mapRx, mapRy);
    int blockSize = 18;
    int numDisparities = 11;
    int uniquenessRatio = 5;
    bm.setBlockSize(2 * blockSize + 5); //SAD窗口大小
    bm.setROI1(validROIL); //左右视图的有效像素区域
    bm.setROI2(validROIR);
    bm.setPreFilterCap(61); //预处理滤波器
    bm.setMinDisparity(32); //最小视差,默认值为0, 可以是负值,int型
    bm.setNumDisparities(numDisparities * 16); //视差窗口,即最大视差值与最小视差值之差,16的整数倍
    bm.setTextureThreshold(10);
    bm.setUniquenessRatio(uniquenessRatio); //视差唯一性百分比,uniquenessRatio主要可以防止误匹配
    bm.setSpeckleWindowSize(100); //检查视差连通区域变化度的窗口大小
    bm.setSpeckleRange(32); //32视差变化阈值,当窗口内视差变化大于阈值时,该窗口内的视差清零
    bm.setDisp12MaxDiff(-1);}

    创建一个compute()方法,该方法的参数是Bitmap类型的左右目摄像头的图像。compute()方法的返回值是图像计算图像结果转换的图像,这给图像可以很直观显示图像的距离。计算结果都存放在xyz矩阵中。

        public Bitmap compute(Bitmap left, Bitmap right) {
    Mat rgbImageL = new Mat();
    Mat rgbImageR = new Mat();
    Mat grayImageL = new Mat();
    Mat rectifyImageL = new Mat();
    Mat rectifyImageR = new Mat();
    Mat grayImageR = new Mat();//用于存放每个像素点距离相机镜头的三维坐标
    xyz = new Mat();
    Mat disp = new Mat();bitmapToMat(left, rgbImageL);bitmapToMat(right, rgbImageR);
    Imgproc.cvtColor(rgbImageL, grayImageL, Imgproc.COLOR_BGR2GRAY);
    Imgproc.cvtColor(rgbImageR, grayImageR, Imgproc.COLOR_BGR2GRAY);
    Imgproc.remap(grayImageL, rectifyImageL, mapLx, mapLy, Imgproc.INTER_LINEAR);
    Imgproc.remap(grayImageR, rectifyImageR, mapRx, mapRy, Imgproc.INTER_LINEAR);
    bm.compute(rectifyImageL, rectifyImageR, disp); //输入图像必须为灰度图
    Calib3d.reprojectImageTo3D(disp, xyz, Q, true); //在实际求距离时,ReprojectTo3D出来的X / W, Y / W, Z / W都要乘以16
    Core.multiply(xyz, new Mat(xyz.size(), CvType.CV_32FC3, new Scalar(16, 16, 16)), xyz);// 用于显示处理
    Mat disp8U = new Mat(disp.rows(), disp.cols(), CvType.CV_8UC1);
    disp.convertTo(disp, CvType.CV_32F, 1.0 / 16); //除以16得到真实视差值
    Core.normalize(disp, disp8U, 0, 255, Core.NORM_MINMAX, CvType.CV_8U);
    Imgproc.medianBlur(disp8U, disp8U, 9);
    Bitmap resultBitmap = Bitmap.createBitmap(disp8U.cols(), disp8U.rows(), Bitmap.Config.ARGB_8888);matToBitmap(disp8U, resultBitmap);return resultBitmap;}

    执行上一步计算图像的距离之后,通过getCoordinate()方法可以获取图像中实际的三维坐标,结构是x, y, z

        public double[] getCoordinate(int dstX, int dstY) {
    double x = xyz.get(dstY, dstX)[0];
    double y = xyz.get(dstY, dstX)[1];
    double z = xyz.get(dstY, dstX)[2];return new double[]{x, y, z};}

    又是上面的双目测距工具类,接下来就可以很方便实现双目测距。在MainActivity.java中,简单几步就完成了双目测距,在使用OpenCV之前一定要执行OpenCVLoader.initDebug(),然后读取assets文件夹中的图像,分别是是左右目拍摄保存的图像,把他们转化成Bitmap用于下一步执行距离计算。

    //初始化if (OpenCVLoader.initDebug()) {
    Log.d(TAG, "OpenCVLoader初始化成功");}// 加载图片try {
    leftBitmap = BitmapFactory.decodeStream(getAssets().open("Left3.bmp"));
    rightBitmap = BitmapFactory.decodeStream(getAssets().open("Right3.bmp"));
    imageViewLeft.setImageBitmap(leftBitmap);
    imageViewRight.setImageBitmap(rightBitmap);} catch (IOException e) {
    e.printStackTrace();}

    因为我们已经编写了一个StereoBMUtil工具类,在这里就可以直接计算这两张图像的物体距离了。计算完成之后,为了方便查看图像中的距离,把结果图在ImageView上显示,然后为ImageView添加点击获取坐标事件。用户在点击之后会获取到图像中的坐标,然后使用这个坐标从xyz中获取拍摄物体的实际三维坐标。

    // 执行StereoBM算法
    button.setOnClickListener(v -> {try {
    Bitmap result = stereoBMUtil.compute(leftBitmap, rightBitmap);
    imageViewResult.setImageBitmap(result);} catch (Exception e) {
    e.printStackTrace();}});// 点击计算后的图片,获取三维坐标数据
    imageViewResult.setOnTouchListener((v, event) -> {// 获取触摸点的坐标 x, y
    float x = event.getX();
    float y = event.getY();// 目标点的坐标
    float[] dst = new float[2];
    Matrix imageMatrix = imageViewResult.getImageMatrix();
    Matrix inverseMatrix = new Matrix();
    imageMatrix.invert(inverseMatrix);
    inverseMatrix.mapPoints(dst, new float[]{x, y});
    int dstX = (int) dst[0];
    int dstY = (int) dst[1];// 获取该点的三维坐标
    double[] c = stereoBMUtil.getCoordinate(dstX, dstY);
    String s = String.format("点(%d, %d) 三维坐标:[%.2f, %.2f, %.2f]", dstX, dstY, c[0], c[1], c[2]);
    Log.d(TAG, s);
    textView.setText(s);return true;});

    效果图如下:

    ba68c5bc7af9fe6a1d777898ad6779a0.png

    使用摄像头测距

    上面的是实现读取两张计算物体距离,并没有使用摄像头拍摄,那么接下来我们就通过使用Android设备接的双目摄像头,实时拍摄图像计算物体距离。创建一个新的Activity,命名为CameraActivity,按照通常的调用摄像头的方式,这样获取到的图像是左右目摄像头拍摄的图片拼接在一起的并且旋转的,我们需要的是把他们旋转回来并把他们裁剪分割,这样就可以获取到了两种分别是左右目摄像头拍摄的图像。

    // 拍照获取左右摄像头的图像
    button2.setOnClickListener(v -> {
    bgView.setVisibility(View.VISIBLE);
    ll.setVisibility(View.VISIBLE);
    Bitmap imgBitmap = mTextureView.getBitmap();
    Bitmap b = Utils.rotateBitmap(imgBitmap, 360 - sensorOrientation);
    List<Bitmap> bitmapList = Utils.bisectionBitmap(b);// 左右目摄像头的图像
    leftBitmap = bitmapList.get(0);
    rightBitmap = bitmapList.get(1);
    imageViewLeft.setImageBitmap(leftBitmap);
    imageViewRight.setImageBitmap(rightBitmap);});// 把图像翻转回来public static Bitmap rotateBitmap(Bitmap bitmap, int angle) {
    Matrix matrix = new Matrix();
    matrix.postRotate(angle);return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);}// 裁剪分割左右目图像public static List<Bitmap> bisectionBitmap(Bitmap bitmap) {
    List<Bitmap> bitmapList = new ArrayList<>();
    Bitmap left = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth() / 2, bitmap.getHeight(), null, true);
    bitmapList.add(left);
    Bitmap right = Bitmap.createBitmap(bitmap, bitmap.getWidth() / 2, 0, bitmap.getWidth() / 2, bitmap.getHeight(), null, true);
    bitmapList.add(right);return bitmapList;}

    接下来的处理方式就跟之前的一样了,使用StereoBMUtil工具类读取分割后的左右目摄像头的图像执行计算,把结果图在ImageView上显示,然后为ImageView添加点击获取坐标事件。用户在点击之后会获取到图像中的坐标,然后使用这个坐标从xyz中获取拍摄物体的实际三维坐标。

    // 执行StereoBM算法
    button4.setOnClickListener(v -> {
    Bitmap result = stereoBMUtil.compute(leftBitmap, rightBitmap);
    imageViewResult.setImageBitmap(result);});// 点击计算后的图片,获取三维坐标数据
    imageViewResult.setOnTouchListener((v, event) -> {// 获取触摸点的坐标 x, y
    float x = event.getX();
    float y = event.getY();
    float[] dst = new float[2];
    Matrix imageMatrix = imageViewResult.getImageMatrix();
    Matrix inverseMatrix = new Matrix();
    imageMatrix.invert(inverseMatrix);
    inverseMatrix.mapPoints(dst, new float[]{x, y});
    int dstX = (int) dst[0];
    int dstY = (int) dst[1];// 获取该点的三维坐标
    double[] c = stereoBMUtil.getCoordinate(dstX, dstY);
    String s = String.format("点(%d, %d) 三维坐标:[%.2f, %.2f, %.2f]", dstX, dstY, c[0], c[1], c[2]);
    Log.d(TAG, s);
    textView.setText(s);return true;});

    效果图如下:

    a6b2aa34e21c9bde3155117a3a6e45cc.png

    本项目源码: https://resource.doiduoyi.com/#cosaa9o

    5d21e37b7bc68f1e6d47f6945ce162ab.png34967873da04f3fbe322b4e96dde116d.png
    展开全文
  • 双目测距原理

    万次阅读 多人点赞 2019-05-28 16:16:42
    双目测距基本原理: 双目测距实际操作分4个步骤:相机标定——双目校正——双目匹配——计算深度信息。 相机标定:摄像头由于光学透镜的特性使得成像存在着径向畸变,可由三个参数k1,k2,k3确定;由于装配方面...

    双目测距基本原理:

    双目测距实际操作分4个步骤:相机标定——双目校正——双目匹配——计算深度信息。

    相机标定:摄像头由于光学透镜的特性使得成像存在着径向畸变,可由三个参数k1,k2,k3确定;由于装配方面的误差,传感器与光学镜头之间并非完全平行,因此成像存在切向畸变,可由两个参数p1,p2确定。单个摄像头的定标主要是计算出摄像头的内参(焦距f和成像原点cx,cy、五个畸变参数(一般只需要计算出k1,k2,p1,p2,对于鱼眼镜头等径向畸变特别大的才需要计算k3))以及外参(标定物的世界坐标)。而双目摄像头定标不仅要得出每个摄像头的内部参数,还需要通过标定来测量两个摄像头之间的相对位置(即右摄像头相对于左摄像头的旋转矩阵R、平移向量t)。

    双目校正:双目校正是根据摄像头定标后获得的单目内参数据(焦距、成像原点、畸变系数)和双目相对位置关系(旋转矩阵和平移向量),分别对左右视图进行消除畸变和行对准,使得左右视图的成像原点坐标一致(CV_CALIB_ZERO_DISPARITY标志位设置时发生作用)、两摄像头光轴平行、左右成像平面共面、对极线行对齐。这样一幅图像上任意一点与其在另一幅图像上的对应点就必然具有相同的行号,只需在该行进行一维搜索即可匹配到对应点。
    双目匹配:双目匹配的作用是把同一场景在左右视图上对应的像点匹配起来,这样做的目的是为了得到视差图。双目匹配被普遍认为是立体视觉中最困难也是最关键的问题。得到视差数据,通过上述原理中的公式就可以很容易的计算出深度信息。

     

     

    双目摄像机的物理机构

    网上大部分人都写了这一点,也仿佛只有这一点有写的价值和物理意义。
    这里本来想放个控件(可调节动画),一直弄不上来,就算了。需要的可以联系我要下,下面放两张图片。

    在这里插入图片描述

    图中可以得出的结论
    1.深度变化(EG*EF/(AB+CD)或者H到EF的距离),会导致AB,CD和AB+CD的变化,这里不过多强调AB,CD的变化,只讨论AB+CD,这个原因后边会提到。当深度变大时,AB+CD逐渐变小。
    从公式(公式看不懂没关系,它只是我推导的,大家也可以自己推一下,推导是三角形的比例关系)
    AC=EF-AB-DC
    设Z为深度
    那么AC/EF=(Z-EG)/Z
    这样就可以推导出来了。
    在这里插入图片描述

    从这个图我们就可以明显看出只要我们的深度不变,那么我们的AB+CD也就不会改变,可以看出,深度和单独的AB与CD没有直接关系,而只与两者的和有关。

    AB+CD 与同一距离的 视差 是想等的。  

    AB + DC = XR - XT  

    注意此处 AB DC 用向量相加  (AB + DC =  =  (Bx-Ax)+ (Cx - Dx)   【Bx 为左图像的中点x, Dx为右图像的中点x  Ax,Cx为两幅图同一特征点的x坐标】

    XR - XT = XRx - XTx  (XRx 与 XTx 分别是两幅图同一特征点的x坐标)

    备注:此处的公式都是假设摄像头是水平的,如果摄像头垂直,应该使用 y 坐标。

     

    单目测距原理:

    先通过图像匹配进行目标识别(各种车型、行人、物体等),再通过目标在图像中的大小去估算目标距离。这就要求在估算距离之前首先对目标进行准确识别,是汽车还是行人,是货车、SUV还是小轿车。准确识别是准确估算距离的第一步。要做到这一点,就需要建立并不断维护一个庞大的样本特征数据库,保证这个数据库包含待识别目标的全部特征数据。比如在一些特殊地区,为了专门检测大型动物,必须先行建立大型动物的数据库;而对于另外某些区域存在一些非常规车型,也要先将这些车型的特征数据加入到数据库中。如果缺乏待识别目标的特征数据,就会导致系统无法对这些车型、物体、障碍物进行识别,从而也就无法准确估算这些目标的距离。

    单/双目方案的优点与难点

    从上面的介绍,单目系统的优势在于成本较低,对计算资源的要求不高,系统结构相对简单;缺点是:(1)需要不断更新和维护一个庞大的样本数据库,才能保证系统达到较高的识别率;(2)无法对非标准障碍物进行判断;(3)距离并非真正意义上的测量,准确度较低。

    双目检测原理:

    通过对两幅图像视差的计算,直接对前方景物(图像所拍摄到的范围)进行距离测量,而无需判断前方出现的是什么类型的障碍物。所以对于任何类型的障碍物,都能根据距离信息的变化,进行必要的预警或制动。双目摄像头的原理与人眼相似。人眼能够感知物体的远近,是由于两只眼睛对同一个物体呈现的图像存在差异,也称“视差”。物体距离越远,视差越小;反之,视差越大。视差的大小对应着物体与眼睛之间距离的远近,这也是3D电影能够使人有立体层次感知的原因。
     

    上图中的人和椰子树,人在前,椰子树在后,最下方是双目相机中的成像。其中,右侧相机成像中人在树的左侧,左侧相机成像中人在树的右侧,这是因为双目的角度不一样。再通过对比两幅图像就可以知道人眼观察树的时候视差小,而观察人时视差大。因为树的距离远,人的距离近。这就是双目三角测距的原理。双目系统对目标物体距离感知是一种绝对的测量,而非估算。

    理想双目相机成像模型

    根据上述推导,要求得空间点P离相机的距离(深度)z,必须知道:
    1、相机焦距f,左右相机基线b(可以通过先验信息或者相机标定得到)。
    2、视差 :,即左相机像素点(xl, yl)和右相机中对应点(xr, yr)的关系,这是双目视觉的核心问题。

     

    重点来看一下视差(disparity),视差是同一个空间点在两个相机成像中对应的x坐标的差值,它可以通过编码成灰度图来反映出距离的远近,离镜头越近的灰度越亮; (前提是两个摄像头是水平,如果两颗摄像头是垂直的,则使用y坐标的差值)

     

    极线约束

    对于左图中的一个像素点,如何确定该点在右图中的位置?需要在整个图像中地毯式搜索吗?当然不用,此时需要用到极线约束。
    如上图所示。O1,O2是两个相机,P是空间中的一个点,P和两个相机中心点O1、O2形成了三维空间中的一个平面PO1O2,称为极平面(Epipolar plane)。极平面和两幅图像相交于两条直线,这两条直线称为极线(Epipolar line)。
    P在相机O1中的成像点是P1,在相机O2中的成像点是P2,但是P的位置是未知的。我们的目标是:对于左图的P1点,寻找它在右图中的对应点P2,这样就能确定P点的空间位置。
    极线约束(Epipolar Constraint)是指当空间点在两幅图像上分别成像时,已知左图投影点p1,那么对应右图投影点p2一定在相对于p1的极线上,这样可以极大的缩小匹配范围。即P2一定在对应极线上,所以只需要沿着极线搜索便可以找到P1的对应点P2。
     

    非理性情况:

    上面是两相机共面且光轴平行,参数相同的理想情况,当相机O1,O2不是在同一直线上怎么办呢?事实上,这种情况非常常见,因为有些场景下两个相机需要独立固定,很难保证光心完全水平,即使固定在同一个基板上也会由于装配的原因导致光心不完全水平,如下图所示:两个相机的极线不平行,并且不共面。

    这种情况下拍摄的两张左右图片,如下图所示。

    左图中三个十字标志的点,右图中对应的极线是右图中的三条白色直线,也就是对应的搜索区域。我们看到这三条直线并不是水平的,如果进行逐点搜索效率非常低。

    图像矫正技术

    图像矫正是通过分别对两张图片用单应性矩阵(homography matrix)变换得到,目的是把两个不同方向的图像平面(下图中灰色平面)重新投影到同一个平面且光轴互相平行(下图中黄色平面),这样转化为理想情况的模型。


    经过图像矫正后,左图中的像素点只需要沿着水平的极线方向搜索对应点就可以了。从下图中我们可以看到三个点对应的视差(红色双箭头线段)是不同的,越远的物体视差越小,越近的物体视差越大。

    上面的主要工作是在极线上寻找匹配点,但是由于要保证两个相机参数完全一致是不现实的,并且外界光照变化和视角不同的影响,使得单个像素点鲁棒性很差。所以匹配工作是一项很重要的事情,这也关系着双目视觉测距的准确性。

    双目视觉的工作流程

    相机镜头畸变校正原理及方法,之前介绍过,这个基本是通用的,可以用张正友校准法。


    双目测距的优点与难点

    从上面的介绍看出,双目系统优势:(1)成本比单目系统要高,但尚处于可接受范围内,并且与激光雷达等方案相比成本较低;(2)没有识别率的限制,因为从原理上无需先进行识别再进行测算,而是对所有障碍物直接进行测量;(3)直接利用视差计算距离,精度比单目高;(4)无需维护样本数据库,因为对于双目没有样本的概念。

    双目系统的难点:

    (1)计算量非常大,对计算单元的性能要求非常高,这使得双目系统的产品化、小型化的难度较大。所以在芯片或FPGA上解决双目的计算问题难度比较大。国际上使用双目的研究机构或厂商,绝大多数是使用服务器进行图像处理与计算,也有部分将算法进行简化后,使用FPGA进行处理。

    (2)双目的配准效果,直接影响到测距的准确性。

    2.1、对环境光照非常敏感。双目立体视觉法依赖环境中的自然光线采集图像,而由于光照角度变化、光照强度变化等环境因素的影响,拍摄的两张图片亮度差别会比较大,这会对匹配算法提出很大的挑战。

    2.2、不适用于单调缺乏纹理的场景。由于双目立体视觉法根据视觉特征进行图像匹配,所以对于缺乏视觉特征的场景(如天空、白墙、沙漠等)会出现匹配困难,导致匹配误差较大甚至匹配失败。

    2.3、计算复杂度高。该方法需要逐像素匹配;又因为上述多种因素的影响,为保证匹配结果的鲁棒性,需要在算法中增加大量的错误剔除策略,因此对算法要求较高,想要实现可靠商用难度大,计算量较大。
    2.4、相机基线限制了测量范围。测量范围和基线(两个摄像头间距)关系很大:基线越大,测量范围越远;基线越小,测量范围越近。所以基线在一定程度上限制了该深度相机的测量范围。


    ---------------项目开源:-----------

    卡内基梅隆大学双目实验室

    Oxford大牛:Andrew Zisserman,http://www.robots.ox.ac.uk/~vgg/hzbook/code/,主要研究多幅图像的几何学,该网站提供了部分工具,相当实用,还有例子

    Cambridge:http://mi.eng.cam.ac.uk/milab.html,剑桥大学的机器智能实验室,里面有三个小组,Computer Vision & Robotics, Machine Intelligence, Speech

    stanford:http://ai.stanford.edu/~asaxena/reconstruction3d/,主要对于单张照片的三维重建

    caltech:http://www.vision.caltech.edu/bouguetj/calib_doc/,这是我们Computer Vision老师课件上的连接,主要是用于摄像机标定的工具集,当然也有涉及对标定图像三维重建的前期处理过程

    JP Tarel:http://perso.lcpc.fr/tarel.jean-philippe/,个人主页


    ------------匹配与3D重建算法:-----------

    https://www.cnblogs.com/polly333/p/5130375.html

    http://blog.csdn.net/wangyaninglm/article/details/51533549

    http://blog.csdn.net/wangyaninglm/article/details/51531333


    https://www.zhihu.com/question/29885222?sort=created

    http://blog.csdn.net/wangyaninglm/article/details/51558656

    http://blog.csdn.net/wangyaninglm/article/details/51558310

    https://www.cnblogs.com/mysunnyday/archive/2011/05/09/2041115.html
     

     

     

     

    参考:

    https://blog.csdn.net/piaoxuezhong/article/details/79016615

    http://m.blog.csdn.net/article/details?id=52829190

    https://blog.csdn.net/a6333230/article/details/82865439

    https://blog.csdn.net/bit_cs2010/article/details/52829190

    展开全文
  • 双目测距数学原理详解

    万次阅读 多人点赞 2016-12-21 11:24:17
    前言最近用到了双目测距的知识,乍想一下这应该是一个很简单很经典的知识了,理论介绍应该很对并且很详尽才对。可是真正想要明白到能给别人讲懂,还是花了一番功夫。网上的类似的文章很多,但是到多都是一样的知识的...

    这是我的推广信息,以激励自己更好的分享自己的知识和经验!也希望看到的你能够多多支持,谢谢!

    1. 滴滴云AI大师:

    目前滴滴云正在大力推广自己的云计算服务,需要购买的朋友们用我的AI大师码 「2049」在滴滴云上购买 GPU / vGPU / 机器学习产品可享受 9
    折优惠,点击这里前往滴滴云官网

    前言

    最近用到了双目测距的知识,乍想一下这应该是一个很简单很经典的知识了,理论介绍应该很对并且很详尽才对。可是真正想要明白到能给别人讲懂,还是花了一番功夫。网上的类似的文章很多,但是到多都是一样的知识的重复,看过的人不知道看没看懂就转载,没有加自己感想,导致我理解花了一番功夫,所以还是写一篇记录下吧。如果真的献丑了,请大家包含并指正,共同进步。

    双目测距理论

    相机成像中的坐标系

    这里写图片描述
    这里写图片描述
    这里写图片描述
    这里写图片描述

    三维估计

    实际场景中物体的三维坐标可以通过双目立体视觉技术来确定。如下图是双目立体视觉原理图,OL和OR是左右相机的光心,它们的光轴和各自的成像平面如图所示。假设两相机的内部和外部参数完全相同,焦距为f,光心之间的距离(基线)为B,两台相机在同一平面上,机他们的投影中心的Y坐标相等。同一时刻空间点p(x,y,z)在两相机上成像点分别为Pleft和Pright。
    这里写图片描述
    由三角几何关系有:
    这里写图片描述
    这个公式重在搞懂各个变量所在的坐标系。**其中Xleft和Xright分别在左、右相机的图像平面下讨论;也就是说它们的坐标系在各自的图像平面坐标系下的坐标,原点分别为各自光轴与像平面的交点。**而f和B是常值,Y也是在图像坐标系下讨论,但是是相同的。x,y,z则是在左相机坐标系下讨论,原点为OL。有了以上基础,就可以理解公式了。另外视差D的理解也非常重要,D就是Xleft-Xright。还记得Xleft和Xright的含义吗,能理解D吗?D不是图上Pleft与Pright的距离,就是Xleft-Xright,就是Xleft-Xright。 重要的事情说三遍。这应该能理解视差D是什么了,就是在各自的图像中,对应点成像的位置越相似,视差就越小,也就说明物体越远。那么有上式可得
    这里写图片描述

    展开全文
  • 双目测距算法

    2018-12-18 11:08:07
    双目测距算法,利用两个摄像头读入视频,进行配准定位,进行测距
  • 原理图示原理很简单,利用了相似三角形计算距离,所以双目测距的主要任务在于前期摄像头的定标、双目图像点的特征匹配上。常用做法具体步骤1.双目定标和校正,获得摄像头的参数矩阵摄像头定标一般都需要一个放在...
  • 双目测距】2 双目测距原理

    千次阅读 2018-11-25 17:05:29
    双目测距原理推导 如下图,为一组平行双目视觉模型。 平行双目立体视觉模型 让两摄像机光心相距T平行放置。 左右成像仪的像素原点都是在图像的左上角; P点为现实场景中的一个目标点; 和是目标点P在左右图像...
  • 算法的双目立体视觉、双目测距(双目校正和立体匹配)(文档里包含了测试图片)
  • opencv双目测距

    2017-04-19 20:23:58
    opencv运用matlab标定数据进行双目测距
  • 【参考资料】[1]深度相机原理揭秘——双目立体视觉https://www.sohu.com/a/203027140_100007727[2]双目测距原理https://blog.csdn.net/u011808673/article/details/90641589[3]相机标定原理及实现...
  • 双目测距代码 python opencv 利用双目摄像头拍照,测距

    万次阅读 热门讨论 2018-03-19 22:33:03
    好久没有写博客了,手都感觉好生疏,最近一直在研究工控机,水下机器人等,好不容易闲下来,没办法呀,继续前行吧,前面一直说双目测距,但没有高速大家如何获得这个双目标注得图像,我在这把这代码贴一下吧,获得...
  • 算法的双目立体视觉、双目测距(双目校正和立体匹配)(文档里包含了测试图片)
  • AI人工智能使用OpenCV/python进行双目测距 在做SLAM时,希望用到深度图来辅助生成场景,所以要构建立体视觉,在这里使用OpenCV的Stereo库和python来进行双目立体视觉的图像处理。立体标定应用标定数据转换成深度图标...
  • sift算法实现双目测距

    2020-12-27 21:00:23
    用opencv以及sift算法实现的双目测距工程,测量误差在500mm-1000mm时达到5mm以内 用opencv以及sift算法实现的双目测距工程,测量误差在500mm-1000mm时达到5mm以内
  • 双目测距 ZED OpenCV

    2020-03-27 03:40:49
    使用双目相机ZED OpenCV3.1 完成一个双目测距,使用OpenCV3.1中 ximgproc的disparity_filter类,得到效果不错的深度图,并且转换成实际的距离。编译版本为release 使用CMake编译带扩展的OpenCV3.1,需要配置zedsdk。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 714
精华内容 285
关键字:

双目测距