google-ai-edge / mediapipe

Cross-platform, customizable ML solutions for live and streaming media.
https://ai.google.dev/edge/mediapipe
Apache License 2.0
26.84k stars 5.09k forks source link

Neon error when importing mediapipe python on raspberry pi 3 #1629

Closed Projudah closed 3 years ago

Projudah commented 3 years ago

Help, After building and installing mediapipe on a virtual env, i get this error

Traceback (most recent call last):
  File "hands.py", line 2, in <module>
    import mediapipe as mp*
  File "/home/pi/python8/mp_env/lib/python3.8/site-packages/mediapipe/__init__.py", line 16, in <module>
    from mediapipe.python import *
  File "/home/pi/python8/mp_env/lib/python3.8/site-packages/mediapipe/python/__init__.py", line 17, in <module>
    from mediapipe.python._framework_bindings import resource_util
ImportError: /home/pi/python8/mp_env/lib/python3.8/site-packages/mediapipe/python/_framework_bindings.cpython-38-arm-linux-gnueabihf.so: undefined symbol: _ZN3ruy14Kernel8bitNeonERKNS_16KernelParams8bitILi4ELi2EEE

I installed open-cv with both options 1, and options 2. I'm running this on a raspberry pi 3 B, with swappartion.

jiuqiant commented 3 years ago

The official documentation points to https://github.com/jiuqiant/mediapipe_python_aarch64 for aarch64 Linux users.

Please read https://github.com/jiuqiant/mediapipe_python_aarch64/blob/main/README.md or try https://github.com/jiuqiant/mediapipe_python_aarch64/blob/main/manylinux_aarch64/mediapipe-0.8.1-cp38-cp38-manylinux2014_aarch64.whl on Raspberry Pi 3B.

Projudah commented 3 years ago

Thanks for the quick reply Yeah, i'm pretty sure i followed that document, and everything built without errors but a lot of info messages,

when i ran python3 -m pip install mediapipe/dist/mediapipe-0.8-cp38-cp38-linux_aarch64.whl after setup.py bdist_wheel the error i get is undefined symbol: __atomic_load_8 or something like that, then when i run setup.py install --link-opencv i get the above error with Neon. i was also getting some gcc7.1 info messages pop up whilst building but im not sure if it means anything.

and also when trying pip install dist/mediapipe-0.8.1-cp38-cp38-manylinux2014_aarch64.whl i get a not supported on this platform error.

jiuqiant commented 3 years ago

For "undefined symbol: __atomic_load_8", can you add -latomic into https://github.com/google/mediapipe/blob/39309bedba255aee2a4f31b29b65609857698ada/third_party/BUILD#L144 and rerun python3 setup.py gen_protos && python3 setup.py bdist_wheel to see if it helps? Here is a similar issue for your reference: https://forum.juce.com/t/juce-in-raspberry-pi-4b-solved/41895.

I think we need to build opencv rather than linking the existing library to avoid missing Neon symbol issue

Projudah commented 3 years ago

okay i'll try right now and get back to you

Projudah commented 3 years ago

update, so i added -libatomic to third_party/BUILD and ran bdist_wheel and then pip installed, but i still get

Python 3.8.7 (default, Feb  7 2021, 12:36:27) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import mediapipe
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pi/python8/mp_env/lib/python3.8/site-packages/mediapipe/__init__.py", line 16, in <module>
    from mediapipe.python import *
  File "/home/pi/python8/mp_env/lib/python3.8/site-packages/mediapipe/python/__init__.py", line 17, in <module>
    from mediapipe.python._framework_bindings import resource_util
ImportError: /home/pi/python8/mp_env/lib/python3.8/site-packages/mediapipe/python/_framework_bindings.cpython-38-arm-linux-gnueabihf.so: undefined symbol: _ZN3ruy14Kernel8bitNeonERKNS_16KernelParams8bitILi4ELi2EEE

i installed open cv via both

sudo apt-get install libopencv-core-dev libopencv-highgui-dev \
                       libopencv-calib3d-dev libopencv-features2d-dev \
                       libopencv-imgproc-dev libopencv-video-dev

and then setup_opencv.sh when i got similar errors as above.

but i feel like something is wrong because i have ffmpeg only under usr/local/lib.. but opencv under both usr/local/include and usr/include

jiuqiant commented 3 years ago

Can you paste the content of your third_party/BUILD here?

Projudah commented 3 years ago

ok @jiuqiant

# Copyright 2019 The MediaPipe Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

licenses(["notice"])  # Apache License 2.0

exports_files(["LICENSE"])

package(default_visibility = ["//visibility:public"])

cc_library(
    name = "glog",
    visibility = ["//visibility:public"],
    deps = select({
        "//mediapipe:android_x86": [
            "@com_github_glog_glog_no_gflags//:glog",
        ],
        "//mediapipe:android_x86_64": [
            "@com_github_glog_glog_no_gflags//:glog",
        ],
        "//mediapipe:android_armeabi": [
            "@com_github_glog_glog_no_gflags//:glog",
        ],
        "//mediapipe:android_arm": [
            "@com_github_glog_glog_no_gflags//:glog",
        ],
        "//mediapipe:android_arm64": [
            "@com_github_glog_glog_no_gflags//:glog",
        ],
        "//mediapipe:ios": [
            "@com_github_glog_glog_no_gflags//:glog",
        ],
        "//mediapipe:macos": [
            "@com_github_glog_glog//:glog",
        ],
        "//mediapipe:windows": [
            "@com_github_glog_glog//:glog",
        ],
        "//conditions:default": [
            "@com_github_glog_glog//:glog",
        ],
    }),
)

config_setting(
    name = "opencv_source_build",
    define_values = {
        "OPENCV": "source",
    },
    visibility = ["//visibility:public"],
)

alias(
    name = "opencv",
    actual = select({
        ":opencv_source_build": ":opencv_cmake",
        "//conditions:default": ":opencv_binary",
    }),
    visibility = ["//visibility:public"],
)

load("@rules_foreign_cc//tools/build_defs:cmake.bzl", "cmake_external")

# Note: this determines the order in which the libraries are passed to the
# linker, so if library A depends on library B, library B must come _after_.
# Hence core is at the bottom.
OPENCV_MODULES = [
    "imgproc",
    "core",
]

# Note: passing both BUILD_SHARED_LIBS=ON and BUILD_STATIC_LIBS=ON to cmake
# still only builds the shared libraries, so we have to choose one or the
# other. We build shared libraries by default, but this variable can be used
# to switch to static libraries.
OPENCV_SHARED_LIBS = False

OPENCV_SO_VERSION = "3.4"

cmake_external(
    name = "opencv_cmake",
    # Values to be passed as -Dkey=value on the CMake command line;
    # here are serving to provide some CMake script configuration options
    cache_entries = {
        "CMAKE_BUILD_TYPE": "Release",
        # The module list is always sorted alphabetically so that we do not
        # cause a rebuild when changing the link order.
        "BUILD_LIST": ",".join(sorted(OPENCV_MODULES)),
        "BUILD_TESTS": "OFF",
        "BUILD_PERF_TESTS": "OFF",
        "BUILD_EXAMPLES": "OFF",
        "BUILD_SHARED_LIBS": "ON" if OPENCV_SHARED_LIBS else "OFF",
        "WITH_ITT": "OFF",
        "WITH_JASPER": "OFF",
        "WITH_WEBP": "OFF",
        # When building tests, by default Bazel builds them in dynamic mode.
        # See https://docs.bazel.build/versions/master/be/c-cpp.html#cc_binary.linkstatic
        # For example, when building //mediapipe/calculators/video:opencv_video_encoder_calculator_test,
        # the dependency //mediapipe/framework/formats:image_frame_opencv will
        # be built as a shared library, which depends on a cv::Mat constructor,
        # and expects it to be provided by the main exacutable. The main
        # executable depends on libimage_frame_opencv.so and links in
        # libopencv_core.a, which contains cv::Mat. However, if
        # libopencv_core.a marks its symbols as hidden, then cv::Mat is in
        # opencv_video_encoder_calculator_test but it is not exported, so
        # libimage_frame_opencv.so fails to find it.
        "OPENCV_SKIP_VISIBILITY_HIDDEN": "ON" if not OPENCV_SHARED_LIBS else "OFF",
        # The COPY actions in modules/python/python_loader.cmake have issues with symlinks.
        # In any case, we don't use this.
        "OPENCV_SKIP_PYTHON_LOADER": "ON",
        # Need to set this too, for the same reason.
        "BUILD_opencv_python": "OFF",
        # Ccache causes issues in some of our CI setups. It's not clear that
        # ccache would be able to work across sandboxed Bazel builds, either.
        # In any case, Bazel does its own caching of the rule's outputs.
        "ENABLE_CCACHE": "OFF",
        "WITH_TENGINE": "OFF",
        "ENABLE_NEON": "OFF",
    },
    lib_source = "@opencv//:all",
    linkopts = [] if OPENCV_SHARED_LIBS else [
        # When using static libraries, the binary that eventually depends on the
        # libraries also needs to link in their dependencies, which therefore
        # have to be listed here.
        # This list depends on which dependencies CMake finds when it configures
        # the build, and so depends on what is installed on the local system.
        # After building, the linkopts for the current setup can be extracted
        # from lib/pkgconfig/opencv.pc in bazel-out
        "-lz",
        "-ldl",
        "-lm",
        "-lpthread",
        "-latomic",
    ],
    shared_libraries = select({
        "@bazel_tools//src/conditions:darwin": ["libopencv_%s.%s.dylib" % (module, OPENCV_SO_VERSION) for module in OPENCV_MODULES],
        # Only the shared objects listed here will be linked in the directory
        # that Bazel adds to the RUNPATH of dependent executables. You cannot
        # list both the versioned and unversioned name of the .so, and the
        # versioned name is the one that the executables actually reference.
        "//conditions:default": ["libopencv_%s.so.%s" % (module, OPENCV_SO_VERSION) for module in OPENCV_MODULES],
    }) if OPENCV_SHARED_LIBS else None,
    static_libraries = [
        "libopencv_%s.a" % module
        for module in OPENCV_MODULES
    ] if not OPENCV_SHARED_LIBS else None,
)

alias(
    name = "opencv_binary",
    actual = select({
        "//mediapipe:android_x86": "@android_opencv//:libopencv_x86",
        "//mediapipe:android_x86_64": "@android_opencv//:libopencv_x86_64",
        "//mediapipe:android_armeabi": "@android_opencv//:libopencv_armeabi-v7a",
        "//mediapipe:android_arm": "@android_opencv//:libopencv_armeabi-v7a",
        "//mediapipe:android_arm64": "@android_opencv//:libopencv_arm64-v8a",
        "//mediapipe:ios": "@ios_opencv//:opencv",
        "//mediapipe:macos": "@macos_opencv//:opencv",
        "//mediapipe:windows": "@windows_opencv//:opencv",
        "//conditions:default": "@linux_opencv//:opencv",
    }),
)

cc_library(
    name = "libffmpeg",
    visibility = ["//visibility:public"],
    deps = select({
        "//mediapipe:android_x86": [],
        "//mediapipe:android_x86_64": [],
        "//mediapipe:android_armeabi": [],
        "//mediapipe:android_arm": [],
        "//mediapipe:android_arm64": [],
        "//mediapipe:ios": [],
        "//mediapipe:macos": [
            "@macos_ffmpeg//:libffmpeg",
        ],
        "//conditions:default": [
            "@linux_ffmpeg//:libffmpeg",
        ],
    }),
)

android_library(
    name = "androidx_annotation",
    exports = [
        "@maven//:androidx_annotation_annotation",
    ],
)

android_library(
    name = "androidx_appcompat",
    exports = [
        "@maven//:androidx_appcompat_appcompat",
    ],
)

android_library(
    name = "androidx_constraint_layout",
    exports = [
        "@maven//:androidx_constraintlayout_constraintlayout",
    ],
)

android_library(
    name = "androidx_core",
    exports = [
        "@maven//:androidx_core_core",
    ],
)

android_library(
    name = "androidx_legacy_support_v4",
    exports = [
        "@maven//:androidx_legacy_legacy_support_v4",
    ],
)

android_library(
    name = "androidx_material",
    exports = [
        "@maven//:com_google_android_material_material",
    ],
)

android_library(
    name = "androidx_recyclerview",
    exports = [
        "@maven//:androidx_recyclerview_recyclerview",
    ],
)

android_library(
    name = "camerax_camera2",
    exports = [
        "@maven//:androidx_camera_camera_camera2",
    ],
)

android_library(
    name = "camerax_core",
    exports = [
        "@maven//:androidx_camera_camera_core",
    ],
)

android_library(
    name = "camerax_lifecycle",
    exports = [
        "@maven//:androidx_camera_camera_lifecycle",
    ],
)
Projudah commented 3 years ago

am I missing anything ? @jiuqiant or could it be I have a bad installation of opencv

arron2003 commented 3 years ago

Had this exact problem recently. I am using raspberrypi-4b with Raspbian GNU/Linux 10 (armv7l not aarch64).

The issue is that bazel does not compile with flags to enable neon. You need to add these to bazel_command in setup.py.

        '--copt=-march=armv7-a',
        '--copt=-mfpu=neon-vfpv4',
jiuqiant commented 3 years ago

We are closing this issue for now due to lack of activity.

Had this exact problem recently. I am using raspberrypi-4b with Raspbian GNU/Linux 10 (armv7l not aarch64).

The issue is that bazel does not compile with flags to enable neon. You need to add these to bazel_command in setup.py.

        '--copt=-march=armv7-a',
        '--copt=-mfpu=neon-vfpv4',

Thanks for posting your solution. Closing this issue now.