简体中文 繁體中文 English Deutsch 한국 사람 بالعربية TÜRKÇE português คนไทย Français Japanese

站内搜索

搜索

活动公告

通知:为庆祝网站一周年,将在5.1日与5.2日开放注册,具体信息请见后续详细公告
04-22 00:04
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

OpenCV中puttext函数内存释放技巧与常见问题解决方法详解

SunJu_FaceMall

3万

主题

1116

科技点

3万

积分

白金月票

碾压王

积分
32766

立华奏

发表于 2025-10-6 12:50:29 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
引言

OpenCV作为计算机视觉领域最广泛使用的库之一,提供了丰富的图像处理功能。其中,putText函数是一个常用的文本渲染工具,用于在图像上添加文字信息。然而,在实际开发中,许多开发者常常遇到内存管理问题,特别是在处理大量图像或长时间运行的应用程序时。本文将深入探讨OpenCV中putText函数的内存释放技巧,并提供常见问题的解决方案,帮助开发者更高效地使用这一功能。

putText函数基础

putText函数是OpenCV中用于在图像上绘制文本的函数,其基本语法如下:
  1. void cv::putText(
  2.     cv::Mat& img,                    // 要绘制文本的图像
  3.     const std::string& text,         // 要绘制的文本字符串
  4.     cv::Point org,                   // 文本左下角的坐标
  5.     int fontFace,                    // 字体类型
  6.     double fontScale,                // 字体缩放因子
  7.     cv::Scalar color,                // 文本颜色
  8.     int thickness = 1,               // 文本线条粗细(可选)
  9.     int lineType = 8,                // 线条类型(可选)
  10.     bool bottomLeftOrigin = false    // 原点位置(可选)
  11. );
复制代码

字体类型选项

OpenCV提供了多种内置字体类型:

• cv::FONT_HERSHEY_SIMPLEX:正常大小无衬线字体
• cv::FONT_HERSHEY_PLAIN:小号无衬线字体
• cv::FONT_HERSHEY_DUPLEX:正常大小无衬线字体(比SIMPLEX复杂)
• cv::FONT_HERSHEY_COMPLEX:正常大小衬线字体
• cv::FONT_HERSHEY_TRIPLEX:正常大小衬线字体(比COMPLEX复杂)
• cv::FONT_HERSHEY_COMPLEX_SMALL:小号衬线字体
• cv::FONT_HERSHEY_SCRIPT_SIMPLEX:手写风格字体
• cv::FONT_HERSHEY_SCRIPT_COMPLEX:更复杂的手写风格字体

内存管理机制

OpenCV中的cv::Mat对象使用引用计数机制进行内存管理。当使用putText函数时,它会直接在输入的Mat对象上绘制文本,不会创建新的图像对象。这意味着putText函数本身不会导致内存泄漏,因为它不会分配新的内存。

然而,在某些情况下,特别是在循环中频繁调用putText函数时,可能会出现内存问题。这些问题通常不是由putText函数本身引起的,而是由不正确的内存管理实践导致的。

Mat对象的内存管理

cv::Mat对象包含两部分信息:

1. 矩阵头(包含矩阵尺寸、存储方法、存储地址等信息)
2. 指向像素矩阵的指针

当复制一个Mat对象时,默认情况下只复制矩阵头,而像素矩阵被共享。这就是所谓的”浅拷贝”。只有当需要修改像素数据时,才会执行”深拷贝”,创建新的像素矩阵。
  1. cv::Mat img1 = cv::imread("image.jpg");
  2. cv::Mat img2 = img1;  // 浅拷贝,只复制矩阵头,共享像素数据
  3. // 修改img2不会影响img1,因为putText会触发深拷贝
  4. cv::putText(img2, "Hello", cv::Point(50, 50),
  5.            cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
复制代码

内存释放技巧

1. 正确使用Mat对象

确保在不再需要Mat对象时释放它们。在C++中,当Mat对象超出作用域时,其析构函数会自动调用,释放相关内存。
  1. void processImages() {
  2.     cv::Mat image = cv::imread("image.jpg");
  3.     // 使用puttext在图像上添加文本
  4.     cv::putText(image, "Hello, OpenCV!", cv::Point(50, 50),
  5.                cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
  6.    
  7.     // 处理图像...
  8.     cv::imshow("Processed Image", image);
  9.     cv::waitKey(0);
  10.    
  11. } // 当image超出作用域时,其内存会自动释放
复制代码

2. 避免在循环中重复创建Mat对象

在循环中处理多个图像时,尽量重用Mat对象,而不是在每次迭代中都创建新的对象。
  1. void processMultipleImages(const std::vector<std::string>& imagePaths) {
  2.     cv::Mat image;  // 在循环外创建Mat对象
  3.     for (const auto& path : imagePaths) {
  4.         image = cv::imread(path);  // 重用image对象
  5.         if (!image.empty()) {
  6.             cv::putText(image, "Processed", cv::Point(50, 50),
  7.                        cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
  8.             // 处理图像...
  9.             cv::imshow("Processed Image", image);
  10.             cv::waitKey(1000);  // 显示1秒
  11.         }
  12.     }
  13. } // image对象在函数结束时自动释放
复制代码

3. 显式释放Mat对象

在某些情况下,可能需要显式释放Mat对象占用的内存。可以使用release()方法:
  1. void processAndRelease() {
  2.     cv::Mat image = cv::imread("image.jpg");
  3.     cv::putText(image, "Hello, OpenCV!", cv::Point(50, 50),
  4.                cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
  5.    
  6.     // 处理图像...
  7.     cv::imshow("Processed Image", image);
  8.     cv::waitKey(0);
  9.    
  10.     // 显式释放内存
  11.     image.release();
  12.    
  13.     // 现在image为空矩阵
  14.     if (image.empty()) {
  15.         std::cout << "Image memory has been released." << std::endl;
  16.     }
  17. }
复制代码

4. 使用智能指针管理Mat对象

在复杂的程序中,可以使用智能指针来管理Mat对象的生命周期。
  1. #include <memory>
  2. void processWithSmartPointer() {
  3.     // 使用shared_ptr管理Mat对象
  4.     std::shared_ptr<cv::Mat> imagePtr = std::make_shared<cv::Mat>(cv::imread("image.jpg"));
  5.    
  6.     if (!imagePtr->empty()) {
  7.         cv::putText(*imagePtr, "Hello, OpenCV!", cv::Point(50, 50),
  8.                    cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
  9.         
  10.         // 处理图像...
  11.         cv::imshow("Processed Image", *imagePtr);
  12.         cv::waitKey(0);
  13.     }
  14. } // 当imagePtr超出作用域时,相关内存会自动释放
复制代码

5. 处理大量图像时的内存优化

当处理大量图像时,可以采用以下策略优化内存使用:
  1. void processLargeImageSet(const std::vector<std::string>& imagePaths) {
  2.     // 预先分配一个足够大的Mat对象
  3.     cv::Mat image;
  4.    
  5.     for (size_t i = 0; i < imagePaths.size(); ++i) {
  6.         // 加载新图像前释放旧图像的内存
  7.         if (!image.empty()) {
  8.             image.release();
  9.         }
  10.         
  11.         // 加载新图像
  12.         image = cv::imread(imagePaths[i]);
  13.         
  14.         if (!image.empty()) {
  15.             cv::putText(image, "Image " + std::to_string(i+1), cv::Point(50, 50),
  16.                        cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
  17.             
  18.             // 处理图像...
  19.             cv::imshow("Processed Image", image);
  20.             cv::waitKey(100);
  21.         }
  22.     }
  23.    
  24.     // 最后释放内存
  25.     if (!image.empty()) {
  26.         image.release();
  27.     }
  28. }
复制代码

常见问题及解决方案

1. 问题:图像显示为黑色或白色,文本不可见

原因:这通常是由于文本颜色与背景颜色相同或相似导致的。

解决方案:根据图像背景亮度自动选择对比度明显的文本颜色。
  1. void drawVisibleText() {
  2.     cv::Mat image = cv::imread("image.jpg");
  3.     if (image.empty()) {
  4.         std::cerr << "Could not open or find the image!" << std::endl;
  5.         return;
  6.     }
  7.    
  8.     // 计算图像的平均亮度
  9.     cv::Scalar meanValue = cv::mean(image);
  10.     double avgBrightness = (meanValue[0] + meanValue[1] + meanValue[2]) / 3.0;
  11.    
  12.     // 根据背景亮度选择文本颜色
  13.     cv::Scalar textColor = avgBrightness < 128 ? cv::Scalar(255, 255, 255) : cv::Scalar(0, 0, 0);
  14.    
  15.     // 添加文本
  16.     cv::putText(image, "Visible Text", cv::Point(50, 50),
  17.                cv::FONT_HERSHEY_SIMPLEX, 1, textColor, 2);
  18.    
  19.     cv::imshow("Visible Text", image);
  20.     cv::waitKey(0);
  21. }
复制代码

2. 问题:文本位置不正确

原因:可能是由于坐标系统理解错误或图像尺寸变化导致的。

解决方案:获取文本尺寸并据此调整文本位置。
  1. void drawCenteredText() {
  2.     cv::Mat image = cv::imread("image.jpg");
  3.     if (image.empty()) {
  4.         std::cerr << "Could not open or find the image!" << std::endl;
  5.         return;
  6.     }
  7.    
  8.     std::string text = "Centered Text";
  9.     int fontFace = cv::FONT_HERSHEY_SIMPLEX;
  10.     double fontScale = 1;
  11.     int thickness = 2;
  12.    
  13.     // 获取文本尺寸
  14.     int baseline = 0;
  15.     cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, thickness, &baseline);
  16.    
  17.     // 计算文本位置以使其居中
  18.     cv::Point textOrg((image.cols - textSize.width) / 2,
  19.                      (image.rows + textSize.height) / 2);
  20.    
  21.     // 添加文本
  22.     cv::putText(image, text, textOrg, fontFace, fontScale,
  23.                cv::Scalar(0, 255, 0), thickness);
  24.    
  25.     cv::imshow("Centered Text", image);
  26.     cv::waitKey(0);
  27. }
复制代码

3. 问题:内存泄漏

原因:虽然putText函数本身不会导致内存泄漏,但在循环中不正确地使用Mat对象可能会导致内存问题。

解决方案:避免在循环中动态分配Mat对象而不释放。
  1. // 错误的做法:在循环中不断创建新的Mat对象而不释放
  2. /*
  3. void memoryLeakExample() {
  4.     for (int i = 0; i < 1000; i++) {
  5.         cv::Mat* image = new cv::Mat(cv::imread("image.jpg"));
  6.         cv::putText(*image, "Text", cv::Point(50, 50),
  7.                    cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
  8.         // 忘记释放内存,导致内存泄漏
  9.     }
  10. }
  11. */
  12. // 正确的做法:使用栈对象或智能指针
  13. void noMemoryLeakExample() {
  14.     // 方法1:使用栈对象
  15.     for (int i = 0; i < 1000; i++) {
  16.         cv::Mat image = cv::imread("image.jpg");
  17.         if (!image.empty()) {
  18.             cv::putText(image, "Text", cv::Point(50, 50),
  19.                        cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
  20.         }
  21.         // image对象在每次循环结束时自动释放
  22.     }
  23.    
  24.     // 方法2:使用智能指针
  25.     for (int i = 0; i < 1000; i++) {
  26.         std::shared_ptr<cv::Mat> imagePtr = std::make_shared<cv::Mat>(cv::imread("image.jpg"));
  27.         if (!imagePtr->empty()) {
  28.             cv::putText(*imagePtr, "Text", cv::Point(50, 50),
  29.                        cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
  30.         }
  31.         // imagePtr在每次循环结束时自动释放
  32.     }
  33. }
复制代码

4. 问题:非ASCII字符显示不正确

原因:OpenCV的putText函数对非ASCII字符的支持有限。

解决方案:使用OpenCV的freetype模块或使用其他方法渲染文本。
  1. // 方法1:使用OpenCV的freetype模块(需要OpenCV编译时包含freetype支持)
  2. #include <opencv2/freetype.hpp>
  3. void drawChineseText() {
  4.     cv::Mat image = cv::imread("image.jpg");
  5.     if (image.empty()) {
  6.         std::cerr << "Could not open or find the image!" << std::endl;
  7.         return;
  8.     }
  9.    
  10.     // 创建FreeType2实例
  11.     cv::Ptr<cv::freetype::FreeType2> ft2 = cv::freetype::createFreeType2();
  12.    
  13.     // 加载中文字体文件(需要提供字体文件路径)
  14.     std::string fontPath = "simhei.ttf";  // 替换为你的字体文件路径
  15.     if (ft2->loadFontData(fontPath, 0)) {
  16.         std::string chineseText = "你好,世界!";
  17.         
  18.         // 使用putTextRender绘制中文文本
  19.         ft2->putText(image, chineseText, cv::Point(50, 50), 20,
  20.                     cv::Scalar(0, 255, 0), -1, 8, true);
  21.         
  22.         cv::imshow("Chinese Text", image);
  23.         cv::waitKey(0);
  24.     } else {
  25.         std::cerr << "Failed to load font: " << fontPath << std::endl;
  26.     }
  27. }
  28. // 方法2:将文本渲染为图像然后叠加
  29. cv::Mat renderTextToImage(const std::string& text, int fontHeight, cv::Scalar color) {
  30.     // 这里使用Qt库渲染文本,你也可以使用其他图形库
  31.     QImage textImage(QSize(text.length() * fontHeight, fontHeight * 2), QImage::Format_ARGB32);
  32.     textImage.fill(Qt::transparent);
  33.    
  34.     QPainter painter(&textImage);
  35.     painter.setPen(QColor(color[2], color[1], color[0]));  // OpenCV使用BGR,Qt使用RGB
  36.     painter.setFont(QFont("Arial", fontHeight));
  37.     painter.drawText(0, fontHeight, QString::fromStdString(text));
  38.     painter.end();
  39.    
  40.     // 将QImage转换为cv::Mat
  41.     cv::Mat mat(textImage.height(), textImage.width(), CV_8UC4,
  42.                 const_cast<uchar*>(textImage.bits()), textImage.bytesPerLine());
  43.    
  44.     cv::Mat result;
  45.     cv::cvtColor(mat, result, cv::COLOR_BGRA2BGR);
  46.    
  47.     return result;
  48. }
  49. void drawTextAsImage() {
  50.     cv::Mat image = cv::imread("image.jpg");
  51.     if (image.empty()) {
  52.         std::cerr << "Could not open or find the image!" << std::endl;
  53.         return;
  54.     }
  55.    
  56.     std::string text = "你好,世界!";
  57.    
  58.     // 将文本渲染为图像
  59.     cv::Mat textImage = renderTextToImage(text, 30, cv::Scalar(0, 255, 0));
  60.    
  61.     // 将文本图像叠加到原始图像上
  62.     cv::Rect roi(cv::Point(50, 50), textImage.size());
  63.     if (roi.x + roi.width <= image.cols && roi.y + roi.height <= image.rows) {
  64.         cv::Mat targetROI = image(roi);
  65.         textImage.copyTo(targetROI);
  66.     }
  67.    
  68.     cv::imshow("Text as Image", image);
  69.     cv::waitKey(0);
  70. }
复制代码

5. 问题:文本大小不一致

原因:字体缩放因子不适当或图像分辨率不同。

解决方案:根据图像尺寸动态调整字体大小。
  1. void drawScaledText() {
  2.     cv::Mat image = cv::imread("image.jpg");
  3.     if (image.empty()) {
  4.         std::cerr << "Could not open or find the image!" << std::endl;
  5.         return;
  6.     }
  7.    
  8.     std::string text = "Scaled Text";
  9.    
  10.     // 基于图像宽度计算字体大小
  11.     double fontScale = image.cols / 1000.0;  // 假设参考宽度为1000像素
  12.     fontScale = std::max(0.5, std::min(fontScale, 5.0));  // 限制字体大小范围
  13.    
  14.     cv::putText(image, text, cv::Point(50, 50),
  15.                cv::FONT_HERSHEY_SIMPLEX, fontScale, cv::Scalar(0, 255, 0), 2);
  16.    
  17.     cv::imshow("Scaled Text", image);
  18.     cv::waitKey(0);
  19. }
复制代码

6. 问题:文本超出图像边界

原因:文本位置或大小导致部分或全部文本位于图像外部。

解决方案:检查文本尺寸并调整位置以确保文本完全在图像内。
  1. void drawBoundedText() {
  2.     cv::Mat image = cv::imread("image.jpg");
  3.     if (image.empty()) {
  4.         std::cerr << "Could not open or find the image!" << std::endl;
  5.         return;
  6.     }
  7.    
  8.     std::string text = "Bounded Text";
  9.     int fontFace = cv::FONT_HERSHEY_SIMPLEX;
  10.     double fontScale = 1;
  11.     int thickness = 2;
  12.    
  13.     // 获取文本尺寸
  14.     int baseline = 0;
  15.     cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, thickness, &baseline);
  16.    
  17.     // 计算文本位置,确保完全在图像内
  18.     cv::Point textOrg(50, 50);
  19.    
  20.     // 调整x坐标
  21.     if (textOrg.x < 0) textOrg.x = 0;
  22.     if (textOrg.x + textSize.width > image.cols) {
  23.         textOrg.x = image.cols - textSize.width;
  24.     }
  25.    
  26.     // 调整y坐标
  27.     if (textOrg.y - textSize.height < 0) {
  28.         textOrg.y = textSize.height;
  29.     }
  30.     if (textOrg.y > image.rows) {
  31.         textOrg.y = image.rows;
  32.     }
  33.    
  34.     cv::putText(image, text, textOrg, fontFace, fontScale,
  35.                cv::Scalar(0, 255, 0), thickness);
  36.    
  37.     cv::imshow("Bounded Text", image);
  38.     cv::waitKey(0);
  39. }
复制代码

实际应用示例

下面是一个综合示例,展示了如何在实际应用中正确使用putText函数,并处理常见的内存问题和显示问题:
  1. #include <opencv2/opencv.hpp>
  2. #include <vector>
  3. #include <string>
  4. #include <memory>
  5. #include <algorithm>
  6. class TextRenderer {
  7. private:
  8.     cv::Mat image;
  9.     std::vector<std::string> texts;
  10.     std::vector<cv::Point> positions;
  11.     std::vector<cv::Scalar> colors;
  12.     std::vector<double> fontScales;
  13.    
  14. public:
  15.     TextRenderer(const std::string& imagePath) {
  16.         image = cv::imread(imagePath);
  17.         if (image.empty()) {
  18.             throw std::runtime_error("Failed to load image: " + imagePath);
  19.         }
  20.     }
  21.    
  22.     ~TextRenderer() {
  23.         if (!image.empty()) {
  24.             image.release();
  25.         }
  26.     }
  27.    
  28.     void addText(const std::string& text, const cv::Point& position,
  29.                 const cv::Scalar& color = cv::Scalar(0, 0, 0),
  30.                 double fontScale = 1.0) {
  31.         texts.push_back(text);
  32.         positions.push_back(position);
  33.         colors.push_back(color);
  34.         fontScales.push_back(fontScale);
  35.     }
  36.    
  37.     void renderAllTexts() {
  38.         if (image.empty() || texts.empty()) {
  39.             return;
  40.         }
  41.         
  42.         for (size_t i = 0; i < texts.size(); i++) {
  43.             renderSingleText(texts[i], positions[i], colors[i], fontScales[i]);
  44.         }
  45.     }
  46.    
  47.     void display(const std::string& windowName = "Text Renderer") {
  48.         if (!image.empty()) {
  49.             cv::imshow(windowName, image);
  50.             cv::waitKey(0);
  51.         }
  52.     }
  53.    
  54.     void save(const std::string& outputPath) {
  55.         if (!image.empty()) {
  56.             cv::imwrite(outputPath, image);
  57.         }
  58.     }
  59.    
  60. private:
  61.     void renderSingleText(const std::string& text, const cv::Point& position,
  62.                          const cv::Scalar& color, double fontScale) {
  63.         if (image.empty() || text.empty()) {
  64.             return;
  65.         }
  66.         
  67.         // 限制字体大小范围
  68.         fontScale = std::max(0.5, std::min(fontScale, 5.0));
  69.         
  70.         // 获取文本尺寸以确保文本在图像边界内
  71.         int baseline = 0;
  72.         cv::Size textSize = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX,
  73.                                            fontScale, 2, &baseline);
  74.         
  75.         // 调整文本位置以确保完全在图像内
  76.         cv::Point adjustedPosition = position;
  77.         
  78.         // 调整x坐标
  79.         if (adjustedPosition.x < 0) adjustedPosition.x = 0;
  80.         if (adjustedPosition.x + textSize.width > image.cols) {
  81.             adjustedPosition.x = image.cols - textSize.width;
  82.         }
  83.         
  84.         // 调整y坐标
  85.         if (adjustedPosition.y - textSize.height < 0) {
  86.             adjustedPosition.y = textSize.height;
  87.         }
  88.         if (adjustedPosition.y > image.rows) {
  89.             adjustedPosition.y = image.rows;
  90.         }
  91.         
  92.         // 渲染文本
  93.         cv::putText(image, text, adjustedPosition,
  94.                    cv::FONT_HERSHEY_SIMPLEX, fontScale, color, 2);
  95.     }
  96. };
  97. // 批量处理图像的函数
  98. void batchProcessImages(const std::vector<std::string>& inputPaths,
  99.                        const std::vector<std::string>& outputPaths,
  100.                        const std::string& watermarkText) {
  101.     if (inputPaths.size() != outputPaths.size()) {
  102.         std::cerr << "Input and output path vectors must have the same size!" << std::endl;
  103.         return;
  104.     }
  105.    
  106.     // 预先分配一个Mat对象以重用
  107.     cv::Mat image;
  108.    
  109.     for (size_t i = 0; i < inputPaths.size(); ++i) {
  110.         // 释放前一个图像的内存
  111.         if (!image.empty()) {
  112.             image.release();
  113.         }
  114.         
  115.         // 加载新图像
  116.         image = cv::imread(inputPaths[i]);
  117.         
  118.         if (image.empty()) {
  119.             std::cerr << "Failed to load image: " << inputPaths[i] << std::endl;
  120.             continue;
  121.         }
  122.         
  123.         // 创建文本渲染器
  124.         TextRenderer renderer("");
  125.         renderer.setImage(image);
  126.         
  127.         // 根据图像尺寸计算字体大小
  128.         double fontScale = std::min(image.cols, image.rows) / 1000.0;
  129.         fontScale = std::max(0.5, std::min(fontScale, 3.0));
  130.         
  131.         // 计算图像的平均亮度以选择水印颜色
  132.         cv::Scalar meanValue = cv::mean(image);
  133.         double avgBrightness = (meanValue[0] + meanValue[1] + meanValue[2]) / 3.0;
  134.         cv::Scalar watermarkColor = avgBrightness < 128 ?
  135.                                    cv::Scalar(255, 255, 255) : cv::Scalar(0, 0, 0);
  136.         
  137.         // 添加水印文本(右下角)
  138.         int baseline = 0;
  139.         cv::Size textSize = cv::getTextSize(watermarkText, cv::FONT_HERSHEY_SIMPLEX,
  140.                                           fontScale, 2, &baseline);
  141.         cv::Point watermarkPosition(image.cols - textSize.width - 20,
  142.                                    image.rows - 20);
  143.         
  144.         renderer.addText(watermarkText, watermarkPosition, watermarkColor, fontScale);
  145.         
  146.         // 渲染所有文本
  147.         renderer.renderAllTexts();
  148.         
  149.         // 保存结果
  150.         renderer.save(outputPaths[i]);
  151.         
  152.         std::cout << "Processed: " << inputPaths[i] << " -> " << outputPaths[i] << std::endl;
  153.     }
  154.    
  155.     // 最后释放内存
  156.     if (!image.empty()) {
  157.         image.release();
  158.     }
  159. }
  160. int main() {
  161.     try {
  162.         // 示例1:基本使用
  163.         TextRenderer renderer("example.jpg");
  164.         
  165.         // 添加多个文本
  166.         renderer.addText("Hello, OpenCV!", cv::Point(50, 50), cv::Scalar(0, 255, 0));
  167.         renderer.addText("Text Rendering Example", cv::Point(100, 150), cv::Scalar(255, 0, 0));
  168.         renderer.addText("Memory Management", cv::Point(200, 250), cv::Scalar(0, 0, 255), 1.5);
  169.         
  170.         // 渲染所有文本
  171.         renderer.renderAllTexts();
  172.         
  173.         // 显示结果
  174.         renderer.display();
  175.         
  176.         // 保存结果
  177.         renderer.save("output.jpg");
  178.         
  179.         // 示例2:批量处理图像
  180.         std::vector<std::string> inputPaths = {"image1.jpg", "image2.jpg", "image3.jpg"};
  181.         std::vector<std::string> outputPaths = {"output1.jpg", "output2.jpg", "output3.jpg"};
  182.         batchProcessImages(inputPaths, outputPaths, "Watermark");
  183.     }
  184.     catch (const std::exception& e) {
  185.         std::cerr << "Error: " << e.what() << std::endl;
  186.         return -1;
  187.     }
  188.    
  189.     return 0;
  190. }
复制代码

总结

在使用OpenCV的putText函数时,正确的内存管理和问题解决技巧对于开发稳定的应用程序至关重要。本文介绍了putText函数的基本用法、内存管理机制、内存释放技巧以及常见问题的解决方案。关键点包括:

1. 理解OpenCV的内存管理机制:cv::Mat对象使用引用计数机制进行内存管理,理解这一点对于避免内存问题至关重要。
2. 正确使用Mat对象:确保在不再需要Mat对象时释放它们,避免在循环中重复创建而不释放。
3. 使用智能指针:在复杂的程序中,使用智能指针来管理Mat对象的生命周期可以大大简化内存管理。
4. 处理文本显示问题:解决文本颜色、位置、大小和边界问题,确保文本在图像上正确显示。
5. 处理非ASCII字符:使用OpenCV的freetype模块或其他方法渲染非ASCII字符。
6. 批量处理优化:在处理大量图像时,重用Mat对象并及时释放内存,以提高性能并避免内存问题。

理解OpenCV的内存管理机制:cv::Mat对象使用引用计数机制进行内存管理,理解这一点对于避免内存问题至关重要。

正确使用Mat对象:确保在不再需要Mat对象时释放它们,避免在循环中重复创建而不释放。

使用智能指针:在复杂的程序中,使用智能指针来管理Mat对象的生命周期可以大大简化内存管理。

处理文本显示问题:解决文本颜色、位置、大小和边界问题,确保文本在图像上正确显示。

处理非ASCII字符:使用OpenCV的freetype模块或其他方法渲染非ASCII字符。

批量处理优化:在处理大量图像时,重用Mat对象并及时释放内存,以提高性能并避免内存问题。

通过遵循这些技巧和最佳实践,开发者可以避免常见的内存问题,并创建稳定、高效的文本渲染应用程序。希望本文能帮助读者更好地理解和使用OpenCV中的putText函数,并在实际开发中应用这些技巧。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

手机版|联系我们|小黑屋|TG频道|RSS |网站地图

Powered by Pixtech

© 2025-2026 Pixtech Team.

>