OpenCV在圖像上繪制文字示例

OpenCV計算機視覺開發實踐:基于Qt C++ - 商品搜索 - 京東

OpenCV中除了提供繪制各種圖形的函數外,還提供了一個特殊的繪制函數,用于在圖像上繪制文字。這個函數是putText(),它是命名空間cv中的函數,其聲明如下:

void cv::putText(cv::Mat& img, ???????? // 待繪制的圖像const string& text, ?? // 待繪制的文字cv::Point origin, ???? // 文本框的左下角int fontFace, ???????? // 字體 (如cv::FONT_HERSHEY_PLAIN)double fontScale, ???? // 尺寸因子,值越大,文字就越大cv::Scalar color, ???? // 線條的顏色(RGB)int thickness = 1, ??? // 線條寬度int lineType = 8, ???? // 線型(4鄰域或8鄰域,默認為8鄰域)bool bottomLeftOrigin = false // true='origin at lower left'
);

這個函數可以簡單地在圖像上繪制一些文字,由text指定的文字將在以左上角為原點的文字框中以color指定的顏色繪制出來,除非bottomLeftOrigin標志設置為真,這種情況以左下角為原點,使用的字體由fontFace參數決定。常用的字體宏是FONT_HERSHEY_SIMPLEX(普通大小無襯線字體)和FONT_HERSHEY_PLAIN(小號無襯線字體)。任何一個字體都可以和CV::FONT_ITALIC 組合使用(通過“或”操作,或操作符號是|)來得到斜體。每種字體都有一個“自然”大小,當fontScale不是1.0時,在文字繪制之前字體大小將由這個數來縮放。

這里解釋一下襯線。襯線指的是字母結構筆畫之外的裝飾性筆畫。有襯線的字體叫襯線體(Serif),沒有襯線的字體叫無襯線體(Sans-Serif)。襯線體的特征是在字的筆畫開始、結束的地方有額外的裝飾,而且筆畫的粗細會有所不同。襯線體很容易識別,它強調了每個字母筆畫的開始和結束,因此易讀性比較高。中文字體中的宋體就是一種標準的襯線體。無襯線體(Sans-Serif Font)沒有額外的裝飾,而且筆畫的粗細差不多。這類字體通常是機械的和統一線條的,它們往往擁有相同的曲率、筆直的線條和銳利的轉角。無襯線體與漢字字體中的黑體相對應。

另外,在實際繪制文字之前,還可以使用cv::getTextSize()接口先獲取待繪制文本框的大小,以方便放置文本框。getTextSize函數可以獲取字符串的寬度和高度,該函數聲明如下:

Size cv::getTextSize(const string& text,cv::Point origin,int fontFace,double fontScale,int thickness,int* baseLine);

其中參數text表示輸入的文本文字;fontFace表示文字字體類型;fontScale表示字體縮放系數;thickness表示字體筆畫線寬;baseLine是一個輸出參數,表示文字最底部的y坐標。函數返回值中包含文本框的大小。

【例4.12】繪制文字

?? 新建一個控制臺工程,工程名是test。

?? 打開main.cpp,輸入如下代碼:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include<opencv2\imgproc.hpp>
using namespace std;
using namespace cv;int main()
{string text = "Funny text inside the box";// int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;     // 手寫風格字體int fontFace = FONT_HERSHEY_SCRIPT_COMPLEX;double fontScale = 2;       // 字體縮放比int thickness = 3;Mat img(600, 800, CV_8UC3, Scalar::all(0));int baseline = 0;Size textSize = getTextSize(text, fontFace, fontScale, thickness, &baseline);baseline += thickness;// center the textPoint textOrg((img.cols - textSize.width) / 2, (img.rows - textSize.height) / 2);// draw the boxrectangle(img, textOrg + Point(0, baseline), textOrg + Point(textSize.width, -textSize.height), Scalar(0, 0, 255));line(img, textOrg + Point(0, thickness), textOrg + Point(textSize.width, thickness), Scalar(0, 0, 255));putText(img, text, textOrg, fontFace, fontScale, Scalar::all(255), thickness, 8);imshow("text", img);waitKey(0);return 0;
}

在上述代碼中,我們通過getTextSize函數獲取包含字體的文本框的大小,并畫線顯示在矩形中。最后通過文本繪制函數putText畫出一段字符串“Funny text inside the box”。

?? 保存工程并運行,結果如圖4-8所示。

圖4-8

下面我們通過一個比較綜合的例子來實現隨機畫圖,比如隨機畫線,隨機畫圓,隨機繪制文本等。

【例4.13】綜合實例:隨機畫圖

?? 新建一個控制臺工程,工程名是test。

?? 打開main.cpp,輸入如下代碼:

#include <opencv2/opencv.hpp>
using namespace cv;
#include<iostream>
using namespace std;
#define FALSE 0
#define TRUE 1#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
const int NUMBER = 100;
const int DELAY = 5;
const int window_width = 900;
const int window_height = 600;
int x_1 = -window_width / 2;
int x_2 = window_width * 3 / 2;
int y_1 = -window_width / 2;
int y_2 = window_width * 3 / 2;
static Scalar randomColor(RNG& rng);
int Drawing_Random_Lines(Mat image, char* window_name, RNG rng);
int Drawing_Random_Rectangles(Mat image, char* window_name, RNG rng);
int Drawing_Random_Ellipses(Mat image, char* window_name, RNG rng);
int Drawing_Random_Polylines(Mat image, char* window_name, RNG rng);
int Drawing_Random_Filled_Polygons(Mat image, char* window_name, RNG rng);
int Drawing_Random_Circles(Mat image, char* window_name, RNG rng);
int Displaying_Random_Text(Mat image, char* window_name, RNG rng);
int Displaying_Big_End(Mat image, char* window_name, RNG rng);
int main(void)
{int c;char window_name[] = "Drawing_2 Tutorial";RNG rng(0xFFFFFFFF);Mat image = Mat::zeros(window_height, window_width, CV_8UC3);  // 創建一個初始化為零的矩陣imshow(window_name, image);waitKey(DELAY);// 然后我們開始隨機畫圖c = Drawing_Random_Lines(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Rectangles(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Ellipses(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Polylines(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Filled_Polygons(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Circles(image, window_name, rng);if (c != 0) return 0;c = Displaying_Random_Text(image, window_name, rng);if (c != 0) return 0;c = Displaying_Big_End(image, window_name, rng);if (c != 0) return 0;waitKey(0);return 0;
}
static Scalar randomColor(RNG& rng)
{int icolor = (unsigned)rng;return Scalar(icolor & 255, (icolor >> 8) & 255, (icolor >> 16) & 255);
}
int Drawing_Random_Lines(Mat image, char* window_name, RNG rng)
{Point pt1, pt2;for (int i = 0; i < NUMBER; i++){pt1.x = rng.uniform(x_1, x_2);pt1.y = rng.uniform(y_1, y_2);pt2.x = rng.uniform(x_1, x_2);pt2.y = rng.uniform(y_1, y_2);line(image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Rectangles(Mat image, char* window_name, RNG rng)
{Point pt1, pt2;int lineType = 8;int thickness = rng.uniform(-3, 10);for (int i = 0; i < NUMBER; i++){pt1.x = rng.uniform(x_1, x_2);pt1.y = rng.uniform(y_1, y_2);pt2.x = rng.uniform(x_1, x_2);pt2.y = rng.uniform(y_1, y_2);rectangle(image, pt1, pt2, randomColor(rng), MAX(thickness, -1), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Ellipses(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 0; i < NUMBER; i++){Point center;center.x = rng.uniform(x_1, x_2);center.y = rng.uniform(y_1, y_2);Size axes;axes.width = rng.uniform(0, 200);axes.height = rng.uniform(0, 200);double angle = rng.uniform(0, 180);ellipse(image, center, axes, angle, angle - 100, angle + 200,randomColor(rng), rng.uniform(-1, 9), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Polylines(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 0; i < NUMBER; i++){Point pt[2][3];pt[0][0].x = rng.uniform(x_1, x_2);pt[0][0].y = rng.uniform(y_1, y_2);pt[0][1].x = rng.uniform(x_1, x_2);pt[0][1].y = rng.uniform(y_1, y_2);pt[0][2].x = rng.uniform(x_1, x_2);pt[0][2].y = rng.uniform(y_1, y_2);pt[1][0].x = rng.uniform(x_1, x_2);pt[1][0].y = rng.uniform(y_1, y_2);pt[1][1].x = rng.uniform(x_1, x_2);pt[1][1].y = rng.uniform(y_1, y_2);pt[1][2].x = rng.uniform(x_1, x_2);pt[1][2].y = rng.uniform(y_1, y_2);const Point* ppt[2] = { pt[0], pt[1] };int npt[] = { 3, 3 };polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1, 10), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Filled_Polygons(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 0; i < NUMBER; i++){Point pt[2][3];pt[0][0].x = rng.uniform(x_1, x_2);pt[0][0].y = rng.uniform(y_1, y_2);pt[0][1].x = rng.uniform(x_1, x_2);pt[0][1].y = rng.uniform(y_1, y_2);pt[0][2].x = rng.uniform(x_1, x_2);pt[0][2].y = rng.uniform(y_1, y_2);pt[1][0].x = rng.uniform(x_1, x_2);pt[1][0].y = rng.uniform(y_1, y_2);pt[1][1].x = rng.uniform(x_1, x_2);pt[1][1].y = rng.uniform(y_1, y_2);pt[1][2].x = rng.uniform(x_1, x_2);pt[1][2].y = rng.uniform(y_1, y_2);const Point* ppt[2] = { pt[0], pt[1] };int npt[] = { 3, 3 };fillPoly(image, ppt, npt, 2, randomColor(rng), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Circles(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 0; i < NUMBER; i++){Point center;center.x = rng.uniform(x_1, x_2);center.y = rng.uniform(y_1, y_2);circle(image, center, rng.uniform(0, 300), randomColor(rng),rng.uniform(-1, 9), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Displaying_Random_Text(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 1; i < NUMBER; i++){Point org;org.x = rng.uniform(x_1, x_2);org.y = rng.uniform(y_1, y_2);putText(image, "Testing text rendering", org, rng.uniform(0, 8),rng.uniform(0, 100)*0.05 + 0.1, randomColor(rng), rng.uniform(1, 10), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Displaying_Big_End(Mat image, char* window_name, RNG)
{Size textsize = getTextSize("OpenCV forever!", FONT_HERSHEY_COMPLEX, 3, 5, 0);Point org((window_width - textsize.width) / 2, (window_height - textsize.height) / 2);int lineType = 8;Mat image2;for (int i = 0; i < 255; i += 2){image2 = image - Scalar::all(i);putText(image2, "OpenCV forever!", org, FONT_HERSHEY_COMPLEX, 3,Scalar(i, i, 255), 5, lineType);imshow(window_name, image2);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}

從上面代碼可以看到,在主函數中,要做的第一件事是創建一個隨機數生成器對象:RNG rng(0xFFFFFFFF);。在本例中,RNG使用值0xFFFFFFFF來進行初始化。

然后創建一個初始化為零的矩陣image(這意味著它將顯示為黑色),并指定其高度、寬度和類型。

接著開始隨機畫圖。查看代碼可以看到,這里主要是8個自定義函數。這些函數都遵循相同的模式,因此我們只分析其中幾個函數,因為相同的解釋適用于所有函數。比如函數Drawing_Random_Lines用來在隨機坐標處畫線,因此畫線函數line的首尾點pt1和pt2的坐標都是隨機生成的。同樣地,函數Drawing_Random_Circles用來隨機畫圓;函數Displaying_Random_Text用來繪制文本,并且文本的位置、顏色等也是隨機產生的;函數Displaying_Big_End用來繪制程序結束時所顯示的文本“OpenCV forever!”。

?? 保存工程并運行,結果如圖4-9所示。

圖4-9

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/86062.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/86062.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/86062.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

synchronized的技巧與要點

一、基本概念 目的&#xff1a;解決多線程并發訪問共享資源時的數據競爭問題&#xff0c;保證原子性、可見性和有序性&#xff08;JMM內存模型&#xff09;。性質&#xff1a;可重入鎖&#xff08;同一線程可重復獲取同一把鎖&#xff09;、獨占鎖&#xff08;互斥鎖&#xff…

特殊混淆案例還原指南:突破變形控制流與量子加密的技術解析

引言?? 在JavaScript混淆領域,傳統的字符串加密和控制流平坦化已無法滿足高端防護需求。2023年Snyk安全報告指出,Top級商業產品已轉向??多態變形控制流??和??量子加密技術??,這類混淆方案占比17%,但導致的反向工程失敗率高達94%。本文將通過三個工業級混淆案例(…

基于Python、tkinter、sqlite3 和matplotlib的校園書店管理系統

寫一個小例子練習一下python語言。一個基于Python的校園書店管理系統&#xff0c;使用了tkinter庫構建圖形用戶界面&#xff08;GUI&#xff09;&#xff0c;sqlite3 進行數據庫管理&#xff0c;matplotlib用于統計分析可視化。系統支持用戶登錄、書籍管理、客戶管理、員工管理…

機器學習×第十四卷:集成學習中篇——她從每次錯誤中修正自己

&#x1f380;【開場 她終于愿意回看自己貼錯的地方了】 &#x1f98a;狐狐&#xff1a;“她貼過你很多次&#xff0c;但每次貼歪了&#xff0c;都只是低頭沉默。” &#x1f43e;貓貓&#xff1a;“現在不一樣了喵……她開始反思&#xff0c;是不是哪一刻該繞過來貼你背后&…

LeetCode 2537.統計好子數組的數目

給你一個整數數組 nums 和一個整數 k &#xff0c;請你返回 nums 中 好 子數組的數目。 一個子數組 arr 如果有 至少 k 對下標 (i, j) 滿足 i < j 且 arr[i] arr[j] &#xff0c;那么稱它是一個 好 子數組。 子數組 是原數組中一段連續 非空 的元素序列。 示例 1&#x…

Python 開發環境管理和常用命令

包管理器選擇 從輕到重: venv → virtualenv → conda venv: Python 3.3 內置&#xff0c;輕量級虛擬環境virtualenv: 第三方包&#xff0c;支持更多Python版本conda: 科學計算友好&#xff0c;包含包管理和環境管理 Python 版本支持 查看各版本支持狀態&#xff1a;Status…

macOS - 根據序列號查看機型、保障信息

文章目錄 最近在看 MacBook 二手機&#xff0c;有個咸魚賣家放個截圖 說不清參數&#xff0c;于是想根據 序列號 查看機型。蘋果提供了這樣的網頁&#xff1a; https://checkcoverage.apple.com/ &#xff08;無需登錄&#xff09; 結果 2025-06-20&#xff08;五&#xff09;…

數字化項目調研過程中需要的文章

Hello&#xff0c;大家好 &#xff0c;我是東哥說-MES 最近寫了不少的文章&#xff0c;為了方便閱讀&#xff0c;特意重新整理了數字化相關的文章鏈接&#xff0c;也便于大家閱讀 數字工廠項目啟動與業務需求調研執行指南-CSDN博客文章瀏覽閱讀725次&#xff0c;點贊28次&…

LangChain4j之會話功能AiServices工具類的使用(系列二)

概述 LangChain4j 的會話功能 AiServices 工具類&#xff0c;可助力輕松實現智能對話。它能記錄對話上下文&#xff0c;讓 AI 回答連貫且貼合情境。使用起來&#xff0c;先引入類&#xff0c;配置好相關參數&#xff0c;如模型地址、密鑰等。接著&#xff0c;調用相應方法傳入…

Qt 中使用 gtest 做單元測試

作者&#xff1a;billy 版權聲明&#xff1a;著作權歸作者所有&#xff0c;商業轉載請聯系作者獲得授權&#xff0c;非商業轉載請注明出處 gtest 簡介 GoogleTest&#xff08;也稱為gtest&#xff09;是由 Google 開發的一個 C 單元測試框架&#xff0c;用于編寫、組織和運行…

WPF TreeView 數據綁定完全指南:MVVM 模式實現

WPF TreeView 數據綁定完全指南&#xff1a;MVVM 模式實現 一、TreeView 綁定的核心概念1.1 MVVM 模式下的 TreeView 綁定原理1.2 綁定關系示意圖 二、完整實現步驟2.1 創建節點模型類2.2 創建 ViewModel2.3 XAML 綁定配置2.4 設置 Window 的 DataContext 三、關鍵特性詳解3.1 …

坤馳科技QTS4200戰鷹(Battle Eagle)系列實時頻譜分析記錄回放系統

QTS4200戰鷹(Battle Eagle)系列 實時頻譜分析記錄回放系統 精準采集&#xff5c;高效回放&#xff5c;拓展頻譜分析新邊界 坤馳科技傾力打造新一代集實時頻譜分析、高速信號記錄與精準信號回放于一體的便攜式系統&#xff0c;為無線電監測、無線通信、國防等領域提供全面而高…

Flask(二) 路由routes

文章目錄 基本路由定義路由參數路由規則設置請求方法&#xff08;GET/POST&#xff09;路由函數返回靜態文件和模板Blueprint&#xff08;模塊化路由&#xff09;顯示當前所有路由 Flask 路由是 Web 應用程序中將 URL 映射到 Python 函數的機制。 定義路由&#xff1a;使用 app…

在el-image組件的預覽中添加打印功能(自定義功能)

思路&#xff1a;給圖片添加點擊事件&#xff0c;通過js獲取預覽的工具欄&#xff0c;在工具欄中添加自定義按鈕及事件 1、html 中 image標簽 <el-image style"width: 139px; height: 89px" :src"fileUrl" :preview-src-list"[fileUrl]" cli…

TongWeb替換tomcat

1、背景 國家近年來大力推進信息技術應用創新產業&#xff08;信創&#xff09;&#xff0c;要求關鍵領域采用自主可控的國產軟硬件。Tomcat作為國外開源產品&#xff0c;存在潛在的安全風險和技術依賴。TongWeb作為國產中間件&#xff0c;符合信創目錄要求&#xff0c;滿足政府…

聯合語音和文本機器翻譯,支持多達100種語言(nature子刊論文研讀)

簡介&#xff1a; &#x1f30d; SEAMLESSM4T 是一種單一模型&#xff0c;實現了跨越多達 101 種源語言和多種目標語言的語音到語音、語音到文本、文本到語音和文本到文本翻譯及自動語音識別。&#x1f680; 該模型性能顯著超越現有級聯系統&#xff0c;特別是在語音到文本和語…

網站公安網安備案查詢API集成指南

網站公安網安備案查詢API集成指南 引言 隨著互聯網應用的日益普及&#xff0c;網絡安全和個人隱私保護越來越受到重視。公安網安備案作為保障網絡安全的重要措施之一&#xff0c;對于確保網站合法合規運營具有重要意義。為了幫助開發者更加便捷地獲取網站的公安網安備案信息&a…

如何用遠程調試工具排查 WebView 與原生通信問題(iOS或Android)

WebView 在移動端開發中的角色越來越關鍵&#xff0c;尤其在混合架構&#xff08;Hybrid&#xff09;項目中&#xff0c;它作為前端與原生的橋梁&#xff0c;承載了大量交互行為。但這個橋梁并不總是穩固&#xff0c;尤其是在涉及 JSBridge 通信 時&#xff0c;前端調用原生接口…

使用 spark-submit 運行依賴第三方庫的 Python 文件

python文件在spark集群運行真的麻煩&#xff0c;煩冗 spark運行分為了三個模式&#xff0c;本地模式/client模式/cluster模式 文章目錄 本地模式client模式cluster模式參考 本地模式 現在的spark支持python3了&#xff0c;支持python2的版本已經很落后了&#xff0c;所以需要…

【android bluetooth 協議分析 05】【藍牙連接詳解2】【acl_interface_t介紹】

1. acl_interface_t 介紹 acl_interface_t 結構體及其子結構體&#xff0c;目的是封裝處理 Classic、LE、SCO 連接及鏈路事件的回調函數&#xff0c;用于 HCI 事件與上層藍牙協議棧的解耦分發。 system/main/shim/acl_legacy_interface.h typedef struct {void (*on_connect…