【Opencv】PIL Opencv 向图片写入文字并旋转文字,Opencv图片旋转不截断,Opencv图片旋转不裁剪

news2025/1/10 11:49:32

文章目录

  • 失真
  • Pillow的实现
  • Opencv的实现
    • 不裁剪的旋转图像
    • 旋转文字并贴图

失真

刚性变换: 只有物体的位置(平移变换)和朝向(旋转变换)发生改变,而形状不变,得到的变换称为刚性变换。刚性变换是最一般的变换。

使用透视变换,文字会扭曲失真。刚性变换就不会。

一些介绍: https://blog.csdn.net/liuweiyuxiang/article/details/86510191

在这里插入图片描述

Pillow的实现

创建一张空图写文字:
在这里插入图片描述
旋转了-30度:
在这里插入图片描述
将RGBA图像paste到大图中。
在这里插入图片描述

Python代码:

from PIL import Image, ImageDraw, ImageFont


def draw_text_with_rotation(image, position, text, font_size, color, angle):
    draw = ImageDraw.Draw(image)
    font = ImageFont.truetype("STKAITI.TTF", font_size)
    width, height = draw.textsize(text, font=font)
    rotated_text = Image.new("RGBA", (width, height), (0, 0, 0, 0))
    text_draw = ImageDraw.Draw(rotated_text)
    text_draw.text((0, 0), text, font=font, fill=color)
    rotated_text.save("rotated_text1.png")
    rotated_text = rotated_text.rotate(-angle, resample=Image.BICUBIC, expand=True)
    rotated_text.save("rotated_text2.png")
    image.paste(rotated_text, position, rotated_text)
    rotated_text_width, rotated_text_height = rotated_text.size
    return rotated_text_width, rotated_text_height


# 创建一个空白图像
width, height = 800, 600
background_color = (255, 255, 255)  # 白色
image = Image.new("RGB", (width, height), background_color)

# 在大图中写入文本并旋转
text = "Hello, World!是吗可以的呀"
text_position = (200, 200)
text_font_size = 30
text_color = (0, 0, 0)  # 黑色
rotation_angle = -30

rotated_text_width, rotated_text_height = draw_text_with_rotation(image, text_position, text, text_font_size,
                                                                  text_color, rotation_angle)
# 画一个红色框框选上文字区域
draw = ImageDraw.Draw(image)
draw.rectangle((text_position[0], text_position[1], text_position[0] + rotated_text_width,
                text_position[1] + rotated_text_height), outline=(255, 0, 0))
# 保存图片
image.save("rotated_text3.png")

Opencv的实现

不裁剪的旋转图像

参考imutils得到:

import math

import cv2
import numpy as np

def rotate_bound2(image, angle):
    # grab the dimensions of the image and then determine the center
    # 抓取图像的尺寸,然后确定中心
    (h, w) = image.shape[:2]
    (cX, cY) = (w / 2, h / 2)
    # grab the rotation matrix (applying the negative of the angle to rotate clockwise), then grab the sine and cosine (i.e., the rotation components of the matrix)
    # 抓取旋转矩阵(应用角度的负数顺时针旋转),然后抓取正弦和余弦(即矩阵的旋转分量)
    M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    # compute the new bounding dimensions of the image
    # 计算图像的新边界尺寸
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))
    # adjust the rotation matrix to take into account translation
    # 调整旋转矩阵以考虑平移
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY
    # perform the actual rotation and return the image
    # 执行实际旋转并返回图像
    return cv2.warpAffine(image, M, (nW, nH), flags=cv2.INTER_CUBIC)


def rotate_image(image, angle):
    angle = angle % 360.0
    if angle == 0:
        return image.copy()
    if angle == 180:
        return cv2.rotate(image, cv2.ROTATE_180)
    if angle == 90:
        return cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE)
    if angle == 270:
        return cv2.rotate(image, cv2.ROTATE_90_COUNTERCLOCKWISE)
    return rotate_bound2(image, angle)


# 读取RGBA
image = cv2.imread('rotated_text1.png', cv2.IMREAD_UNCHANGED)

# 对图像进行旋转并扩展
rotated_image = rotate_image(image, 45)

# SAVE
cv2.imwrite("rotated_text1_rotated.png", rotated_image)

在这里插入图片描述

旋转文字并贴图

import math

import cv2
import numpy as np


def rotate_bound2(image, angle):
    # grab the dimensions of the image and then determine the center
    # 抓取图像的尺寸,然后确定中心
    (h, w) = image.shape[:2]
    (cX, cY) = (w / 2, h / 2)
    # grab the rotation matrix (applying the negative of the angle to rotate clockwise), then grab the sine and cosine (i.e., the rotation components of the matrix)
    # 抓取旋转矩阵(应用角度的负数顺时针旋转),然后抓取正弦和余弦(即矩阵的旋转分量)
    M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])
    # compute the new bounding dimensions of the image
    # 计算图像的新边界尺寸
    nW = int((h * sin) + (w * cos))
    nH = int((h * cos) + (w * sin))
    # adjust the rotation matrix to take into account translation
    # 调整旋转矩阵以考虑平移
    M[0, 2] += (nW / 2) - cX
    M[1, 2] += (nH / 2) - cY
    # perform the actual rotation and return the image
    # 执行实际旋转并返回图像
    return cv2.warpAffine(image, M, (nW, nH), flags=cv2.INTER_CUBIC)


def rotate_image(image, angle):
    angle = angle % 360.0
    if angle == 0:
        return image.copy()
    if angle == 180:
        return cv2.rotate(image, cv2.ROTATE_180)
    if angle == 90:
        return cv2.rotate(image, cv2.ROTATE_90_CLOCKWISE)
    if angle == 270:
        return cv2.rotate(image, cv2.ROTATE_90_COUNTERCLOCKWISE)
    return rotate_bound2(image, angle)


def draw_text_with_rotation(image, position, text, font_size, color, angle):
    # 定义字体样式
    font = cv2.FONT_HERSHEY_SIMPLEX
    thickness = 2
    # 获取文字的宽度和高度
    text_size, baseline = cv2.getTextSize(text, font, font_size, thickness)
    print(text_size, baseline)
    text_width, text_height = text_size

    # 灰度图上白纸黑字
    text_image = np.zeros((text_height + baseline, text_width, 1), np.uint8)
    cv2.putText(text_image, text, (0, text_height), font, font_size, (255,), thickness)  # top-left corner.
    # 灰度图给到透明通道上
    text_image2 = np.zeros((text_height + baseline, text_width, 4), np.uint8)
    text_image2[:, :, 3] = text_image[:, :, 0]
    text_image = text_image2

    cv2.imwrite("self1.png", text_image)
    rotated_text = rotate_image(text_image, angle)
    cv2.imwrite("self2.png", rotated_text)
    rotated_text_height, rotated_text_width = rotated_text.shape[:2]
    image[position[0]:position[0] + rotated_text_height, position[1]:position[1] + rotated_text_width] = rotated_text
    return rotated_text_width, rotated_text_height


# 创建一个空白图像
width, height = 800, 600
image = np.zeros((height, width, 4), np.uint8)

# 在大图中写入文本并旋转
text = "Hello, World"
text_position = (200, 200)
text_font_size = 1
text_color = (255, 255, 255)  # 黑色
rotation_angle = -30

rotated_text_width, rotated_text_height = draw_text_with_rotation(image, text_position, text, text_font_size,
                                                                  text_color, rotation_angle)
# 画一个红色框框选上文字区域
cv2.rectangle(image, (text_position[0], text_position[1]),
              (text_position[0] + rotated_text_width, text_position[1] + rotated_text_height), (0, 0, 255, 255), 2)
# 保存图片
cv2.imwrite("self3.png", image)

文字图:
在这里插入图片描述
旋转后:
在这里插入图片描述

贴图:
在这里插入图片描述

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

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

相关文章

Multi-Query Attention 阅读笔记

《Fast Transformer Decoding: One Write-Head is All You Need》 核心贡献:优化 multi-head attention 为文中命名的 multi-query attention,减少多head相关运算,不降低精度 且 大幅提升解码速度。 具体对比如下: multi-head a…

win下编译ycm报错 “could not find any instance of Visual Studio” 解决办法

ycm-core/YouCompleteMe: A code-completion engine for Vim 是一款vim插件,可为不同的代码类型提供语义级别的补全能力。 问题描述 通过vim-plug插件管理器安装ycm后,还需对进入其插件目录~\vimfiles\plugged\YouCompleteMe 进行编译python .\install…

分类预测 | MATLAB实现GA-LSTM遗传算法优化长短期记忆网络的数据多输入分类预测

分类预测 | MATLAB实现GA-LSTM遗传算法优化长短期记忆网络的数据多输入分类预测 目录 分类预测 | MATLAB实现GA-LSTM遗传算法优化长短期记忆网络的数据多输入分类预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MATLAB实现GA-LSTM遗传算法优化长短期记忆网络的数据多…

DS18B20-STM32温度读取

command data 高地位组合即为温度数据 1. 初始化时钟 void Init_DS18B20(void) {char CY 1;while (CY){DQ_OUT();DQ_SET_H(); delay_us(20); DQ_SET_L(); //送出低电平复位信号delay_us(360); //延时至少480usdelay_us(240);DQ_SET_H(); …

忆联携手中国移动,企业级NVME SSD评测及生态推进计划发布仪式圆满成功

6月27日,中国信通院、中国移动和中国电信在ODCC 2023夏季全会上发布了“企业级NVME SSD评测及生态推进计划”(以下简称“推进计划”),忆联作为中国移动重要的合作伙伴受邀出席该“推进计划”成立仪式环节,与中国信通院…

vue watch监听不生效,解决办法

1、在data里定义监听的属性,解决问题 2、使用深度监听

(0day通用)中庆纳博某系统敏感信息泄露+未授权修改密码

申明:本次测试只作为学习用处,请勿未授权进行渗透测试,切勿用于其它用途! 1.漏洞背景 北京中庆纳博信息技术有限公司,简称中庆纳博,是有20年历史的中庆集团旗下核心企业,专注于教育信息化的深度…

UDP SocketAPI

1、TCP与UDP区别 TCP:有连接,可靠传输,面向字节流,全双工 UDP:无连接,不可靠传输,面向数据报,全双工 2、UDP sockeAPI的核心类 DatagramSocket:相当于对socket文件进…

Swift 单元测试入门

含义:编程语言中的单元测试是为了确保编写的代码按预期工作。 给定一个特定的输入,希望代码带有一个特定的输出。通过测试代码,能够给当前的重构和发布建立信心,因为将能够确保代码在成功运行的测试套件后按预期工作。 一、单元测…

macos中回退键是Command+shift+z,我该如何改成Command+y?

macos中回退键是Commandshiftz,我该如何改成Commandy? 操作如下,打开系统设置-键盘 在「菜单标题」中手动输入需要更改快捷键的菜单项名称,注意要完全一致(见下图)。 最后说一句,撤销与重做是非常基础的系…

VS2017编译64位库出现问题解决方法

1、问题:VS2017编译32位Release库正常通过,但是64位库总是报错 解决方法:添加setupapi.lib到依赖项中

线性代数笔记整理

文章目录 1 行列式2 矩阵(本质是数表)3 方程组的解4 向量5 矩阵的特征值和特征向量6 相似矩阵和相似对角化7 合同对角化8 二次型及其标准型 1 行列式 2 矩阵(本质是数表) 3 方程组的解 4 向量 5 矩阵的特征值和特征向量 6 相似矩阵…

【MATLAB第47期】基于MATLAB的多卷积层的卷积神经网络MCNN分类预测模型,含交叉验证,可自定义层数

【MATLAB第47期】基于MATLAB的多卷积层的卷积神经网络MCNN分类预测模型,含交叉验证,可自定义层数 一、展示效果 依次对比卷积层数为1/2/3时的分类预测结果 可得出,随着卷积层数量增加,训练集/测试集正确率基本上得到改进。 1.一…

GPIO模拟时序控制外设4——红外发射管

文章目录 前言红外发射管简介NEC协议HS0038NEC 的逻辑“1”与逻辑“0”NEC的数据帧格式 编程思路1. GPIO管脚2. 模拟同步头3.发送逻辑“0”与逻辑“1”发送一个字节数据发送一帧数据结束码现象 总结 前言 上一篇介绍了使用GPIO模拟时序实现I2C协议的功能,本文继续使…

DELL戴尔笔记本电脑灵越Inspiron 14 54105418原厂Win10系统恢复原装OEM出厂状态系统

Dell戴尔笔记本电脑,灵越Inspiron 14 5410&5418原装出厂OEM系统镜像原厂系统文件 系统自带所有驱动、出厂主题壁纸LOGO、Office办公软件等预装程序 链接:https://pan.baidu.com/s/1Qj_dW5lj71e9d71-je4dXw?pwdz3z1 提取码:z3z1

Oracle Recovery Tools恢复csc higher than block scn---惜分飞

有客户强制关闭数据库,结果有数据块报坏块,dbv检查为:csc higher than block scn问题 该问题主要是由于scn异常导致通过Oracle Recovery工具进行修复 dbv再次验证数据块ok,Oracle Recovery完美代替bbed解决该问题 通过OraRecovery工具快速解决csc higher than block scn故障…

IntelliJ IDEA如何自动生成serialVersionUID

IntelliJ IDEA如何自动生成serialVersionUID? 实体对象在流中传输时,需要将其序列化。 对象的类型实现Serializable接口public class ClassName implements java.io.Serializable { } 生成版本号serialVersionUID单击类名,按Alt Enter,在出…

C语言的##使用

##在C/C中具有连接字符串的作用 #include<stdio.h> #define TEST(_name, _inst_alloc) \printf("token6 %d\n",_name##_inst_alloc); int main() {int token6 100;TEST(token, 6);return 0; }

[环境配置][原创]VS2019新建项目一直打转转圈很久才能正常显示模板项目

不知道什么时候VS2019新建一个C#或者C项目越来越慢&#xff0c;点击新建项目一直是下面状态 我记得以前最多等个几秒都是可以出来的&#xff0c;后面发现要一分钟以上。这个确实令人抓狂。于是找到一种方法可以明显改善这个问题&#xff0c;那就是卸载Nsight相关程序。一般都是…