C++ OpenCV【解决putText不能显示中文】

这篇具有很好参考价值的文章主要介绍了C++ OpenCV【解决putText不能显示中文】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        使用cv::putText写中文字符时输出结果为"??????"。。。。。。这怎么能忍?

        python方法中可以将opencv图片转化为PIL,写中文之后再转回opencv格式。

        C++方法中通常利用freetype库来实现,freetype打包的win32静态库可以在C#通过dll引用进行调用,这需要其版本跟CvxText对应,否则会出现错误,其在x64平台也一样。

        本文采用windows的GDI显示系统的TrueType字体,没有封装,就两个函数,分成h和cpp文件,可以自己编辑文件名和函数名,也可以直接将cpp的代码复制到你需要的程序中。


 【putText.h】

#ifndef PUTTEXT_H_
#define PUTTEXT_H_

#include <windows.h>
#include <string>
#include <opencv2/opencv.hpp>

using namespace cv;

void GetStringSize(HDC hDC, const char* str, int* w, int* h);
void putTextHusky(Mat &dst, const char* str, Point org, Scalar color, int fontSize,
	const char *fn = "Arial", bool italic = false, bool underline = false);

#endif // PUTTEXT_H_

  【putText.cpp】

#include "putText.h"

void GetStringSize(HDC hDC, const char* str, int* w, int* h)
{
	SIZE size;
	GetTextExtentPoint32A(hDC, str, strlen(str), &size);
	if (w != 0) *w = size.cx;
	if (h != 0) *h = size.cy;
}

void putTextHusky(Mat &dst, const char* str, Point org, Scalar color, int fontSize, const char* fn, bool italic, bool underline)//后俩参数:斜体,下划线
{
	CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3));

	int x, y, r, b;
	if (org.x > dst.cols || org.y > dst.rows) return;
	x = org.x < 0 ? -org.x : 0;
	y = org.y < 0 ? -org.y : 0;

	LOGFONTA lf;
	lf.lfHeight = -fontSize;
	lf.lfWidth = 0;
	lf.lfEscapement = 0;
	lf.lfOrientation = 0;
	lf.lfWeight = 5;
	lf.lfItalic = italic;   //斜体
	lf.lfUnderline = underline; //下划线
	lf.lfStrikeOut = 0;
	lf.lfCharSet = DEFAULT_CHARSET;
	lf.lfOutPrecision = 0;
	lf.lfClipPrecision = 0;
	lf.lfQuality = PROOF_QUALITY;
	lf.lfPitchAndFamily = 0;
	strcpy_s(lf.lfFaceName, fn);

	HFONT hf = CreateFontIndirectA(&lf);
	HDC hDC = CreateCompatibleDC(0);
	HFONT hOldFont = (HFONT)SelectObject(hDC, hf);

	int strBaseW = 0, strBaseH = 0;
	int singleRow = 0;
	char buf[1 << 12];
	strcpy_s(buf, str);
	char *bufT[1 << 12];  // 这个用于分隔字符串后剩余的字符,可能会超出。
	//处理多行
	{
		int nnh = 0;
		int cw, ch;

		const char* ln = strtok_s(buf, "\n", bufT);
		while (ln != 0)
		{
			GetStringSize(hDC, ln, &cw, &ch);
			strBaseW = max(strBaseW, cw);
			strBaseH = max(strBaseH, ch);

			ln = strtok_s(0, "\n", bufT);
			nnh++;
		}
		singleRow = strBaseH;
		strBaseH *= nnh;
	}

	if (org.x + strBaseW < 0 || org.y + strBaseH < 0)
	{
		SelectObject(hDC, hOldFont);
		DeleteObject(hf);
		DeleteObject(hDC);
		return;
	}

	r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1;
	b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1;
	org.x = org.x < 0 ? 0 : org.x;
	org.y = org.y < 0 ? 0 : org.y;

	BITMAPINFO bmp = { 0 };
	BITMAPINFOHEADER& bih = bmp.bmiHeader;
	int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4));

	bih.biSize = sizeof(BITMAPINFOHEADER);
	bih.biWidth = strBaseW;
	bih.biHeight = strBaseH;
	bih.biPlanes = 1;
	bih.biBitCount = 24;
	bih.biCompression = BI_RGB;
	bih.biSizeImage = strBaseH * strDrawLineStep;
	bih.biClrUsed = 0;
	bih.biClrImportant = 0;

	void* pDibData = 0;
	HBITMAP hBmp = CreateDIBSection(hDC, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0);

	CV_Assert(pDibData != 0);
	HBITMAP hOldBmp = (HBITMAP)SelectObject(hDC, hBmp);

	//color.val[2], color.val[1], color.val[0]
	SetTextColor(hDC, RGB(255, 255, 255));
	SetBkColor(hDC, 0);
	//SetStretchBltMode(hDC, COLORONCOLOR);

	strcpy_s(buf, str);
	const char* ln = strtok_s(buf, "\n", bufT);
	int outTextY = 0;
	while (ln != 0)
	{
		TextOutA(hDC, 0, outTextY, ln, strlen(ln));
		outTextY += singleRow;
		ln = strtok_s(0, "\n", bufT);
	}
	uchar* dstData = (uchar*)dst.data;
	int dstStep = dst.step / sizeof(dstData[0]);
	unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep;
	unsigned char* pStr = (unsigned char*)pDibData + x * 3;
	for (int tty = y; tty <= b; ++tty)
	{
		unsigned char* subImg = pImg + (tty - y) * dstStep;
		unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep;
		for (int ttx = x; ttx <= r; ++ttx)
		{
			for (int n = 0; n < dst.channels(); ++n) {
				double vtxt = subStr[n] / 255.0;
				int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n];
				subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv);
			}

			subStr += 3;
			subImg += dst.channels();
		}
	}

	SelectObject(hDC, hOldBmp);
	SelectObject(hDC, hOldFont);
	DeleteObject(hf);
	DeleteObject(hBmp);
	DeleteDC(hDC);
}

        第二个函数putTextHusky(),默认使用Arial字体,也可以设置成操作系统中已经安装的字体,如“宋体”、“微软雅黑”、“Times New Roman”等;默认显示非斜体、非下划线。

【示例】

#include <opencv2/opencv.hpp>
#include "putText.h"

using namespace std;
using namespace cv;

int main()//自己写库解决putText无法显示中文字符问题
{
	Mat img = imread("lyf.png");

	putText(img, "中文无法显示...", Point(50, 50), 2, 1, Scalar(0, 0, 255), 1, 8, false);
	putTextHusky(img, "Arial字体...", Point(50, 100), Scalar(0, 0, 255), 30, "Arial");
	putTextHusky(img, "微软雅黑字体...", Point(50, 150), Scalar(0, 255, 0), 30, "微软雅黑", true, true);
	putTextHusky(img, "楷体字体...\n", Point(50, 200), Scalar(128, 255, 0), 30, "楷体", true, true);
	//imwrite("lyfWrite.png", img);
	imshow("test", img);
	waitKey(0);
	
	system("pause");
	return 0;
}

c++ opencv puttext 中文,OpenCV学习,opencv,c++,计算机视觉文章来源地址https://www.toymoban.com/news/detail-538321.html

到了这里,关于C++ OpenCV【解决putText不能显示中文】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++的OpenCV】第十五课-OpenCV的绘图工具(rectangle、circle、line、polylines、putText)常用方法简介

    🎉🎉🎉 欢迎各位来到小白 p i a o 的学习空间! color{red}{欢迎各位来到小白piao的学习空间!} 欢迎各位来到小白 p ia o 的学习空间! 🎉🎉🎉 💖 C++Python所有的入门技术皆在 我的主页 color{#0cc123}{我的主页} 我的主页 :我的主页 1.1.1 利用构造函数Mat中的一些形式完成快速创

    2024年02月06日
    浏览(37)
  • Opencv C++ 绘制中文

    GitHub - ITC-AI/Opencv_Chinese: C++ 的 Opencv绘制中文 参考 https://blog.csdn.net/long630576366/article/details/131440684 X64的编译链 Arm的编译链 (1) 安装opencv 在 Ubuntu 上安装 OpenCV,你可以使用以下命令: 在 CentOS 上安装 OpenCV,你可以使用以下命令: (2) 安装FreeType 在 Ubuntu 上安装 FreeType,可以使用

    2024年04月17日
    浏览(36)
  • opencv显示图像中文标题乱码解决

    最终解决效果: 解决方法:通过指定编码返回字符串 完整示例代码: c++默认支持中文,直接调用imshow可显示 C++示例代码: 命令行执行python代码:

    2024年02月11日
    浏览(45)
  • 【C++的OpenCV】第三课-OpenCV图像加载和显示

    本章节中,将会学习到: 加载图像(cv::imread()函数) 创建一个图像显示的窗口(cv::namedWindow()函数) 在窗口中显示图片(cv::imshow()函数) 功能介绍:         从指定路径中读取所选择的图像 参数解释: Mat image:     image 是一个Mat的对象。     Mat 是一种OpenCV中的图像存储

    2024年02月05日
    浏览(37)
  • C++ 使用opencv加载并显示RGB图像和深度图像

    rgb图像是一般的彩色图像格式,深度图像是存储在xml文件中,c++读取代码如下: 当然,需要安装并配置opencv,配置opencv细节可参考其他博客 效果如下: 若opencv加载深度数据集失败,就请参考这篇博客,这是作者在加载深度数据时失败所写解决方法:https://mp.csdn.net/mp_blog/cr

    2024年02月12日
    浏览(33)
  • OpenCV4(C++)—— 视频和摄像头的加载、显示与保存

      视频或摄像头的加载是使用 cv::VideoCapture 类。(这个类和 ifstream 类比较相似,视频或摄像头的加载和文本文件操作是大致相同。主要步骤:(1)加载(打开)视频或视像头。(2) 判断加载是否成功。 (3)读取内容。(4)关闭。) 注意:   (1)VideoCapture类变量同时

    2024年02月06日
    浏览(41)
  • Baumer工业相机堡盟工业相机如何使用OpenCV实现相机图像的显示(C++)

    ​ Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度

    2024年01月20日
    浏览(39)
  • DEV C++光标不在有汉字一行时汉字不显示以及中文乱码问题解决方法

    前言:博主刚开始使用DEV C++时真的是被这两个问题搞得焦头烂额(orz),以至于有中文时都用拼音代替,但是这样程序运行出来后实在是太影响阅读了。于是我上网搜集资料,但网上的资料真的是让人眼花缭乱,于是在此我把这两个问题罗列出来,用图文方式简单粗暴的让读

    2023年04月08日
    浏览(46)
  • 【opencv3】鼠标框选矩形并显示当前像素点坐标和矩形中心点坐标C++

    (1)用鼠标在图中框选矩形目标,然后保存框选的图片; (2)鼠标拖动过程中要求显示框的线条以及鼠标当前像素点信息(坐标和RGB值); (3)拖动完成后单独显示框取的图像,拖动完成后cout输出框中心像素点坐标。 鼠标事件: 鼠标左键按下时(event == CV_EVENT_LBUTTONUP),标

    2024年02月09日
    浏览(50)
  • Baumer工业相机堡盟工业相机如何使用BGAPISDK和OpenCV设置图像进行比例显示(C++)

    Baumer工业相机堡盟相机是一种高性能、高质量的工业相机,可用于各种应用场景,如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能,可以实时传输高分辨率图像。此外,该相机还具有快速数据传输、低功耗、易于集成以及高度可扩

    2024年02月10日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包