草庐IT

OpenCV-Python学习(20)—— OpenCV 图像几何变换之图像旋转(cv.warpAffine、cv.getRotationMatrix2D、cv.rotate、np.rot90)

Rattenking 2024-05-14 原文

1. 学习目标

  1. 学习旋转矩阵;
  2. 学习使用 OpenCV 的 cv.warpAffine 函数进行图片的旋转;
  3. 学习使用 OpenCV 的 cv.getRotationMatrix2D 来计算不同旋转中心的不同角度的 MAR 旋转变换矩阵;
  4. 学习使用 OpenCV 的 cv.rotate 进行特殊角度的旋转(90,180,270 度)。

2. 不同中心的旋转矩阵计算

2.1 图像以原点 (0, 0) 为中心

图像以原点 (0, 0) 为中心、顺时针旋转角度 θ 进行旋转的计算公式:

逆时针为负数,顺时针为正数

2.2 图像以任意点 (x0, y0) 为旋转中心

图像以任意点 (x0, y0) 为旋转中心、顺时针旋转角度 θ 的旋转操作,可以先将原点平移到旋转中心 (x0, y0) ,然后按照原点旋转,最后再平移回坐标原点的计算公式:

逆时针为负数,顺时针为正数

逆时针为正数,顺时针为负数

计算公式结果参考:cv2.getRotationMatrix2D的旋转矩阵的正确形式!!!

3. 图像旋转函数

3.1 cv.warpAffine() 函数使用

cv.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst

3.2 参数说明

参数说明
src表示输入图像。
M表示变换矩阵,2行3列。
dsize表示输出图像的大小,二元元组 (width, height)。
dst表示变换操作的输出图像,可选项。
flags表示插值方法,整型(int),可选项。
borderMode表示边界像素方法,整型(int),可选项,默认值为 cv.BORDER_REFLECT。
borderValue表示边界填充值,可选项,默认值为 0(黑色填充)。

3.3 flags 值说明

说明
cv.INTER_LINEAR表示双线性插值(默认方法)。
cv.INTER_AREA表示使用像素区域关系重采样,缩小图像时可以避免波纹出现。
cv.INTER_NEAREST表示最近邻插值。
cv.INTER_CUBIC表示 4x4 像素邻域的双三次插值。
cv.INTER_LANCZOS4表示 8x8 像素邻域的Lanczos插值。

4. 以原点(0,0)旋转任意角度实例

4.1 旋转实例

逆时针为负数,顺时针为正数

import cv2 as cv
import numpy as np

# 图像旋转(以原点(0,0)为中心旋转)
def image_rotate(src, rotate=0):
  h,w,c = src.shape
  cos_val = np.cos(np.deg2rad(rotate))
  sin_val = np.sin(np.deg2rad(rotate))
  M = np.float32([[cos_val, -sin_val, 0], [sin_val, cos_val, 0]])
  img = cv.warpAffine(src, M, (w,h))
  return img

if __name__ == "__main__":
  img = cv.imread("./images/lena.jpg")
  cv.imshow("origin", img)
  cv.imshow("img_rotate_30", image_rotate(img,30))
  cv.imshow("img_rotate_45", image_rotate(img,45))
  cv.waitKey(0)
  cv.destroyAllWindows()

4.2 旋转效果

5. 逆时针为正数,顺时针为负数

5.1 旋转实例

import cv2 as cv
import numpy as np

# 图像旋转(以原点(0,0)为中心旋转)
def image_rotate(src, rotate=0):
  h,w,c = src.shape
  cos_val = np.cos(np.deg2rad(rotate))
  sin_val = np.sin(np.deg2rad(rotate))
  M = np.float32([[cos_val, sin_val, 0], [-sin_val, cos_val, 0]])
  img = cv.warpAffine(src, M, (w,h))
  return img

if __name__ == "__main__":
  img = cv.imread("./images/lena.jpg")
  cv.imshow("origin", img)
  cv.imshow("img_rotate_30", image_rotate(img,30))
  cv.imshow("img_rotate_45", image_rotate(img,45))
  cv.waitKey(0)
  cv.destroyAllWindows()

5.2 旋转效果

6. 以任意点为中心旋转任意角度实例(逆时针为正数,顺时针为负数)

6.1 旋转实例

import cv2 as cv
import numpy as np

# 计算旋转变换矩阵
def handle_rotate_val(x,y,rotate):
  cos_val = np.cos(np.deg2rad(rotate))
  sin_val = np.sin(np.deg2rad(rotate))
  return np.float32([
      [cos_val, sin_val, x * (1 - cos_val) - y * sin_val],
      [-sin_val, cos_val, x * sin_val + y * (1 - cos_val)]
    ])

# 图像旋转(以任意点为中心旋转)
def image_rotate(src, rotate=0):
  h,w,c = src.shape
  M = handle_rotate_val(w//2,h//2,rotate)
  img = cv.warpAffine(src, M, (w,h))
  return img

if __name__ == "__main__":
  img = cv.imread("./images/lena.jpg")
  cv.imshow("origin", img)
  cv.imshow("img_rotate_30", image_rotate(img,30))
  cv.imshow("img_rotate_45", image_rotate(img,45))
  cv.waitKey(0)
  cv.destroyAllWindows()

6.2 旋转效果

7. cv.getRotationMatrix2D 函数

OpenCV 提供了 cv.getRotationMatrix2D 函数, 根据旋转角度和位移计算旋转变换矩阵 MAR。

7.1 cv.getRotationMatrix2D() 函数说明

cv.getRotationMatrix2D(center, angle, scale) → M

7.2 参数说明

参数说明
center表示旋转中心坐标,二元元组 (x0, y0)。
angle表示旋转角度,单位为角度,逆时针为正数,顺时针为负数
scale表示缩放因子。

7.3 使用 cv.getRotationMatrix2D 计算变换矩阵的实例

import cv2 as cv

# 图像旋转(以任意点为中心旋转)
def image_rotate(src, rotate=0):
  h,w,c = src.shape
  M = cv.getRotationMatrix2D((w//2,h//2),rotate,1)
  img = cv.warpAffine(src, M, (w,h))
  return img

if __name__ == "__main__":
  img = cv.imread("./images/lena.jpg")
  cv.imshow("origin", img)
  cv.imshow("img_rotate_30", image_rotate(img,30))
  cv.imshow("img_rotate_45", image_rotate(img,45))
  cv.waitKey(0)
  cv.destroyAllWindows()

7.4 旋转结果

8. cv.rotate 函数

8.1 cv.rotate() 函数说明

cv.rotate( src, rotateCode[, dst] ) → dst

8.2 参数说明

参数说明
src表示变换操作的输入图像。
rotateCode表示枚举,指定旋转角度。
dst表示变换操作的输出图像,ndarray 多维数组。

8.3 rotateCode 值说明

说明
cv.ROTATE_90_CLOCKWISE表示顺时针旋转 90 度。
cv.ROTATE_180表示旋转 180 度。
cv.ROTATE_90_COUNTERCLOCKWISE表示逆时针旋转 90 度。

8.4 cv.rotate 旋转实例

import cv2 as cv
import numpy as np

# 图像旋转(以特殊角度旋转)
def image_rotate(src):
  img_90 = cv.rotate(src,cv.ROTATE_90_CLOCKWISE)
  cv.imshow("ROTATE_90_CLOCKWISE", img_90)
  img_180 = cv.rotate(src,cv.ROTATE_180)
  cv.imshow("ROTATE_180", img_180)
  img_270 = cv.rotate(src,cv.ROTATE_90_COUNTERCLOCKWISE)
  cv.imshow("ROTATE_90_COUNTERCLOCKWISE", img_270)
  return img

if __name__ == "__main__":
  img = cv.imread("./images/lena.jpg")
  cv.imshow("origin", img)
  image_rotate(img)
  cv.waitKey(0)
  cv.destroyAllWindows()

8.5 旋转效果

9. np.rot90 函数

9.1 np.rot90() 函数说明

np.rot90(src, k, axes)  → dst

9.2 参数说明

参数说明
src表示变换操作的输入图像。
k表示阵列旋转90度的次数。
axes表示 array 在轴定义的平面中旋转。 轴必须不同。
dst表示变换操作的输出图像。

9.3 旋转实例

import cv2 as cv
import numpy as np

# 图像旋转(以特殊角度旋转)
def image_rotate(src):
  img_90 = np.rot90(src,1)
  cv.imshow("rot90", img_90)
  img_180 = np.rot90(src,2)
  cv.imshow("rot180", img_180)
  img_270 = np.rot90(src,3)
  cv.imshow("rot270", img_270)
  return img

if __name__ == "__main__":
  img = cv.imread("./images/lena.jpg")
  half_img = cv.resize(img,None,fx=0.5,fy=0.5)
  cv.imshow("origin", half_img)
  image_rotate(half_img)
  cv.waitKey(0)
  cv.destroyAllWindows()

9.4 旋转结果

10. 总结

  1. cv.rotate 和 np.rot90 两个方法只能旋转特殊角度,只能是90度的整数倍数。
  2. cv.warpAffine 可以对图像进行任意角度旋转;
  3. 实现自定原点旋转,需要借助 cv.getRotationMatrix2D 计算变化矩阵;
  4. cv.getRotationMatrix2D 的实现原理需要注意旋转角度对应的顺【逆】时针旋转!!!
  5. 注意:cv.getRotationMatrix2D 的旋转角度【逆时针为正数,顺时针为负数】!!!

有关OpenCV-Python学习(20)—— OpenCV 图像几何变换之图像旋转(cv.warpAffine、cv.getRotationMatrix2D、cv.rotate、np.rot90)的更多相关文章

  1. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  2. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  3. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  4. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  5. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  6. ruby-on-rails - 在 Ruby (on Rails) 中使用 imgur API 获取图像 - 2

    我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path

  7. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

  8. ruby - 是否有将图像文件转换为 ASCII 艺术的命令行程序或库? - 2

    有这样的事吗?我想在Ruby程序中使用它。 最佳答案 试试这个http://csl.sublevel3.org/jp2a/此外,Imagemagick可能还有一些东西 关于ruby-是否有将图像文件转换为ASCII艺术的命令行程序或库?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6510445/

  9. ruby-on-rails - 使用 Dragonfly 从 URL 分配图像 - 2

    我正在使用Dragonfly在Rails3.1应用程序上处理图像。我正在努力通过url将图像分配给模型。我有一个很好的表格:{:multipart=>true}do|f|%>RemovePicture?Dragonfly的文档指出:Dragonfly提供了一个直接从url分配的访问器:@album.cover_image_url='http://some.url/file.jpg'但是当我在控制台中尝试时:=>#ruby-1.9.2-p290>picture.image_url="http://i.imgur.com/QQiMz.jpg"=>"http://i.imgur.com/QQ

  10. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

随机推荐