草庐IT

利用手机摄像头采集图片运行ORB-SLAM2

身在江湖的郭大侠 2023-04-04 原文

一、ROS配置安装

二、ORB_SLAM2配置安装

可参考前文  

ROS仿真环境安装与配置_身在江湖的郭大侠的博客-CSDN博客

三、Android手机摄像头与ROS建立通信

GitHub有个开源的项目,可以通过wifi将摄像头捕捉到的图片传输到ROS,地址:

https://github.com/hitcm/Android_Camera-IMU

作者也给出了博文,

ROS实时采集Android的图像和IMU数据 - hitcm - 博客园

下载代码、安装工具包

git clone https://github.com/hitcm/Android_Camera-IMU.git

sudo apt-get install ros-melodic-imu-tools  # 按实际安装indigo、Kinetic 等安装对应的工具包

三个文件

Camera_Imu.apk安装到手机上,注意有的手机可能因为安装版本过高导致无法运行此程序,可以试着在手机上装一个虚拟软件如VMOS Pro,这个安卓版本是7.1可以运行,还有一个版本的apk

Releases · huaibovip/android_ros_sensors · GitHub

这个版本的apk带源码,大佬可以二次开发,但是此apk笔者并未试成功

手机和电脑要在同一局域网下,在实验前可以在手机上安装一个ping工具,确保电脑和手机的网络是互通的,笔者是虚拟机,为了让手机与虚拟机的网互通,这是把虚拟机的网络模式设为桥接模式

 

 虚拟机打开

Terminal1 输入:

roscore

Android: 打开应用,在 在 IP Port 中修改 IP 地址为 PC的 IP地址,port不需要修改(PC 的 IP 可在 PC 终端输入 ifconfig 查看),之后点击 Connect,连接成功则进入相机界面。

Terminal 2 到下载git文件的目录打开android_cam-imu.launch:

cd Android_Camera-IMU      
roslaunch android_cam-imu.launch

这是会弹出一个Rviz界面:

如果要实时显示则

  • 如果要实时显示 image,需要 Add - By topic - 添加/camera/image_raw/image。
  • 如果要显示 imu,则需要 Add - By topic - 添加 imu,且在 Fix Frame 中 将 map 改为 imu。

 

 PS:

可以在Ubuntu里面用

rostopic list

查询订阅的主题,可以看到有订阅的图像和imu

 

 

 手机摄像头标定

为了 ORB-SLAM2 准确运行,需要对手机摄像头进行标定。标定方式为:对棋盘格标定板进行各个方向的拍照,之后基于 OpenCV 进行标定。注意这里采集的图片需要和 ORB-SLAM2 程序读取到的一致,所以不能直接使用手机自带相机 app 拍照,因为手机会自动通过算法进行校正,而上述通信传输的是 raw images。因此,首先我们需要完成的任务是:采集并保存摄像头图像。

使用下图作为标定板(参考资料),可直接在电脑屏幕上显示,对其拍照即可。

注意:

  • 实验发现,使用长宽格数不一样的棋盘标定板效果更好。
  • 实验发现,标定板周围要是白色的才行,黑色的提取不出角点来(在电脑屏幕上显示标定板时尤其需要注意)。
  • 摄像头需要从不同方向拍摄棋盘格,可参考 OpenCV 安装目录下 samples/data 中的 left0x.jpg 系列标定图片。

采集并保存图片

目前没有找到直接保存的方法,所以我们选择写一个 ROS node 来接收手机传来的图像,再通过 OpenCV 进行显示和保存。

为了方便,我们选择直接在 ORB-SLAM2 的 ros_mono.cc 的代码基础上进行修改,在 ros_mono.cc 同一目录下写了个 ros_camera_capture.cc:

/**
* This file is to capture images from Android phone, for camera calibration
* This file is used with Android_Camera-IMU
*/

#include<iostream>
#include<algorithm>
#include<fstream>
#include<chrono>

#include<ros/ros.h>
#include <cv_bridge/cv_bridge.h>

#include<opencv2/core/core.hpp>

#include"../../../include/System.h"

using namespace std;

string save_dir = "PATH"; // 修改为自己保存图片的路径
int imgId = 0;

void GrabImage(const sensor_msgs::ImageConstPtr& msg);

int main(int argc, char **argv)
{

    std::cout << "To save the current frame, please press 'Q' or 'q' " << std::endl;
    std::cout << "The images will be saved to " <<  save_dir << std::endl;

    ros::init(argc, argv, "PClistener");
    ros::start();

    ros::NodeHandle nodeHandler;
    ros::Subscriber sub = nodeHandler.subscribe("/camera/image_raw", 1, GrabImage);

    ros::spin();

    ros::shutdown();

    return 0;
}

void GrabImage(const sensor_msgs::ImageConstPtr& msg)
{
    string imgname;
    cv_bridge::CvImageConstPtr cv_ptr;
    try
    {
        cv_ptr = cv_bridge::toCvShare(msg);
        cv::Mat img = cv_ptr->image;
        cv::imshow("img_name", img);

        char key = cv::waitKey(1);
        // press "q" to save the image 
        if(key == 'q' || key == 'Q'){  
            imgId++;
            imgname = "img_" + to_string(imgId) + ".jpg";
            cv::imwrite(save_dir + imgname, img);
            std::cout << "has saved image "<< imgId << " to " << save_dir << std::endl;
        }
    }
    catch (cv_bridge::Exception& e)
    {
        ROS_ERROR("cv_bridge exception: %s", e.what());
        return;
    }
}

注意捕捉图像存储地址换成自己的

另外,在 ORB_SLAM2/Examples/ROS/ORB_SLAM2 目录中的 CMakeLists.txt 中添加如下内容(添加在 # Node for monocular camera 上方即可):

# Node for capture images for camera calibration
rosbuild_add_executable(CameraCapture
src/ros_camera_capture.cc
)

target_link_libraries(CameraCapture
${LIBS}
)

之后重新编译 ORB_SLAM2 项目。

cd PATH/ORB_SLAM2
./build_ros.sh

使用方法:

Terminal 1:

roscore

手机进入 app 运行

Terminal 2: 在 Android_Camera-IMU 目录

roslaunch android_cam-imu.launch

(可以关掉 Rviz)

Terminal 3:

rosrun ORB_SLAM2 CameraCapture

鼠标选中弹出的图像框,按下 q 键保存图像。一定要多角度多捕捉几张图片,否则很难捕捉到关键点。像这样

 

进行标定

使用 OpenCV samples 中的代码实现。参考资料

标定例程

新建一个工作目录(文件夹)camera_calibration_opencv,将 OpenCV 安装目录中的 samples/cpp/tutorial_code/calib3d/camera_calibration 文件夹内的内容拷贝至该目录。

修改 VID5.xml

VID5.xml 中存储着标定图像的路径,所以要在 VID.xml 中添加所有标定图像的路径,eg:图片换成自己捕捉照片存储的位置

<?xml version="1.0"?>
<opencv_storage>
<images>
/home/ghj/Desktop/slam/pictureimg_1.jpg
/home/ghj/Desktop/slam/pictureimg_2.jpg
/home/ghj/Desktop/slam/pictureimg_3.jpg
/home/ghj/Desktop/slam/pictureimg_4.jpg
/home/ghj/Desktop/slam/pictureimg_5.jpg
</images>
</opencv_storage>

修改 in_VID5.xml

表示棋盘格的宽和高,注意,这里的宽度和高度是指内部交叉点的个数,而不是方形格的个数。如上图棋盘的数据就是9和6。

<BoardSize_Width> 9</BoardSize_Width>
<BoardSize_Height>6</BoardSize_Height>

修改为每格的边长 (mm),拿尺子量。

<Square_Size>20</Square_Size>

修改 输入的VID5.xml 的路径(换成自己的))

<Input>"/home/ghj/Desktop/slam/camera_calibration_opencv/VID5.xml"</Input>

修改输出参数信息存储的地址(换成自己的)

  <Write_outputFileName>"/home/ghj/Desktop/slam/camera_calibration_opencv/out_camera_data.xml"</Write_outputFileName>

 此处原来是0,需要改为1,表示引入切向畸变参数(因为 ORB-SLAM2 中也引入了切向畸变参数),否则只有径向畸变参数。

<Calibrate_FixPrincipalPointAtTheCenter> 1 </Calibrate_FixPrincipalPointAtTheCenter>

其它地方应该不需要改动,想进一步了解可看其中的注释。

<?xml version="1.0"?>
<opencv_storage>
<Settings>
  <!-- Number of inner corners per a item row and column. (square, circle) -->
  <BoardSize_Width> 9</BoardSize_Width>
  <BoardSize_Height>6</BoardSize_Height>
  
  <!-- The size of a square in some user defined metric system (pixel, millimeter)-->
  <Square_Size>20</Square_Size>
  
  <!-- The type of input used for camera calibration. One of: CHESSBOARD CIRCLES_GRID ASYMMETRIC_CIRCLES_GRID -->
  <Calibrate_Pattern>"CHESSBOARD"</Calibrate_Pattern>
  
  <!-- The input to use for calibration. 
		To use an input camera -> give the ID of the camera, like "1"
		To use an input video  -> give the path of the input video, like "/tmp/x.avi"
		To use an image list   -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml"
		-->
  <Input>"/home/ghj/Desktop/slam/camera_calibration_opencv/VID5.xml"</Input>
  <!--  If true (non-zero) we flip the input images around the horizontal axis.-->
  <Input_FlipAroundHorizontalAxis>0</Input_FlipAroundHorizontalAxis>
  
  <!-- Time delay between frames in case of camera. -->
  <Input_Delay>100</Input_Delay>	
  
  <!-- How many frames to use, for calibration. -->
  <Calibrate_NrOfFrameToUse>25</Calibrate_NrOfFrameToUse>
  <!-- Consider only fy as a free parameter, the ratio fx/fy stays the same as in the input cameraMatrix. 
	   Use or not setting. 0 - False Non-Zero - True-->
  <Calibrate_FixAspectRatio> 1 </Calibrate_FixAspectRatio>
  <!-- If true (non-zero) tangential distortion coefficients  are set to zeros and stay zero.-->
  <Calibrate_AssumeZeroTangentialDistortion>1</Calibrate_AssumeZeroTangentialDistortion>
  <!-- If true (non-zero) the principal point is not changed during the global optimization.-->
  <Calibrate_FixPrincipalPointAtTheCenter> 1 </Calibrate_FixPrincipalPointAtTheCenter>
  
  <!-- The name of the output log file. -->
  <Write_outputFileName>"/home/ghj/Desktop/slam/camera_calibration_opencv/out_camera_data.xml"</Write_outputFileName>
  <!-- If true (non-zero) we write to the output file the feature points.-->
  <Write_DetectedFeaturePoints>1</Write_DetectedFeaturePoints>
  <!-- If true (non-zero) we write to the output file the extrinsic camera parameters.-->
  <Write_extrinsicParameters>1</Write_extrinsicParameters>
  <!-- If true (non-zero) we show after calibration the undistorted images.-->
  <Show_UndistortedImage>1</Show_UndistortedImage>
 
</Settings>
</opencv_storage>

编译

在工作目录 camera_calibration_opencv 中新建 CMakeLists.txt:

project(Camera_Calibration)
set(CMAKE_CXX_STANDARD 11)

find_package(OpenCV 3.0 QUIET)
if(NOT OpenCV_FOUND)    
    find_package(OpenCV 2.4.3 QUIET)
    if(NOT OpenCV_FOUND)
        message(FATAL_ERROR "OpenCV > 2.4.3 not found.")
    endif()
endif()

include_directories(${OpenCV_INCLUDE_DIR})
add_executable(Camera_Calibration camera_calibration.cpp)
target_link_libraries(Camera_Calibration ${OpenCV_LIBS})

之后编译:

cd camera_calibration_opencv
mkdir build
cd build
cmake ..
make

运行,标定

cd camera_calibration_opencv
./build/Camera_Calibration ../in_VID5.xml

程序启动后会显示标定图像的角点提取情况,之后会显示校正后图像,一个一个全部关闭后才会保存标定参数至 out_camera_data.xml。

 标定结果写入camera_calibration/out_cam

 

  • <camera_matrix type_id="opencv-matrix"> 是相机内参矩阵,顺序为 fx, 0, cx; 0, fy, cy; 0, 0, 1。
  • <distortion_coefficients type_id="opencv-matrix"> 是畸变参数,其顺序为 k1, k2, p1, p2, k3。

之后在 ORB_SLAM2 中新建一个配置文件 mycam.yaml(建哪儿都行),将 TUM1.yaml 的内容拷贝过来,并把其中的 Camera 参数进行修改。

注意: 相机参数对 ORB-SLAM2 的运行效果有极大影响(尤其是初始化),所以标定过程须认真完成。

运行 ORB-SLAM2 Mono

Terminal 1:

roscore

手机进入 app 运行

Terminal 2: 在 Android_Camera-IMU 目录

roslaunch android_cam-imu.launch

(可以关掉 Rviz)

Terminal 3(加载的两个文件换成自己的):

rosrun ORB_SLAM2 Mono /home/ghj/ROS_SIM/src/ORB_SLAM2/Vocabulary/ORBvoc.txt /home/ghj/ROS_SIM/src/ORB_SLAM2/Examples/ROS/ORB_SLAM2/mycam.yaml

运行效果展示:

 

注意: ORB-SLAM2 Mono 还是比较难以初始化的(其设置的初始化条件相对苛刻),在开始时,选择特征纹理丰富的区域,多上下左右平移相机,有利于初始化。

简化启动

上述启动步骤需要启动3个终端,挺麻烦的,所以可以选择写一个脚本来自动启动这3个终端。参考资料

新建 ORB_SLAM2_with_AndroidPhone.sh,在其中填入:

gnome-terminal --title="roscore" -x bash -c "roscore"
# 暂停 2s,保证几个不同终端的启动顺序
sleep 2s;  

gnome-terminal --title="AndroidPhone" -x bash -c "cd /home/ghj/Desktop/slam/Android_Camera-IMU; roslaunch android_cam-imu.launch"
sleep 2s;

gnome-terminal --title="ORB-SLAM2" -x bash -c "rosrun ORB_SLAM2 Mono /home/ghj/ROS_SIM/src/ORB_SLAM2/Vocabulary/ORBvoc.txt /home/ghj/ROS_SIM/src/ORB_SLAM2/Examples/ROS/ORB_SLAM2/mycam.yaml"

之后赋予权限(仅需一次):

chmod +x ORB_SLAM2_with_AndroidPhone.sh

运行:

./ORB_SLAM2_with_AndroidPhone.sh

即可一次性打开3个终端,并运行相关命令。之后手机再打开 app 就可以了。

注意: 此时终端运行结束后会自动退出,如果不想自动退出,可 在terminal点右键,选择Preferences然后找到Command,里面有一项When command exits,后面选择为Hold the terminal open。参考资料

 

 

有关利用手机摄像头采集图片运行ORB-SLAM2的更多相关文章

  1. 怎样用一台手机做自媒体? - 2

    其实做自媒体的成本并不高,入门只需要一部手机即可!在手机上找视频素材、使用手机剪辑视频、最后使用手机发布视频作品获得收益!方法并不难,今天这期内容就来给粉丝们分享一种小方法,每天稳定收益100-300,抓紧点赞收藏!1、找素材(1)使用手机拍摄自己喜欢的经典段落,使用程序把文案内容提取出来(2)也可以在豆瓣、知乎、微博等网站中找一些自己需要的文案素材(3)把文案进行润色修改,可以加入一些自己的观点(4)视频素材可以使用软件中自带的素材,也可以在素材网站中下载完整版的素材2、文案配音(1)把复制好的文案直接导入小程序中(2)调整音色、音调后一键合成音频即可(3)可以选择自己朗读配音,需要花一点时

  2. 如何使用手机远程访问自己的电脑? - 2

    手机访问电脑后AnyViewer可以做什么? 您成功将手机连接到Windows电脑后,然后您可以做任何您想做的事情,例如:查看文件和运行应用程序。电源管理:在远程会话中,点击电源管理,您可以看到三个项目:锁定、重启和关机,供您在不同情况下管理计算机。如果您需要暂时离开远程会话,可以锁定计算机。如果计算机死机,您可以重新启动它,然后再次连接。如果您已完成计算机上的所有工作,您可以使用手机远程关闭它。更改图像质量:当电脑和手机的网络都处于良好状态时,您可以选择高图像质量以获得更好的体验。当网络状况不佳时,您可以选择低图像质量以获得更流畅的操作。     显示桌面:我们无法在手机上按Windows+

  3. 手机 & 电脑数据,这样删除才彻底! - 2

    恢复出厂设置后数据还在吗?格式化真的彻底吗?数据到底该怎么删?文章目录前言为什么不能彻底删除数据?手机如何彻底删除数据?第一步:恢复出厂设置第二步:手动覆写数据电脑如何彻底删除数据?方法一:命令提示符方法二:文件粉碎方法三:低级格式化硬盘总结前言个人数据安全再次成为大家关注的热门话题:在日常使用手机和电脑时,我们可能需要删除一些敏感数据,例如银行账户信息、个人照片、聊天记录等。数据删除的目的是保护个人隐私,避免泄露。以下是一些关于如何删除数据的方法。恢复出厂设置,不一定彻底清除手机数据电子产品迭代升级速度越来越快,大家家中的旧手机、旧电脑也越来越多,一键删除、格式化、恢复出厂设置能彻底清除个人

  4. iOS快捷指令:执行Python脚本(利用iSH Shell) - 2

    文章目录前言核心逻辑配置iSH安装Python创建Python脚本配置启动文件测试效果快捷指令前言iOS快捷指令所能做的操作极为有限。假如快捷指令能运行Python程序,那么可操作空间就瞬间变大了。iSH是一款免费的iOS软件,它模拟了一个类似Linux的命令行解释器。我们将在iSH中运行Python程序,然后在快捷指令中获取Python程序的输出。核心逻辑我们用一个“获取当前日期”的Python程序作为演示(其实快捷指令中本身存在“获取当前日期”的操作,因而此需求可以不用Python,这里仅仅为了演示方便),核心代码如下。>>>importtime>>>time.strftime('%Y-%

  5. ruby - Sidekiq 可以利用多个 CPU 内核吗? - 2

    我是Sidekiq的新手,将它与AmazonEC2实例上的Ruby结合使用,以使用ImageMagick处理图像来完成一些工作。在运行它时,我意识到每个工作人员都在同一个核心上运行。我使用EC2c3.2xlarge机器,它们有8个内核。它显示CPU使用率为15%,但一个内核使用了100%,而其他内核使用了0%。Sidekiq可以为不同的worker使用不同的CPU内核吗?如果可以,这种低效率是由ImageMagic造成的吗?我怎样才能让它使用其他内核? 最佳答案 如果您想使用MRI使用多个内核,则需要启动多个Sidekiq进程;为您

  6. Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信) - 2

    运行有问题或需要源码请点赞关注收藏后评论区留言一、利用ContentResolver读写联系人在实际开发中,普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据,比如查看联系人,短信,通话记录等等,以及对这些通讯数据及逆行增删改查。首先要给AndroidMaifest.xml中添加响应的权限配置 下面是往手机通讯录添加联系人信息的例子效果如下分成三个步骤先查出联系人的基本信息,然后查询联系人号码,再查询联系人邮箱代码 ContactAddActivity类packagecom.example.chapter07;importandroid

  7. PLUS模型和InVEST模型生态系统服务多情景模拟预测、ArcGIS空间数据处理、空间分析与制图、土地利用时空变化 - 2

    查看原文>>>基于”PLUS模型+“生态系统服务多情景模拟预测实践技术应用目录第一章、理论基础与软件讲解第二章、数据获取与制备第三章、土地利用格局模拟第四章、生态系统服务评估第五章、时空变化及驱动机制分析第六章、论文撰写技巧及案例分析基于ArcGISPro、Python、USLE、INVEST模型等多技术融合的生态系统服务构建生态安全格局基于生态系统服务(InVEST模型)的人类活动、重大工程生态成效评估、论文写作等具体应用基于ArcGISPro、R、INVEST等多技术融合下生态系统服务权衡与协同动态分析实践应用    本文从数据、方法、实践三方面对生态系统服务多情景预测进行讲解。内容涵盖多

  8. 萤石开放平台——怎么通过API接口远程添加摄像头? - 2

    高科技摄像头特别是海康萤石摄像头,已经不再只局限于简单的视频功能,特别是智能AI的普及,摄像头也华丽变身成了一个个独立的智能个体,可以实现人脸抓拍,人形检测,客流统计等店铺值守场景,也可以实现安全帽识别,车辆识别,非法入侵识别等智慧工地场景。但用户也许会问,摄像头又不会说话,他得知的这些信息怎么告诉我们,还是说需要配一个主机去处理,这成本又有点太高了。这点正是萤石云要为大家解决的,下面来介绍下如何让设备更简便智能的说话。API(应用程序编程接口)提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力。形象一点API可以理解为一个管道,通过该管道,可以传入约定好的命令,来获得摄像头的反馈,

  9. (一)专题介绍:移动端安卓手机改造成linux服务器&linux服务器中安装软件、部署前后端分离项目实战 - 2

    快捷目录前言一、涉及到的相关技术简介二、具体实现过程及踩坑杂谈1.安卓手机改造成linux系统实现方案2.改造后的手机Linux中软件的安装3.手机Linux中安装MySQL5.7踩坑实录4.手机Linux中安装软件的正确方法三、Linux服务器部署前后端分离项目流程1.前提准备(安装必要软件,搭建环境):2.前后端分离项目的详细部署过程:总结前言总体概述:本篇文章隶属于“手机改造服务器部署前后端分离项目”系列专栏,该专栏将分多个板块,每个板块独立成篇来详细记录:手机(安卓)改造成个人服务器(Linux)、Linux中安装软件、配置开发环境、部署JAVA+VUE+MySQL5.7前后端分离项目

  10. Fiddler手机抓包网络报错解决办法 - 2

    首先打开fiddler,点击Tools-Options-Connections一、这里有两个注意点点击HTTPS,左边选项选择如图,右边Actions点击如图第二项会提示Success,点击确定点击Connections,这里注意Fiddlerlistensonport这里面填写默认8888即可,左边三个选项选择如图,以上操作完成后,重启Fiddler二、手机打开WiFi1.长按或者点击Wifi进行修改网络(如不会操作,此处根据具体机型自行百度)修改代理为手动,服务器主机名两种方式可以查到:①win+R,在输入框输入cmd,在弹窗中输入ipconfig,此时IPv4后面的地址就是你的主机ip,

随机推荐