OpencvDay2-图像预处理(一)

目录

一、图像色彩空间转换

1、RGB颜色空间

2、颜色加法

3、颜色加权加法

4、HSV颜色空间

5、图像颜色转换(RGB转Gray(灰度)、HSV等)

二、灰度

1、灰度图

2、最大值法

​3、平均值法

4、加权均值法

5、 两个极端的灰度值

6、结果对比分析

 三、图像二值化处理

1、二值图像

2、阈值法(THRESH_BINARY)

原理:

3、 反阈值法(THRESH_BINARY_INV)

原理:

4、截断阈值法 (THRESH_TRUNC)

原理:

 5、低阈值零处理(THRESH_TOZERO)

原理:

 6、超阈值零处理(THRESH_TOZERO_INV)

原理:

7、OSTU阈值法(自动计算阈值)

1)双峰图片:

2)原理:

8、 自适应二值化(Adaptive Threshold)

原理:

1)取均值法 (cv2.ADAPTIVE_THRESH_MEAN_C:局部均值减去常数C)

 2) 加权求和 (cv2.ADAPTIVE_THRESH_GAUSSIAN_C:加权平均(高斯)减去常数C)

 四、图像翻转

五、图像仿射变换

cv2.warpAffine()函数

常见仿射变换类型

5.1 图像旋转 

5.2 图像平移 

 5.3 图像缩放


一、图像色彩空间转换

OpenCV中,图像色彩空间转换是一个非常基础且重要的操作,就是将图像从一种颜色表示形式转换为另一种表示形式的过程。通过将图像从一个色彩空间转换到另一个色彩空间,可以更好地进行特定类型的图像处理和分析任务。常见的颜色空间包括RGB、HSV、YUV等。

  • 色彩空间转换的作用

    • 提高图像处理效果

    • 节省计算资源

1、RGB颜色空间

RGB(Red, Green, Blue)是最常见的颜色表示方式之一,它通过红、绿、蓝三种颜色的不同强度混合来表示其他颜色。

每个像素通常有三个分量(R、G、B),范围是 0~255:

  • (255, 0, 0) 表示纯红色

  • (0, 255, 0) 表示纯绿色

  • (0, 0, 255) 表示纯蓝色

  • (255, 255, 255) 表示白色

  • (0, 0, 0) 表示黑色

注意:在OpenCV中,颜色是以BGR的方式进行存储的,而不是RGB,这也是上面红色的像素值是(0,0,255)而不是(255,0,0)的原因。     

2、颜色加法

使用OpenCV的cv.add()函数把两幅图像相加,或者可以简单地通过numpy操作添加两个图像,如res = img1 + img2。两个图像应该具有相同的大小和类型。 将多个颜色值的 RGB 分量分别相加,形成新的颜色(常用于图像混合)

OpenCV加法和Numpy加法之间存在差异。OpenCV的加法是饱和操作,而Numpy添加是模运算。

import cv2 as cv
import numpy as np
# 图片读取
cao = cv.imread('../images/cao.png')
cat = cv.resize(cv.imread('../images/xiaomao.jpg'), (cao.shape[1], cao.shape[0]))
# 饱和操作 cv.add(img1, img2)  255饱和
dst1 = cv.add(cao, cat)
# numpy直接相加 取模运算 对256取模 250+10=4
dst2 = cao + cat

x = np.uint8([[250]])
y = np.uint8([[10]])
xy1 = cv.add(x, y) # 255
xy2 = x + y        # 4

注意:使用 cv2.add 是逐像素加法,超出 255 会被截断为 255,不会出现溢出。

3、颜色加权加法

加权加法是一种加法融合方式,即将两张图像按照一定权重合成,常用于透明度混合、图像淡入淡出等。

cv2.addWeighted(src1,alpha,src2,deta,gamma)
  • src1src2:输入图像。
  • alphabeta:两张图象权重。
  • gamma:亮度调整值。
    • gamma > 0,图像会变亮。
    • gamma < 0,图像会变暗。
    • gamma = 0,则没有额外的亮度调整。

公式为:dst = src1 * alpha + src2 * beta + gamma

示例:

# 颜色加权加法 cv.addWeighted(img1, alpha, img2, beta, gamma)
dst3 = cv.addWeighted(cao, 0.7,cat, 0.3, -100)
cv.imshow('dst3', dst3)

4、HSV颜色空间

HSV是另一种重要的颜色空间,全称为 Hue(色调)、Saturation(饱和度)和 Value(明度)。

HSV颜色空间指的是HSV颜色模型,这是一种与RGB颜色模型并列的颜色空间表示法。RGB颜色模型使用红、绿、蓝三原色的强度来表示颜色,是一种加色法模型,即颜色的混合是添加三原色的强度。而HSV颜色空间使用色调(Hue)、饱和度(Saturation)和亮度(Value)三个参数来表示颜色,色调H表示颜色的种类,如红色、绿色、蓝色等;饱和度表示颜色的纯度或强度,如红色越纯,饱和度就越高;亮度表示颜色的明暗程度,如黑色比白色亮度低。

HSV颜色模型是一种六角锥体模型,如下图所示:

为什么有了RGB颜色空间我们还是需要转换成HSV颜色空间来进行图像处理呢?

  • 降维处理有利于计算:在图像处理中,降维处理可以减少计算的复杂性和计算量。HSV颜色空间相对于RGB颜色空间,减少了两个维度(红、绿、蓝),这有利于进行一些计算和处理任务,比如色彩分割、匹配等。

因此,在进行图片颜色识别时,我们会将RGB图像转换到HSV颜色空间,然后根据颜色区间来识别目标颜色。

5、图像颜色转换(RGB转Gray(灰度)、HSV等)

cv2.cvtColor是OpenCV中的一个函数,用于图像颜色空间的转换。可以将一个图像从一个颜色空间转换为另一个颜色空间,比如从RGB到灰度图,或者从RGB到HSV的转换等。

cv.cvtColor(img,code)
  • img:输入图像,可以是一个Numpy数组绘着一个OpenCV的Mat对象

    • Mat 是一个核心的数据结构,主要用于存储图像和矩阵数据。在 Python 中使用 OpenCV 时,通常直接处理的是 NumPy 数组,cv2 模块自动将 Mat 对象转换为 NumPy 数组。二者之间的转换是透明且自动完成的。例如,当你使用 cv2.imread() 函数读取图像时,返回的是一个 NumPy 数组,但在C++中则是 Mat 对象。

  • code:指定转换的类型,可以使用预定义的转换代码。

    • 例如cv2.COLOR_RGB2GRAY表示从rgb到灰度图像的转换。

示例:

import cv2 as cv
img = cv.imread("../images/pig.png")
# 颜色转换 cv.cvtColor(src, code)
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
hsv = cv.cvtColor(img, cv.COLOR_BGR2HSV)
rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB)
cv.imshow("rgb", rgb)
cv.imshow("gray", gray)
cv.imshow("hsv", hsv)
cv.imshow("img", img)
cv.waitKey(0)
cv.destroyAllWindows()
  • 灰度图像是单通道图像,常用于图像处理的预处理步骤,例如边缘检测、图像增强等。
  • 将 RGB 图像转换为 HSV 可方便地基于颜色进行物体检测、抠图等。

二、灰度

在图像处理中,**灰度图(Grayscale Image)**是一种非常常见的图像形式。它只包含亮度信息,没有颜色信息,用单通道(通常是 0~255)来表示不同亮度。

1、灰度图

每个像素只有一个采样颜色的图像,这类图像通常显示为从最暗黑色到最亮的白色的灰度,尽管理论上这个采样可以任何颜色的不同深浅,甚至可以是不同亮度上的不同颜色。灰度图像与黑白图像不同,在计算机图像领域中黑白图像只有黑色与白色两种颜色;但是,灰度图像在黑色与白色之间还有许多级的颜色深度。灰度图像经常是在单个电磁波频谱如可见光内测量每个像素的亮度得到的,用于显示的灰度图像通常用每个采样像素8位的非线性尺度来保存,这样可以有256级灰度。

作用:

  • 降低计算复杂度

  • 更适合图像边缘、轮廓、纹理等处理任务

2、最大值法

对于彩色图像的每个像素,它会从R、G、B三个通道的值中选出最大的一个,并将其作为灰度图像中对应位置的像素值。

例如某图像中某像素点的像素值如上图所示,那么在使用最大值法进行灰度化时,就会从该像素点对应的RGB通道中选取最大的像素值作为灰度值,所以在灰度图中的对应位置上,该像素点的像素值就是121。

特点:

  • 灰度值偏亮,保留图像中最亮的颜色特征

  • 不考虑颜色的平衡性

示例:

import cv2 as cv
import numpy as np
# 读取图像
cat = cv.resize(cv.imread('../images/xiaomao.jpg'), (500, 500))
shape = cat.shape
img = np.zeros((shape[0],shape[1]),dtype=np.uint8)
# 循环遍历每一行
for i in range(shape[0]):
    for j in range(shape[1]):
        img[i, j] = max(cat[i, j, 0], cat[i, j, 1], cat[i, j, 2] )

cv. imshow('cat', img)
cv. waitKey(0)
cv. destroyAllWindows()

​3、平均值法

对于彩色图像的每个像素,它会将R、G、B三个通道的像素值全部加起来,然后再除以三,得到的平均值就是灰度图像中对应位置的像素值。

例如某图像中某像素点的像素值如上图所示,那么在使用平均值进行灰度化时,其计算结果就是(91+121+46)/3=86(对结果进行取整),所以在灰度图中的对应位置上,该像素点的像素值就是86。  

特点:

  • 简单直观,图像亮度中等

  • 对所有颜色通道一视同仁

示例:

import cv2 as cv
import numpy as np
# 读取图像
cat = cv.imread('../images/xiaomao.jpg')
shape = cat.shape
img = np.zeros((shape[0],shape[1]),dtype=np.uint8)
for i in range(shape[0]):
    for j in range(shape[1]):
        # int() 函数将浮点数转换为整型
        img[i, j] =np.uint8((int(cat[i, j, 0])+int(cat[i, j, 1])+int(cat[i, j, 2]))//3)

cv. imshow('cat', img)
cv. waitKey(0)
cv. destroyAllWindows()

4、加权均值法

 对于彩色图像的每个像素,它会按照一定的权重去乘以每个通道的像素值,并将其相加,得到最后的值就是灰度图像中对应位置的像素值。本次示范中,权重的比例为: R乘以0.299,G乘以0.587,B乘以0.114,这是经过大量实验得到的一个权重比例,也是一个比较常用的权重比例。

 例如某图像中某像素点的像素值如上图所示,那么在使用加权平均值进行灰度化时,其计算结果就是10*0.299+121*0.587+46*0.114=79。所以在灰度图中的对应位置上,该像素点的像素值就是79。

特点:

  • 最符合人眼视觉感知

  • 常用于图像处理的标准灰度转换方法

opencv内置默认使用加权法

gray_weighted = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # OpenCV默认使用加权法
cv2.imshow('Weighted Gray', gray_weighted)

示例:

import cv2 as cv
import numpy as np
# 读取图像
cat = cv.imread('../images/xiaomao.jpg')
shape = cat.shape
img = np.zeros((shape[0],shape[1]),dtype=np.uint8)
# 定义权重
wb,wg,wr = 0.114,0.587,0.299

for i in range(shape[0]):
    for j in range(shape[1]):
        img[i, j] = wb*cat[i,j,0]+wg*cat[i,j,1]+wr*cat[i,j,2]

cv. imshow('cat', img)
cv. waitKey(0)
cv. destroyAllWindows()

5、 两个极端的灰度值

最亮图像(全白):

white_img = np.full((300, 300), 255, dtype=np.uint8) cv2.imshow("White Image", white_img)

最暗图像(全黑):

black_img = np.zeros((300, 300), dtype=np.uint8) cv2.imshow("Black Image", black_img)

说明:

  • 最亮值(255)表示纯白,所有像素最大亮度

  • 最暗值(0)表示纯黑,所有像素最小亮度

6、结果对比分析

方法原理简述灰度效果特点
最大值法max(R,G,B)偏亮高亮保留明显
平均值法(R+G+B)/3中间亮度实现简单
加权均值法0.299R+0.587G+0.114B接近真实视觉推荐使用

 三、图像二值化处理

图像二值化是将图像中每个像素的值转换为两个可能的值之一(通常是0和255),以突出目标区域与背景之间的对比。它是图像分割和目标检测等高级任务的基础步骤。

1、二值图像

一幅二值图像的二维矩阵仅由0、1两个值构成,“0”代表黑色,“1”代白色。由于每一像素(矩阵中每一元素)取值仅有0、1两种可能,所以计算机中二值图像的数据类型通常为1个二进制位。二值图像通常用于文字、线条图的扫描识别(OCR)和掩膜图像的存储。

其操作的图像也必须是灰度图。也就是说,二值化的过程,就是将一张灰度图上的像素根据某种规则修改为0和maxval(maxval表示最大值,一般为255,显示白色)两种像素值,使图像呈现黑白的效果,能够帮助我们更好地分析图像中的形状、边缘和轮廓等特征。

  • 简便:降低计算量和计算需求,加快处理速度。
  • 节约资源:二值图像占用空间远小于彩色图。
  • 边缘检测:二值化常作为边缘检测的预处理步骤,因为简化后的图易于识别出轮廓和边界。
cv2.IMREAD_GRAYSCALEOpenCV 中用于指定图像加载模式的一个标志,它告诉函数以灰度格式读取图像。 

2、阈值法(THRESH_BINARY)

原理:

将像素值与指定阈值 T 比较:

  • 若像素值 > T,则设置为最大值(如255)
  • 否则设为0
# 阈值法 二值化
thresh, binary = cv.threshold(gray,127,255,cv.THRESH_BINARY)
cv.imshow('binary',binary)

3、 反阈值法(THRESH_BINARY_INV)

原理:

THRESH_BINARY 相反:

  • 若像素值 > T,设为 0
  • 否则设为最大值
# 反阈值法 二值化
_, binary_inv = cv.threshold(gray,127,255,cv.THRESH_BINARY_INV)
cv.imshow('binary_inv',binary_inv)

4、截断阈值法 (THRESH_TRUNC)

原理:

  • 像素值 > T,则设为 T
  • 否则保持原值
  • 换句话说,经过截断阈值法处理过的二值化图中的最大像素值就是阈值。
# 截断阈值法
_, binary_trunc = cv.threshold(gray,127,255,cv.THRESH_TRUNC)
cv.imshow('binary_trunc',binary_trunc)

 5、低阈值零处理(THRESH_TOZERO)

原理:

  • 像素值 > T,保持不变
  • 否则设为 0
# 低阈值零处理
_, zero = cv.threshold(gray,127,255,cv.THRESH_TOZERO)
cv.imshow('zero',zero)

 6、超阈值零处理(THRESH_TOZERO_INV)

原理:

  • 像素值 > T,设为 0
  • 否则保持不变
# 超阈值零处理
_, zero_inv = cv.threshold(gray,127,255,cv.THRESH_TOZERO_INV)
cv.imshow('zero_inv',zero_inv)

以上介绍的二值化方法都需要手动设置阈值,但是在不同的环境下,摄像头拍摄的图像可能存在差异,导致手动设置的阈值并不适用于所有图像,这可能会导致二值化效果不理想。

因此,我们需要一种能自动计算每张图片阈值的二值化方法,能够根据每张图像的特点自动计算出适合该图像的二值化阈值,从而达到更好的二值化效果。这种二值化方法可以在不同环境下适用,提高图像处理的准确性和鲁棒性。

7、OSTU阈值法(自动计算阈值)

1)双峰图片:

双峰图片就是指灰度图的直方图上有两个峰值,直方图就是对灰度图中每个像素值的点的个数的统计图,如下图所示。

灰度图直方图的基础概念

  1. 灰度级

    • 在灰度图像中,每个像素的值代表其亮度,通常范围是 0 到 255(对于 8 位灰度图像)。

    • 0 表示黑色,255 表示白色,中间的值表示不同程度的灰色。

  2. 直方图定义

    • 直方图是一个柱状图,其中 x 轴表示灰度级(从 0 到 255),y 轴表示对应灰度级在图像中出现的次数(频率)。

    • 每个柱子的高度代表该灰度级在图像中出现的像素数量。

2)原理:

OTSU(大津法)是一种自动寻找最佳阈值的算法。它假设图像由两个类(前景和背景)组成,并计算类间方差最大的阈值。适用于直方图双峰图像

THRESH_OTSU 本身并不是一个独立的阈值化方法,而是与 OpenCV 中的二值化方法结合使用的一个标志。具体来说,THRESH_OTSU 通常与 THRESH_BINARYTHRESH_BINARY_INV 结合使用。在实际应用中,如果你使用 THRESH_OTSU 标志但没有指定其他二值化类型,默认情况下它会与 THRESH_BINARY 结合使用。也就是说,当你仅指定了 cv2.THRESH_OTSU,实际上等同于同时指定了 cv2.THRESH_BINARY + cv2.THRESH_OTSU

OTSU算法是通过一个值将这张图分前景色和背景色(也就是灰度图中小于这个值的是一类,大于这个值的是一类。例如,如果你设置阈值为128,则所有大于128的像素点可以被视作前景,而小于等于128的像素点则被视为背景。),通过统计学方法(最大类间方差)来验证该值的合理性,当根据该值进行分割时,使用最大类间方差计算得到的值最大时,该值就是二值化算法中所需要的阈值。通常该值是从灰度图中的最小值加1开始进行迭代计算,直到灰度图中的最大像素值减1,然后把得到的最大类间方差值进行比较,来得到二值化的阈值。以下是一些符号规定:

下面举个例子,有一张大小为4×4的图片,假设阈值T为1,那么:

也就是这张图片根据阈值1分为了前景(像素为2的部分)和背景(像素为0)的部分,并且计算出了OTSU算法所需要的各个数据,根据上面的数据,我们给出计算类间方差的公式:

g就是前景与背景两类之间的方差,这个值越大,说明前景和背景的差别就越大,效果就越好。OTSU算法就是在灰度图的像素值范围内遍历阈值T,使得g最大,基本上双峰图片的阈值T在两峰之间的谷底。

通过OTSU算法得到阈值之后,就可以结合上面的方法根据该阈值进行二值化,在本实验中有THRESH_OTSU和THRESH_INV_OTSU两种方法,就是在计算出阈值后结合了阈值法和反阈值法。

注意:使用OTSU算法计算阈值时,组件中的thresh参数将不再有任何作用。

示例:

# otsu+阈值法  默认结合阈值法
thresh1, otsu = cv.threshold(gray,200,255,cv.THRESH_OTSU + cv.THRESH_BINARY)
cv.imshow('otsu',otsu)
# otsu+反阈值法
thresh2, otsu_inv = cv.threshold(gray,200,255,cv.THRESH_OTSU + cv.THRESH_BINARY_INV)
cv.imshow('otsu_inv',otsu_inv)

8、 自适应二值化(Adaptive Threshold)

原理:

将整张图像分成小区域,每个区域根据其局部均值或加权平均自动确定阈值。适合光照不均或背景复杂的图像。

与二值化算法相比,自适应二值化更加适合用在明暗分布不均的图片,因为图片的明暗不均,导致图片上的每一小部分都要使用不同的阈值进行二值化处理,这时候传统的二值化算法就无法满足我们的需求了,于是就出现了自适应二值化。

自适应二值化方法会对图像中的所有像素点计算其各自的阈值,这样能够更好的保留图片里的一些信息。

cv2.adaptiveThreshold(image_np_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 7, 10)

1)取均值法 (cv2.ADAPTIVE_THRESH_MEAN_C:局部均值减去常数C)

自适应二值化(Adaptive Thresholding)的核心思想就是为图像中的每个像素点计算一个局部阈值。这种方法与全局阈值化不同,后者对整个图像使用同一个固定的阈值。而在自适应二值化中,每个像素的阈值是基于其周围邻域内的像素值动态确定的。

示例:

auto =cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 11, 2)
cv.imshow('auto',auto)

 2) 加权求和 (cv2.ADAPTIVE_THRESH_GAUSSIAN_C:加权平均(高斯)减去常数C)

对小区域内的像素进行加权求和得到新的阈值,其权重值来自于高斯分布。

高斯分布,通过概率密度函数来定义高斯分布,一维高斯概率分布函数为:

通过改变函数中和的值,我们可以得到如下图像,其中均值为λ,标准差为σ**2。

此时我们拓展到二维图像,一般情况下我们使x轴和y轴的相等并且,此时我们可以得到二维高斯函数的表达式为:

高斯概率函数是相对于二维坐标产生的,其中(x,y)为点坐标,要得到一个高斯滤波器模板,应先对高斯函数进行离散化,将得到的值作为模板的系数。例如:要产生一个3*3的高斯权重核,以核的中心位置为坐标原点进行取样,其周围的坐标如下图所示(x轴水平向右,y轴竖直向上)

将坐标带入上面的公式中,即可得到一个高斯权重核。

而在opencv里,当kernel(小区域)的尺寸为1、3、5、7并且用户没有设置sigma的时候(sigma <= 0),核值就会取固定的系数,这是一种默认的值是高斯函数的近似。

首先还是对边界进行填充,然后计算原图中的左上角(也就是162像素值的位置)的二值化阈值,其计算过程如上图所示,再然后根据选择的二值化方法对左上角的像素点进行二值化,之后核向右继续计算第二个像素点的阈值,第三个像素点的阈值…直到右下角(也就是155像素值的位置)为止。

当核的大小不同时,仅仅是核的参数会发生变化,计算过程与此是一样的。

cv2.adaptiveThreshold参数解释:

1. image_np_gray: 输入图像,这里必须是灰度图像(单通道)。

2. 255: 输出图像的最大值。在二值化后,超过自适应阈值的像素会被设置为该最大值,通常为255表示白色;未超过阈值的像素将被设置为0,表示黑色。

3. cv2.ADAPTIVE_THRESH_GAUSSIAN_C: 自适应阈值类型。在这个例子中,使用的是高斯加权的累计分布函数(CDF),并添加一个常数 C 来计算阈值。另一种可选类型是 cv2.ADAPTIVE_THRESH_MEAN_C,它使用邻域内的平均值加上常数 C 计算阈值。

4. cv2.THRESH_BINARY: 输出图像的类型。这意味着输出图像将会是一个二值图像(binary image),其中每个像素要么是0要么是最大值(在这里是255)。另外还有其他选项如 cv2.THRESH_BINARY_INV 会得到相反的二值图像。

5. 7: blockSize 参数,表示计算每个像素阈值时所考虑的7x7邻域大小(正方形区域的宽度和高度),其值必须是奇数。

6. 10: C 参数,即上面提到的常数值,在计算自适应阈值时与平均值或高斯加权值相加。正值增加阈值,负值降低阈值,具体效果取决于应用场景。

示例:

# 自适应二值化 小区域计算 必须且只能结合阈值法或反阈值法其中一个
auto =cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 11, 2)
cv.imshow('auto',auto)
auto_gauss = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 11, 2)
cv.imshow('auto_gauss',auto_gauss)

 四、图像翻转

在OpenCV中,图片的镜像旋转是以图像的中心为原点进行镜像翻转的。

  • cv2.flip(img,flipcode)

  • 参数

    • img: 要翻转的图像

    • flipcode: 指定翻转类型的标志

      • flipcode=0: 垂直翻转,图片像素点沿x轴翻转

      • flipcode>0: 水平翻转,图片像素点沿y轴翻转

      • flipcode<0: 水平垂直翻转,水平翻转和垂直翻转的结合

import cv2 as cv
# cv.flip(img, flag) 翻转图片
img = cv.resize(cv.imread("../images/1.jpg"), (480,480))
# flag = 0 垂直翻转
# flag = 1 水平翻转
# flag = -1 水平垂直翻转
img_flip = cv.flip(img, 0)
img_flip1 = cv.flip(img, 1)
img_flip2 = cv.flip(img, -1)
cv.imshow("img", img)
cv.imshow("img_flip", img_flip)
cv.imshow("img_flip1", img_flip1)
cv.imshow("img_flip2", img_flip2)
cv.waitKey(0)
cv.destroyAllWindows()

五、图像仿射变换

仿射变换(Affine Transformation)是一种线性变换,保持了点之间的相对距离不变。

  • 仿射变换的基本性质

    • 保持直线

    • 保持平行

    • 比例不变性

    • 不保持角度和长度

  • 常见的仿射变换类型

    • 旋转:绕着某个点或轴旋转一定角度。

    • 平移:仅改变物体的位置,不改变其形状和大小。

    • 缩放:改变物体的大小。

    • 剪切:使物体发生倾斜变形。

仿射变换的基本原理

  • 线性变换

  • 二维空间中,图像点坐标为(x,y),仿射变换的目标是将这些点映射到新的位置 (x', y')。

  • 为了实现这种映射,通常会使用一个矩阵乘法的形式:

    (类似于y=kx+b)

  • a,b,c,d:线性变换矩阵,控制旋转、缩放、剪切等

  • tx,ty:平移变换

    • t_x,t_y 是平移部分的系数,控制图像在平面上的移动。

    • 输入点的坐标被扩展为齐次坐标形式[x,y,1],以便能够同时处理线性变换和平移

cv2.warpAffine()函数

cv2.warpAffine(img,M,dsize)
  • img:输入图像。
  • M:2x3的变换矩阵,类型为np.float32
  • dsize:输出图像的尺寸,形式为(width,height)

常见仿射变换类型

类型描述
平移将图像位置平移
缩放改变图像大小
旋转围绕中心或任意点旋转
剪切将图像拉伸为平行四边形
镜像水平或垂直翻转图像

5.1 图像旋转 

旋转图像可以将图像绕着某个点旋转一定的角度。

cv2.getRotationMatrix2D()函数

cv2.getRotationMatrix2D(center,angle,scale)

  • center:旋转中心点的坐标,格式为(x,y)

  • angle:旋转角度,单位为度,正值表示逆时针旋转负值表示顺时针旋转。

  • scale:缩放比例,若设为1,则不缩放。

  • 返回值M,2x3的旋转矩阵。

示例:

import cv2 as cv
cat = cv.imread("../images/1.jpg")
# 获取旋转矩阵 cv.getRotationMatrix2D(旋转中心点,旋转角度,缩放比例)
M = cv.getRotationMatrix2D((300,400),-45,1)
# 仿射变换函数 cv.warpAffine(src, M, (width, height))
dst = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]))
cv.imshow("cat", cat)
cv.imshow("dst", dst)

cv.waitKey(0)
cv.destroyAllWindows()

5.2 图像平移 

可以将图像中的每个点沿着某个方向移动一定的距离。

  • 假设我们有一个点 P(x,y),希望将其沿x轴方向平移t_x*个单位,沿y轴方向平移t_y个单位到新的位置P′(x′,y′),那么平移公式如下:

在矩阵形式下,该变换可以表示为:

这里的t_x和t_y分别代表在x轴和y轴上的平移量。  

示例:

import cv2 as cv
import numpy as np

cat =cv.resize(cv.imread("../images/xiaomao.jpg"),(500,500))
# 定义平移量
tx,ty = 100,100
# 获取平移矩阵
M = np.float32([[1, 0, tx], [0, 1, ty]])
# 进行平移
dst = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]))

cv.imshow("cat", cat)
cv.imshow("dst", dst)
cv.waitKey(0)
cv.destroyAllWindows()

 5.3 图像缩放

缩放操作可以改变图片的大小。

  • 假设要把图像的宽高分别缩放为0.5和0.8,那么对应的缩放因子sx=0.5,sy=0.8。

  • 点P(x,y)对应到新的位置P'(x',y'),缩放公式为:

    x′=s_x*x

    y′=s_y*y

    在矩阵形式下,该变换可以表示为:

相较于图像旋转中只能等比例的缩放,图像缩放更加灵活,可以在指定方向上进行缩放。

示例:

import cv2 as cv
import numpy as np

cat =cv.resize(cv.imread("../images/xiaomao.jpg"),(500,500))
# 定义平移量
sx,sy = 0.5,0.5
tx,ty = 100,100
# 获取缩放矩阵
M = np.float32([[sx, 0, tx],[0, sy, ty]])

# 进行缩放
dst = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]))

cv.imshow("cat", cat)
cv.imshow("dst", dst)
cv.waitKey(0)
cv.destroyAllWindows()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值