【OpenCV入门】第七部分——图像的几何变换

这篇具有很好参考价值的文章主要介绍了【OpenCV入门】第七部分——图像的几何变换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

缩放

通过resize()方法可以随意更改图像的大小比例:

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

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

dsize参数实现缩放

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

实例1: 将图像按照指定宽高进行缩放

import cv2

img = cv2.imread("3.png")  # 读取图像
dst1 = cv2.resize(img, (100, 100))  # 按照宽100像素、高100像素的大小进行缩放
dst2 = cv2.resize(img, (400, 400))  # 按照宽400像素、高400像素的大小进行缩放
cv2.imshow("img", img)  # 显示原图
cv2.imshow("dst1", dst1)  # 显示缩放图像
cv2.imshow("dst2", dst2)
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法

fx参数和fy参数实现缩放

使用fx参数和fy参数控制缩放时,dsize参数值必须使用None,否则fx和fy会失效。fx参数和fy参数可以使用浮点值,小于1的值表示缩小,大于1的值表示放大。其计算公式为:

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

实例2: 将图像按照指定比例进行缩放

import cv2

img = cv2.imread("3.png")  # 读取图像
# 将宽缩小到原来的1/3、高缩小到原来的1/2
dst3 = cv2.resize(img, None, fx=1/3, fy=1/2)
dst4 = cv2.resize(img, None, fx=1.5, fy=1.5)  # 将宽高扩大1.5倍
cv2.imshow("img", img)  # 显示原图
cv2.imshow("dst3", dst3)  # 显示缩放图像
cv2.imshow("dst4", dst4)  # 显示缩放图像
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法

翻转

水平方向被称为X轴,垂直方向被称为Y轴。图像沿着X轴或者Y轴反转之后,可以呈现出镜面倒影的效果。

dst = cv2.flip(src, flipCode)
  • src: 原始图像
  • flipCode: 翻转类型
  • dst: 翻转之后的图像

flipCode参数值及含义:

参数值 含义
0 沿着X轴翻转
正数 沿着Y轴翻转
负数 同时沿着X轴、Y轴翻转

实例3: 同时实现三种翻转效果

import cv2

img = cv2.imread("3.png")  # 读取图像
dst1 = cv2.flip(img, 0)  # 沿X轴翻转
dst2 = cv2.flip(img, 1)  # 沿Y轴翻转
dst3 = cv2.flip(img, -1)  # 同时沿X轴、Y轴翻转
cv2.imshow("img", img)  # 显示原图
cv2.imshow("dst1", dst1)  # 显示翻转之后的图像
cv2.imshow("dst2", dst2)
cv2.imshow("dst3", dst3)
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法

仿射变换

仿射变换是一种仅在二维平面中发生的几何变形,变换之后的图像仍然可以保持直线的“平直性”和“平行性”,包含平移、旋转和倾斜。

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法

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

M也被叫作仿射矩阵,实际上就是一个2x3的列表,其格式如下所示:

M = [[a, b, c], [d, e, f]]

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

  • 新x = 原x × a + 原y × b + c
  • 新y = 原x × d + 原y × e + f

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

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

通过设定M的值就可以实现多种仿射效果

平移

平移就是让图像中所有的像素同时沿着水平或垂直方向移动。实现这种效果只需要将M的值按照以下格式进行设置:

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

原始图像的像素就会按照以下公式进行变换:

  • 新x = 原x × 1 + 原y × 0 + 水平移动的距离
  • 新y = 原x × 0 + 原y × 1 + 垂直移动的距离

实例4: 让图像向右下方平移

import cv2
import numpy as np

img = cv2.imread("3.png")  # 读取图像
rows = len(img)  # 图像像素行数
cols = len(img[0])  # 图像像素列数
M = np.float32([[1, 0, 50],  # 横坐标向右移动50像素
                [0, 1, 100]])  # 纵坐标向下移动100像素
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow("img", img)  # 显示原图
cv2.imshow("dst", dst)  # 显示仿射变换效果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法

旋转

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

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

实例5: 让图像逆时针旋转

import cv2

img = cv2.imread("3.png")  # 读取图像
rows = len(img)  # 图像像素行数
cols = len(img[0])  # 图像像素列数
center = (rows/2, cols/2)  # 图像的中心点
# 以图像为中心,逆时针旋转30度,缩放0.8倍
M = cv2.getRotationMatrix2D(center, 30, 0.8)
dst = cv2.warpAffine(img, M, (cols, rows))  # 按照M进行仿射
cv2.imshow("img", img)  # 显示原图
cv2.imshow("dst", dst)  # 显示仿射变换效果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法

倾斜

OpenCV需要定位图像的三个点来计算倾斜效果,三个点的位置如下图所示:
【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法
OpenCV会根据这三个点的位置变化来计算其他像素的位置变化。因为要保证图像的“平直性”和“平行性”,所以不需要“右下角”的点做第四个参数,右下角这个点的位置会根据 A、B、C 三点的变化自动计算得出。

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

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

实例6: 让图像向右倾斜

import cv2
import numpy as np

img = cv2.imread("3.png")  # 读取图像
rows = len(img)  # 图像像素行数
cols = len(img[0])  # 图像像素列数
p1 = np.zeros((3, 2), np.float32)  # 32位浮点型空列表,原图三个点
p1[0] = [0, 0]  # 左上角点坐标
p1[1] = [cols - 1, 0]  # 右上角点坐标
p1[2] = [0, rows - 1]  # 左下角点坐标
p2 = np.zeros((3, 2), np.float32)  # 32位浮点型空列表,倾斜图三个点
p2[0] = [50, 0]  # 左上角点坐标,向右挪50像素
p2[1] = [cols - 1, 0]  # 右上角点坐标,位置不变
p2[2] = [0, rows - 1]  # 左下角点坐标,位置不变
M = cv2.getAffineTransform(p1, p2)  # 根据三个点的变化轨迹计算出M矩阵
dst = cv2.warpAffine(img, M, (cols, rows))  # 按照M进行仿射
cv2.imshow("img", img)  # 显示原图
cv2.imshow("dst", dst)  # 显示仿射变换效果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法
想让图像向左倾斜,不能通过移动A点来实现,需要通过移动B点和C点来实现:

p1 = np.zeros((3, 2), np.float32)  # 32位浮点型空列表,原图三个点
p1[0] = [0, 0]  # 左上角点坐标
p1[1] = [cols - 1, 0]  # 右上角点坐标
p1[2] = [0, rows - 1]  # 左下角点坐标
p2 = np.zeros((3, 2), np.float32)  # 32位浮点型空列表,倾斜图三个点
p2[0] = [0, 0]  # 左上角点坐标,位置不变
p2[1] = [cols - 1 - 50, 0]  # 右上角点坐标,向左移动50像素
p2[2] = [50, rows - 1]  # 左下角点坐标,向右移动50像素

透视

如果说仿射是让图像在二维平面中变形,那么透视就是让图像在三维空间中变形。从不同的角度观察物体,会看到不同的变形画面,例如矩形会变成不规则的四边形、直角会变成锐角或钝角、圆形会变成椭圆等。这种变形之后的画面就是透视图。

如图 8.24 所示从图像的底部去观察图 8.25 的话,图像底部距离眼睛较近,所以宽度不变。但图像顶部距离眼睛较远,宽度就会等比缩小,于是观察者就会看到如图 8.26 所示的透视效果。

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法
OpenCV中需要通过定位图像的四个点来计算透视效果,四个点的位置如下图所示。OpenCV会根据这四个点的位置变化计算出其他像素的位置变化。透视效果不能保证图像的“平直性”和“平行性”。

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法

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

warpPerspective() 方法也需要通过 M矩阵来计算透视效果,但得出这个矩阵需要做很复杂的运算,于是OpenCV 提供了getPerspectiveTransform() 方法来自动计算M矩阵。

M = cv2.getPerspectiveTransform(src, dst)
  • src: 原图四个点坐标,格式为4行2列的32位浮点数列表,例如[[0,0],[0,1],[1,0][1,1]]
  • dst: 透视图的四个点坐标,格式与 src一样
  • M: 方法计算出的仿射矩阵

实例7: 模拟从底部观察图像得到的透视效果

import cv2
import numpy as np

img = cv2.imread("demo.png")  # 读取图像
rows = len(img)  # 图像像素行数
cols = len(img[0])  # 图像像素列数
p1 = np.zeros((4, 2), np.float32)  # 32位浮点型空列表,保存原图四个点
p1[0] = [0, 0]  # 左上角点坐标
p1[1] = [cols - 1, 0]  # 右上角点坐标
p1[2] = [0, rows - 1]  # 左下角点坐标
p1[3] = [cols - 1, rows - 1]  # 右下角点坐标
p2 = np.zeros((4, 2), np.float32)  # 32位浮点型空列表,保存透视图四个点
p2[0] = [90, 0]  # 左上角点坐标,向右移动90像素
p2[1] = [cols - 90, 0]  # 右上角点坐标,向左移动90像素
p2[2] = [0, rows - 1]  # 左下角点坐标,位置不变
p2[3] = [cols - 1, rows - 1]  # 右下角点坐标,位置不变
M = cv2.getPerspectiveTransform(p1, p2)  # 根据四个点的变化轨迹计算出M矩阵
dst = cv2.warpPerspective(img, M, (cols, rows))  # 按照M进行仿射
cv2.imshow("img", img)  # 显示原图
cv2.imshow("dst", dst)  # 显示仿射变换效果
cv2.waitKey()  # 按下任何键盘按键后
cv2.destroyAllWindows()  # 释放所有窗体

结果如下:
【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法

** 实例8:** 生成图书封面俯视图

import cv2
import numpy as np

w, h = 320, 480 # 俯视图的宽高
img = cv2.imread("book.jpg") # 读取原图
tmp = cv2.GaussianBlur(img, (5, 5), 0) # 高斯滤波
tmp = cv2.Canny(tmp, 50, 120) # 变为二值边缘图像
# 闭运算,保证边缘闭合
tmp = cv2.morphologyEx(tmp, cv2.MORPH_CLOSE, (15, 15), iterations=2)
# 检测轮廓
contours, _ = cv2.findContours(tmp, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours: # 遍历所有轮廓
    area = cv2.contourArea(c) # 计算轮廓面积
    if area > 10000: # 只处理面积廓大于10000的轮廓
        length = cv2.arcLength(c, True) # 获取轮廓周长
        approx = cv2.approxPolyDP(c, 0.02 * length, True) # 计算出轮廓的端点
        pts1 = np.float32(approx) # 轮廓四个端点的坐标
        pts2 = np.float32([[w, 0], [0, 0], [0, h], [w, h]]) # 正面图对应的四个端点坐标
        M = cv2.getPerspectiveTransform(pts1, pts2) # 创建透视图M矩阵
        tmp = cv2.warpPerspective(img, M, (w, h)) # 根据M矩阵做透视变换
cv2.imshow("img", img) # 展示原图
cv2.imshow("Top view", tmp) # 展示俯视图
cv2.waitKey() # 按下任何按键后
cv2.destroyAllWindows() # 释放所有窗体

结果如下:

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法

cmath模块

除了前述 OpenCV 提供的用于对图像进行几何变换的方法外,借助 Python 中的 cmath模块也能让图像呈现特定的视觉效果。例如让图像呈现波浪效果等。

通过 Python 中的 cmath 模块就能够让图像呈现波浪效果。cmath 模块提供了数学函数在复数域上扩展的运算函数,这些函数允许复数、整数、浮点数等数据类型的数据输入,因此这些函数的返回值也都是复数。要特别注意的是,组成复数的实部和虚部都是浮点数。

这里要用到的是 cmath 模块中用于返回指定弧度的正弦值的 sin()方法

cmath.sin(x)
  • x: 与指定角度对应的弧度

在 cmath 模块中的 sin()方法中,还可以设置与正弦函数对应的正弦图像的振幅和波长。例如把一幅图像的列像素 col 作为弧度,设置与正弦函数对应的正弦图像的振幅为 20、波长为30的关键代码如下所示:

20 * cmath.sin(col/15) # 15是一半的波长

实例9: 呈现波浪效果的图像

import cv2
import numpy as np
import cmath

img = cv2.imread("rice.jpg") # 读取当前项目目录下的图像
shape = img.shape # 获取图像的行像素、列像素和通道数
rows = shape[0] # 获取图像的行像素
columns = shape[1] # 获取图像的列像素
channel = shape[2] # 获取图像的通道数
# 创建了一个行像素与图像的行像素相同,列像素与图像的列像素相同,具有3个通道的画布
canvas = np.zeros([rows, columns, channel], np.uint8)
for row in range(rows): # 遍历图像的行像素
    for col in range(columns): # 遍历图像的列像素
        # 20是波的振幅,15是一半的波长
        # 根据正弦函数计算每个像素点的横坐标移动后的位置
        i = row + 20 * cmath.sin(col/15)
        i = round(np.real(i))  # 将复数结果转为实数,并四舍五入
        if 0 <= i < rows:  # 如果移动后的像素点仍在画布范围内
            canvas[i, col] = img[row, col] # 将原图像的像素点存放到与画布对应的像素点上
cv2.imshow("wave", canvas) # 在一个名为“wave”的窗口中显示呈现波浪效果的图像
cv2.waitKey() # 通过按下键盘上的按键
cv2.destroyAllWindows() # 销毁正在显示的窗口

结果如下:

【OpenCV入门】第七部分——图像的几何变换,OpenCV,opencv,计算机视觉,人工智能,numpy,图像处理,算法文章来源地址https://www.toymoban.com/news/detail-691964.html

到了这里,关于【OpenCV入门】第七部分——图像的几何变换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【OpenCV • c++】图像几何变换 | 图像缩放

    🚀 个人简介:CSDN「 博客新星 」TOP 10 , C/C++ 领域新星创作者 💟 作    者: 锡兰_CC ❣️ 📝 专    栏: 【OpenCV • c++】计算机视觉 🌈 若有帮助,还请 关注➕点赞➕收藏 ,不行的话我再努努力💪💪💪

    2024年02月16日
    浏览(42)
  • 【OpenCV • c++】图像几何变换 | 图像平移

    🚀 个人简介:CSDN「 博客新星 」TOP 10 , C/C++ 领域新星创作者 💟 作    者: 锡兰_CC ❣️ 📝 专    栏: 【OpenCV • c++】计算机视觉 🌈 若有帮助,还请 关注➕点赞➕收藏 ,不行的话我再努努力💪💪💪

    2024年02月16日
    浏览(25)
  • 【OpenCV • c++】图像几何变换 | 图像坐标映射

    🚀 个人简介:CSDN「 博客新星 」TOP 10 , C/C++ 领域新星创作者 💟 作    者: 锡兰_CC ❣️ 📝 专    栏: 【OpenCV • c++】计算机视觉 🌈 若有帮助,还请 关注➕点赞➕收藏 ,不行的话我再努努力💪💪💪   图像的几何变换是指在不改变图像像素值的前提下对图像像素进

    2024年02月12日
    浏览(36)
  • OpenCV:第七章、图像变换

    目录 第七章:图像变换 7.1、基于OpenCV的边缘检测 7.1.1、一般步骤 1、滤波 2、增强 3、检测 7.1.2、canny算子 1、canny算子简介 2、canny边缘检测的步骤 7.2、霍夫变换  7.2.2、OpenCV中的霍夫线变换 7.2.3、霍夫线变换原理        7.2.4、标准霍夫变换:HoughLines()函数    7.2.5、累计概率

    2024年02月03日
    浏览(60)
  • Python-OpenCV中的图像处理-几何变换

    对图像进行各种几个变换,例如移动,旋转,仿射变换等。 cv2.resize() cv2.INTER_AREA v2.INTER_CUBIC v2.INTER_LINEAR res = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC) 或 height, width = img.shape[:2] res = cv2.resize(img, (2 width, 2 height), interpolation=cv2.INTER_CUBIC) OpenCV提供了使用函数cv2.warpAffine()实

    2024年02月13日
    浏览(55)
  • Opencv-C++笔记 (16) : 几何变换 (图像的翻转(镜像),平移,旋转,仿射,透视变换)

    图像旋转是指图像按照某个位置转动一定的角度的过程,旋转中图像仍保持着原始尺寸。图像旋转后图像水平对称轴、垂直对称轴及中心坐标原点都可能会发生变换,因此需要对图像旋转中的坐标进行相应转换。 假设有一个点:P(x,y),它在绕原点 O(0,0) 旋转 β 后,被转换成

    2024年02月14日
    浏览(38)
  • opencv-25 图像几何变换04- 透视 cv2.warpPerspective()

    透视是一种几何学概念,用于描述在三维空间中观察物体时,由于视角的不同而产生的变形效果。在现实世界中,当我们从不同的角度或位置观察物体时,它们会呈现出不同的形状和大小。这种现象被称为透视效果。 透视效果主要由以下几个因素造成: 远近关系 :在视野范

    2024年02月15日
    浏览(35)
  • opencv-23 图像几何变换02-翻转-cv2.flip()

    在 OpenCV 中,图像的翻转采用函数 cv2.flip()实现 ,该函数能够实现图像在水平方向翻转、垂直方向翻转、两个方向同时翻转,其语法结构为: 式中:  dst 代表和原始图像具有同样大小、类型的目标图像。  src 代表要处理的原始图像。  flipCode 代表旋转类型。该参数的意

    2024年02月15日
    浏览(31)
  • opencv-24 图像几何变换03-仿射-cv2.warpAffine()

    仿射变换是指图像可以通过一系列的几何变换来实现平移、旋转等多种操作。该变换能够 保持图像的平直性和平行性。平直性是指图像经过仿射变换后,直线仍然是直线;平行性是指 图像在完成仿射变换后,平行线仍然是平行线。 OpenCV 中的仿射函数为 cv2.warpAffine(),其通过

    2024年02月15日
    浏览(34)
  • OpenCV-Python学习(21)—— OpenCV 图像几何变换之图像翻转(cv.flip、np.flip)

    1. 学习目标 学习 OpenCV 图像的翻转函数 cv.flip; 学习 NumPy 矩阵的反转函数 np.flip; 自己实现矩阵反转的函数。 2. OpenCV 翻转 翻转也称镜像,是指将图像沿轴线进行轴对称变换。水平镜像是将图像沿垂直中轴线进行左右翻转,垂直镜像是将图像沿水平中轴线进行上下翻转,水平

    2024年02月06日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包