OpenCV4 C++ 画图中文乱码问题 (Android JNI)

本文使用的编译环境是 Android NDK,其他的只需要使用自己的编译环境即可

Step1: 下载并编译 harfbuzz

git clone --single-branch -b 8.5.0 https://github.com/harfbuzz/harfbuzz.git
export ANDROID_SDK="/Users/wrj/Library/Android/sdk"
export PATH="${ANDROID_SDK}/cmake/3.22.1/bin:${PATH}"
export ANDROID_NDK="${ANDROID_SDK}/ndk/25.2.9519653"
export ANDROID_ABI="arm64-v8a"
export INSTALL_DIR="../install/harfbuzz"


if [ ! -d "build" ]; then
    mkdir build
fi

pushd build


cmake -G "Unix Makefiles" \
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
-DCMAKE_MAKE_PROGRAM="${ANDROID_NDK}/prebuilt/darwin-x86_64/bin/make" \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI=${ANDROID_ABI} \
-DANDROID_NDK=${ANDROID_NDK} \
-DANDROID_PLATFORM=android-24 \
-DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \
-DHB_BUILD_SUBSET=ON \
-DHB_HAVE_FREETYPE=OFF ..


cmake --build . -- -j6

make install

popd

Step2: 下载并编译 freetype2

git clone --single-branch -b VER-2-13-2 https://github.com/freetype/freetype.git
export ANDROID_SDK="/Users/wrj/Library/Android/sdk"
export PATH="${ANDROID_SDK}/cmake/3.22.1/bin:${PATH}"
export ANDROID_NDK="${ANDROID_SDK}/ndk/25.2.9519653"
export ANDROID_ABI="arm64-v8a"
export INSTALL_DIR="../install"

if [ ! -d "build" ]; then
    mkdir build
fi

pushd build

cmake -G "Unix Makefiles" \
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
-DCMAKE_MAKE_PROGRAM="${ANDROID_NDK}/prebuilt/darwin-x86_64/bin/make" \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI=${ANDROID_ABI} \
-DANDROID_NDK=${ANDROID_NDK} \
-DANDROID_PLATFORM=android-24 \
-DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} ..

cmake --build . -- -j6

make install

popd

Step3: 下载 opencv_contrib

git clone --single-branch -b 4.10.0 https://github.com/opencv/opencv_contrib.git

Step4: 下载编译 opencv

git clone --single-branch -b 4.9.0 https://github.com/opencv/opencv.git

创建 options.txt 文件,用于编译 opencv 自带的库,文件内容如下:

-DBUILD_ZLIB=OFF
-DBUILD_TIFF=OFF
-DBUILD_OPENJPEG=OFF
-DBUILD_JASPER=OFF
-DBUILD_JPEG=OFF
-DBUILD_PNG=OFF
-DBUILD_OPENEXR=OFF
-DBUILD_WEBP=OFF
-DBUILD_TBB=OFF
-DBUILD_IPP_IW=OFF
-DBUILD_ITT=OFF
-DWITH_AVFOUNDATION=OFF
-DWITH_CAP_IOS=OFF
-DWITH_CAROTENE=OFF
-DWITH_CPUFEATURES=ON
-DWITH_EIGEN=OFF
-DWITH_FFMPEG=OFF
-DWITH_GSTREAMER=OFF
-DWITH_GTK=OFF
-DWITH_IPP=OFF
-DWITH_HALIDE=OFF
-DWITH_VULKAN=OFF
-DWITH_INF_ENGINE=OFF
-DWITH_NGRAPH=OFF
-DWITH_JASPER=OFF
-DWITH_OPENJPEG=OFF
-DWITH_JPEG=OFF
-DWITH_WEBP=OFF
-DWITH_OPENEXR=OFF
-DWITH_PNG=OFF
-DWITH_TIFF=OFF
-DWITH_OPENVX=OFF
-DWITH_GDCM=OFF
-DWITH_TBB=OFF
-DWITH_HPX=OFF
-DWITH_OPENMP=ON
-DWITH_PTHREADS_PF=OFF
-DWITH_V4L=OFF
-DWITH_CLP=OFF
-DWITH_OPENCL=OFF
-DWITH_OPENCL_SVM=OFF
-DWITH_VA=OFF
-DWITH_VA_INTEL=OFF
-DWITH_ITT=OFF
-DWITH_PROTOBUF=OFF
-DWITH_IMGCODEC_HDR=OFF
-DWITH_IMGCODEC_SUNRASTER=OFF
-DWITH_IMGCODEC_PXM=OFF
-DWITH_IMGCODEC_PFM=OFF
-DWITH_QUIRC=OFF
-DWITH_ANDROID_MEDIANDK=ON
-DWITH_TENGINE=OFF
-DWITH_ONNX=OFF
-DWITH_TIMVX=OFF
-DWITH_OBSENSOR=OFF
-DWITH_CANN=OFF
-DWITH_FLATBUFFERS=OFF
-DBUILD_SHARED_LIBS=OFF
-DBUILD_opencv_apps=OFF
-DBUILD_ANDROID_PROJECTS=OFF
-DBUILD_ANDROID_EXAMPLES=OFF
-DBUILD_DOCS=OFF
-DBUILD_EXAMPLES=OFF
-DBUILD_PACKAGE=OFF
-DBUILD_PERF_TESTS=OFF
-DBUILD_TESTS=OFF
-DBUILD_WITH_STATIC_CRT=OFF
-DBUILD_FAT_JAVA_LIB=OFF
-DBUILD_ANDROID_SERVICE=OFF
-DBUILD_JAVA=OFF
-DBUILD_OBJC=OFF
-DBUILD_KOTLIN_EXTENSIONS=OFF
-DENABLE_PRECOMPILED_HEADERS=OFF
-DENABLE_FAST_MATH=ON
-DCV_TRACE=OFF
-DBUILD_opencv_java=OFF
-DBUILD_opencv_gapi=OFF
-DBUILD_opencv_objc=OFF
-DBUILD_opencv_js=OFF
-DBUILD_opencv_ts=OFF
-DBUILD_opencv_python2=OFF
-DBUILD_opencv_python3=OFF
-DBUILD_opencv_dnn=OFF
-DBUILD_opencv_imgcodecs=ON
-DBUILD_opencv_videoio=ON
-DBUILD_opencv_calib3d=OFF
-DBUILD_opencv_flann=OFF
-DBUILD_opencv_objdetect=OFF
-DBUILD_opencv_stitching=OFF
-DBUILD_opencv_ml=OFF

创建 extra_options.txt 文件,用于编译 opencv_contrib 库,文件内容如下:

-DWITH_FREETYPE=ON
-DBUILD_opencv_alphamat=OFF
-DBUILD_opencv_aruco=OFF
-DBUILD_opencv_bgsegm=OFF
-DBUILD_opencv_bioinspired=OFF
-DBUILD_opencv_cannops=OFF
-DBUILD_opencv_ccalib=OFF
-DBUILD_opencv_cnn_3dobj=OFF
-DBUILD_opencv_cudaarithm=OFF
-DBUILD_opencv_cudabgsegm=OFF
-DBUILD_opencv_cudacodec=OFF
-DBUILD_opencv_cudafeatures2d=OFF
-DBUILD_opencv_cudafilters=OFF
-DBUILD_opencv_cudaimgproc=OFF
-DBUILD_opencv_cudalegacy=OFF
-DBUILD_opencv_cudaobjdetect=OFF
-DBUILD_opencv_cudaoptflow=OFF
-DBUILD_opencv_cudastereo=OFF
-DBUILD_opencv_cudawarping=OFF
-DBUILD_opencv_cudev=OFF
-DBUILD_opencv_cvv=OFF
-DBUILD_opencv_datasets=OFF
-DBUILD_opencv_dnn_objdetect=OFF
-DBUILD_opencv_dnn_superres=OFF
-DBUILD_opencv_dnns_easily_fooled=OFF
-DBUILD_opencv_dpm=OFF
-DBUILD_opencv_face=OFF
-DBUILD_opencv_freetype=ON
-DBUILD_opencv_fuzzy=OFF
-DBUILD_opencv_hdf=OFF
-DBUILD_opencv_hfs=OFF
-DBUILD_opencv_img_hash=OFF
-DBUILD_opencv_intensity_transform=OFF
-DBUILD_opencv_julia=OFF
-DBUILD_opencv_line_descriptor=OFF
-DBUILD_opencv_matlab=OFF
-DBUILD_opencv_mcc=OFF
-DBUILD_opencv_optflow=OFF
-DBUILD_opencv_ovis=OFF
-DBUILD_opencv_phase_unwrapping=OFF
-DBUILD_opencv_plot=OFF
-DBUILD_opencv_quality=OFF
-DBUILD_opencv_rapid=OFF
-DBUILD_opencv_reg=OFF
-DBUILD_opencv_rgbd=OFF
-DBUILD_opencv_saliency=OFF
-DBUILD_opencv_sfm=OFF
-DBUILD_opencv_shape=OFF
-DBUILD_opencv_signal=OFF
-DBUILD_opencv_stereo=OFF
-DBUILD_opencv_structured_light=OFF
-DBUILD_opencv_superres=OFF
-DBUILD_opencv_surface_matching=OFF
-DBUILD_opencv_text=OFF
-DBUILD_opencv_tracking=OFF
-DBUILD_opencv_videostab=OFF
-DBUILD_opencv_viz=OFF
-DBUILD_opencv_wechat_qrcode=OFF
-DBUILD_opencv_xfeatures2d=OFF
-DBUILD_opencv_ximgproc=OFF
-DBUILD_opencv_xobjdetect=OFF
-DBUILD_opencv_xphoto=OFF

编译 opencv 使得其画图支持中文:

export ANDROID_SDK="/Users/wrj/Library/Android/sdk"
export PATH="${ANDROID_SDK}/cmake/3.22.1/bin:${PATH}"
export ANDROID_NDK="${ANDROID_SDK}/ndk/25.2.9519653"
export ANDROID_ABI="arm64-v8a"
export INSTALL_DIR="../install"

if [ ! -d "build" ]; then 
    mkdir build;
fi

cd build

cmake -G "Unix Makefiles" \
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
-DCMAKE_MAKE_PROGRAM="${ANDROID_NDK}/prebuilt/darwin-x86_64/bin/make" \
-DCMAKE_BUILD_TYPE=Release \
-DANDROID_ABI=${ANDROID_ABI} \
-DANDROID_NDK=${ANDROID_NDK} \
-DANDROID_PLATFORM=android-24 \
`cat ../options.txt` \
-DOPENCV_EXTRA_MODULES_PATH="/Users/wrj/AndroidStudioProjects/opencv_contrib/modules" \
`cat ../extra_options.txt` \
-DFREETYPE_FOUND=1 \
-DFREETYPE_INCLUDE_DIRS="/Users/wrj/AndroidStudioProjects/freetype-2.10.0/install/include/freetype2" \
-DFREETYPE_LIBRARY="/Users/wrj/AndroidStudioProjects/freetype-2.10.0/install/lib" \
-DHARFBUZZ_FOUND=1 \
-DHARFBUZZ_INCLUDE_DIRS="/Users/wrj/AndroidStudioProjects/harfbuzz/install/include/harfbuzz" \
-DHARFBUZZ_LIBRARIES="/Users/wrj/AndroidStudioProjects/harfbuzz/install/lib" \
-DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} ..

cmake --build . -- -j6

make install
cd ..

编译第三方ade 库:

export ADE_INSTALL_DIR=${INSTALL_DIR}/sdk/native/3rdparty/libs/arm64-v8a

cd 3rdparty
if [ ! -d "ade" ]; then
    git clone https://github.com/opencv/ade.git
fi
cd ade

if [ ! -d "build" ]; then 
    mkdir build;
fi
cd build

cmake -G "Unix Makefiles" \
-DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \
-DCMAKE_MAKE_PROGRAM="${ANDROID_NDK}/prebuilt/darwin-x86_64/bin/make" \
-DANDROID_ABI=${ANDROID_ABI} \
-DANDROID_NDK=${ANDROID_NDK} \
-DANDROID_PLATFORM=android-24 \
-DCMAKE_INSTALL_PREFIX="install" ..

make install
mv install/lib/libade.a ../../../install/sdk/native/3rdparty/libs/arm64-v8a

编译结果如下:

编译结果示意图

Step5: 验证是否解决中文乱码问题

网上下载中文字符集或者使用系统自带字符集,找到字符集所在路径,本文使用的路径是 /Users/wrj/projects/test/FangZhengKaiTiJianTi-1.ttf

#include <iostream>
#include <opencv2/freetype.hpp>
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>

bool drawResults(cv::Mat &rgb, const std::string &results, int max_time = -1) {
    std::vector<std::string> parsed_str;
    std::string tmp;
    tmp.reserve(5);
    for (char ch : results) {
        if (ch == '$') {
            parsed_str.push_back(std::move(tmp));
            tmp.clear();
        } else {
            tmp.push_back(ch);
        }
    }

    if (!tmp.empty()) {
        parsed_str.push_back(std::move(tmp));
    }


    std::string time_str;
    if (max_time > 0) {
        time_str = "倒计时: " + std::to_string(max_time - std::stoll(parsed_str[1])) + " 秒";
    } else {
        time_str = "用时: " + parsed_str[1] + " 秒";
    }

    int fontHeight = 25;
    int thickness = -1;
    int baseline = 0;
    int lineType = cv::LINE_AA;
    cv::Scalar color(255, 255, 0);

    if (thickness > 0) {
        baseline += thickness;
    }

    std::string text1 = "成功/总数: " + parsed_str[3] + '/' + parsed_str[4] + "  " + time_str;

    auto ft2 = cv::freetype::createFreeType2();
    ft2->loadFontData("/Users/wrj/projects/test/FangZhengKaiTiJianTi-1.ttf", 0);

    cv::Size text_size1 = ft2->getTextSize(text1, fontHeight, thickness, &baseline);

    int x = 10, y = 10 + text_size1.height;

    ft2->putText(rgb, text1, cv::Point(x, y), fontHeight, color, thickness, lineType, true);

    return true;
}


int main() {
    cv::VideoCapture cap("/Users/wrj/projects/test/720.mp4");
    cv::Mat bgr, rgb;
    initId2Str();
    while (cap.read(bgr)) {
        cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
        drawResults(rgb, "YW$90$0$5$10$141$142$143", 120);
        cv::cvtColor(rgb, bgr, cv::COLOR_RGB2BGR);

        cv::imshow("", bgr);
        cv::waitKey(0);
    }
    cap.release();
    return 0;
}

结果如下:

验证效果图

posted @ 2024-06-04 11:38  RenjieW  阅读(52)  评论(0)    收藏  举报