OpenCV显示中文汉字,未使用CvxText和FreeType库

OpenCV显示中文汉字,未使用CvxText和FreeType库

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

  • putText.h
  • putText.cpp
  • 演示

文件putText.h

后面的cpp文件有一些简要说明。

#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 putTextZH(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

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

#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 putTextZH(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);

}

 

 

演示

读取一个图片加入字体,显示。

#include "opencv2/opencv.hpp"

 

#include "putText.h"

 

using namespace std;

using namespace cv;

 

int main()

{

    Mat img = imread("1000.jpg");

 

    putTextZH(img, "Arial字体换...\n行显示!", Point(50, 50), Scalar(0, 0, 255), 30, "Arial");

    putTextZH(img, "微软雅黑字体换...\n行,斜体,下划线,显示!", Point(50, 100), Scalar(0, 255, 0), 30, "微软雅黑", true, true);

    putTextZH(img, "楷体字体换...\n行,斜体,下划线,显示!", Point(50, 200), Scalar(128, 255, 0), 30, "楷体", true, true);

    putTextZH(img, "梁朝伟", Point(500, 500), Scalar(0, 0, 255), 30, "楷体", false, false);

 

    imshow("test", img);

 

    waitKey();

 

    return 0;

}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/350335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Arquillian测试Spring Data + Spring Boot应用程序(第1部分)

Spring Data的使命是为数据访问提供一个熟悉且一致的&#xff0c;基于Spring的编程模型&#xff0c;同时仍保留基础数据存储的特​​殊特征。 它提供了与一些后端技术的集成&#xff0c;例如JPA&#xff0c;Rest&#xff0c;MongoDB&#xff0c;Neo4J或Redis。 因此&#xff0…

生日祝福小程序_广告配音剪映零基础入门教程第二十六篇:如何给朋友制作生日祝福视频...

经常听到小伙伴问到生日祝福视频怎么做&#xff0c;当然我想既然要为他人做生日祝福视频&#xff0c;那么这个人必定是自己身边比较重要的人&#xff0c;而生日又是每个人都是非常重要的&#xff0c;在这种充满意义的时刻&#xff0c;我们想给自己极其重要的人送上一份祝福&…

putty WinScp 免密登录远程 Linux

该方法的原理是预先生成一对公钥和私钥&#xff0c;私钥以文件的形式保存在本地&#xff0c;公钥保存在远程机器上。这样每次登录只需指定私钥文件&#xff0c;远程机器通过比对公钥和私钥来验证登录的合法性。 Putty 免密登录 第一步 生成公钥/私钥对 使用 putty 安装目录中的…

tensorflow log 日志级别设置

log 日志级别设置 import os os.environ["TF_CPP_MIN_LOG_LEVEL"]1 # 这是默认的显示等级&#xff0c;显示所有信息 os.environ["TF_CPP_MIN_LOG_LEVEL"]2 # 只显示 warning 和 Error os.environ["TF_CPP_MIN_LOG_LEVEL"]3 # 只显示 Error

springcloud微服务实战--笔记--1、基础知识

微服务的问题&#xff1a; 分布式事务和数据一致性。 由于分布式事务本身第实现难度就非常大&#xff0c;所以在微服务架构中&#xff0c;我们更强调在各服务之间进行无事务第调用&#xff0c;而对于数据一致性&#xff0c;只要求数据在最后第处理状态是一致第即可&#xff1b;…

OpenCV imwrite

imwrite(const string& filename, InputArray img, const vector<int>& paramsvector<int>() ) 1、filename:需要写入的文件名&#xff0c;会自己创建&#xff08;像imwrite("1.jpeg",src);这样&#xff09; 2、img:要保存的图像 3、pa…

配置Jenkins以连续交付Spring Boot应用程序

在我以前的文章中&#xff0c;我描述了如何使用一个简单的命令启动连续交付堆栈 。 下一步是准备堆栈&#xff0c;以自动方式构建和部署应用程序。 在这篇文章中&#xff0c;我描述了如何配置堆栈&#xff0c;以便准备处理简单的Spring Boot应用程序 。 尽管我将这些组件作为Do…

虚拟鼠标代替安卓触屏_美术学院18级虚拟空间设计专业数字图像程序基础课程优秀结课成果展示优秀学生王雨禾作品展示...

学生代表&#xff1a;STUDENT REPRESENTATIVE|2018级虚拟空间设计专业 王雨禾此次编程课程的学习&#xff0c;让我受益匪浅&#xff0c;短短八周的时间&#xff0c;使我进一步加深了对自身专业的了解&#xff0c;也启发了我&#xff0c;提供给我一种新的创作方式和新的创作表现…

django定时任务

说明 网上很多资料都是比较旧的&#xff0c;不同的版本使用上存在差异&#xff0c;最好的方式是&#xff0c;根据使用的版本查看官方资料 django-celery-beat 用法和django-celery类似 INSTALLED_APPS [django_celery_beat] BEAT_SCHEDULER django_celery_beat.schedulers:Da…

LOG与DOG的关系

注意&#xff1a;这里只是推出LOG与DOG的关系 1&#xff09;高斯函数&#xff1a; &#xff08;1&#xff09; 2&#xff09;DOG&#xff08;Difference Of Gaussian&#xff09; DoG算子是LoG算子的近似&#xff0c;做法是求取不同sigma方差下的高斯滤波图像的差&#xff0c…

springboot springcloud区别_SpringBoot回顾、Spring Cloud初学

Spring Cloud介绍什么是Spring Cloud&#xff1f;Spring Cloud是一系列框架的有序集合。 它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等&#xff0c;都可以用Spring Boot的…

时间 '2018-08-06T10:00:00.000Z' 格式转化为本地时间(转)

原文:https://blog.csdn.net/sxf_123456/article/details/81582964 from datetime import datetime,timedelta #bucket[key_as_string] 2018-08-06T10:00:00.000Z date_ datetime.strptime(bucket[key_as_string],"%Y-%m-%dT%H:%M:%S.%fZ") #local_time 2018-08-0…

OpenCV minMaxLoc找图像中最小值最大值及它们的位置

void minMaxLoc(InputArray src, double* minVal, double* maxVal0, Point* minLoc0, Point* maxLoc0, InputArray masknoArray()) src&#xff1a;输入图像。 minVal&#xff1a;最小值&#xff0c;可輸入NULL表示不需要。 maxVal &#xff1a;最大值&#xff0c;可輸入NUL…

python无法打开hdf5_保存到hdf5非常慢(Python冻结)

我正在尝试将瓶颈值保存到新创建的hdf5文件中.瓶颈值分批形成(120,10,10,2048).保存一个单独的批次占用超过16个演出,python似乎在那一批冻结.根据最近的调查结果(见更新,似乎hdf5占用大内存是可以的,但冻结部分似乎是一个小故障.我只是试图保存前两批用于测试目的,而且仅用于测…

python request 留位置4

测试 转载于:https://www.cnblogs.com/syw20170419/p/11008870.html

收藏表数据库_选择您的收藏库

收藏表数据库这真的是您应该烦恼的吗&#xff1f; java.util.ArrayList和java.util.HashMap从根本上有问题吗&#xff1f; 对于大多数源代码&#xff0c;答案是–不&#xff1b; 这些实现完全可以。 但是&#xff0c;一如既往&#xff0c;细节决定成败。 并存在情况下&#x…

matlab norm向量和矩阵的范数

一、向量的范数 首先定义一个向量为&#xff1a;a[-5&#xff0c;6&#xff0c;8, -10] 1.1 向量的1范数 向量的1范数即&#xff1a;向量的各个元素的绝对值之和&#xff0c;上述向量a的1范数结果就是&#xff1a;29&#xff0c;MATLAB代码实现为&#xff1a;norm&#xff08;…

不能启动的问题 社区版安装后_CentOS7下安装docker(亲测+完整)

说明&#xff1a;1、docker要求Centos系统内核高于3.10&#xff0c;安装前先验证你的Centos版本是否支持docker&#xff1b;2、docker有两个分支版本&#xff1a;docker CE和docker EE&#xff0c;即社区版和企业版&#xff0c;自学研究建议使用社区版本&#xff1b;本文章介绍…

关于数据可视化页面制作

先出思路 数据可视化&#xff0c;目的是为了让纷繁的数据变得直观&#xff0c;更易领会数据代表的趋势、模型等。既然是带着目的的&#xff0c;应先把目标明确下来。目标写下来&#xff0c;思想上算落地了&#xff0c;那么就能给大脑腾出继续深入或扩展的空间。所以&#xff0c…

GitHub Research:超过50%的Java记录语句写错了

为什么生产日志无法帮助您找到错误的真正根本原因&#xff1f; 询问您是否使用日志文件监视您的应用程序几乎就像询问…您是否喝水。 我们都使用日志&#xff0c;但是我们如何使用它们则是一个完全不同的问题。 在下面的文章中&#xff0c;我们将对日志进行更深入的研究&…