您当前的位置: 首页 > 

牲畜体表信息的三维重建

发布时间:2021-02-04 07:00:00 ,浏览量:1

点击上方“3D视觉工坊”,选择“星标”

干货第一时间送达

引导语:本文为“3D视觉创新应用(三维重建)竞赛”作品集系列之一,该作品由来自中国农业大学团队完成,团队成员:陆杰、苏杨、都敖。全文约2054个字,阅读时长约5分钟,旨在为更多开发者提供学习参考。

一、环境配置 奥比中光OpenNISDK安装(Linux)

奥比中光针对ZaroP1开发板和深度摄像机提供了相关的OpenNI2的SDK,针对Windows/Linux/Android不同平台提供了相关的安装文档.根据官方文档将OpenNI2配置完成,注意官方文档中说Linux平台内置驱动不需要额外安装,但是需要仔细阅读README文件:

OpenNI
------
Website: http://structure.io/openni
Building Prerequisites(前置依赖)
======================
Linux
-----
- GCC 4.x
    From: http://gcc.gnu.org/releases.html
    Or via apt:
    sudo apt-get install g++
- Python 2.6+/3.x
    From: http://www.python.org/download/
    Or via apt:
    sudo apt-get install python
- LibUSB 1.0.x
    From: http://sourceforge.net/projects/libusb/files/libusb-1.0/
    Or via apt:
    sudo apt-get install libusb-1.0-0-dev
- LibUDEV
    sudo apt-get install libudev-dev
- JDK 6.0
    From: http://www.oracle.com/technetwork/java/javase/downloads/jdk-6u32-downloads-1594644.html
    Or via apt:
    sudo apt-get install openjdk-6-jdk
- FreeGLUT3
    From: http://freeglut.sourceforge.net/index.php#download
    Or via apt:
    sudo apt-get install freeglut3-dev
- Doxygen
    From: http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc
    Or via apt:
    sudo apt-get install doxygen
- GraphViz
    From: http://www.graphviz.org/Download_linux_ubuntu.php
    Or via apt:
    sudo apt-get install graphviz

将以上的依赖安装完成之后,运行其中示例代码还需要安装对应的USB驱动,驱动安装方法如下此方法将同目录下的USB驱动文件拷贝到系统目录中,并自动生成环境文件指明OpenNI的路径此方法将同目录下的USB驱动文件拷贝到系统目录中,并自动生成环境文件指明OpenNI的路径,进入安装包OpenNI目录中:

orbbec@localhost:OpenNI$ ./install.sh

最后,在安装文件中找到NiViewer运行文件,若文件不能运行,查看chmod权限。

sudo ./NiViewer

结果图片

经过以上的配置过程,OpenNI的环境就配置完成了。

OpenCV在Arm平台上编译

在运用开发板设备获取数据的时候,通常运用OpenNI2获取数据流,通过OpenCV对数据流进行转换,生成RGB图片和深度图片。 源文件官方地址,本文用的是OpenCV3.4.3版本。OpenCV编译的方法可通过百度搜索,编译完成后对orbbec中OpenNI2SDK和opencv进行配置。

OpenCV+OpenNI2配置

根据官方给出的示例代码,进行编写。由于官方的代码是在Makefile文件中进行编写,所以opencv也需要在其中编写。根据Makefile文件编写规则进行编写。

Includes
CFLAGS = ${shell pkg-config opencv --cflags}
#lib
LDFLAGS = ${shell pkg-config opencv --libs}

其中pkg-config需要在系统中配置opencv.pc文件,文件内容,在安装的文件中可以找到,若没有则可能默认没有生成(opencv4之后的版本默认不生成),需要在编译的时候设置。 opencv环境配置没有问题后,在orbbec提供的OpenNI2的文件中示例代码中进行整合开发。文件位置在:

/OpenNI/Samples/

选择其中SimpleViewer文件夹中的示例代码进行编写。在CommonCppMakefile文件夹中找到CFLAGS和LDFLAGS变量位置,在其后加上:

#Includes
CFLAGS += ${shell pkg-config opencv --cflags}
#lib
LDFLAGS += ${shell pkg-config opencv --libs}

此外还需要在Makefile文件中加入OpenNI头文件的路径和Redist的路径,这就是在配置OpenNI时运行install.sh文件生成的环境文件中的内容,也在同级目录下。其后编译即可通过。接下来就可以使用opencv对数据进行获取保存了。

二、数据获取

根据上文环境配置的结果,对数据获取部分的代码进行调整,由于官方OpenNI2代码运用Makefile进行管理,所以将OpenCV的配置也运用Makefile进行管理。本文以官方示例代码SimpleViewer文件加下的文件作为基础,对其中的Makefile进行配置。 首先,“Makefile”文件内容进行修改,第3、4行为添加部分,内容是官方OpenNI2的相关文件路径:

include CommonDefs.mak
BIN_DIR = Bin
OPENNI2_INCLUDE=/home/orbbec/Desktop/OpenNI-Linux-Arm64-2.3.0.65/OpenNI-Linux-Arm64-2.3.0.65/include/
OPENNI2_REDIST=/home/orbbec/Desktop/OpenNI-Linux-Arm64-2.3.0.65/OpenNI-Linux-Arm64-2.3.0.65/Redist/
INC_DIRS = \
    ../../Include \
    ../../ThirdParty/GL/ \
    ../Common
SRC_FILES = *.cpp
ifeq ("$(OSTYPE)","Darwin")
    CFLAGS += -DMACOS
    LDFLAGS += -framework OpenGL -framework GLUT
else
    CFLAGS += -DUNIX -DGLX_GLXEXT_LEGACY
    USED_LIBS += glut GL
endif
USED_LIBS += OpenNI2
EXE_NAME = SimpleViewer
CFLAGS += -Wall
ifndef OPENNI2_INCLUDE
    $(error OPENNI2_INCLUDE is not defined. Please define it or 'source' the OpenNIDevEnvironment file from the installation)
else ifndef OPENNI2_REDIST
    $(error OPENNI2_REDIST is not defined. Please define it or 'source' the OpenNIDevEnvironment file from the installation)
endif
INC_DIRS += $(OPENNI2_INCLUDE)
include CommonCppMakefile
.PHONY: copy-redist
copy-redist:
    cp -R $(OPENNI2_REDIST)/* $(OUT_DIR)
$(OUTPUT_FILE): copy-redist

接着对“CommonCppMakefile”文件进行修改,45、46行为修改内容,添加的内容主要为OpenCV的编译文件的路径,由环境配置可知,在pkgconfig中配置OpenCV.pc文件后在系统中调用相关命令即可给出OpenCV安装文件的路径:

# take this file's dir
COMMON_CPP_MAKE_FILE_DIR = $(dir $(lastword $(MAKEFILE_LIST)))
include $(COMMON_CPP_MAKE_FILE_DIR)CommonDefs.mak
# define a function to figure .o file for each source file (placed under intermediate directory)
SRC_TO_OBJ = $(addprefix ./$(INT_DIR)/,$(addsuffix .o,$(notdir $(basename $1))))
# create a list of all object files
OBJ_FILES = $(call SRC_TO_OBJ,$(SRC_FILES_LIST))
# define a function to translate any source file to its dependency file (note that the way we create
# dep files, as a side affect of compilation, always puts the files in the INT_DIR with suffix .d)
SRC_TO_DEP = $(addprefix ./$(INT_DIR)/,$(addsuffix .d,$(notdir $(basename $1))))
# create a list of all dependency files
DEP_FILES = $(call SRC_TO_DEP,$(SRC_FILES_LIST))
# older version of gcc doesn't support the '=' symbol in include dirs, so we replace it ourselves with sysroot
INC_DIRS_FROM_SYSROOT = $(patsubst =/%,$(TARGET_SYS_ROOT)/%,$(INC_DIRS))
# append the -I switch to each include directory
INC_DIRS_OPTION = $(foreach dir,$(INC_DIRS_FROM_SYSROOT),-I$(dir))
# append the -L switch to each library directory
LIB_DIRS_OPTION = $(foreach dir,$(LIB_DIRS),-L$(dir)) -L$(OUT_DIR)
# append the -l switch to each library used
USED_LIBS_OPTION = $(foreach lib,$(USED_LIBS),-l$(lib))
# append the -D switch to each define
DEFINES_OPTION = $(foreach def,$(DEFINES),-D$(def))
# tell compiler to use the target system root
ifdef TARGET_SYS_ROOT
    CFLAGS += --sysroot=$(TARGET_SYS_ROOT)
    LDFLAGS += --sysroot=$(TARGET_SYS_ROOT)
endif
# set Debug / Release flags
ifeq "$(CFG)" "Debug"
    CFLAGS += -O0 -g
endif
ifeq "$(CFG)" "Release"
    CFLAGS += -O2 -DNDEBUG
endif
CFLAGS += $(INC_DIRS_OPTION) $(DEFINES_OPTION)
CFLAGS += -fPIC -fvisibility=hidden
ifneq "$(ALLOW_WARNINGS)" "1"
    CFLAGS += -Werror
ifeq ("$(OSTYPE)","Darwin")
    CFLAGS += -Wno-deprecated-declarations -Wno-unused-private-field -Wno-unused-const-variable
endif
endif
LDFLAGS += $(LIB_DIRS_OPTION) $(USED_LIBS_OPTION)
##############this is out method######################
CFLAGS += ${shell pkg-config opencv --cflags}
LDFLAGS += ${shell pkg-config opencv --libs}
#####################################
# some lib / exe specifics
ifneq "$(LIB_NAME)" ""
    OUTPUT_NAME = lib$(LIB_NAME).so
    ifneq ("$(OSTYPE)","Darwin")
        LDFLAGS += -Wl,--no-undefined
        OUTPUT_NAME = lib$(LIB_NAME).so
        OUTPUT_COMMAND = $(CXX) -o $(OUTPUT_FILE) $(OBJ_FILES) $(LDFLAGS) -shared
    else
        LDFLAGS += -undefined error
        OUTPUT_NAME = lib$(LIB_NAME).dylib
        OUTPUT_COMMAND = $(CXX) -o $(OUTPUT_FILE) $(OBJ_FILES) $(LDFLAGS) -dynamiclib -headerpad_max_install_names -install_name $(OUTPUT_NAME)
    endif
endif
ifneq "$(EXE_NAME)" ""
    OUTPUT_NAME = $(EXE_NAME)
    # We want the executables to look for the .so's locally first:
    LDFLAGS += -Wl,-rpath ./
    OUTPUT_COMMAND = $(CXX) -o $(OUTPUT_FILE) $(OBJ_FILES) $(LDFLAGS)
endif
ifneq "$(SLIB_NAME)" ""
    OUTPUT_NAME = lib$(SLIB_NAME).a
    ifneq ("$(OSTYPE)","Darwin")
        OUTPUT_COMMAND = $(AR) -cq $(OUTPUT_FILE) $(OBJ_FILES)
    else
        OUTPUT_COMMAND = libtool -static -o $(OUTPUT_FILE) $(OBJ_FILES)
    endif
endif
define CREATE_SRC_TARGETS
# create a target for the object file (the CXX command creates both an .o file
# and a .d file)
ifneq ("$(OSTYPE)","Darwin")
$(call SRC_TO_OBJ,$1) : $1 | $(INT_DIR)
    $(CXX) -MD -MP -MT "$(call SRC_TO_DEP,$1) $$@" -c $(CFLAGS) -o $$@ $$<
else
$(call SRC_TO_OBJ,$1) : $1 | $(INT_DIR)
    $(CXX) -x c++ -c $(CFLAGS) -o $$@ $$<
endif
endef
#############################################################################
# Targets
#############################################################################
.PHONY: clean-objs clean-defs
include $(COMMON_CPP_MAKE_FILE_DIR)CommonTargets.mak
# create targets for each source file
$(foreach src,$(SRC_FILES_LIST),$(eval $(call CREATE_SRC_TARGETS,$(src))))
# include all dependency files (we don't need them the first time, so we can use -include)
-include $(DEP_FILES)
$(OUTPUT_FILE): $(OBJ_FILES)
    $(OUTPUT_COMMAND)
clean-objs:
    rm -rf $(OBJ_FILES)
clean-defs:
    rm -rf $(DEP_FILES)
clean: clean-objs clean-defs

这样本文以官方SimpleViewer文件夹为基础的Makefile相关文件的编写就完成了,接着就是对文件中主函数文件main.cpp进行代码编写,这样就可以结合openNI和OpenCV进行数据获取。

获取深度图

获取深度图主要用到了openni的接口获取数据流,然后将获取的数据流通过opencv接口转换成深度图像。

#include 
#include "Viewer.h"
#include 
#include#include 
#include 
#include 
#include 
#include 
using namespace std;
using namespace openni;
#define SAMPLE_READ_WAIT_TIMEOUT 2000 //2000ms
int wasKeyboardHit();
int main(int argc, char** argv)
{
    openni::Status rc = openni::STATUS_OK;
    openni::Status rc_d = openni::STATUS_OK;
    openni::Device device;
    openni::VideoStream depth, color;
    const char* deviceURI = openni::ANY_DEVICE;
    rc = openni::OpenNI::initialize();
    printf("After initialization:\n%s\n", openni::OpenNI::getExtendedError());
    rc = device.open(deviceURI);
    if (rc != openni::STATUS_OK)
    {
        printf("SimpleViewer: Device open failed:\n%s\n", openni::OpenNI::getExtendedError());
        openni::OpenNI::shutdown();
        return 1;
    }
    rc = depth.create(device, openni::SENSOR_DEPTH);
    if (rc == openni::STATUS_OK)
        rc = depth.start();
    openni::VideoFrameRef frameDepth;
    openni::DepthPixel* pDepth;
    cout<<"stream start, press any key to stop..."<            
关注
打赏
1688896170
查看更多评论

暂无认证

  • 1浏览

    0关注

    106366博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.5145s