Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 51 additions & 12 deletions Dockerfile.manylinux_2_28_x86_64
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,14 @@ FROM quay.io/pypa/manylinux_2_28_x86_64
ARG MEDIAPIPE_DISABLE_GPU=1
ENV MEDIAPIPE_DISABLE_GPU=${MEDIAPIPE_DISABLE_GPU}

RUN yum install -y java-11-openjdk-devel zip
RUN yum install -y java-21-openjdk-devel zip
ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk
WORKDIR /tmp/bazel_build
ADD https://github.com/bazelbuild/bazel/releases/download/7.4.1/bazel-7.4.1-dist.zip bazel.zip
RUN unzip bazel.zip
RUN rm -f bazel.zip
RUN curl -fL --retry 5 --retry-delay 5 --retry-connrefused \
-o /usr/local/bin/bazel https://github.com/bazelbuild/bazel/releases/download/7.4.1/bazel-7.4.1-linux-x86_64 && \
chmod +x /usr/local/bin/bazel

ENV PATH="/opt/python/cp36-cp36m/bin:${PATH}"
ENV EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk"
ENV BAZEL_LINKLIBS=-lm:-lstdc++
RUN ./compile.sh
RUN cp /tmp/bazel_build/output/bazel /bin/bazel


# Install Clang 18
Expand All @@ -47,6 +45,12 @@ RUN mkdir /tmp/llvm-project && wget -qO - https://github.com/llvm/llvm-project/a
mkdir /tmp/llvm-project/build && cd /tmp/llvm-project/build && cmake -DLLVM_ENABLE_PROJECTS='clang;lld' -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/lib/llvm-18/ ../llvm && \
make -j$(nproc) && make -j$(nproc) install && rm -rf /tmp/llvm-project

# Install newer libstdc++ headers/libs for C++20 <span> support.
RUN yum install -y gcc-toolset-14-gcc gcc-toolset-14-gcc-c++ gcc-toolset-14-libstdc++-devel
ENV CPLUS_INCLUDE_PATH="/opt/rh/gcc-toolset-14/root/usr/include/c++/14:/opt/rh/gcc-toolset-14/root/usr/include/c++/14/x86_64-redhat-linux:/opt/rh/gcc-toolset-14/root/usr/include/c++/14/backward"
ENV LIBRARY_PATH="/opt/rh/gcc-toolset-14/root/usr/lib64"
ENV LD_LIBRARY_PATH="/opt/rh/gcc-toolset-14/root/usr/lib64"

# Install OpenGL
RUN yum install -y mesa-libGL mesa-libGL-devel mesa-libEGL mesa-libEGL-devel
RUN yum install -y mesa-libGLES-devel
Expand All @@ -56,8 +60,9 @@ RUN yum install -y epel-release && yum install -y java-11-openjdk \
java-11-openjdk-devel zip emacs portaudio-devel

# Copy Protobuf Compiler binary
ARG PROTOC_ZIP=protoc-25.1-linux-x86_64.zip
RUN curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v25.1/$PROTOC_ZIP
ARG PROTOC_VERSION=28.3
ARG PROTOC_ZIP=protoc-${PROTOC_VERSION}-linux-x86_64.zip
RUN curl -fLo $PROTOC_ZIP https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/$PROTOC_ZIP
RUN unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
RUN unzip -o $PROTOC_ZIP -d /usr/local 'include/*'
RUN rm -f $PROTOC_ZIP
Expand All @@ -71,7 +76,7 @@ RUN cd /tmp/bazel_build/opencv && git checkout 4.10.0 && cd release && cmake ..
-DCMAKE_C_COMPILER=/usr/lib/llvm-18/bin/clang -DCMAKE_CXX_COMPILER=/usr/lib/llvm-18/bin/clang++ \
-DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=/usr/local \
-DBUILD_SHARED_LIBS=OFF -DBUILD_LIST=imgproc,core \
-DWITH_ITT=OFF -DWITH_IPP=OFF -DBUILD_EXAMPLES=OFF \
-DWITH_ITT=OFF -DWITH_IPP=OFF -DBUILD_EXAMPLES=OFF -DBUILD_opencv_apps=OFF \
-DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_opencv_ts=OFF \
-DCV_ENABLE_INTRINSICS=ON -DWITH_EIGEN=ON -DWITH_PTHREADS=ON -DWITH_PTHREADS_PF=ON
RUN cd /tmp/bazel_build/opencv/release && make -j 16 && make install
Expand All @@ -85,12 +90,46 @@ RUN export MP_VERSION_NUMBER=$(awk '/MEDIAPIPE_FULL_VERSION/ {split($0, a, "=");

# Set build flags for MediaPipe and OpenCV.
RUN echo "build --client_env=CC=/usr/lib/llvm-18/bin/clang++" >> .bazelrc && \
echo "build --action_env=LIBRARY_PATH=/opt/rh/gcc-toolset-14/root/usr/lib64" >> .bazelrc && \
echo "build --action_env=LD_LIBRARY_PATH=/opt/rh/gcc-toolset-14/root/usr/lib64" >> .bazelrc && \
echo "build --linkopt=-L/opt/rh/gcc-toolset-14/root/usr/lib64" >> .bazelrc && \
echo "build --linkopt=-lstdc++" >> .bazelrc && \
echo "build --host_action_env=CC=/opt/rh/gcc-toolset-14/root/usr/bin/gcc" >> .bazelrc && \
echo "build --host_action_env=CXX=/opt/rh/gcc-toolset-14/root/usr/bin/g++" >> .bazelrc && \
echo "build --host_linkopt=-L/opt/rh/gcc-toolset-14/root/usr/lib64" >> .bazelrc && \
echo "build --host_linkopt=-lstdc++" >> .bazelrc && \
echo "build --cxxopt=--gcc-toolchain=/opt/rh/gcc-toolset-14/root/usr" >> .bazelrc && \
echo "build --linkopt=--gcc-toolchain=/opt/rh/gcc-toolset-14/root/usr" >> .bazelrc && \
echo "build --host_cxxopt=--gcc-toolchain=/opt/rh/gcc-toolset-14/root/usr" >> .bazelrc && \
echo "build --host_linkopt=--gcc-toolchain=/opt/rh/gcc-toolset-14/root/usr" >> .bazelrc && \
echo "build --define=xnn_enable_avxvnniint8=false" >> .bazelrc && \
echo 'cc_library(name = "opencv", srcs = ["local/lib64/libopencv_imgproc.a", "local/lib64/libopencv_core.a"],hdrs = glob(["local/include/opencv4/opencv2/**/*.h*"]), includes = ["local/include/opencv4/"], linkstatic = 1, visibility = ["//visibility:public"])' > third_party/opencv_linux.BUILD && \
sed -i "s|bazel_command.append('--define=OPENCV=source')|pass|g" setup.py

# Apply diff to reduce the number of OpenCV dependencies.
RUN patch -p1 < mediapipe_python_build.diff
ARG MEDIAPIPE_PYTHON_BUILD_DIFF_URL=""
RUN if [ ! -f mediapipe_python_build.diff ] && [ -n "${MEDIAPIPE_PYTHON_BUILD_DIFF_URL}" ]; then \
DIFF_URL="${MEDIAPIPE_PYTHON_BUILD_DIFF_URL}"; \
case "${DIFF_URL}" in \
https://github.com/*/blob/*) \
DIFF_URL="$(echo "${DIFF_URL}" | sed -e 's|^https://github.com/|https://raw.githubusercontent.com/|' -e 's|/blob/|/|')"; \
;; \
esac; \
if ! curl -fsSL "${DIFF_URL}" -o mediapipe_python_build.diff; then \
echo "Failed to download mediapipe_python_build.diff; continuing without patch." >&2; \
rm -f mediapipe_python_build.diff; \
fi; \
fi && \
if [ -s mediapipe_python_build.diff ]; then \
patch -p1 < mediapipe_python_build.diff; \
else \
echo "mediapipe_python_build.diff not found; skipping OpenCV dependency reduction patch." >&2; \
fi

# Disable GenAI converter targets when not needed.
RUN sed -i '/genai\\/converter/d' mediapipe/tasks/c/BUILD && \
sed -i "s/ENABLE_ODML_CONVERTER=1/ENABLE_ODML_CONVERTER=0/g" setup.py && \
rm -rf mediapipe/tasks/c/genai

ARG PYTHON_BIN="/opt/python/cp312-cp312/bin/python3.12"
RUN $PYTHON_BIN -m pip install --upgrade pip setuptools
Expand Down
19 changes: 19 additions & 0 deletions build_manylinux_wheel.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail

# Builds the manylinux image and extracts wheels into ./wheelhouse.
IMAGE_NAME="${IMAGE_NAME:-mp_manylinux}"
PYTHON_BIN="${PYTHON_BIN:-/opt/python/cp312-cp312/bin/python3.12}"
MEDIAPIPE_PYTHON_BUILD_DIFF_URL="${MEDIAPIPE_PYTHON_BUILD_DIFF_URL:-}"
CONTAINER_NAME="${CONTAINER_NAME:-mp_pip_package_container}"

DOCKER_BUILDKIT=1 docker build \
-f Dockerfile.manylinux_2_28_x86_64 \
-t "${IMAGE_NAME}" . \
--build-arg "PYTHON_BIN=${PYTHON_BIN}" \
--build-arg "MEDIAPIPE_PYTHON_BUILD_DIFF_URL=${MEDIAPIPE_PYTHON_BUILD_DIFF_URL}"

docker create -ti --name "${CONTAINER_NAME}" "${IMAGE_NAME}:latest" >/dev/null
mkdir -p wheelhouse
docker cp "${CONTAINER_NAME}:/wheelhouse/." wheelhouse/
docker rm -f "${CONTAINER_NAME}" >/dev/null
28 changes: 28 additions & 0 deletions mediapipe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,31 @@
# 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.
import warnings

try:
import mediapipe.tasks.python as tasks
from mediapipe.tasks.python.vision.core.image import Image
from mediapipe.tasks.python.vision.core.image import ImageFormat
except Exception as e: # pragma: no cover - optional tasks dependencies
tasks = None
Image = None
ImageFormat = None
warnings.warn(
"MediaPipe tasks APIs could not be imported. Some functionality may be "
f"unavailable. Original error: {e}",
RuntimeWarning,
)

try:
from mediapipe.python import solutions
except Exception as e: # pragma: no cover - optional solutions dependencies
solutions = None
warnings.warn(
"MediaPipe solutions APIs could not be imported. Some functionality may "
f"be unavailable. Original error: {e}",
RuntimeWarning,
)


__version__ = '0.10.32'
2 changes: 0 additions & 2 deletions mediapipe/tasks/c/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ cc_binary(
":mediapipe_tasks_c_version_script.lds",
"//mediapipe/tasks/c/audio/audio_classifier:audio_classifier_c_lib",
"//mediapipe/tasks/c/core:common",
"//mediapipe/tasks/c/genai/bundler:llm_bundler_utils_c_lib",
"//mediapipe/tasks/c/genai/converter:llm_converter_c_lib",
"//mediapipe/tasks/c/metadata:flatbuffer_api_c_lib",
"//mediapipe/tasks/c/text/language_detector:language_detector_c_lib",
"//mediapipe/tasks/c/text/text_classifier:text_classifier_c_lib",
Expand Down
36 changes: 28 additions & 8 deletions mediapipe/tasks/python/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,34 @@

"""MediaPipe Tasks API."""

from . import audio
from . import components
from . import core
from . import genai
from . import text
from . import vision
import importlib
import warnings

BaseOptions = core.base_options.BaseOptions

def _safe_import(name: str):
try:
return importlib.import_module(name)
except Exception as e: # pragma: no cover - optional modules
warnings.warn(
f"MediaPipe Tasks submodule '{name}' could not be imported: {e}",
RuntimeWarning,
)
return None


audio = _safe_import(__name__ + ".audio")
components = _safe_import(__name__ + ".components")
core = _safe_import(__name__ + ".core")
genai = _safe_import(__name__ + ".genai")
text = _safe_import(__name__ + ".text")
vision = _safe_import(__name__ + ".vision")

if core is not None:
BaseOptions = core.base_options.BaseOptions
else:
BaseOptions = None

# Remove unnecessary modules to avoid duplication in API docs.
del core
if core is not None:
del core

11 changes: 10 additions & 1 deletion mediapipe/tasks/python/metadata/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@

import flatbuffers

from mediapipe.tasks.cc.metadata.python import _pywrap_metadata_version
try:
from mediapipe.tasks.cc.metadata.python import _pywrap_metadata_version
except ModuleNotFoundError: # pragma: no cover - optional native extension
_pywrap_metadata_version = None
from mediapipe.tasks.metadata import metadata_schema_py_generated as _metadata_fb
from mediapipe.tasks.metadata import schema_py_generated as _schema_fb
from mediapipe.tasks.python.core import mediapipe_c_bindings
Expand Down Expand Up @@ -391,6 +394,12 @@ def load_metadata_buffer(self, metadata_buf):
self._validate_metadata(metadata_buf)

# Gets the minimum metadata parser version of the metadata_buf.
if _pywrap_metadata_version is None:
raise RuntimeError(
"Metadata population requires mediapipe.tasks.cc, which is not "
"available in this build. Use a MediaPipe build that ships the "
"native metadata bindings or avoid metadata export."
)
min_version = _pywrap_metadata_version.GetMinimumMetadataParserVersion(
bytes(metadata_buf))

Expand Down
36 changes: 23 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from setuptools.command import build_py
from setuptools.command import install

__version__ = 'dev'

MP_DISABLE_GPU = os.environ.get('MEDIAPIPE_DISABLE_GPU') != '0'
IS_WINDOWS = (platform.system() == 'Windows')
IS_MAC = (platform.system() == 'Darwin')
Expand All @@ -39,6 +39,17 @@
MP_THIRD_PARTY_BUILD = os.path.join(MP_ROOT_PATH, 'third_party/BUILD')
MP_ROOT_INIT_PY = os.path.join(MP_ROOT_PATH, '__init__.py')

def _read_version():
version_file = os.path.join(MP_ROOT_PATH, 'mediapipe', 'version.bzl')
with open(version_file, 'r') as f:
for line in f:
if line.startswith('MEDIAPIPE_FULL_VERSION'):
return line.split('=')[1].strip().strip('"')
return 'dev'


__version__ = _read_version()

GPU_OPTIONS_DISABLED = ['--define=MEDIAPIPE_DISABLE_GPU=1']
GPU_OPTIONS_ENABLED = [
'--copt=-DTFLITE_GPU_EXTRA_GLES_DEPS',
Expand Down Expand Up @@ -134,18 +145,7 @@ def _add_mp_init_files():
"""Add __init__.py to mediapipe root directories to make the subdirectories indexable."""
open(MP_ROOT_INIT_PY, 'w').close()
# Save the original mediapipe/__init__.py file.
shutil.copyfile(MP_DIR_INIT_PY, _get_backup_file(MP_DIR_INIT_PY))
mp_dir_init_file = open(MP_DIR_INIT_PY, 'a')
mp_dir_init_file.writelines([
'\n',
'import mediapipe.tasks.python as tasks\n',
'from mediapipe.tasks.python.vision.core.image import Image\n',
'from mediapipe.tasks.python.vision.core.image import ImageFormat\n',
'\n\n',
"__version__ = '{}'".format(__version__),
'\n',
])
mp_dir_init_file.close()



def _copy_to_build_lib_dir(build_lib, file):
Expand Down Expand Up @@ -412,3 +412,13 @@ def run(self):
license='Apache 2.0',
keywords='mediapipe',
)
def _read_version():
version_file = os.path.join(MP_ROOT_PATH, 'mediapipe', 'version.bzl')
with open(version_file, 'r') as f:
for line in f:
if line.startswith('MEDIAPIPE_FULL_VERSION'):
return line.split('=')[1].strip().strip('"')
return 'dev'


__version__ = _read_version()
2 changes: 1 addition & 1 deletion third_party/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ OPENCV_MODULES = [
# 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 = True
OPENCV_SHARED_LIBS = False

OPENCV_SO_VERSION = "3.4"

Expand Down
Loading