ROI切割:
在读取一个图像的时候,我们可能只对图像中的某一区域感兴趣,所以我们可以把需要的部分单独截取出来,这样还可以运算速度。
在计算机视觉领域,使用OpenCV读取RGB图像时会将其转换为三维Numpy数组。该数组中的每个数值对应图像的一个像素值:第一维(轴0)表示图像高度,第二维(轴1)表示宽度,第三维(轴2)则对应BGR三个颜色通道的像素值(需注意OpenCV默认以BGR顺序存储图像),因此我们可以通过设置切片范围来选取特定高度和宽度区域,获取该区域内的所有像素值,从而完成图像块的提取。利用Numpy的切片操作,我们就能实现ROI切割。这种方法只需提取感兴趣区域的像素,过滤无关部分,显著降低了数据处理和存储的开销。
注意:在OpenCV中,坐标的x轴的正方向是水平向右,y轴的正方向是垂直向下,与数学上的二维坐标并不相同。
python
import cv2
image = cv2.imread('图片路径')
(w, h, _) = image.shape #获取图片宽高
x_min, x_max = 10, 370 #设定裁剪区域
y_min, y_max = 150, 390
img_rec = cv2.rectangle(image, (x_min - 2, y_min - 2), (x_max + 2, y_max + 2), (0, 0, 255), 2)#将提取区域用矩形画出来
#提取目标中的感兴趣区域
ROI_img = image[y_min: y_max, x_min: x_max]
cv2.imshow("image", image) #原图
cv2.imshow("ROI_img", ROI_img) #裁剪区域
cv2.waitKey(0)


图像旋转:
将图像以某一点为中心旋转图片所有像素点,旋转后图片像素组成不变.
1. 单点旋转

由图我们就知道
所以
可得,
然而,在OpenCV中,旋转时是以图像的左上角为旋转中心,且以逆时针为正方向,因此上面的例子中其实是个负值,那么该矩阵可写为:
可得到旋转矩阵,
然而我们所要的不仅仅是可以围绕图像左上角进行旋转,而是可以围绕任意点进行旋转。那么我们可以将其转化成绕原点的旋转,其过程为:
-
首先将旋转点移到原点
-
按照上面的旋转矩阵进行旋转得到新的坐标点
-
再将得到的旋转点移回原来的位置
那么在以任意点为旋转中心时,除了要进行旋转之外,还要进行平移操作。
假设P'沿x轴移动a,沿y轴移动b到P''
则有,
那么矩阵,
所以旋转矩阵先左乘再右乘
得到仿射变换矩阵
这样我们就可以通过这个矩阵计算出图像中绕任意一点旋转后的坐标。
单点旋转在OpenCV中通常指绕图像中的某个特定点(如中心点或任意坐标点)进行旋转变换。
2. 图片旋转
理解了单点旋转原理后,图像旋转的概念就变得清晰了。本质上,图像旋转就是将每个像素坐标代入仿射变换矩阵计算新位置。OpenCV提供了便捷的cv2.getRotationMatrix2D()函数来获取旋转矩阵,该函数需要三个关键参数:
- Center:旋转中心坐标(x,y)
- Angle:旋转角度
- Scale:缩放比例(用于调整图像大小变化)
python
import cv2
image = cv2.imread('fs.jpg')
#获取图片像素
h,w = image.shape[:2]
#计算旋转坐标,中心点坐标
center = (h//2,w//2)
#旋转角度
angle = 45
#获取旋转矩阵
m = cv2.getRotationMatrix2D(center,angle,1)
#进行仿射变换
img = cv2.warpAffine(image,m,(h,w))
cv2.imshow('image',image)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3. 插值方法
在图像处理与计算机图形学领域,插值(Interpolation)是通过已知数据点推断新数据点的重要方法。该方法广泛应用于图像缩放、旋转、变形等操作,以及像素值的计算处理。
图像插值算法主要解决图像变换过程中因像素间隔变化导致的信息缺失与质量下降问题。当进行缩放或旋转等操作时,需要为新像素位置估算对应值,而插值算法正是基于现有像素值预测未知位置像素值的关键技术。本次将介绍五种常见插值算法。
3.1 最近邻插值(INTER_NEAREST)
公式:
- dstX:目标图像中某点的x坐标
- srcWidth:原始图像的宽度
- dstWidth:目标图像的宽度
- dstY:目标图像中某点的y坐标
- srcHeight:原始图像的高度
- dstHeight:目标图像的高度
- srcX和srcY:目标图像某点对应原始图像中的坐标
该公式的核心作用是为目标图像的每个像素点找到对应的原始图像坐标,进而通过插值算法计算新的像素值。
例如:

将一个2x2图像放大为4x4的图像,根据公式,可以得到放大后(0,0)对应原图像中的坐标
换句话说,目标图像中的(0,0)点对应原图的(0,0)点。根据最近邻插值原理,当坐标转换出现小数时需要进行四舍五入取整,最终目标像素值直接采用其最近的原图像素值。因此放大后图像(0,0)位置将保留原图(0,0)处的像素值10。
那么坐标(1,0)对应的就是原图中的(0.5,0),但是需要对坐标值取整,结果为(0,0),所以放大后的图像(1,0)处的像素值就是原图像中(0,0)处的像素值。、
3.2 双线性插值(INTER_LINEAR)
双线性插值是一种常用的图像处理算法,主要用于图像缩放、旋转和平移等变换操作中的像素值估算。当图像尺寸发生变化时,原始像素坐标可能无法与新图像网格对齐,此时就需要通过插值计算来确定非整数坐标处的像素值。
双线性插值的工作原理如下:
首先确定目标图像坐标(x', y')对应原图像的浮点坐标(x, y)。在原图像上找到包围(x, y)的四个最近邻像素点:P00(x0,y0)、P01(x0,y1)、P10(x1,y0)、P11(x1,y1),这些点构成一个2×2邻域矩阵。
插值过程分为两个步骤:
- 水平方向:在P00和P10之间进行线性插值,计算x坐标上的中间值
- 垂直方向:利用第一步的结果,分别在P00-P01和P10-P11之间进行线性插值,最终结合y坐标上的权重值
通过这两个方向的线性插值组合,最终得到目标点(x', y')的像素估计值。

还是先使用目标点与原点之间的公式,比如我们计算出了新图像中的某点所对应的原图像的点P,其周围的点分别为Q12、Q22、Q11、Q21, 要插值的P点不在其周围点的连线上,这时候就需要用到双线性插值了。首先延申P点得到P和Q11、Q21的交点R1与P和Q12、Q22的交点R2,如上图
先计算R1、R2插值:
然后使用R1、R2计算P点的插值,
注意:插值结果与顺序无关,先x后y和先y后x插值结果一样
3.3 像素区域插值(INTER_AREA)
像素区域插值主要分为图像缩小和放大两种情况,两者的工作原理存在差异。
在图像缩小场景中,像素区域插值相当于一个均值滤波器(滤波器本质上是一个核,具体概念将在后续实验中详细介绍)。其实现原理是对指定区域(均值滤波器/核)内的像素值进行平均计算。
在图像放大场景中,处理方式取决于放大比例:当放大倍数为整数时,其工作原理与最近邻插值相似;当放大倍数非整数时,则会采用双线性插值算法来完成放大操作。
3.4 双三次插值(INTER_CUBIC)
与双线性插值法类似,该方法同样通过映射计算,在目标点附近区域进行加权运算来获取放大图像的像素值。不同之处在于,双三次插值法需要利用原图像中相邻的16个像素点进行加权计算。
假设原图像A的尺寸为m×n,目标缩放图像B的尺寸为M×N。已知图像A的所有像素值,而图像B需要求解。要确定目标图像B中任意像素点(X,Y)的值,需执行以下步骤:
- 定位像素(X,Y)在原图像A中对应的坐标(x,y)
- 选取原图像A中距离(x,y)最近的16个相邻像素
- 通过BiCubic基函数计算这16个像素的权重系数
- 将16个像素值按各自权重进行加权求和,得到目标像素(X,Y)的最终值
下图中的P点表示目标图像B在坐标(X,Y)处通过上述公式计算得出的对应原图像A的位置。由于P点坐标可能出现小数,我们将其表示为(x+u,y+v),其中x和y为整数部分,u和v为小数部分。这样就能确定P点周围最近的16个像素位置,记为a(i,j)(i,j=0,1,2,3),如下图所示

BiCubic函数:
其中,a一般取-0.5或-0.75。
我们需要将16个点的坐标代入函数,计算出16个像素对应的权重W(x)。由于BiCubic函数是一维的,因此需要分别计算像素点的行和列权重。以a00点为例:先代入x=0计算P点在x方向的权重,再代入y=0计算y方向的权重。其余像素点同理处理。最终,我们可以得到目标图像B在(X,Y)处的像素值计算公式为:
以此类推出所有像素点
3.5 Lanczos插值(INTER_LANCZOS4)
Lanczos插值方法与双三次插值的核心思想相似,其主要区别在于:前者采用8×8像素邻域范围,并使用不同于BiCubic函数的权重计算公式。
权重公式:
其中a通常取2或者3,当a=2时,该算法适用于图像缩小。a=3时,该算法适用于图像放大。
与双三次插值一样,这里也需要将像素点分行和列分别带入计算权重值,其他像素点也是这样的计算过程,最终我们就可以得到P所对应的目标图像B在(X,Y)处的像素值为:
其中[x]、[y]表示对坐标值向下取整,通过该方法就可以计算出新的图像中所有的像素点的像素值。
4.边缘填充方式

如图所示,左图经过45度逆时针旋转后,原图的四个顶点在右图中已经消失。同时,右图新形成的四个顶点区域实际上是空白区域,因此需要进行填充处理。右图采用了像素值为(0,0,0)的黑色填充方式。在实际应用中,边缘填充是图像处理的常见需求,接下来我们将介绍五种常用的边缘填充方法。
4.1 边界复制(BORDER_REPLICATE)
- 当卷积核移动到图像边缘时,部分核会超出图像边界,导致无法计算。
- 边界复制通过扩展图像边缘的像素值,使卷积核能够正常计算。
边界复制会直接复制最边缘的像素向外扩展,如
4.2 边界反射(BORDER_REFLECT)
- 将边界内的数据以对称方式反射到边界外,使边界过渡更自然。
- 适用于周期性不明显但需要平滑过渡的场景。
通过镜像对称的方式扩展边界数据,以减少边界效应带来的误差或失真。
4.3 边界反射101(BORDER_REFLECT_101)
- 边界反射101(REFLECT_101):现代标准,反射轴在像素之间,无重复值
- 边界反射(REFLECT):传统方法,反射轴在像素上,会重复边缘值
4.4 边界常数(BORDER_CONSTANT)
边界常数填充是图像处理和信号处理中最基础的边界处理方式之一,也称为"零填充"(Zero Padding)或"常量填充"。
使用时需指定常数,否则0填充
4.5边界包裹(BORDER_WRAP)
包裹边界(也称为周期填充或环形填充)是一种特殊的边界处理方式,它假设数据具有周期性,通过将数据对边内容进行循环填充来实现边界扩展。
图片镜像旋转
图像旋转是围绕特定点进行的变换,而镜像旋转则是围绕坐标轴进行的翻转操作。镜像旋转主要分为三种类型:
- 水平翻转:图像沿y轴进行对称翻转,像素点坐标从(x,y)变为(-x,y)
- 垂直翻转:图像沿x轴进行对称翻转,像素点坐标从(x,y)变为(x,-y)
- 水平垂直翻转:同时进行水平和垂直翻转,像素点坐标从(x,y)变为(-x,-y)
python
import cv2
image = cv2.imread('car.png')
#图片反转,0垂直,1水平,-1垂直和水平
#图片垂直反转
img0 = cv2.flip(image,0)
#图片水平反转
img1 = cv2.flip(image,1)
#图片同时水平和垂直反转
img2 = cv2.flip(image,-1)
cv2.imshow('image',image)
cv2.imshow('img0',img0)
cv2.imshow('img1',img1)
cv2.imshow('img2',img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像缩放
图像缩放与旋转的原理类似,都是通过调整像素数量来实现几何变换。在缩放过程中,系统会根据需求增加或减少像素,并采用插值算法计算新像素值。本实验提供了五种插值方法:最近邻插值、双线性插值、像素区域插值、立方插值以及Lanczos插值,这些方法与图像旋转实验中的插值选项完全一致。
图像缩放方法:
python
cv2.resize(image_np, dsize=None, fx=0.6, fy=0.6, interpolation=cv2.INTER_LINEAR)
image_np:这是待缩放的原始图像,它是一个numpy数组表示的图像。
None :这个参数代表目标图像的尺寸(宽度和高度),在这里设置为 None
意味着我们不直接指定新图像的具体尺寸,而是通过接下来的 fx
和 fy
参数来按比例缩放原图像。
fx :这是一个缩放因子,用来控制图像水平方向(宽度)的缩放比例。如果 fx=0.6
,那么原图像的宽度将缩小到原来宽度的60%。
fy :同样是一个缩放因子,但它控制的是图像垂直方向(高度)的缩放比例。当 fy=0.6
时,原图像的高度将缩小到原来高度的60%。
interpolation :插值方法,用于决定如何计算新尺寸图像中的像素值。cv2.INTER_LINEAR
表示双线性插值,这是一种常用的、平滑且质量相对较高的插值方式,能够较好地保留图像细节和连续性。