【mediapipe嵌入式实战01】Linux环境的mediapipe编译(快跑)


最近想要将 mediapipe 中 facemesh 这个功能移植到硬件上,所以第一步是要编译一下 mediapipe,因为 mediapipe 是谷歌出的,自然也是要用 google 的 bazel 编译器进行编译。只是第一次接触,踩的坑有点多,花了将近 3 天的时间才成功地编译。

首先说一下我的系统的是 centos 8,gcc 版本是 8.5,opencv 的版本是 4.1.2。

09/25更新:

如果你是像将 mediapipe 编译成静态库使用到自己的项目里的话,下面就可以不用阅读了,bazel 没办法像 cmake 一样输出你想要的 dll 或者 so 文件,而且也不支持,我看了官方仓库也有人提这个 issue,貌似维护者也说了 google 已经不投入资源在这个项目里了,mediapipe 对 C++ 的支持这么差,属实有些逆天。

后来找到一个别人封装的 C 语言库 libmediapipe,可以编译出各平台所需的头文件和库文件,后续使用这个库文件就不需要再用 bazel 编译了,可以直接用 cmake 编译了。不过里面需要根据自己的环境进行一些调整,也就是还是要进行一轮 bazel 编译,所以还是可以看看这篇文章的。

官网版本建议

Note: To interoperate with OpenCV, OpenCV 3.x to 4.1 are preferred. OpenCV 2.x currently works but interoperability support may be deprecated in the future.

Note: If you plan to use TensorFlow calculators and example apps, there is a known issue with gcc and g++ version 6.3 and 7.3. We recommend installing gcc and g++ version 8.x.

Note: To make Mediapipe work with TensorFlow, please set Python 3.7 as the default Python version and install the Python “six” library by running pip3 install --user six.

bazel 安装

我是按照这篇文章(安装bazelisk)进行安装的,因为不知道为啥,官网的 centos 下的安装指南页面是 404。但是其他系统的安装指南都可以在官网找到。

安装 mediapipe 及其依赖

下载 opencv 和 ffmpeg

opencv 可以用 yum 命令安装,也可以自己源码编译,但是最好版本是要在 3.0 以上,我是之前就源码编译过了。

下载 mediapipe

$ git clone --depth 1 https://github.com/google/mediapipe.git

# Change directory into MediaPipe root directory
$ cd mediapipe

修改编译配置文件

有 3 个文件要进行修改

  • mediapipe/WORKSPACE

opencv 和 ffmpeg 的 path 改称自己系统的对应路径。

new_local_repository(
    name = "linux_opencv",
    build_file = "@//third_party:opencv_linux.BUILD",
    path = "/usr/local",
)

new_local_repository(
    name = "linux_ffmpeg",
    build_file = "@//third_party:ffmpeg_linux.BUILD",
    path = "/usr/local",
)
  • mediapipe/third_party/opencv_linux.BUILD

按照自己的情况进行修改

cc_library(
    name = "opencv",
    srcs = glob(
        [
            "lib/libopencv_core.so",
            "lib/libopencv_highgui.so",
            "lib/libopencv_imgcodecs.so",
            "lib/libopencv_imgproc.so",
            "lib/libopencv_video.so",
            "lib/libopencv_videoio.so",
        ],
    ),
    hdrs = glob([
        # For OpenCV 3.x
        "include/opencv2/**/*.h*",
        # For OpenCV 4.x
        # "include/opencv4/opencv2/**/*.h*",
    ]),
    includes = [
        # For OpenCV 3.x
        "include/",
        # For OpenCV 4.x
        # "include/opencv4/",
    ],
    linkstatic = 1,
    visibility = ["//visibility:public"],
)
  • mediapipe/third_party/ffmpeg_linux.BUILD

也是按照自己的情况修改。

cc_library(
    name = "libffmpeg",
    srcs = glob(
        [
            "lib/libav*.so",
        ],
    ),
    hdrs = glob(["include/libav*/*.h"]),
    includes = ["include"],
    linkopts = [
        "-lavcodec",
        "-lavformat",
        "-lavutil",
    ],
    linkstatic = 1,
    visibility = ["//visibility:public"],
)

编译命令

$ export GLOG_logtostderr=1
# Need bazel flag 'MEDIAPIPE_DISABLE_GPU=1' if you are running on Linux desktop with CPU only
$ bazel run --define MEDIAPIPE_DISABLE_GPU=1 \
    mediapipe/examples/desktop/hello_world:hello_world

# Should print:
# Hello World!
# Hello World!
# Hello World!
# Hello World!
# Hello World!
# Hello World!
# Hello World!
# Hello World!
# Hello World!
# Hello World!

踩坑记录

上面的自然是顺利的情况下的整个流程,但是到了自己上手的时候哪有这么顺利(悲)。下面就说一下我遇到的问题。

依赖库下载 timeout

就是一些依赖没有下载成功,如果没有科学上网的话,多运行几次,总能下载完成。

numpy 找不到

ModuleNotFoundError: No module named 'numpy'
Is numpy installed?

这是没有找到 numpy,因为是根据 python 的路径来寻找 numpy 的,所以可以指定 python 的路径来解决这个问题。

whereis python

获得 python 的路径之后,加上选项 --action_env PYTHON_BIN_PATH="path to python bin"来进行编译,就不会再提示这个错误了。

gcc permission denied / linux-sandbox failed

这个是困扰我最久的问题,每次编译到一定程度,就会显示:

gcc: error: mediapipe/framework/<filename>.cc: Permission denied
gcc: fatal error: no input files

虽然这一看就是权限问题,但是我还是走了很多歪路:

  • 可能是 gcc 在 root 和 user 的权限不一样,其实两个环境下都可以运行 gcc
  • 可能是 linux 的沙盒屏蔽了对某些文件的读写,导致失败,禁用了沙盒,其实也没用
  • 可能是 bazel 命令没有使用 sudo 运行,但是用 sudo 运行结果也一样
  • 可能是没有清理 bazel 缓存的影响,使用 bazel clean --expunge 清理了也一样
  • 也将打印出来无法写入的文件使用 chmod -R 777 给了读写的权限,但是还是不行
  • 以为是依赖项目没有链接成功,又重新源码编译了 abseil 和 protobuf,但是还是不行

上面都尝试过多次之后,感觉很绝望,于是去 github 上提 issue。

结果突然好像灵光一闪,比对了了一下 root 和 user 下的 ~/.bashrc 文件内的内容,发现两个的系统路径和库路径是不太一样的,user 下的很多路径都没有加上去。于是都加上去, source 一下生效。

然后再在 user 下使用

export GLOG_logtostderr=1 && bazel build mediapipe/examples/desktop/face_mesh:face_mesh_cpu --action_env PYTHON_BIN_PATH="/home/cai/anaconda3/envs/yolov8/bin/python3.8" --verbose_failures --sandbox_debug -c opt --define MEDIAPIPE_DISABLE_GPU=1

编译一下,顺利的完成了编译,卡了三天的编译终于顺利解决了。

编译tensorflow的时候出错

这是我编译 libmediapipe 出现的,其中的 shell 文件也调用了 bazel 进行编译,出现这个错误之后,我将 bazel 的编译模式改称 -c opt 之后就顺利完成了。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
嵌入式操作系统Linux编译移植搭建可以分为以下几个步骤: 1. 适合的Linux内核版本:嵌入式系统开发需要选择适合的Linux内核版本,可以选择已有的版本或自己编译。选择时需要考虑硬件平台和应用需求。 2. 配置交叉编译环境:交叉编译环境是在一种操作系统下编译另一种操作系统的程序,需要安装交叉编译工具链。工具链包括交叉编译器、交叉调试器等。 3. 配置内核:根据硬件平台和应用需求,配置内核。配置文件一般位于内核源码树的根目录下,可以使用make menuconfig或make xconfig等工具进行配置。 4. 编译内核:使用交叉编译工具链编译内核源码。编译后会生成内核镜像和模块。 5. 移植内核:将编译好的内核镜像和模块移植到目标硬件平台,并进行测试和调试。 6. 配置根文件系统:嵌入式Linux系统需要一个根文件系统,可以选择已有的或自己制作。根文件系统包括文件系统镜像、启动脚本等。 7. 移植根文件系统:将根文件系统移植到目标硬件平台,并进行测试和调试。 8. 应用开发:根据应用需求开发应用程序,并将其编译链接到根文件系统中。应用程序可以使用交叉编译工具链编译。 以上是嵌入式操作系统Linux平台的编译移植搭建的一般步骤。具体实现过程需要根据具体的硬件平台、应用需求和开发环境进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值