文章目录

  • ● opencv文字旋转 putText旋转90°
  • 1. cv::getTextSize获取文字的尺寸textSize
  • 2. 设置文字图像textImg尺寸格式
  • 3. 将文字绘制在文字图像textImg上
  • 4. 对文字图像textImg进行旋转
  • 5. 在原图img上设置用来放置文字图像textImg的roi区域
    • 5.1 矩形区域roi
    • 5.2 行列范围roi
  • 6. 将文字图像textImg放置在roi区域上
    • 6.1 copyTo
      • 6.1.1 不设置掩膜
      • 6.2.2 设置掩膜
    • 6.2 `+` / `add()`
  • 7. 流程代码
  • 8. 封装代码
    • 8.1 centerPoint位置
  • 9. 完整测试代码
    • 9.1 测试效果图

● opencv文字旋转 putText旋转90°

  • putText本身不支持对文字进行旋转,所以将文字写在图像上,将图像进行旋转后再贴到原如上(可设置掩膜),以实现文字旋转的效果

1. cv::getTextSize获取文字的尺寸textSize

std::string text="treeAndCat";
int fontFace=cv::FONT_HERSHEY_SIMPLEX;//字体
double fontScale=2;//缩放系数
cv::Scalar color=cv::Scalar(255,255,255);//颜色
int thickness = 4;//线条粗细
int lineType = 8;//线型
int baseLine;//相当于四线格的第三行高度
  • cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, thickness, &baseLine);

2. 设置文字图像textImg尺寸格式

  • cv::Mat textImg=cv::Mat::zeros(textSize.height+baseLine+thickness,textSize.width,/*CV_8UC1*/img.type());

    • textSize.width 文字的宽度
    • textSize.height 文字的高度(相当于四线格的第一第二行高度)
    • baseLine 基线相对于最底部文本点的y坐标(相当于四线格的第三行高度)
      • 所以在设置文字的roi时高度应该是textSize.height+baseLine
      • 尤其是文字中含fgjpqy字母时不要忘记加baseLine
      • 虽然纯数字不含fgjpq但cv::getTextSize计算出的baseLine也不为0


3. 将文字绘制在文字图像textImg上

  • cv::putText(textImg,text,cv::Point(0,textSize.height+0.5*baseLine),fontFace,fontScale,color,thickness,lineType);

    • 注意putText第三个参数为左下角坐标不是左上角
    • 因为不含fgjpq不担心超出,这里再加上了0.5*baseLine,是为了在文字上下各留0.5*baseLine的空白,(倘若含fgjpq就不要加0.5*baseLine了,上方会超出图像)
  • 一开始误将坐标写为左上角坐标导致textImg基本没有写到文字

  • putText第三个参数的y坐标一开始设为textSize.height没加0.5*baseLine,导致文字底端紧贴图像底部,上方仍有空余不美观

  • 第三个参数设置为cv::Point(0,textSize.height+baseLine)的效果

  • 第三个参数设置为cv::Point(0,textSize.height+0.5*baseLine)的效果


4. 对文字图像textImg进行旋转

  • cv::rotate(textImg,textImg,cv::ROTATE_90_COUNTERCLOCKWISE);

    • cv::ROTATE_90_COUNTERCLOCKWISE 逆时针旋转90°
    • cv::ROTATE_90_CLOCKWISE 顺时针旋转90°


5. 在原图img上设置用来放置文字图像textImg的roi区域

5.1 矩形区域roi

  • cv::Mat textRoi=img(cv::Rect(leftTopPoint.x,leftTopPoint.y,width,height));

    • cv::Rect里的参数分别为 左上角坐标x,y值以及区域宽高

5.2 行列范围roi

  • cv::Mat textRoi=img(cv::Range(rowStart,rowEnd),cv::Range(colStart,colEnd));

    • cv::Range里的参数分别为起止行,列;注意不包含结束行/列,相当于左闭右开 [start,end)

6. 将文字图像textImg放置在roi区域上

6.1 copyTo

6.1.1 不设置掩膜

  • textImg.copyTo(textRoi);

    • 会将整个textImg贴在原图roi处,textImg上非文字部分的图像可能会遮住原图的部分信息,如下图

6.2.2 设置掩膜

  • textImg.copyTo(textRoi,textImg);

    • 由于textImg设置了黑底白字,所以可以直接用它本身当掩膜(textRoi上只显示textImg在掩膜上不为0的像素),即只将textImg图像上的文字贴在了原图上
  • 另一种掩膜思路(这个复杂一点 可结合思考copyTo的掩膜)

    • 将水印加在原图上,对于需要作为水印的图,首先将这张图由彩色图转换为单通道灰度图,再利用阈值将灰度图转换为二值图,那么这张二值图就会成为掩膜;在原图上取与掩膜图同样大小的roi区域;对两张图进行按位与bitwise_and(有0为0),掩膜上的黑色区域在roi上也是黑色的;其次对掩膜进行非运算取反操作bitwise_not(掩膜黑白颠倒),再将掩膜与水印图进行位与bitwise_and(掩膜上的黑色区域在水印图上也是黑色的,非黑色部分正好是roi上的黑色区域),最后将进行了掩膜的roi与水印图相加add()

6.2 + / add()

  • 图像+图像 img1=img2+img3;

    • 相加图像尺寸应相同,相同位置像素值相加(单通道灰度图为对应位置像素的灰度值相加,多通道为各通道的每个像素值相加)
  • 图像+标量 img1=img2+a;

    • img2各通道的每个像素值加a
  • +add()的区别

    • +sum=mod(a+b,256) (取模操作,超出255的取模,如和为300最后sum就为45;直接使加法时需谨慎,超出255的话很亮的区域反而变暗了)
    • cv::add()sum=a+b>255 ? 255:a+b(饱和操作,超出255的设为255)
void cv::add(InputArray src1,InputArray src2,OutputArray dst,InputArray mask = noArray(),int dtype = -1)

7. 流程代码

//获取文字尺寸
cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, thickness, &baseLine);
//创建文字图像
cv::Mat textImg=cv::Mat::zeros(textSize.height+baseLine+thickness,textSize.width,img.type());
//将文字写到图像上
cv::putText(textImg,text,cv::Point(0,textImg.size().height-thickness),fontFace,fontScale,color,thickness,lineType);
//对图像进行旋转
cv::rotate(textImg,textImg,cv::ROTATE_90_COUNTERCLOCKWISE);
//在原图上取图像大小roi
cv::Mat textRoi=img(cv::Rect(leftTopPoint.x,leftTopPoint.y,textImg.size().width,textImg.size().height));
//将文字图像贴到原图上
textImg.copyTo(textRoi,textImg);
//或者使用add()与上方代码效果相同(因为我的图是黑底白字的,其他颜色的可能会有些区别)
//textRoi=textRoi+textImg
  • 最终效果图 将文字横着写在图像竖线上方


8. 封装代码

  • 还是封装成一个函数吧,方便调用
/** @brief Rotate and put the text on image.对文字进行旋转贴在图像上
@param img input image 输入图像
//@param leftTopPoint the upper-left corner point of roi 左上角坐标
//感觉设置roi左上角坐标还需考虑文字的大小,参数还是设置为文字底部中点坐标吧,位置如最后图片说明
@param centerPoint the center point of the bottom line 文字底线中点坐标见下图
@param text the text you want to write on the image 输入文字
@param rotate the angle of rotation; negative <0,270°; zero =0,180°; positive >0,90°. 旋转角度,<0 逆时针旋转90°;>0 顺时针旋转90°;=0 旋转180°
**/
void putTextRotate(cv::Mat &img, const cv::Point2f /*&leftTopPoint*/&centerPoint, const std::string &text,const int &rotate=-1)
{//对于字体的参数就不设置形参了(形参太多也麻烦不过也可以设置成默认参数),大多数时候都是一样的,有需要的直接在这个函数内更改就行int fontFace=cv::FONT_HERSHEY_SIMPLEX;//字体double fontScale=2;//缩放系数cv::Scalar color=cv::Scalar(255,255,255);//颜色 如果输入的是单通道图 cv::Scalar()里参数须更改为一个数 如cv::Scalar(255)//另外如果你的原图是白底的导致文字不能设置为白色的话,后期的掩膜需要重新设置,有两种方法:1.在将旋转后的文字图像贴在roi上之前,新建一张图mask保存将文字图像进行阈值处理后文字设置为白色的图,将这张图作为掩膜 textImg.copyTo(textRoi,mask); 2.一开始就画两张图,一张为黑底你需要的颜色的字体的图textImg,一张为黑底白色字体的图mask,后面mask须跟着textImg一起旋转,最后就可以直接将mask作为掩膜textImg.copyTo(textRoi,mask);int thickness = 4;//线条粗细int lineType = 8;//线型int baseLine;//相当于四线格的第三行高度//获取文字尺寸cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, thickness, &baseLine);// baseLine+=thickness;//加上线宽不然会有小部分线条被截断//将文字图像设置为黑底方便后期做掩膜cv::Mat textImg=cv::Mat::zeros(textSize.height+baseLine+thickness,textSize.width,img.type());//因为输入的文字可能含有gjpq为防止下端被截断,左下角y坐标就设置为textImg.size().height-thickness相当于textSize.height+baseLine,(-thickness是为了底部的部分线条不被截断)cv::putText(textImg,text,cv::Point(0,textImg.size().height-thickness),fontFace,fontScale,color,thickness,lineType);//对文字图像进行旋转//小于0 顺时针旋转270° 即逆时针旋转90°cv::Mat textRoi;if(rotate<0){cv::rotate(textImg,textImg,cv::ROTATE_90_COUNTERCLOCKWISE);textRoi=img(cv::Rect(centerPoint.x-textImg.size().width,centerPoint.y-0.5*textImg.size().height,textImg.size().width,textImg.size().height));}//大于0 顺时针旋转90°else if(rotate>0){cv::rotate(textImg,textImg,cv::ROTATE_90_CLOCKWISE);textRoi=img(cv::Rect(centerPoint.x,centerPoint.y-0.5*textImg.size().height,textImg.size().width,textImg.size().height));}//等于0 旋转180°else{cv::rotate(textImg,textImg,cv::ROTATE_180);textRoi=img(cv::Rect(centerPoint.x-0.5*textImg.size().width,centerPoint.y,textImg.size().width,textImg.size().height));}//取roi//cv::Mat textRoi=img(cv::Rect(leftTopPoint.x,leftTopPoint.y,textImg.size().width,textImg.size().height));//将文字贴在图像上textImg.copyTo(textRoi,textImg);//若原图不是黑底add和加法直接用不可行,要用的话须自己设置掩膜等//cv::add(textImg,textRoi,textRoi);//textRoi=textRoi+textImg;
}

8.1 centerPoint位置

  • 如图centerPoint位于文字底部中点即图中的红点,从第二张图起依次是旋转180°,顺时针旋转90°,逆时针旋转90°



9. 完整测试代码

  • 加几句写一个完整的测试程序,读取图像然后将文字逆时针旋转90°写在图像中央
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>/** @brief Rotate and put the text on image.对文字进行旋转贴在图像上
@param img input image 输入图像
@param centerPoint the center point of the bottom line 文字底线中点坐标见上图
@param text the text you want to write on the image 输入文字
@param rotate the angle of rotation; negative <0,270°; zero =0,180°; positive >0,90°. 旋转角度,<0 逆时针旋转90°;>0 顺时针旋转90°;=0 旋转180°
**/
void putTextRotate(cv::Mat &img, const cv::Point2f /*&leftTopPoint*/&centerPoint, const std::string &text,const int &rotate=-1)
{//对于字体的参数就不设置形参了(形参太多也麻烦不过也可以设置成默认参数),大多数时候都是一样的,有需要的直接在这个函数内更改就行int fontFace=cv::FONT_HERSHEY_SIMPLEX;//字体double fontScale=2;//缩放系数cv::Scalar color=cv::Scalar(255,255,255);//颜色int thickness = 4;//线条粗细int lineType = 8;//线型int baseLine;//相当于四线格的第三行高度//获取文字尺寸cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, thickness, &baseLine);// baseLine+=thickness;//将文字图像设置为黑底方便后期做掩膜cv::Mat textImg=cv::Mat::zeros(textSize.height+baseLine+thickness,textSize.width,img.type());std::cout<<"textImgSize: "<<textImg.size().width<<" , "<<textImg.size().height<<std::endl;//因为输入的文字可能含有gjpq为防止下端被截断,左下角y坐标就设置为textSize.height+baseLinecv::putText(textImg,text,cv::Point(0,textImg.size().height-thickness),fontFace,fontScale,color,thickness,lineType);//对文字图像进行旋转//小于0 顺时针旋转270° 即逆时针旋转90°cv::Mat textRoi;if(rotate<0){cv::rotate(textImg,textImg,cv::ROTATE_90_COUNTERCLOCKWISE);textRoi=img(cv::Rect(centerPoint.x-textImg.size().width,centerPoint.y-0.5*textImg.size().height,textImg.size().width,textImg.size().height));}//大于0 顺时针旋转90°else if(rotate>0){cv::rotate(textImg,textImg,cv::ROTATE_90_CLOCKWISE);textRoi=img(cv::Rect(centerPoint.x,centerPoint.y-0.5*textImg.size().height,textImg.size().width,textImg.size().height));}//等于0 旋转180°else{cv::rotate(textImg,textImg,cv::ROTATE_180);textRoi=img(cv::Rect(centerPoint.x-0.5*textImg.size().width,centerPoint.y,textImg.size().width,textImg.size().height));}std::cout<<"textRoiSize: "<<textRoi.size().width<<" , "<<textRoi.size().height<<std::endl;//取roi//cv::Mat textRoi=img(cv::Rect(leftTopPoint.x,leftTopPoint.y,textImg.size().width,textImg.size().height));//将文字贴在图像上textImg.copyTo(textRoi,textImg);//这里由于原图不是黑底的所以add和加法直接用不可行,要用的话须自己设置掩膜等//cv::add(textImg,textRoi,textRoi);//textRoi=textRoi+textImg;
}int main()
{cv::Mat img = cv::imread("E:/desktop/01.jpg");if(img.empty()){std::cout<<"error!"<<std::endl;return 0;}std::cout<<"imgSize: "<<img.size().width<<" , "<<img.size().height<<std::endl;cv::Point2f centerPoint=cv::Point2f(0.5*img.size().width,0.5*img.size().height);std::string text="tree&cat";putTextRotate(img,centerPoint,text,-1);cv::imwrite("tree&cat.jpg",img);return 0;
}

9.1 测试效果图


opencv文字旋转 putText旋转90°相关推荐

  1. python图片旋转脚本_Python+OpenCV 实现图片无损旋转90°且无黑边

    0. 引言 有如上一张图片,在以往的图像旋转处理中,往往得到如图所示的图片. 然而,在进行一些其他图像处理或者图像展示时,黑边带来了一些不便.本文解决图片旋转后出现黑边的问题,实现了图片尺寸不变的旋转 ...

  2. python怎么导入opencv_对python opencv 添加文字 cv2.putText 的各参数介绍

    如下所示: cv2.putText(img, str(i), (123,456)), font, 2, (0,255,0), 3) 各参数依次是:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字 ...

  3. python中的字体英文名_对python opencv 添加文字 cv2.putText 的各参数介绍

    如下所示: cv2.putText(img, str(i), (123,456)), font, 2, (0,255,0), 3) 各参数依次是:图片,添加的文字,左上角坐标,字体,字体大小,颜色,字 ...

  4. 点击图片旋转180_一起来点亮斗门!请你旋转手机屏幕90横屏并点击图片!

    夕阳西下 万家灯火亮起 斗门之夜流光溢彩 夜斗门有多美? 我们一起来点亮她! 请旋转手机屏幕90° 横屏观看并 点击图片 点击图片 点击图片 看斗门华丽变身! 日落时分 余晖洒落在河面上 斗门的夜 在 ...

  5. OpenCV 文字绘制cv::putText详解

    ref:https://blog.csdn.net/guduruyu/article/details/68491211 https://blog.csdn.net/keith_bb/article/d ...

  6. OpenCV这么简单为啥不学——1.4、基础标识绘制(绘制线line函数、rectangle函数绘制四边形、circle函数绘制圆形、putText函数绘制文字、putText绘制中文文字)

    OpenCV这么简单为啥不学--1.4.基础标识绘制(绘制线line函数.rectangle函数绘制四边形.circle函数绘制圆形.putText函数绘制文字.putText绘制中文文字) 目录 O ...

  7. 用C语言编写一个3*3矩阵的转置、水平镜像、顺时针90度旋转、逆时针90度旋转、180度旋转、垂直镜像

    设一个3*3d矩阵 1:求转置 int main(){int a[3][3];int len1 = sizeof(a) / sizeof(a[0]);int len2 = sizeof(a[0]) / ...

  8. C++/Qt 使用OpenCV打开摄像头,旋转视频,计算fps

    C++/Qt 使用OpenCV打开摄像头,旋转视频,计算fps 设置摄像头参数 不要随意修改,同时也不一样会修改成功,需要根据实际摄像头的参数选择设置 /*设置摄像头参数 不要随意修改capture. ...

  9. 【OpenCV】文字绘制 putText

    Backto OpenCV Index 在图像上绘制文字, void putText( InputOutputArray img, const String& text, Point org, ...

最新文章

  1. 【AD】破解WindowsServer2008R2 AD域控目录还原模式密码及域管理员账号密码
  2. sql--找含有制定字符列的表
  3. 深入Linux内核网络堆栈
  4. tableau实战系列(三十九)-Tableau可视化之多种地图绘制汇总
  5. 成功解决but is 0 and 2 (computed from start 0 and end 9223372 over shape with rank 2 and stride-1)
  6. 人工智能的本源与展望:从亚里士多德到平行智能
  7. BZOJ2081 [Poi2010]Beads
  8. 构建入门Restful Web服务
  9. vb 数组属性_[读书笔记]CSAPP:7[VB]机器级表示:函数
  10. python 启动参数_python启动参数
  11. vc6.0安装过程中出现的问题——解决
  12. 许愿墙|爱墙 js代码
  13. 凯利讯分享ECL电路与TTL电路的使用注意事项
  14. 彻底掌握Quartus——基础篇
  15. Zoreto+坚果云+pdf expert(papership) 实现文献管理和批注同步
  16. Android接收开机广播接收速度慢的原因
  17. 回车、换行、空格的ASCII码值(不同OS平台下文件换行定义)
  18. 不要在学习启动管理器和元编程上浪费时间
  19. postgresql数据库操作
  20. 多测师拱墅校区肖sir_高级金牌讲师_html讲解

热门文章

  1. linux版本剪辑软件下载,OpenShot Video Editor(电脑后期视频编辑软件) V2.4.3 Linux版
  2. Mac安装使用Virtualenv
  3. 【每天学点管理】——以矛盾激发思维的“头脑风暴”
  4. 超级试题助手一键更改题目顺序和选项顺序
  5. android获取activity截图,Android Activity 不能被截屏的解决方法
  6. Vscode正则查找替换
  7. 涂鸦云平台设备授权介绍
  8. Mysql中索引失效得原因和解决
  9. Potplayer使用
  10. 日志打印的15个建议!血泪啊!