日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android双目三维重建:Android双目摄像头实现双目测距

發布時間:2024/3/13 Android 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android双目三维重建:Android双目摄像头实现双目测距 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Android雙目三維重建:Android雙目攝像頭實現雙目測距

目錄

Android雙目三維重建:Android雙目攝像頭實現雙目測距

1.開發版本

2.Android雙目攝像頭

3.雙目相機標定

?(1)雙目相機標定-Python版

?(2)雙目相機標定-Matlab版

4.相機參數配置

5.Android 雙目測距

(1) 核心算法

(2) JNI C++接口

(3) JNI Java接口

6. Android Demo測試效果

7.雙目三維重建項目代碼(Android版本)下載

8. 雙目三維重建項目代碼(C/C++版本)

9. 雙目三維重建項目代碼(Python版本)

10.參考資料


本篇博文是《雙目三維重建系統(雙目標定+立體校正+雙目測距+點云顯示)Python??????》的續作,我們將使用OpenCV C++實現雙目測距,并將算法移植到Android系統,實現一個Android版本雙目三維重建系統。由于我們只考慮三維重建實現雙目測距效果,因而去除了PCL和Open3d庫三維顯示效果,但依然保留了視差圖,深度圖等可視化效果,用戶可以通過觸摸手機屏幕點擊圖像位置,即可獲得對應的世界坐標以及深度距離信息。

從效果來看,Android版本的雙目測距和Python版本的效果幾乎一致,可以達到準實時的檢測效果,基本可以達到工業級別測距精度,可在Android開發板運行,非常適合應用于無人機,智能小車測距避障等場景。?

?來~先看一下Android版本的Demo效果圖(觸摸手機屏幕點擊圖像位置,會顯示對應距離信息):?

Android版本的Demo體驗:https://download.csdn.net/download/guyuealian/87611878

未使用WLS濾波器使用WLS濾波器

?誠然,網上有很多C++版本雙測距的代碼,但項目都不是十分完整,而且恢復視差圖效果也一般,難以達到商業實際應用,究其原因,主要有下面幾個:

  • 雙目攝像頭質量問題,
  • 雙目標定存在問題,導致校準誤差較大
  • 沒有使用WLS濾波器對視差圖進行濾波,該方法可以極大提高視差圖的效果

本篇將著重介紹OpenCV C++項目實現雙目測距的過程,關于雙目相機標定+雙目校正+雙目匹配等內容,請查看鄙人另一篇博客?《雙目三維重建系統(雙目標定+立體校正+雙目測距+點云顯示)Python??????》

【尊重原則,轉載請注明出處】https://blog.csdn.net/guyuealian/article/details/129762989


更多項目《OpenCV實現雙目測距》系列文章請參考:

  • OpenCV實現雙目測距(Python版本)雙目三維重建系統(雙目標定+立體校正+雙目測距+點云顯示)Python
  • OpenCV實現雙目測距(C/C++版本)OpenCV C++雙目三維重建:雙目攝像頭實現雙目測距
  • OpenCV實現雙目測距(Android版本)https://blog.csdn.net/guyuealian/article/details/129762989

  • 1.開發版本

    Android SDK,NDK,Jave等版本信息,請參考:

    ? 項目開發需要依OpenCV庫,同時也需要用到opencv_contrib庫

    • opencv 4.5.3
    • opencv_contrib 4.5.3

    Android項目源碼,已經配置好了opencv,無需重新下載和配置


    2.Android雙目攝像頭

    開發前,你需要準備有一臺Android系統的雙目攝像頭,要求如下

    • 從雙目三維重建原理中可知,左右攝像頭的成像平面盡可能在一個平面內,成像平面不在同一個平面的,盡管可以立體矯正,其效果也差很多。
    • 雙目攝像頭必須是同一個平面,不能一個前置攝像頭,一個后置攝像頭(代碼層面可以分為前置和后置攝像頭,但實物機器必須同時前置或者同時后置)
    • 基線不太建議太小,作為測試,一般baseline在3~9cm就可以滿足需求,有些無人車的雙目基線更是恐怖到1~2米長
    • 一分錢,一分貨,相機的質量好壞,直接決定了你的成像效果
    • 雙目攝像頭必須重新標定獲得雙目相機內外參數信息,然后編輯源碼,修改為自己雙目相機的相機參數


    3.雙目相機標定

    注意,Android版本的雙目三維重建系統的源碼,不涉及雙目標定的相關內容,如果那你需要適配自己的手機雙目攝像頭,你需要重新標定,詳細步驟參考如下:

    ?(1)雙目相機標定-Python版

    請參考鄙人另一篇博客,無需Matlab,即可進行相機標定:雙目三維重建系統(雙目標定+立體校正+雙目測距+點云顯示)Python

    該方法雙目標定完成后,會得到一個雙目相機內外參數信息(stereo_cam.yml)文件:

    %YAML:1.0 --- size: !!opencv-matrixrows: 2cols: 1dt: ddata: [ 640., 480. ] K1: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 7.6159209686584518e+02, 0., 3.2031427422505453e+02, 0.,7.6167321445963728e+02, 2.2467546927337131e+02, 0., 0., 1. ] D1: !!opencv-matrixrows: 1cols: 5dt: ddata: [ 3.4834574885170888e-02, -5.5261651661983137e-02,5.7491952731614823e-04, -4.2764224824172658e-05,1.8477350140315381e-02 ] K2: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 7.6327773941976670e+02, 0., 2.8768149948082271e+02, 0.,7.6350419442870850e+02, 2.1897333598636970e+02, 0., 0., 1. ] D2: !!opencv-matrixrows: 1cols: 5dt: ddata: [ 3.5020972475517692e-02, -4.0770660841280497e-02,-4.4231087565750534e-04, -1.0552562170995372e-03,-9.7749906830348537e-02 ] R: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 9.9999370552351063e-01, 7.8563885326366346e-04,3.4600122760633780e-03, -7.9503151737356746e-04,9.9999600079883766e-01, 2.7140949167922721e-03,-3.4578661403601796e-03, -2.7168286517956050e-03,9.9999033095517087e-01 ] T: !!opencv-matrixrows: 3cols: 1dt: ddata: [ -6.0005833133148414e+01, 1.7047017063672587e-01,6.0300223404957642e-01 ] E: !!opencv-matrixrows: 3cols: 3dt: ddata: [ -1.1005724987007073e-04, -6.0346296076620343e-01,1.6883191705475561e-01, 3.9550629985097430e-01,-1.6255182474732952e-01, 6.0007339329190145e+01,-1.2276256904913259e-01, -6.0005727085740176e+01,-1.6345135556766910e-01 ] F: !!opencv-matrixrows: 3cols: 3dt: ddata: [ -6.7250769136371160e-10, -3.6870834234286016e-06,1.6143104894409041e-03, 2.4160347372858321e-06,-9.9287680075344234e-07, 2.7862421257891157e-01,-1.1014218394645766e-03, -2.7856049650040260e-01, 1. ] R1: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 9.9997618806974742e-01, -2.0278309638726887e-03,-6.5963016213173775e-03, 2.0367881225372914e-03,9.9999701250432615e-01, 1.3514719999064883e-03,6.5935413581266105e-03, -1.3648750875444691e-03,9.9997733090723306e-01 ] R2: !!opencv-matrixrows: 3cols: 3dt: ddata: [ 9.9994547731576255e-01, -2.8407384289991728e-03,-1.0048512373976153e-02, 2.8270879178959596e-03,9.9999506202764499e-01, -1.3724045434755307e-03,1.0052361397026631e-02, 1.3439216883706559e-03,9.9994857062992937e-01 ] P1: !!opencv-matrixrows: 3cols: 4dt: ddata: [ 7.3741438842621210e+02, 0., 3.1126281356811523e+02, 0., 0.,7.3741438842621210e+02, 2.2189782714843750e+02, 0., 0., 0., 1.,0. ] P2: !!opencv-matrixrows: 3cols: 4dt: ddata: [ 7.3741438842621210e+02, 0., 3.1126281356811523e+02,-4.4251577456670653e+04, 0., 7.3741438842621210e+02,2.2189782714843750e+02, 0., 0., 0., 1., 0. ] Q: !!opencv-matrixrows: 4cols: 4dt: ddata: [ 1., 0., 0., -3.1126281356811523e+02, 0., 1., 0.,-2.2189782714843750e+02, 0., 0., 0., 7.3741438842621210e+02, 0.,0., 1.6664137886344466e-02, 0. ]

    參數說明:?

    • 參數size,對應圖像寬高(width,height)
    • 參數K1,對應左目相機內參矩陣(3×3)
    • 參數D1,對應左目相機畸變系數矩陣(5×1)
    • 參數K2,對應右目相機內參矩陣(3×3)
    • 參數D2,對應右目相機畸變系數矩陣(5×1)
    • 參數T,對應雙目相機平移向量T(3×1)
    • 參數R,對應雙目相機旋轉矩陣R(3×3)
    • 至于配置文件中的參數,如R1, R2, P1, P2, Q這些重投影矩陣,可默寫即可,不用修改,這些在運行時,會重新計算。

    ?(2)雙目相機標定-Matlab版

    網上已經存在很多Matlab雙目相機標定的教程,請自行百度哈 ;使用Matlab工具箱進行雙目相機標定后,請對應參數進行修改

    需要注意的是:旋轉矩陣R是(3×3)二維矩陣,而Matlab給出的是旋轉向量om(1×3),請使用cv2.Rodrigues()將旋轉向量轉為旋轉矩陣,參考下面的代碼進行轉換

    import cv2import numpy as np# 定義旋轉矩陣R,旋轉向量omR = [[9.9999370551606337e-01, 7.8563882630048958e-04, 3.4600144345510440e-03],[-7.9503149273969136e-04, 9.9999600080163187e-01, 2.7140938945082542e-03],[-3.4578682997252063e-03, -2.7168276311286426e-03, 9.9999033095047696e-01]]R = np.asarray(R)print(f"旋轉矩陣R:\n {R}")# 把旋轉矩陣R轉化為旋轉向量omom, _ = cv2.Rodrigues(R)print(f"旋轉向量om:\n {om}")# 把旋轉向量om轉換為旋轉矩陣RR1, _ = cv2.Rodrigues(om)print(f"旋轉矩陣R1:\n {R1}")

    4.相機參數配置

    • 雙目相機標定完成后,得到了相機內外參數信息
    • 根據自己相機參數,修改項目app/src/main/cpp/src/stereo_reconstruct.h文件
    • 下面C++代碼中,定義了雙目相機CameraParam變量camera1,用戶需要根據自己的雙目相機,修改對應的相機內外參數。

    /*** 雙目攝像頭的相機參數*/ struct CameraParam { int width; //圖像的寬度width int height; //圖像的高度height Mat cameraMatrixL; //左相機內參K1(3×3) Mat distCoeffL; //左相機畸變系數D1(5×1) Mat cameraMatrixR; //右相機內參K2(3×3) Mat distCoeffR; //右相機畸變系數D2(5×1) Mat T; //平移向量T(3×1) Mat R; //旋轉矩陣R(3×3),如果是(3×1)旋轉向量,請使用cv::Rodrigues()進行變換轉為(3×3)旋轉矩陣R };/**** 設置攝像頭參數,需要根據雙目攝像頭標定結果進行填寫*/ static CameraParam camera1 = { 640,//width 480,//height (Mat_<double>(3, 3) << 7.6159209686633153e+02, 0., 3.2031427422691633e+02, 0., 7.6167321446015626e+02, 2.2467546926913309e+02, 0., 0., 1.),//cameraMatrixL (Mat_<double>(5, 1) << 3.4834574887256914e-02, -5.5261651680159028e-02, 5.7491952534806736e-04, -4.2764223950233445e-05, 1.8477350164208820e-02),//distCoeffL (Mat_<double>(3, 3) << 7.6327773983796783e+02, 0., 2.8768149776326379e+02, 0., 7.6350419482215057e+02, 2.1897333669573928e+02, 0., 0., 1.), (Mat_<double>(5, 1) << 3.5020967512300320e-02, -4.0770565902033332e-02, -4.4231049297594003e-04, -1.0552565496142535e-03, -9.7750314807571667e-02), (Mat_<double>(3, 1) << -6.0005833075452117e+01, 1.7047023105446815e-01, 6.0300273851103448e-01), (Mat_<double>(3, 3) << 9.9999370551606337e-01, 7.8563882630048958e-04, 3.4600144345510440e-03, -7.9503149273969136e-04, 9.9999600080163187e-01, 2.7140938945082542e-03, -3.4578682997252063e-03, -2.7168276311286426e-03, 9.9999033095047696e-01), };

    5.Android 雙目測距

    Android OpenCV版本的雙目測距與Python版本雙目測距的效果幾乎一致,基本可以達到工業級別測距精度。由于我們只考慮三維重建實現雙目測距效果,因而去除了PCL和Open3d庫三維顯示效果,但依然保留了視差圖,深度圖等可視化效果,用戶可以通過觸摸手機屏幕點擊圖像位置,即可獲得對應的世界坐標以及深度距離信息。

    (1) 核心算法

    Android版本的雙目測距算法,核心代碼都使用C++開發,上層應用Java部分通過JNI調用opencv C++算法,函數接口聲明,都已經給出了詳細的參數說明,為了方便大家學習,函數命名和實現邏輯與Python版本的幾乎一致:

    Python版本C++版本
    ??
    • 這是C++核心算法部分函數定義
    // // Created by 390737991@qq.com on 2018/10/6. //#ifndef CAMERA_CALIBRATION_RECONSTRUCT_CPP_STEREO_RECONSTRUCT_H #define CAMERA_CALIBRATION_RECONSTRUCT_CPP_STEREO_RECONSTRUCT_H#include <opencv2/opencv.hpp> #include <iostream>using namespace std; using namespace cv;static cv::Mat xyz_coord; //用于存放每個像素點距離相機鏡頭的三維坐標 static cv::Point start; //鼠標按下的起始點 static cv::Rect buttonRect; //定義矩形選框 static bool buttonStatus = false; //是否選擇對象/*** 雙目攝像頭的相機參數*/ struct CameraParam {int width; //圖像的寬度widthint height; //圖像的高度heightMat cameraMatrixL; //左相機內參K1(3×3)Mat distCoeffL; //左相機畸變系數D1(5×1)Mat cameraMatrixR; //右相機內參K2(3×3)Mat distCoeffR; //右相機畸變系數D2(5×1)Mat T; //平移向量T(3×1)Mat R; //旋轉矩陣R(3×3),如果是(3×1)旋轉向量,請使用cv::Rodrigues()進行變換轉為(3×3)旋轉矩陣R };/**** 設置攝像頭參數,需要根據雙目攝像頭標定結果進行填寫*/ static CameraParam camera1 = {640,//width480,//height(Mat_<double>(3, 3)<< 7.6159209686633153e+02, 0., 3.2031427422691633e+02, 0., 7.6167321446015626e+02, 2.2467546926913309e+02, 0., 0., 1.),//cameraMatrixL(Mat_<double>(5, 1)<< 3.4834574887256914e-02, -5.5261651680159028e-02, 5.7491952534806736e-04, -4.2764223950233445e-05, 1.8477350164208820e-02),//distCoeffL(Mat_<double>(3, 3)<< 7.6327773983796783e+02, 0., 2.8768149776326379e+02, 0., 7.6350419482215057e+02, 2.1897333669573928e+02, 0., 0., 1.),(Mat_<double>(5, 1)<< 3.5020967512300320e-02, -4.0770565902033332e-02, -4.4231049297594003e-04, -1.0552565496142535e-03, -9.7750314807571667e-02),(Mat_<double>(3, 1)<< -6.0005833075452117e+01, 1.7047023105446815e-01, 6.0300273851103448e-01),(Mat_<double>(3, 3)<< 9.9999370551606337e-01, 7.8563882630048958e-04, 3.4600144345510440e-03, -7.9503149273969136e-04, 9.9999600080163187e-01, 2.7140938945082542e-03, -3.4578682997252063e-03, -2.7168276311286426e-03, 9.9999033095047696e-01), };#ifdef PLATFORM_ANDROIDstatic void onMouse(int event, int x, int y, int, void *) { } static void show_image(const string &winname, cv::Mat &image, int delay = 0, int flags = cv::WINDOW_AUTOSIZE) { } static bool get_video_capture(string video_file, cv::VideoCapture &cap, int width = -1, int height = -1, int fps = -1) {return true; } static bool get_video_capture(int camera_id, cv::VideoCapture &cap, int width = -1, int height = -1, int fps = -1) {return true; } #else/**** 鼠標響應回調函數* @param event* @param x* @param y*/ static void onMouse(int event, int x, int y, int, void *) {if (buttonStatus) {buttonRect.x = MIN(x, start.x);buttonRect.y = MIN(y, start.y);buttonRect.width = std::abs(x - start.x);buttonRect.height = std::abs(y - start.y);}switch (event) {case EVENT_LBUTTONDOWN: //鼠標左按鈕按下的事件start = Point(x, y);buttonRect = Rect(x, y, 0, 0);buttonStatus = true;cout << "image(x,y)=" << start;cout << " world coords=(x,y,depth)=" << xyz_coord.at<Vec3f>(start) << endl;break;case EVENT_LBUTTONUP: //鼠標左按鈕釋放的事件buttonStatus = false;if (buttonRect.width > 0 && buttonRect.height > 0)break;} }/**** 顯示圖像* @param winname 窗口名稱* @param image 圖像* @param delay 顯示延遲,0表示阻塞顯示* @param flags 顯示方式*/ static void show_image(const string &winname, cv::Mat &image, int delay = 0, int flags = cv::WINDOW_AUTOSIZE) {cv::namedWindow(winname, flags);cv::imshow(winname, image);cv::waitKey(delay); }/**** 讀取視頻文件* @param video_file 視頻文件* @param cap 視頻流對象* @param width 設置圖像的寬度* @param height 設置圖像的高度* @param fps 設置視頻播放頻率* @return*/ static bool get_video_capture(string video_file, cv::VideoCapture &cap, int width = -1, int height = -1, int fps = -1) {//VideoCapture video_cap;cap.open(video_file);if (width > 0 && height > 0) {cap.set(cv::CAP_PROP_FRAME_WIDTH, width); //設置圖像的寬度cap.set(cv::CAP_PROP_FRAME_HEIGHT, height); //設置圖像的高度}if (fps > 0) {cap.set(cv::CAP_PROP_FPS, fps);}if (!cap.isOpened())//判斷是否讀取成功{return false;}return true; }/**** 讀取攝像頭* @param camera_id 攝像頭ID號,默認從0開始* @param cap 視頻流對象* @param width 設置圖像的寬度* @param height 設置圖像的高度* @param fps 設置視頻播放頻率* @return*/ static bool get_video_capture(int camera_id, cv::VideoCapture &cap, int width = -1, int height = -1, int fps = -1) {//VideoCapture video_cap;cap.open(camera_id); //攝像頭ID號,默認從0開始if (width > 0 && height > 0) {cap.set(cv::CAP_PROP_FRAME_WIDTH, width); //設置捕獲圖像的寬度cap.set(cv::CAP_PROP_FRAME_HEIGHT, height); //設置捕獲圖像的高度}if (fps > 0) {cap.set(cv::CAP_PROP_FPS, fps);}if (!cap.isOpened()) //判斷是否成功打開相機{return false;}return true; }#endifclass StereoReconstruct { public:/**** 構造函數,初始化StereoReconstruct* @param camera 雙目相機參數* @param use_wls 是否使用WLS濾波器對視差圖進行濾波* @param vis 是否顯示*/StereoReconstruct(CameraParam camera, bool use_wls = true, bool vis = false);/**** release*/~StereoReconstruct();/**** 開始雙目測距任務* @param frameL* @param frameR*/void task(Mat frameL, Mat frameR, int delay = 0);/**** 畸變校正和立體校正* @param imgL 左視圖* @param imgR 右視圖* @param rectifiedL 校正后左視圖* @param rectifiedR 校正后右視圖*/void get_rectify_image(Mat &imgL, Mat &imgR, Mat &rectifiedL, Mat &rectifiedR);/**** 獲得視差圖* @param imgL 畸變校正和立體校正后的左視圖* @param imgR 畸變校正和立體校正后的右視圖* @param dispL 返回視差圖* @param use_wls 是否使用WLS濾波器對視差圖進行濾波*/void get_disparity(Mat &imgL, Mat &imgR, Mat &dispL, bool use_wls = true);//SGBM匹配算法/**** 計算像素點的3D坐標(左相機坐標系下)* @param disp 視差圖* @param points_3d 返回三維坐標points_3d,三個通道分布表示(X,Y,Z),其中Z是深度圖depth, 即距離,單位是毫米(mm)* @param scale 單位變換尺度,默認scale=1.0,單位為毫米*/void get_3dpoints(Mat &disp, Mat &points_3d, float scale = 1.0);/**** 將輸入深度圖轉換為偽彩色圖,方面可視化* @param depth* @param colormap*/void get_visual_depth(cv::Mat &depth, cv::Mat &colormap, float clip_max = 6000.0);/**** 顯示矯正效果* @param rectifiedL* @param rectifiedR*/void show_rectify_result(cv::Mat rectifiedL, cv::Mat rectifiedR);/**** 可視化視差圖和深度圖* @param frameL* @param frameR* @param points_3d* @param disp* @param delay*/void show_2dimage(Mat &frameL, Mat &frameR, Mat &points_3d, Mat &disp, int delay);/**** 顯示Mat的最大最小值* @param src* @param vmin 最小值下限* @param vmax 最大值下限*/void clip(cv::Mat &src, float vmin, float vmax);/**** 顯示Mat的最大最小值* @param src* @param th* @param vmin*/void clip_min(cv::Mat &src, float th, float vmin);public:string depth_windows = "depth-color"; // 深度圖的窗口名稱int vis; // 是否可視化int use_wls; // 是否使用WLS濾波器對視差圖進行濾波Size image_size; // 圖像寬高(width,height)Rect validROIL; // 圖像校正之后,會對圖像進行裁剪,這里的左視圖裁剪之后的區域Rect validROIR; // 圖像校正之后,會對圖像進行裁剪,這里的右視圖裁剪之后的區域Mat mapLx, mapLy, mapRx, mapRy; // 映射表Mat Rl, Rr, Pl, Pr, Q; // 校正后的旋轉矩陣R,投影矩陣P, 重投影矩陣QMat dispL; // 視差圖(CV_32F)Mat disp_colormap; // 視差圖可視化圖(CV_8UC3)Mat depth; // 深度圖(CV_32F)Mat depth_colormap; // 深度圖可視化圖(CV_8UC3)Mat points_3d; // 世界坐標圖(CV_32F)cv::Ptr<cv::StereoSGBM> sgbm; };#endif //CAMERA_CALIBRATION_RECONSTRUCT_CPP_STEREO_RECONSTRUCT_H

    (2) JNI C++接口

    #include <jni.h> #include <string> #include <fstream> #include "src/stereo_reconstruct.h" #include "android_utils.h" #include "debug.h" #include "opencv2/opencv.hpp"StereoReconstruct *stereo = nullptr;JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {return JNI_VERSION_1_6; }JNIEXPORT void JNI_OnUnload(JavaVM *vm, void *reserved) {}extern "C" JNIEXPORT void JNICALL Java_com_cv_binocular_reconstruct_StereoReconstruct_init(JNIEnv *env, jclass clazz, jboolean use_wls) {CameraParam camera = camera1;//雙目相機參數(請根據自己雙目相機標定結果進行修改)//bool use_wls = true; //是否使用WLS濾波器對視差圖進行濾波stereo = new StereoReconstruct(camera, use_wls, false); }extern "C" JNIEXPORT void JNICALL Java_com_cv_binocular_reconstruct_StereoReconstruct_reBuild(JNIEnv *env, jclass clazz, jobject bitmapL,jobject bitmapR,jobject disp_colormap,jobject depth_colormap) {Mat frameL; // 左視圖Mat frameR; // 右視圖BitmapToMatrix(env, bitmapL, frameL);BitmapToMatrix(env, bitmapR, frameR);stereo->task(frameL, frameR, 0);MatrixToBitmap(env, stereo->disp_colormap, disp_colormap); //視差圖可視化圖(CV_8UC3)MatrixToBitmap(env, stereo->depth_colormap, depth_colormap);//視差圖可視化圖(CV_8UC3)LOGW("frameL : (%d,%d)", frameL.cols, frameL.rows);LOGW("disp_colormap : (%d,%d)", stereo->disp_colormap.cols, stereo->disp_colormap.rows);LOGW("depth_colormap : (%d,%d)", stereo->depth_colormap.cols, stereo->depth_colormap.rows); }extern "C" JNIEXPORT jobject JNICALL Java_com_cv_binocular_reconstruct_StereoReconstruct_getWorld(JNIEnv *env, jclass clazz, jint x,jint y) {cv::Vec3f point = stereo->points_3d.at<Vec3f>(Point(x, y));float cx = point[0];float cy = point[1];float cz = point[2];LOGW("image(x,y)=[%d,%d] world=(x,y,depth)=[%3.2f,%3.2f,%3.2f]mm", x, y, cx, cy, cz);auto cls_point = env->FindClass("com/cv/binocular/reconstruct/Point3d");auto init_id = env->GetMethodID(cls_point, "<init>", "(FFF)V");env->PushLocalFrame(1);jobject obj = env->NewObject(cls_point, init_id, cx, cy, cz);obj = env->PopLocalFrame(obj);return obj; }

    (3) JNI Java接口

    package com.cv.binocular.reconstruct;import android.graphics.Bitmap;public class StereoReconstruct {static {System.loadLibrary("binocular_wrapper");}/**** 初始化* @param use_wls 是否使用WLS濾波器對視差圖進行濾波*/public static native void init(boolean use_wls);/**** 進行雙目三維重建* @param frameL: 輸入左視圖* @param frameR:輸入右視圖* @param disp_colormap:輸出視差圖可視化圖* @param depth_colormap:輸出深度圖可視化圖* @return*/public static native void reBuild(Bitmap frameL, Bitmap frameR, Bitmap disp_colormap, Bitmap depth_colormap);/**** 將圖像坐標映射為世界坐標(world coordinate)* @param x 輸入圖像像素坐標x* @param y 輸入圖像像素坐標y* @return Point3d世界坐標(x, y, z),其中z為深度距離*/public static native Point3d getWorld(int x, int y); }

    6. Android Demo測試效果

    Android版本雙目測距Demo源碼提供圖片,視頻和攝像頭三種方式測試

    • Android Demo圖片測試:項目資源(src/main/assets)自帶一對左右視圖的測試圖片,你需要將測試圖片拷貝到你的手機,然后在Demo APP點擊【圖片】打開圖片即可;如果你想測試自己的圖片,請將左視圖文件命名為left***.png,右視圖文件命名為right***.png,否則不能正常加載左右視圖。圖片格式支持jpg,png等多種格式
    • Android Demo視頻測試:項目資源(src/main/assets)自帶一對左右視圖的視頻文件,你需要將測試視頻拷貝到你的手機,然后在Demo APP點擊【視頻】打開視頻即可;如果你想測試自己的視頻,請將左視圖視頻文件命名為left***.mp4,右視圖視頻文件命名為right***.mp4,否則不能正常加載左右視圖。視頻格式支持mp4,avi等多種格式
    • Android Demo攝像頭測試:需要Android設備支持兩個攝像頭,源碼部分cameraL = 0對應前置攝像頭,cameraR = 1對應后置攝像頭,僅作為Android手機測試使用;真實Android手機,雙目攝像頭必須要同一平面上。

    ??Android版本的Demo效果圖(觸摸手機屏幕點擊圖像位置,會顯示對應距離信息):??

    Android版本的Demo體驗:https://download.csdn.net/download/guyuealian/87611878

    ?從測試效果可以看到,使用WLS濾波后,視差圖的整體效果都有明顯改善,但速度會變慢哦

    未使用WLS濾波器使用WLS濾波器


    7.雙目三維重建項目代碼(Android版本)下載

    完整的Android項目代碼請公眾號咨詢聯系(非無償)

    整體Android項目源碼包含:

    • Demo支持使用WLS濾波器對視差圖進行濾波
    • Demo支持雙目測距,誤差在1cm內(觸摸手機屏幕點擊圖像位置,會顯示對應距離信息)
    • Demo支持圖片,視頻,攝像頭測試
    • 所有依賴庫都已經配置好,可直接build運行

    8. 雙目三維重建項目代碼(C/C++版本)

    目前已經實現了OpenCV C++版本的雙目測距,與Python版本效果幾乎一致,

    詳細請查看鄙人另一篇博客《OpenCV C++雙目攝像頭實現雙目測距》:OpenCV C++雙目三維重建:雙目攝像頭實現雙目測距_opencv雙目三維重建_AI吃大瓜的博客-CSDN博客

    ?


    9. 雙目三維重建項目代碼(Python版本)

    如果你需要Python版本的雙目測距,?請查看鄙人另一篇博客《雙目三維重建系統(雙目標定+立體校正+雙目測距+點云顯示)Python》

    雙目測距Demo視頻


    10.參考資料

  • OpenCV C++雙目三維重建:雙目攝像頭實現雙目測距
  • 雙目三維重建:雙目攝像頭實現雙目測距(Python)
  • 雙目三維重建系統(雙目標定+立體校正+雙目測距+點云顯示)Python
  • ?https://blog.csdn.net/guyuealian/article/details/129762989

  • Ubuntu18.04安裝opencv和opencv_contrib
  • 總結

    以上是生活随笔為你收集整理的Android双目三维重建:Android双目摄像头实现双目测距的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 无码人妻精品一区二区三区温州 | 亚洲爱爱网 | 在线国产日韩 | 很黄的性视频 | 国产精品一区二区自拍 | julia一区二区三区中文字幕 | 国产一二区在线 | 亚洲成人av免费 | 免费啪啪网 | 双性人做受视频 | 欧美xxxxbbbb| 日韩少妇中文字幕 | 在线观看免费的av | 椎名由奈在线观看 | 精品一区二区三区久久 | www.国产在线 | 影音先锋在线观看视频 | 精品无码一区二区三区的天堂 | 欧美激情婷婷 | 日本少妇xxxxx | www.视频一区| 色噜| 调教一区二区三区 | 欧美日本久久 | 国产一区导航 | 性色av一区二区三区四区 | 国产三级精品三级在线观看 | 偷偷在线观看免费高清av | 精品久久伊人 | 久久国产中文字幕 | 日韩有码中文字幕在线 | 91色九色| 中日韩av在线 | 精品国产一区二区视频 | 中文字幕av高清 | v99av| 中文字幕在线观看第一页 | 精品人伦一区二区三区蜜桃网站 | 暖暖av在线| 欧美一区二区在线看 | 向日葵视频在线播放 | 色综合天天综合网国产成人网 | 国产精品扒开做爽爽爽的视频 | 免费高清欧美大片在线观看 | 国产香蕉一区二区三区 | 日本伦理一区二区三区 | 欧美日韩一区二区三区国产精品成人 | 日本50路肥熟bbw | 国产伦精品一区二区免费 | 91麻豆精品一二三区在线 | 少妇性高潮视频 | 中文字幕成人网 | 欧美成人一区二区三区四区 | 久久久久久久999 | 污网站在线免费看 | 欧美在线观看视频一区 | 综合av第一页 | 日韩一区二区在线免费观看 | 国产精品二区在线观看 | av不卡在线播放 | 成人在线免费小视频 | 在线观看亚洲网站 | 特大黑人巨人吊xxxx | 亚洲aaa视频| 一级日韩片 | 亚洲妇女体内精汇编 | 国产一区二区久久精品 | 日韩美女一级片 | 久久久国产成人 | 午夜影院免费看 | 日本少妇性生活 | 免费欧美 | 国产黄大片在线观看画质优化 | 亚洲乱色熟女一区二区 | 卡通动漫精品一区二区三区 | 嫩草视频在线播放 | 亚洲无人区码一码二码三码 | 日本h在线 | 国精品人妻无码一区二区三区喝尿 | 国产毛片高清 | 色综合影视 | 欧美亚洲精品在线 | 91视频99| 一个人在线免费观看www | 国产欧美久久久精品免费 | 中文字幕人妻一区二区三区视频 | 成人免费看 | 天堂а√在线中文在线 | 免费视频网站在线观看入口 | 精久久久久久久 | 女人囗交吞精囗述 | 性高湖久久久久久久久免费 | 蜜桃视频网站 | 狠狠爱免费视频 | av片免费在线播放 | 岛国午夜视频 | 日本男人天堂网 | 中文字幕99页 | 国产成人自拍视频在线观看 |