首页 > 其他分享 >苦学Opencv的第六天:图像的几何变换

苦学Opencv的第六天:图像的几何变换

时间:2024-07-20 10:27:18浏览次数:13  
标签:img dst cv2 像素 Opencv 几何变换 参数 苦学 图像

Python OpenCV入门到精通学习日记:图像的几何变换

前言

几何变换,顾名思义就是修改图像的几何结构,例如大小,角度和形状等等,让图像呈现不同的效果。这些几何变换的操作一般都涉及复杂且精密的计算,Opencv将这些计算过程全部都包装成了各种灵活的方法,我们只需要修改一些参数,就能实现图像的变换效果。

图像的几何变换 缩放 翻转 仿射变换 平移 透视 旋转 倾斜

仿射变换是难点内容

图像的几何变换

1 缩放

顾名思义就是缩小和放大,Opencv提供了resize()方法可以随意修改图像的大小比例。

dst = cv2.resize(src, dsize, fx, fy, interpolation)

参数说明:
	src:原始图像。
	dsize:输出图像的大小,格式为(宽,高),单位为像素。
	fx:可选参数。水平方向的缩放比例。
	fy:可选参数。垂直方向的缩放比例。
	interpolation:可选参数。缩放的插值方式。在图像缩小或放大时需要删减或补充像素,该参数可以指定使用哪种算法对像素进行增减。建议使用默认值。
	dst:缩值之后的图像。

resize()方法有两种使用方法,一种是通过dsize参数实现缩放,另一种是通过fx和fy参数实现缩放。

1.1 dsize参数实现缩放

dsize参数的格式是一个元组,例如(100,200),表示将图像按照宽100,高200像素的大小进行缩放。如果使用dsize参数,就可以不用写fx和fy参数。

示例:将一个图像按照宽100像素、高100像素的大小进行缩小,再按照宽600像素、高600像素的大小进行放大。

import cv2
img = cv2.imread("img.png")
dst1 = cv2.resize(img,(100,100))
dst2 = cv2.resize(img,(600,600))
cv2.imshow("img",img)
cv2.imshow("dst1",dst1)
cv2.imshow("dst2",dst2)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

1.2 fx和fy参数实现缩放

使用fx,fy参数时,dsize参数必须为None,否则fx和fy参数会失效。而且fx,fy参数可以使用浮点值,小于1的值表示缩小,大于1的值表示放大。

  • 新图像宽度 = round(fx * 原图像宽度)
  • 新图像高度 = round(fy * 原图像宽度)

示例:将一个图像宽缩小到原来的1/3、高缩小到原来的1/2,再将图像宽放大2倍,高也放大2倍

img = cv2.imread("img.png")
dst1 = cv2.resize(img,None,fx=1/3,fy=1/2)
dst2 = cv2.resize(img,None,fx=2,fy=2)
cv2.imshow("dst1",dst1)
cv2.imshow("dst2",dst2)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

2 翻转

翻转就是沿着x,y轴翻转,主要是呈现出镜面或倒影的效果。

OpenCV通过cv2.flip()方法实现翻转效果。

dst = cv2.flip(src, flipCode)

参数说明:
 src:原始图像。
 flipCode:翻转类型,类型值及含义如表所示。
 dst:翻转之后的图像。
类型值含义
0沿X轴翻转
正数沿Y轴翻转
负数同时沿X轴、Y轴翻转

代码都是千篇一律了,这里我就给出关键代码:

dst = cv2.flip(img,0)
dst = cv2.flip(img,1)
dst = cv2.flip(img,-1)

3 仿射变换(难点)

仿射变换是一种仅在二维平面中发生的几何变换,变换之后的图像仍然可以保持直线的“平直性”和“平行性”,也就是说原来的直线变换之后还是直线,平行线变换之后还是平行线

这里借用书上原图:
在这里插入图片描述

OpenCV通过cv2. warpAffine()方法实现仿射变换效果。

dst = cv2.warpAffine(src, M, dsize, flags, borderMode,borderValue)

参数说明:
	src:原始图像。
	M:一个2行3列的矩阵,根据此矩阵的值变换原图中的像素位置。
	dsize:输出图像的尺寸大小。
	flags:可选参数,插值方式,建议使用默认值。
	borderMode:可选参数,边界类型,建议使用默认值。
	borderValue:可选参数,边界值,默认为0,建议使用默认值。
	dst:经过反射变换后输出图像。

M也被叫作仿射矩阵,实际上就是一个2×3的列表。
M = [[a, b, c],[d, e, f]]

图像做何种仿射变换,完全取决于M的值,仿射变换输出的图像按照以下公式进行计算:

新x = 原来x * a + 原来y * b + c
新y = 原来x * d + 原来y * e + f

原x和原y表示原始图像中像素的横坐标和纵坐标,新x与新y表示同一个像素经过仿射变换后在新图像中的横坐标和纵坐标。

M矩阵中的数字采用32位浮点格式,可以采用两种方式创建M。

  1. 创建一个全是0的M:M = np.zeros((2,3),np.float32)
  2. 创建M的同时赋予具体数值:M = np.float32([[1,2,3],[4,5,6]])

掌握了这个概念后,我们可以开始实现图像的平移,旋转和倾斜了。

3.1 平移

平移就是让图像中所有的像素同时沿着水平或垂直方向移动。

M = [[1,0,水平移动的距离],[0,1,垂直移动的距离]]

套入之前给的公式,计算得出:

新x = 原来x + 水平移动的距离
新y = 原来y + 垂直移动的距离

移动规律遵循:左负右正,上负下正

了解了这些之后我们可以进行尝试:将图像向右移动50像素、向下移动100像素。

import cv2,numpy as np
img = cv2.imread("img.png") # 图片被存储为三维数组(y,x,通道数)
y = len(img) # 这里 len(img) 返回的是图片数组的行数,即图片的高度
x = len(img[0]) # 这里 img[0] 是图片的第一行像素,len(img[0]) 返回的是这一行中像素列的数量,即图片的宽度
M = np.float32([[1,0,50],[0,1,100]])
dst = cv2.warpAffine(img,M,(x,y))
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

3.2 旋转

让图像旋转也是通过M矩阵实现的,但得出这个矩阵需要做很复杂的运算,于是OpenCV提供了getRotationMatrix2D()方法自动计算旋转图像的M矩阵。

M = cv2.getRotationMatrix2D(center, angle, scale)

参数说明:
	center:旋转的中心点坐标。
	angle:旋转的角度(不是弧度)。正数表示逆时针旋转,负数表示顺时针旋转。
	scale:缩放比例,浮点类型。如果取值1,表示图像保持原来的比例。
	M:getRotationMatrix2D()方法计算出的仿射矩阵。

示例:让图像逆时针旋转30°的同时缩小到原来的80%

import cv2
img = cv2.imread("img.png")
x = len(img[0])
y = len(img)
center = (y/2,x/2) # 坐标应为(y,x)
M = cv2.getRotationMatrix2D(center,30,0.8)
dst = cv2.warpAffine(img,M,(x,y))
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

3.3 倾斜

Opencv需要定位图像的三个点来计算倾斜效果,这三个点分别是左上角A,右上角B,左下角C。Opencv会根据这三个点的位置变化来计算其他像素的位置变化。右下角的点会根据ABC三个点的变化自动计算。

这里借用书上原图:
在这里插入图片描述

让图像倾斜也是需要通过M矩阵实现的,但得出这个矩阵需要做很复杂的运算,于是OpenCV提供了getAffineTransform()方法来自动计算倾斜图像的M矩阵。

M = cv2.getAffineTransform(src, dst)

参数说明:
	src:原图3个点坐标,格式为3行2列的32位浮点数列表,例如:[[0, 1], [1, 0], [1, 1]]。
	dst:倾斜图像的3个点坐标,格式与src一样。
	M:getAffineTransform()方法计算出的仿射矩阵。

我们可以尝试让图像向右倾斜:

import cv2,numpy as np
img = cv2.imread("img.png")
x = len(img[0])
y = len(img)
p1 = np.zeros((3,2),np.float32) # 生成一个3*2的数组并向里面填入数据作为原来的三个点
p1[0] = [0,0]
p1[1] = [x-1,0]
p1[2] = [0,y-1]
p2 = np.zeros((3,2),np.float32) # 生成一个3*2的数组并向里面填入数据作为修改的三个点
p2[0] = [50,0]
p2[1] = [x-1,0]
p2[2] = [0,y-1]
M = cv2.getAffineTransform(p1,p2)
dst = cv2.warpAffine(img,M,(x,y))
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

同理,如果想让图像向左倾斜,需要移动右上角和左下角的点

4 透视

仿射变换是让图像在二维中变形,那么透视就是让图像在三维中变形。从不同角度来观察物体,会看见不同的变形画面,这种变形的画面就是透视图。

为了让大家直观感受,这里引用书中原图:
在这里插入图片描述

Opencv中需要通过定位图像的4个点来计算透视效果,这四个点就是倾斜功能提及的三个点和右下角一个点,Opencv根据这四个点的位置变化来计算其他的像素的位置变化。但是透视效果不能保证图像的“平直性”和“平行性”。

Opencv通过warpPerspective()来实现透视效果。

dst = cv2.warpPerspective(src, M, dsize, flags,borderMode, borderValue)

参数说明:
	src:原始图像。
	M:一个3行3列的矩阵,根据此矩阵的值变换原图中的像素位置。
	dsize:输出图像的尺寸大小。
	flags:可选参数,插值方式,建议使用默认值。
	borderMode:可选参数,边界类型,建议使用默认值。
	borderValue:可选参数,边界值,默认为0,建议使用默认值。
	dst:经过透视变换后输出图像。

透视也是需要M矩阵进行复杂的运算,在Opencv中提供了getPerspectiveTransform()方法自动计算M矩阵。

语法和前面的getAffineTransform()很像,唯一不同的就是getPerspectiveTransform()的src和dst参数是四个点的坐标,格式为4*2的32位浮点数列表。

学到这里,我们可以模拟从底部观察图像了:

import cv2
import numpy as np
img = cv2.imread("img.png")
x = len(img[0])
y = len(img)
p1 = np.zeros((4,2),np.float32)
p1[0] = [0,0]
p1[1] = [x-1,0]
p1[2] = [0,y-1]
p1[3]= [x-1,y-1]
p2 = np.zeros((4,2),np.float32)
p2[0] = [90,0]
p2[1] = [x-91,0]
p2[2] = [0,y-1]
p2[3] = [x-1,y-1]
M = cv2.getPerspectiveTransform(p1,p2)
dst = cv2.warpPerspective(img,M,(x,y))
cv2.imshow("img",img)
cv2.imshow("dst",dst)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

小结

今天难点主要在M矩阵上,书中并没有提到M矩阵的计算内容,只是给了我们调用函数,可以直接处理图像,使用大家只要熟练掌握并灵活运用M矩阵,就能够对图像进行几何变换操作。

明天开始学图像的阈值处理。

有些代码没有标注注释,看不懂的可以评论区讨论,看见必回。

标签:img,dst,cv2,像素,Opencv,几何变换,参数,苦学,图像
From: https://blog.csdn.net/qq_71745595/article/details/140512785

相关文章

  • Error: Assertion failed (nimages > 0) in cv::calibrateCameraRO, file D:\opencv4
    报错信息:Error:Assertionfailed(nimages>0)incv::calibrateCameraRO,fileD:\opencv4\opencv\opencv-4.1.0\modules\calib3d\src\calibration.cpp,line3691  原因:①图片路径问题,没有指向包含棋盘格的图片②图片中不包含棋盘格或者图片模糊等问题,导致查找棋盘......
  • OpenCV ----像素距离与连通域
    文章目录一.图像像素距离变换1.常用距离的三种定义:(1)欧式距离-----DIST_L2(2)街区距离-----DIST_L1(3)棋盘距离------DIST_C2.distanceTransform()------距离转换函数(1)函数原型(2)运用演示二.图像连通域(1)定义(2)邻域(3)标记连通域函数-----connectedComponents()(3)connecte......
  • OpenCV教程04:结合pillow在图片上显示中文文字
    1.如果添加的内容是纯英文文字,直接使用cv2.putText函数操作即可。但它不支持自定义字体文件,仅限于这些内置的字体样式。如果你需要更复杂的字体支持,可能需要使用其他库,如PythonImagingLibrary(PIL)或Pillow。可用的字体列表:cv2.FONT_HERSHEY_SIMPLEX-正常大小的无......
  • Python与OpenCV的魔法:批量将照片变身为精美素描图
    1.前言在数字图像处理领域,图像转换和滤波是非常常见的操作。特别是将彩色照片转换为素描图,这种技术可以用于艺术创作、图像分析以及一些特殊的图像处理需求。本文将详细介绍如何使用Python和OpenCV库批量将任意图片转换为素描图。2.简介OpenCV(OpenSourceComputerVisionL......
  • OpenCV窗口交互(窗口滑动条,鼠标响应)
    窗口交互操作#####(1)图像窗口滑动条​Open-CV中创建滑动条函数原型为:intcreateTrackbar(constString&trackbarname,constString&winname,int*value,intcount,TrackbarCallbackonChange=......
  • 使用OpenCV实现摄像头测距
    使用OpenCV实现摄像头测距摄像头测距就是计算照片中的目标物体到相机的距离。可以使用相似三角形(triangle similarity)方法实现,或者使用更复杂但更准确的相机模型的内参来实现这个功能。使用相似三角形计算物体到相机的距离假设物体的宽度为 W,将其放到离相机距离为 D ......
  • Python学习笔记—100页Opencv详细讲解教程
    目录1创建和显示窗口...-4-2加载显示图片...-6-3保存图片...-7-4视频采集...-8-5视频录制...-11-6控制鼠标...-12-7TrackBar控件...-14-8.RGB和BGR颜色空间...-16-9.HSV和HSL和YUV..-17-10颜色空间的转化...-18-11mat的深......
  • OpenCV开发笔记(七十八):在ubuntu上搭建opencv+python开发环境以及匹配识别Demo
    若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/140435870长沙红胖子Qt(长沙创微智科)博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…OpenCV开发专栏......
  • Turtlebot3在ROS Gazebo中使用OpenCV检测并跟踪球体
    原文链接:https://www.youtube.com/watch?v=Rw6ATkORRG8   一个小巧的机器人在虚拟世界中敏捷地追踪着一个滚动的球体。Turtlebot3,一个搭载ROS操作系统的智能机器人,在Gazebo仿真环境中,利用OpenCV的神奇力量,展现出令人惊叹的视觉追踪能力。 Turtlebot3的"眼睛"是一台高清......
  • opencv—常用函数学习_“干货“_7
    目录十九、模板匹配从图像中提取矩形区域的子像素精度补偿(getRectSubPix)在图像中搜索和匹配模板(matchTemplate)比较两个形状(轮廓)的相似度(matchShapes)解释二十、图像矩计算图像或轮廓的矩(moments)计算图像或轮廓的Hu不变矩(HuMoments)解释使用示例二一、......