python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python图像几何变换

使用Python进行图像几何变换的操作流程

作者:封奚泽优

本文介绍了图像处理中的基本几何变换操作,主要包括图像缩放、平移、旋转等基础变换,以及仿射变换和透射变换等高级变换方法,同时讲解了图像金字塔的构建方法,包括向上采样(pyrUp)和向下采样(pyrDown),需要的朋友可以参考下

算数操作

图像的加法

OpenCV加法是饱和操作,Numpy加法是模运算。

import cv2
import numpy as np
 
x = np.uint8([250])
y = np.uint8([10])
print(x)  # [[250]]
print(y)  # [[10]]
print(cv2.add(x, y))  # [[255]]
print(x + y)  # [4]

OpenCV加法 

# cv2.add() 是 OpenCV 中用于执行图像加法运算的核心函数,与 Python 的普通加法运算符 (+) 不同,它使用饱和运算防止溢出。
dst = cv2.add(src1, src2[, dst[, mask[, dtype]]])
参数类型描述
src1numpy.ndarray第一个输入数组(图像)
src2numpy.ndarray 或 标量第二个输入数组或标量值
dstnumpy.ndarray (可选)输出数组(与输入相同大小和类型)
masknumpy.ndarray (可选)8位单通道掩码,指定要修改的输出数组元素
dtypeint (可选)输出数组的深度(如 cv2.CV_8U, cv2.CV_32F)

中文标题会乱码,干脆使用英文标题了,键盘按下任意键退出,只是关闭窗口程序不会结束。

import cv2
 
# 读取两张相同尺寸的图像
img1 = cv2.imread("image1.jpg")  # 替换为你的图片路径
img2 = cv2.imread("image2.jpg")  # 替换为你的图片路径
 
# 检查图像是否成功读取
if img1 is None or img2 is None:
    print("错误:无法读取图像文件")
    exit()
 
# 调整img2尺寸匹配img1
if img1.shape != img2.shape:
    img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))  # 注意宽高顺序
 
# 直接相加
result = cv2.add(img1, img2)
 
# 显示结果
cv2.imshow("OpenCV Addition", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Numpy加法 

很明显直接相加的话图像直接失真了。

result = img1 + img2
import cv2
 
# 读取两张相同尺寸的图像
img1 = cv2.imread("image1.jpg")  # 替换为你的图片路径
img2 = cv2.imread("image2.jpg")  # 替换为你的图片路径
 
# 检查图像是否成功读取
if img1 is None or img2 is None:
    print("错误:无法读取图像文件")
    exit()
 
# 调整img2尺寸匹配img1
if img1.shape != img2.shape:
    img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))  # 注意宽高顺序
 
# 直接相加
result = img1 + img2
 
# 显示结果
cv2.imshow("Numpy Addition", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像的混合

# cv2.addWeighted() 是 OpenCV 中最重要和最常用的图像处理函数之一,用于实现图像的加权混合(也称为alpha混合)。
# dst = src1 × alpha + src2 × beta + gamma
dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])
参数类型描述默认值重要说明
src1numpy.ndarray第一个输入图像(矩阵)必填支持多通道图像(如BGR彩色 图)
alphafloat第一个图像的权重系数必填通常范围0.0-1.0,但可为任意实数
src2numpy.ndarray第二个输入图像(矩阵)必填必须与src1尺寸和通道数相同
betafloat第二个图像的权重系数必填通常alpha + beta = 1.0
gammafloat添加到加权和的标量值必填用于亮度调整,通常为0
dstnumpy.ndarray输出图像None可选,用于预分配输出数组
dtypeint输出数组的深度-1可选,如cv2.CV_8U, cv2.CV_32F
import cv2
 
# 读取两张相同尺寸的图像
img1 = cv2.imread("image1.jpg")  # 替换为你的图片路径
img2 = cv2.imread("image2.jpg")  # 替换为你的图片路径
 
# 检查图像是否成功读取
if img1 is None or img2 is None:
    print("错误:无法读取图像文件")
    exit()
 
# 调整img2尺寸匹配img1
if img1.shape != img2.shape:
    img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))  # 注意宽高顺序
 
# 图像混合
result = cv2.addWeighted(img1, 0.3, img2, 0.7, 0)
# 显示结果
cv2.imshow("Image Mixing", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

几何变换

图像缩放

对图像进行放大或缩小。

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

参数详解:

重要规则:必须指定 dsize 或 (fx, fy),但不能同时指定两者

插值方法对比

插值方法枚举值时间复杂度质量适用场景
最近邻插值cv2.INTER_NEARESTO(1)像素艺术、实时处理
双线性插值cv2.INTER_LINEARO(4)默认选择,平衡速度质量
双三次插值cv2.INTER_CUBICO(16)高质量放大,照片处理
区域插值cv2.INTER_AREAO(1)中高缩小图像首选
Lanczos插值cv2.INTER_LANCZOS4O(64)极高专业级放大,医学影像

 绝对尺寸

resized = cv2.resize(img, (400, 300))

相对尺寸

# 缩小为原图的50%
half_size = cv2.resize(img, None, fx=0.5, fy=0.5)

图像平移

指定平移矩阵后,调用cv.warpAffine()平移图像。

dst = cv2.warpAffine(
    src, 
    M, 
    dsize, 
    dst=None, 
    flags=cv2.INTER_LINEAR, 
    borderMode=cv2.BORDER_CONSTANT, 
    borderValue=0
)

必需参数

参数类型描述
srcnumpy.ndarray输入图像 (单通道或多通道)
Mnumpy.ndarray (2×3)2×3仿射变换矩阵
dsizetuple输出图像尺寸 (width, height)

可选参数

参数类型默认值描述
dstnumpy.ndarrayNone输出图像数组 (预分配内存)
flagsintcv2.INTER_LINEAR插值方法
borderModeintcv2.BORDER_CONSTANT边界填充模式
borderValuescalar0边界填充值 (BORDER_CONSTANT时使用)

 M仿射变换矩阵

M = [ a11  a12  b1 ]
    [ a21  a22  b2 ]

变换类型与矩阵关系

变换类型矩阵公式说明
平移[[1, 0, tx], [0, 1, ty]]tx, ty 为平移量
旋转cv2.getRotationMatrix2D(center, angle, scale)中心点、角度、缩放
缩放[[sx, 0, 0], [0, sy, 0]]sx, sy 为缩放因子
倾斜[[1, shx, 0], [shy, 1, 0]]shx, shy 为倾斜因子
组合变换M = M1 × M2矩阵乘法组合多个变换
import cv2
import numpy as np
 
# 读取两张相同尺寸的图像
img = cv2.imread("image1.jpg")  # 替换为你的图片路径
 
# 检查图像是否成功读取
if img is None:
    print("错误:无法读取图像文件")
    exit()
# x移动200px,y移动150px
M = np.float32([[1, 0, 200], [0, 1, 150]])  # 平移矩阵
result = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]))
 
# 显示结果
cv2.imshow("Image Translation", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像旋转

调用cv.getRotationMatrix2D获取旋转矩阵,然后调用cv.warpAffine()进行旋转。

# 生成旋转矩阵
retval = cv2.getRotationMatrix2D(center, angle, scale)
参数类型描述
centertuple (x, y)旋转中心点坐标
anglefloat旋转角度(度),逆时针为正
scalefloat缩放比例 (1.0 = 保持原大小)

返回值:retval: 2×3 仿射变换矩阵 (numpy.ndarray, dtype=float64)

此时M:[[  0.70710678   0.70710678 -50.33008589]
               [ -0.70710678   0.70710678 418.49242405]]

import cv2
 
# 读取两张相同尺寸的图像
img = cv2.imread("image1.jpg")  # 替换为你的图片路径
 
# 检查图像是否成功读取
if img is None:
    print("错误:无法读取图像文件")
    exit()
# 旋转中心,旋转角度,缩放因子
M = cv2.getRotationMatrix2D((img.shape[1] / 2, img.shape[0] / 2), 45, 1)  # 旋转矩阵
# 进行旋转
result = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]))
 
# 显示结果
cv2.imshow("Image Rotation", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

仿射变换

调用getAffineTransform将创建变换矩阵,最后该矩阵传递给cv.warpAffine()进行变换。

# 通过三对对应点建立源图像与目标图像之间的几何映射关系
M = cv2.getAffineTransform(src, dst)
参数类型描述
srcnumpy.ndarray (3×2)源图像中的三个点坐标 (float32)
dstnumpy.ndarray (3×2)目标图像中的三个对应点坐标 (float32)

 返回值:M: 2×3 仿射变换矩阵 (numpy.ndarray, dtype=float64)

此时M:[[  1.26666667   0.6        -83.33333333]
               [ -0.33333333   1.          66.66666667]]

import cv2
import numpy as np
 
# 读取两张相同尺寸的图像
img = cv2.imread("image1.jpg")  # 替换为你的图片路径
 
# 检查图像是否成功读取
if img is None:
    print("错误:无法读取图像文件")
    exit()
 
# 定义源图像和目标图像的顶点
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
# 计算仿射变换矩阵
M = cv2.getAffineTransform(pts1, pts2)
# 进行仿射变换
result = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]))
 
# 显示结果
cv2.imshow("Affine Transformation", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

透射变换

通过函数getPerspectiveTransform()找到变换矩阵,将cv.warpPerspective()进行投射变换。

M = cv2.getPerspectiveTransform(src, dst[, solveMethod])
参数类型描述
srcnumpy.ndarray (4×2)源图像中的四个点坐标 (float32)
dstnumpy.ndarray (4×2)目标图像中的四个对应点坐标 (float32)
solveMethodint矩阵求解方法 (默认 DECOMP_LU)

 此时T:[[ 1.05587376e+00  9.18151097e-02 -6.50969128e+01]
               [ 4.69010049e-02  1.12562412e+00 -7.57920240e+01]
               [ 1.83251448e-04  5.13337001e-04  1.00000000e+00]]

dst = cv2.warpPerspective(
    src, 
    M, 
    dsize, 
    dst=None, 
    flags=cv2.INTER_LINEAR, 
    borderMode=cv2.BORDER_CONSTANT, 
    borderValue=0
)
参数类型描述默认值
srcnumpy.ndarray输入图像 (单通道或多通道)-
Mnumpy.ndarray (3×3)透 视变换矩阵 (单应性矩阵)-
dsizetuple输出图像尺寸 (width, height)-
dstnumpy.ndarray输出图像 (预分配内存)None
flagsint插值方法 + 可选标志INTER_LINEAR
borderModeint边界处理模式BORDER_CONSTANT
borderValuescalar边界填充值0
import cv2
import numpy as np
 
# 读取两张相同尺寸的图像
img = cv2.imread("image1.jpg")  # 替换为你的图片路径
 
# 检查图像是否成功读取
if img is None:
    print("错误:无法读取图像文件")
    exit()
# 透 视变换
# 定义源点
pts1=np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
# 定义目标点
pts2=np.float32([[0, 0], [300, 0], [0, 300], [300, 300]])
# 获取透 视变换矩阵
T=cv2.getPerspectiveTransform(pts1, pts2)
 
result = cv2.warpPerspective(img, T, (img.shape[1], img.shape[0]))
 
# 显示结果
cv2.imshow("Transmission Transformation", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

图像金字塔

向上采样:cv.pyrUp()

向下采样:cv.pyrDown()

dst = cv2.pyrUp(
    src, 
    dst=None, 
    dstsize=None, 
    borderType=cv2.BORDER_DEFAULT
)
 
dst = cv2.pyrDown(
    src, 
    dst=None, 
    dstsize=None, 
    borderType=cv2.BORDER_DEFAULT
)
参数类型描述默认值
srcnumpy.ndarray输入图像-
dstnumpy.ndarray输出图像 (可选)None
dstsizetuple输出图像大小 (width, height)None
borderTypeint边界填充类型cv2.BORDER_DEFAULT
import cv2
import numpy as np
 
# 读取两张相同尺寸的图像
img = cv2.imread("image1.jpg")  # 替换为你的图片路径
 
# 检查图像是否成功读取
if img is None:
    print("错误:无法读取图像文件")
    exit()
 
up_img = cv2.pyrUp(img)  # 上采样
down_img = cv2.pyrDown(img)  # 下采样
 
# 显示结果
cv2.imshow("enlarge", up_img)
cv2.imshow("Image Pyramid", img)
cv2.imshow("shrink", down_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

特性图像金字塔图像缩放
目的创建多尺度表示用于特征分析改变图像尺寸以适应特定需求
输出一组不同尺度的图像序列单一尺寸的图像
数学基础高斯平滑+下采样/上采样插值算法
可逆性不可逆(信息损失)部分可逆(取决于算法)
典型应用多尺度特征检测、图像融合显示适配、预处理、存储优化
OpenCV函数pyrUp()pyrDown()resize()

以上就是使用Python进行图像几何变换的操作流程的详细内容,更多关于Python图像几何变换的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文