当前位置: 首页 > news >正文

什么?OpenCV调用cv2.putText()乱码?寻找支持中文的方法之旅

文章标题

  • 一、OpenCV
    • 1.关于
    • 2.根因
  • 二、Java版
    • 1.java-opencv(不支持中文,需要编译,支持版本为4.9.0)
      • 1.1 pom依赖
      • 1.2 demo代码
      • 1.3 OpenCV库文件
        • 1.3.1 Windows平台下载安装
        • 1.3.2 Linux平台编译
        • 1.3.3 验证是否更新
        • 1.3.4 so有哪些依赖
      • 1.4 docker打包上线
      • 1.5 测试结果
    • 2. javacv(不支持中文,不需要编译,支持版本为4.11.0)
      • 2.1 pom依赖
      • 2.2 demo代码
      • 2.3 maven打包
      • 2.4 docker打包上线
      • 2.5 测试结果
    • 3.java-native版(不支持中文,不需要编译,不需要pom依赖)
      • 3.1 demo代码
      • 3.2 docker打包上线
      • 3.3 测试结果
  • 三、python版
    • 1. opencv-python不支持中文(我想大多数人都遇到过)
    • 2. opencv-python-rolling支持中文(我想大多数人都没想到过)
    • 3. demo代码
  • 参考

一、OpenCV

Open Source Computer Vision Library
开源的计算机视觉库

https://opencv.org/
https://github.com/opencv/opencv

1.关于

OpenCV(开源计算机视觉库)是一个开源计算机视觉和机器学习软件库。由C++编写,其他语言可以通过动态链接库调用
它拥有 C++、Python、Java 和 MATLAB 接口,并支持 Windows、Linux、 Android 和 Mac OS。

2.根因

cv2.putText 基于 OpenCV 的底层绘制函数,这些函数通常只支持单字节的 ASCII 字符集,无法识别和处理像中文这样的多字节字符。

二、Java版

需求描述:在一张图片里面画框,并在框上面添加标签和置信度。具体数据结构如下:

public class Detection {private String label;private float[] bbox; // 边界框坐标 [x1, y1, x2, y2](归一化)private float confidence; // 置信度public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}public float[] getBbox() {return bbox;}public void setBbox(float[] bbox) {this.bbox = bbox;}public float getConfidence() {return confidence;}public void setConfidence(float confidence) {this.confidence = confidence;}
}

测试图片如下:
在这里插入图片描述

测试数据如下:

[{"label": "卫衣","bbox": [0.18,0.25,0.60,0.90],"confidence": 0.95,"description": "左侧人物穿着黑色卫衣,上半身从肩膀到腰部清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。"},{"label": "卫衣","bbox": [0.52,0.20,0.87,0.74],"confidence": 0.95,"description": "右侧人物同样穿着黑色卫衣,上半身从肩膀到腰部也清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。处理多人场景时,按照从左到右的顺序进行标注。"}
]

1.java-opencv(不支持中文,需要编译,支持版本为4.9.0)

起初参见了这篇文章:Intro to OpenCV with Java

1.1 pom依赖

<!-- https://mvnrepository.com/artifact/org.openpnp/opencv -->
<dependency><groupId>org.openpnp</groupId><artifactId>opencv</artifactId><version>4.9.0-0</version>
</dependency>

1.2 demo代码

	// 静态代码块加载OpenCV库static {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);}public String bbox(byte[] fileBytes, List<Detection> detections) {// 1. 读取图像文件Mat img = Imgcodecs.imdecode(new MatOfByte(fileBytes), Imgcodecs.IMREAD_COLOR);if (img.empty()) {throw new IllegalArgumentException("无法读取图像");}// 2. 获取图像尺寸int h = img.rows();int w = img.cols();// 3. 绘制边界框和置信度for (Detection detection : detections) {float[] bbox = detection.getBbox();float confidence = detection.getConfidence();// 转换归一化坐标到绝对坐标int x1 = (int) (bbox[0] * w);int y1 = (int) (bbox[1] * h);int x2 = (int) (bbox[2] * w);int y2 = (int) (bbox[3] * h);// 绘制红色矩形框(OpenCV中颜色通道为BGR,红色为(0,0,255))Imgproc.rectangle(img,new Point(x1, y1),new Point(x2, y2),new Scalar(0, 0, 255), // BGR颜色3 // 线宽);// 添加置信度标签String label = detection.getLabel() + String.format(" %.2f", confidence);Imgproc.putText(img,label,new Point(x1, y1 - 10), // 文本位置Imgproc.FONT_HERSHEY_SIMPLEX, // 字体0.7, // 字体大小new Scalar(0, 0, 255), // 文本颜色(红色)2 // 文本线宽);}// 4. 将Mat转换为Base64MatOfByte matOfByte = new MatOfByte();Imgcodecs.imencode(".jpg", img, matOfByte);byte[] byteArray = matOfByte.toArray();// 5. 编码为Base64字符串return Base64.getEncoder().encodeToString(byteArray);}

1.3 OpenCV库文件

1.3.1 Windows平台下载安装

https://opencv-java-tutorials.readthedocs.io/en/latest/01-installing-opencv-for-java.html#install-opencv-3-x-under-windows
下载opencv:https://github.com/opencv/opencv/releases/download/4.9.0/opencv-4.9.0-windows.exe
opencv_java490.dll 放到:C:\Windows\System32中
或可以制定路径:-Djava.library.path=/nfs/opencv

1.3.2 Linux平台编译
 docker build -t dockerdance/java-opencv:17.0.16_8-jdk-noble-4.9.0 . -f Dockerfile-opencv
# https://whichjdk.com/
# https://adoptium.net/zh-CN/temurin/releases?version=8&os=any&arch=any  Temurin 8.0.462+8
# https://adoptium.net/zh-CN/temurin/releases?version=17&os=any&arch=any Temurin 17.0.16+8
# https://releases.ubuntu.com/ noble Ubuntu 24.04.2 LTS
# https://hub.docker.com/layers/library/eclipse-temurin/8u462-b08-jdk-noble/images/sha256-8a5c518422bbf3017338bd7ee3da6ae8a7f7643f266f2367d41a737f6fa4c51a
# https://hub.docker.com/layers/library/eclipse-temurin/17.0.16_8-jdk-noble/images/sha256-bdc4fab96f2ebc23fb7014023e22d522f1e765253876cc60ec896156a10cf01c
FROM eclipse-temurin:17.0.16_8-jdk-noble
LABEL authors="d"# 创建工作目录
WORKDIR /usr/src/opencv_build# 下载 OpenCV 4.9.0 源码
COPY opencv-4.9.0.tar.gz .
#RUN wget https://github.com/opencv/opencv/archive/4.9.0.tar.gz -O opencv-4.9.0.tar.gz# 解压
RUN tar -zxvf opencv-4.9.0.tar.gz# 更新包索引
RUN apt update
# 安装编译工具
RUN apt install -y build-essential cmake git
# 安装 OpenCV 依赖的图像/视频处理库
RUN apt install -y libjpeg-dev libpng-dev libtiff-dev libwebp-dev \libavcodec-dev libavformat-dev libswscale-dev \libv4l-dev libxvidcore-dev libx264-dev \libgtk-3-dev libatlas-base-dev gfortran
RUN apt install -y libfreetype6 libfreetype6-dev  libharfbuzz0b libharfbuzz-dev
# 创建编译目录
WORKDIR /usr/src/opencv_build/opencv-4.9.0/build
# 配置 CMake(关键:启用 Java 绑定)
RUN cmake -DCMAKE_BUILD_TYPE=RELEASE \-DCMAKE_INSTALL_PREFIX=/usr/local \-DBUILD_SHARED_LIBS=OFF \-DBUILD_opencv_java=ON \-DOPENCV_GENERATE_PKGCONFIG=ON \-DWITH_FREETYPE=ON \-DWITH_JPEG=ON \-DWITH_PNG=ON  \..# 编译(根据 CPU 核心数调整 -j 参数,如 4 核用 -j4)
RUN make -j$(nproc)
# 安装到系统
RUN make install
# 更新动态链接库缓存
RUN ldconfigWORKDIR /appENTRYPOINT ["top", "-b"]

运行docker并将里面编译好的so复制出来:

docker run -d dockerdance/java-opencv:17.0.16_8-jdk-noble-4.9.0
docker cp  ea254c5cb3c5:/usr/src/opencv_build/opencv-4.9.0/build/lib/* /usr/local/lib

libopencv_java490.so 放到:/usr/local/lib中
也可以制定路径:-Djava.library.path=/nfs/opencv

1.3.3 验证是否更新
ldconfig -p | grep libopencv_ml.so.409
1.3.4 so有哪些依赖
readelf -d libopencv_java490.so|grep NEED

1.4 docker打包上线

docker build -t dockerdance/annotation_opencv:1.0.0 .
# https://whichjdk.com/
# https://adoptium.net/zh-CN/temurin/releases?version=8&os=any&arch=any  Temurin 8.0.462+8
# https://adoptium.net/zh-CN/temurin/releases?version=17&os=any&arch=any Temurin 17.0.16+8
# https://releases.ubuntu.com/ noble Ubuntu 24.04.2 LTS
# https://hub.docker.com/layers/library/eclipse-temurin/8u462-b08-jdk-noble/images/sha256-8a5c518422bbf3017338bd7ee3da6ae8a7f7643f266f2367d41a737f6fa4c51a
# https://hub.docker.com/layers/library/eclipse-temurin/17.0.16_8-jdk-noble/images/sha256-bdc4fab96f2ebc23fb7014023e22d522f1e765253876cc60ec896156a10cf01c
FROM eclipse-temurin:17.0.16_8-jdk-noble
LABEL authors="d"# 更新包索引
RUN apt update
# 安装 OpenCV 依赖的图像/视频处理库
RUN apt install -y ffmpegWORKDIR /usr/local/lib
COPY src/main/resources/lib/libopencv_*.so /usr/local/libWORKDIR /app
COPY target/*.jar app.jar
ENTRYPOINT ["/bin/sh", "-c", "ldconfig && ldconfig -p | grep libopencv_ml.so.409 && java -Djava.library.path=/usr/local/lib -jar app.jar"]
docker run -d -p 8080:8080 dockerdance/annotation_opencv:1.0.0

1.5 测试结果

curl -O "https://i-blog.csdnimg.cn/direct/ceda80935d124108ad3394641ebe5aa4.jpeg"
curl --location --request POST 'http://localhost:8080/draw-bboxes' \
--header 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' \
--header 'Content-Type: multipart/form-data' \
--form 'file=@"ceda80935d124108ad3394641ebe5aa4.jpeg"' \
--form 'detections="[ { \"label\": \"卫衣\", \"bbox\": [0.18, 0.25, 0.60, 0.90], \"confidence\": 0.95, \"description\": \"左侧人物穿着黑色卫衣,上半身从肩膀到腰部清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。\" }, { \"label\": \"卫衣\", \"bbox\": [0.52, 0.20, 0.87, 0.74], \"confidence\": 0.95, \"description\": \"右侧人物同样穿着黑色卫衣,上半身从肩膀到腰部也清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。处理多人场景时,按照从左到右的顺序进行标注。\" } ]"'

将生成的base64转为图片:https://base64.guru/converter/decode/image

originresult
在这里插入图片描述在这里插入图片描述

2. javacv(不支持中文,不需要编译,支持版本为4.11.0)

2.1 pom依赖

<!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
<dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.12</version>
</dependency>

2.2 demo代码

public String bbox(byte[] fileBytes, List<Detection> detections) throws Exception {try {// 将字节数据转换为Mat对象Mat img = opencv_imgcodecs.imdecode(new Mat(fileBytes), opencv_imgcodecs.IMREAD_COLOR);if (img.empty()) {throw new Exception("无法读取图像");}// 获取图像尺寸int h = img.rows();int w = img.cols();// 遍历所有检测结果并绘制边界框for (Detection detection : detections) {float[] bbox = detection.getBbox();float confidence = detection.getConfidence();// 转换归一化坐标到绝对坐标int x1 = (int) (bbox[0] * w);int y1 = (int) (bbox[1] * h);int x2 = (int) (bbox[2] * w);int y2 = (int) (bbox[3] * h);// 绘制红色矩形框 (OpenCV中颜色是BGR格式)opencv_imgproc.rectangle(img, new Point(x1, y1), new Point(x2, y2),new Scalar(0, 0, 255, 0), 3, opencv_imgproc.LINE_AA, 0);// 准备置信度标签String label = detection.getLabel() + String.format(" %.2f", confidence);// 绘制标签opencv_imgproc.putText(img, label, new Point(x1, y1 - 10),opencv_imgproc.FONT_HERSHEY_SIMPLEX, 0.7,new Scalar(0, 0, 255, 0), 2, opencv_imgproc.LINE_AA, false);}// 将Mat编码为JPEGByteArrayOutputStream outputStream = new ByteArrayOutputStream();try (Java2DFrameConverter converter = new Java2DFrameConverter();FrameConverter<Mat> frameConverter = new OpenCVFrameConverter.ToMat()) {Frame frame = frameConverter.convert(img);BufferedImage bufferedImage = converter.convert(frame);javax.imageio.ImageIO.write(bufferedImage, "jpg", outputStream);}// 转换为Base64字符串return Base64.getEncoder().encodeToString(outputStream.toByteArray());} catch (Exception e) {throw new Exception("无法读取图像");}}

2.3 maven打包

原生二进制文件本身就很大,我们需要为每个支持的平台使用不同的库。但是,如果您的应用程序不依赖所有这些库,或者不需要支持所有这些平台,那么除了手动逐个排除依赖项或从超级 JAR 中删除文件之外,还有一些方法可以轻松减少依赖项的数量。
https://github.com/bytedeco/javacpp-presets/wiki/Reducing-the-Number-of-Dependencies

指定平台可以减少jar的大小

mvn clean package -Dmaven.test.skip=true -Djavacpp.platform=linux-x86_64

2.4 docker打包上线

docker build -t dockerdance/annotation_javacv:1.0.0 .
# https://whichjdk.com/
# https://adoptium.net/zh-CN/temurin/releases?version=8&os=any&arch=any  Temurin 8.0.462+8
# https://adoptium.net/zh-CN/temurin/releases?version=17&os=any&arch=any Temurin 17.0.16+8
# https://releases.ubuntu.com/ noble Ubuntu 24.04.2 LTS
# https://hub.docker.com/layers/library/eclipse-temurin/8u462-b08-jdk-noble/images/sha256-8a5c518422bbf3017338bd7ee3da6ae8a7f7643f266f2367d41a737f6fa4c51a
# https://hub.docker.com/layers/library/eclipse-temurin/17.0.16_8-jdk-noble/images/sha256-bdc4fab96f2ebc23fb7014023e22d522f1e765253876cc60ec896156a10cf01c
FROM eclipse-temurin:17.0.16_8-jdk-noble
LABEL authors="duhongming"WORKDIR /app
COPY target/*.jar app.jar
ENTRYPOINT ["java", "-jar","app.jar"]
docker run -d -p 8080:8080 dockerdance/annotation_javacv:1.0.0

2.5 测试结果

curl -O "https://i-blog.csdnimg.cn/direct/ceda80935d124108ad3394641ebe5aa4.jpeg"
curl --location --request POST 'http://localhost:8080/draw-bboxes' \
--header 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' \
--header 'Content-Type: multipart/form-data' \
--form 'file=@"ceda80935d124108ad3394641ebe5aa4.jpeg"' \
--form 'detections="[ { \"label\": \"卫衣\", \"bbox\": [0.18, 0.25, 0.60, 0.90], \"confidence\": 0.95, \"description\": \"左侧人物穿着黑色卫衣,上半身从肩膀到腰部清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。\" }, { \"label\": \"卫衣\", \"bbox\": [0.52, 0.20, 0.87, 0.74], \"confidence\": 0.95, \"description\": \"右侧人物同样穿着黑色卫衣,上半身从肩膀到腰部也清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。处理多人场景时,按照从左到右的顺序进行标注。\" } ]"'

将生成的base64转为图片:https://base64.guru/converter/decode/image

originresult
在这里插入图片描述在这里插入图片描述

3.java-native版(不支持中文,不需要编译,不需要pom依赖)

3.1 demo代码

// 中文字体private static Font chineseFont;static {// 初始化支持中文的字体try {// 尝试加载系统中的中文字体,可根据实际情况修改字体名称
//            chineseFont = new Font("SimHei", Font.PLAIN, 14);// 如果需要使用自定义字体文件,可使用以下代码chineseFont = Font.createFont(Font.TRUETYPE_FONT,AnnotationNativeApplication.class.getResourceAsStream("/fonts/simhei.ttf")).deriveFont(14f);} catch (Exception e) {// 字体加载失败时使用默认字体chineseFont = new Font(Font.SANS_SERIF, Font.PLAIN, 14);System.err.println("警告:中文字体加载失败,使用默认字体,可能导致中文显示异常");}}public String bbox(InputStream file, List<Detection> detections) throws IOException {// 1. 读取图像文件// 使用ImageIO读取流并转换为BufferedImageBufferedImage bufferedImage = ImageIO.read(file);// 2. 获取图像尺寸int h = bufferedImage.getHeight();int w = bufferedImage.getWidth();// 创建绘图对象Graphics2D g2d = bufferedImage.createGraphics();// 设置抗锯齿,使文字更清晰g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);// 3. 绘制边界框和置信度for (Detection detection : detections) {float[] bbox = detection.getBbox();float confidence = detection.getConfidence();// 转换归一化坐标到绝对坐标int x1 = (int) (bbox[0] * w);int y1 = (int) (bbox[1] * h);int x2 = (int) (bbox[2] * w);int y2 = (int) (bbox[3] * h);// 准备置信度标签String label = detection.getLabel() + String.format(" %.2f", confidence);// 绘制红色矩形框 (注意: BufferedImage使用RGB格式)g2d.setColor(Color.RED);g2d.setStroke(new BasicStroke(3));g2d.drawRect(x1, y1, x2 - x1, y2 - y1);// 设置字体g2d.setFont(chineseFont);// 计算标签位置,确保不超出图像顶部int labelY = y1 - 10;if (labelY < 15) { // 字体高度大约15pxlabelY = 15;}// 绘制标签g2d.drawString(label, x1, labelY);}// 释放资源g2d.dispose();// 将Mat编码为JPEGByteArrayOutputStream outputStream = new ByteArrayOutputStream();ImageIO.write(bufferedImage, "jpg", outputStream);// 转换为Base64字符串return Base64.getEncoder().encodeToString(outputStream.toByteArray());}

3.2 docker打包上线

docker build -t dockerdance/annotation_native:1.0.0 .
# https://whichjdk.com/
# https://adoptium.net/zh-CN/temurin/releases?version=8&os=any&arch=any  Temurin 8.0.462+8
# https://adoptium.net/zh-CN/temurin/releases?version=17&os=any&arch=any Temurin 17.0.16+8
# https://releases.ubuntu.com/ noble Ubuntu 24.04.2 LTS
# https://hub.docker.com/layers/library/eclipse-temurin/8u462-b08-jdk-noble/images/sha256-8a5c518422bbf3017338bd7ee3da6ae8a7f7643f266f2367d41a737f6fa4c51a
# https://hub.docker.com/layers/library/eclipse-temurin/17.0.16_8-jdk-noble/images/sha256-bdc4fab96f2ebc23fb7014023e22d522f1e765253876cc60ec896156a10cf01c
FROM eclipse-temurin:17.0.16_8-jdk-noble
LABEL authors="duhongming"WORKDIR /app
COPY target/*.jar app.jar
ENTRYPOINT ["java", "-jar","app.jar"]
docker run -d -p 8080:8080 dockerdance/annotation_native:1.0.0

3.3 测试结果

curl -O "https://i-blog.csdnimg.cn/direct/ceda80935d124108ad3394641ebe5aa4.jpeg"
curl --location --request POST 'http://localhost:8080/draw-bboxes' \
--header 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36' \
--header 'Content-Type: multipart/form-data' \
--form 'file=@"ceda80935d124108ad3394641ebe5aa4.jpeg"' \
--form 'detections="[ { \"label\": \"卫衣\", \"bbox\": [0.18, 0.25, 0.60, 0.90], \"confidence\": 0.95, \"description\": \"左侧人物穿着黑色卫衣,上半身从肩膀到腰部清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。\" }, { \"label\": \"卫衣\", \"bbox\": [0.52, 0.20, 0.87, 0.74], \"confidence\": 0.95, \"description\": \"右侧人物同样穿着黑色卫衣,上半身从肩膀到腰部也清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。处理多人场景时,按照从左到右的顺序进行标注。\" } ]"'

将生成的base64转为图片:https://base64.guru/converter/decode/image

originresult
在这里插入图片描述在这里插入图片描述

三、python版

看了很多网上的资料,以及询问了很多AI的意见,我发现都不能满足我的要求。解决方法都是:
一、转换为Pillow
二、使用FreeType
三、使用Pygame
上面的三种方法都能解决中文乱码的问题,我也成功显示了中文结果。但是我的项目涉及视频处理,对于实时性要求比较高,以上的三种方法对我而言都不理想,因为都大幅增加了处理的时间,比如当我使用Pillow绘制文本时,总时长为60秒的视频,只做处理不绘制任何文本的情况下用时18-20秒,但绘制文本后居然用了30-33秒。也就是说绘制文本居然增加了50%的用时,这对于实时性要求高的场景明显不合理。上面的三种解决方法都会大幅增加用时,具体的用时为Pillow>Pygame>FreeType。经过我实验下来,我发现OpenCV读取视频并保存视频不做任何处理的情况下用时5-6秒,使用cv2.putText()绘制文本用时只增加2-4秒。所以我决定找到使用cv2.putText()绘制中文文本的方法。

1. opencv-python不支持中文(我想大多数人都遇到过)

requirements.txt

opencv-python

2. opencv-python-rolling支持中文(我想大多数人都没想到过)

requirements.txt

opencv-python-rolling
numpy<2

3. demo代码

import base64import cv2def draw_bboxes(filename, detections):# 1. 读取图像文件(从字节数据)# 将字节数据转换为numpy数组# nparr = np.frombuffer(file_bytes, np.uint8)# 解码为OpenCV图像(BGR格式)img = cv2.imread(filename, cv2.IMREAD_COLOR)if img is None:raise ValueError("无法读取图像")# 2. 获取图像尺寸h, w = img.shape[:2]  # 高度和宽度(rows, cols)# 3. 绘制边界框和置信度for detection in detections:bbox = detection["bbox"]confidence = detection["confidence"]# 转换归一化坐标到绝对坐标x1 = int(bbox[0] * w)y1 = int(bbox[1] * h)x2 = int(bbox[2] * w)y2 = int(bbox[3] * h)# 绘制红色矩形框(OpenCV中颜色通道为BGR,红色为(0,0,255))cv2.rectangle(img,(x1, y1),  # 左上角点(x2, y2),  # 右下角点(0, 0, 255),  # BGR颜色(红色)3  # 线宽)# 添加置信度标签label = f"{detection['label']} {confidence:.2f}"cv2.putText(img,label,(x1, y1 - 10),  # 文本位置cv2.FONT_HERSHEY_SIMPLEX,  # 字体0.7,  # 字体大小(0, 0, 255),  # 文本颜色(红色)2  # 文本线宽)cv2.imshow("image", img)# 4. 将图像转换为Base64# 编码为JPG格式ret, buffer = cv2.imencode('.jpg', img)if not ret:raise RuntimeError("无法编码图像为JPG格式")# 5. 编码为Base64字符串byte_array = buffer.tobytes()return base64.b64encode(byte_array).decode('utf-8')base64_str = draw_bboxes('test.jpg', [{"label": "卫衣", "bbox": [0.18, 0.25, 0.60, 0.90], "confidence": 0.95,"description": "左侧人物穿着黑色卫衣,上半身从肩膀到腰部清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。"},{"label": "卫衣", "bbox": [0.52, 0.20, 0.87, 0.74], "confidence": 0.95,"description": "右侧人物同样穿着黑色卫衣,上半身从肩膀到腰部也清晰可见。锚框紧密包围其上半身区域,置信度高因为图像清晰且无遮挡。处理多人场景时,按照从左到右的顺序进行标注。"}])
print(base64_str)
originresult
在这里插入图片描述在这里插入图片描述

参考

https://www.baeldung.com/java-opencv
https://blog.csdn.net/Luobinhai/article/details/145533477
https://zhuanlan.zhihu.com/p/615815756

http://www.dtcms.com/a/347056.html

相关文章:

  • Vue3+ElementPlus倒计时示例
  • 入校申请|基于SprinBoot+vue的入校申报审批系统(源码+数据库+文档)
  • [激光原理与应用-332]:结构设计 - Solidworks - 特征(Feature)是构成三维模型的基本单元,是设计意图的载体,也是参数化设计的核心。
  • LeetCode 面试经典 150_数组/字符串_找出字符串中第一个匹配项的下标(23_28_C++_简单)(KMP 算法)
  • 「ECG信号处理——(24)基于ECG和EEG信号的多模态融合疲劳分析」2025年8月23日
  • 构建真正自动化知识工作的AI代理
  • 日志搜索系统前端页面(暂无后端功能)
  • 【leetcode】92. 反转链表2
  • k8s总结
  • Sentinel相关记录
  • 语义通信高斯信道仿真代码
  • uniapp对接一键登录
  • 【数据结构】布隆过滤器的概率模型详解及其 C 代码实现
  • uniapp 页面跳转及字符串转义
  • uniApp对接实人认证
  • uniapp mixins的使用
  • Java接口响应速度优化
  • Python SystemVerilog (Python SV)
  • mysql没有mvcc之前遇到了什么问题
  • CSS变量
  • k8sday15
  • 【typenum】 24 去除尾部零的特性(private.rs片段)
  • [激光原理与应用-320]:结构设计 - Solidworks - 软件工具UI组织的核心概念
  • 【软件设计模式】策略模式
  • 【MongoDB与MySQL对比】
  • 【React ✨】从零搭建 React 项目:脚手架与工程化实战(2025 版)
  • SpringBoot applicationContext.getBeansOfType获取某一接口所有实现类,应用于策略模式
  • Claude Code快捷键介绍(Claude Code命令、Claude Code指令、Claude Code /命令、Claude命令、Claude指令)
  • GEO优化供应商:AI搜索时代的“答案”构建与移山科技的引领,2025高性价比实战指南
  • LeetCode Hot 100 第二天