【OpenCV 】插值的方法原理,图片缩放,矫正,边界填充
de-feedback 2024-09-14 16:31:00 阅读 86
图像旋转 缩放
计算机中的图像是以数组的方式储存,每个位置储存了像素点的像素值。对图像进行旋转缩放,就是对数组进行操作,乘以对应的矩阵,进行空间变换,而矩阵的行列式的值,就是缩放的倍数。
进行缩放旋转操作时,会产生像素点的变化,空间和数量的变化,所以需要对变化的图片进行插值
插值是通过变化后图像的像素点的坐标,通过缩放倍数,找到原图对应的像素点坐标,通过权重得到新的像素值
其中目标像素点与原图像的像素点的对应公式如下所示:
s
r
c
X
=
d
s
t
X
∗
s
r
c
W
i
d
t
h
d
s
t
W
i
d
t
h
s r c X=d s t X*{\frac{s r c W i d t h}{d s t W i d t h}}
srcX=dstX∗dstWidthsrcWidth
s
r
c
Y
=
d
s
t
Y
∗
s
r
c
H
e
i
g
h
t
d
s
t
H
e
i
g
h
t
s r c Y=d s t Y*{\frac{s r c H e i g h t}{d s t H e i g h t}}
srcY=dstY∗dstHeightsrcHeight
src是原图,dst是变换后的图像,通过缩放倍数,得到对应原图的x和y的坐标,是个小数。
最近零插值INTER_NEAREST
通过对得到的坐标向下取整,直接获得原图对应位置的像素值
双线性插值INTER_LINEAR
根据得到的小数坐标重新取像素值,权重取决于和周围点的距离,越近权重越高
小数的坐标对应原图周围四个像素点,对两个方向分别根据距离加权求和,之后再对的到的两个值进行加权求和
把p分为到两个点R1 R2 分别通过Q12Q22 和 Q11Q21根据距离获得像素值,再根据距离由R1R2得到p的像素值
f
(
R
1
)
≈
x
2
−
x
x
2
−
x
1
f
(
Q
11
)
+
x
−
x
1
x
2
−
x
1
f
(
Q
21
)
f(R_{1})\approx\frac{x_{2}-x}{x_{2}-x_{1}}f(Q_{11})+\frac{x-x_{1}}{x_{2}-x_{1}}f(Q_{21})
f(R1)≈x2−x1x2−xf(Q11)+x2−x1x−x1f(Q21)
f
(
R
2
)
≈
x
2
−
x
x
2
−
x
1
f
(
Q
12
)
+
x
−
x
1
x
2
−
x
1
f
(
Q
22
)
f(R_{2})\approx\frac{x_{2}-x}{x_{2}-x_{1}}f(Q_{12})+\frac{x-x_{1}}{x_{2}-x_{1}}f(Q_{22})
f(R2)≈x2−x1x2−xf(Q12)+x2−x1x−x1f(Q22)
f
(
P
)
≈
y
2
−
y
y
2
−
y
1
f
(
R
1
)
+
y
−
y
1
y
2
−
y
1
f
(
R
2
)
f(P)\approx{\frac{y_{2}-y}{y_{2}-y_{1}}}f(R_{1})+{\frac{y-y_{1}}{y_{2}-y_{1}}}f(R_{2})
f(P)≈y2−y1y2−yf(R1)+y2−y1y−y1f(R2)
v
像素区域插值INTER_AREA
缩小图像,变成均值滤波放大图像
整数倍是最近邻插值否则就是双线性插值
双三次插值INTER_CUBIC
使用原图中的16像素点进行加权求像素值
像素点的权重通过公式分别求出水平方向和垂直方向的权重,再相乘
BiCubic函数
a为-0.5或-0.75
Lanczos插值INTER_LANCZOS4
和双三次插值相似,但是使用了64个像素点
使用新的权重公式
a = 2是适用于缩小,a=3适用放大
<code>import cv2
import numpy
nut = cv2.imread('./media/nut.png')
w = nut.shape[0]
h = nut.shape[1]
mat = cv2.getRotationMatrix2D((0,0),0,2)
nut1 = cv2.warpAffine(nut,mat,(h*2,w*2),flags=cv2.INTER_LINEAR)
nut2 = cv2.warpAffine(nut,mat,(h*2,w*2),flags=cv2.INTER_CUBIC)
nut3 = cv2.warpAffine(nut,mat,(h*2,w*2),flags=cv2.INTER_LANCZOS4)
nut4 = cv2.warpAffine(nut,mat,(h*2,w*2),flags=cv2.INTER_NEAREST)
cv2.imshow('nut1',nut1)
cv2.imshow('nut2',nut2)
cv2.imshow('nut3',nut3)
cv2.imshow('nut4',nut4)
cv2.imshow('nut',nut)
cv2.waitKey(0)
边界填充
<code>import cv2
import numpy as np
# 边界复制 BORDER_REPLICATE 把边界的像素值作为边缘的填充
# 边界反射 BORDER_REFLECT 以边界为对称线反转过去作为边缘填充
# 边界反射101 BORDER_REFLECT_101 边界放射不同之处在于 不把边界作为对称的部分
# 边界常数 BORDER_CONSTANT 指定常数 以常数填充
# 边界包裹 BORDER_WRAP 平铺
img = cv2.imread('./media/nut.png')
shape = img.shape
m = cv2.getRotationMatrix2D((shape[0]//2,shape[1]//2),45,0.25)
img2 = cv2.warpAffine(img,m,(shape[1],shape[0]),flags=cv2.INTER_LINEAR,borderMode=cv2.BORDER_REPLICATE)
img3 = cv2.warpAffine(img,m,(shape[1],shape[0]),cv2.INTER_AREA,borderMode=cv2.BORDER_REFLECT)
img4 = cv2.warpAffine(img,m,(shape[1],shape[0]),cv2.INTER_CUBIC,borderMode=cv2.BORDER_REFLECT_101)
img5 = cv2.warpAffine(img,m,(shape[1],shape[0]),cv2.INTER_LANCZOS4,borderMode=cv2.BORDER_CONSTANT,borderValue=127)
img6 = cv2.warpAffine(img,m,(shape[1],shape[0]),cv2.INTER_LANCZOS4,borderMode=cv2.BORDER_WRAP)
cv2.imshow('img',img)
cv2.imshow('img2',img2)
cv2.imshow('img3',img3)
cv2.imshow('img4',img4)
cv2.imshow('img5',img5)
cv2.imshow('img6',img6)
cv2.waitKey(0)
图片翻转
<code>import cv2
import numpy as np
img = cv2.imread('./media/nut.png')
img1 = img[::-1] # 垂直翻转
img2 = cv2.flip(img,0) # 0 垂直翻转
img3 = cv2.flip(img,1) # 大于0 水平翻转
img4 = cv2.flip(img,-1) # 小于0 水平垂直翻转
cv2.imshow('img',img)
cv2.imshow('img1',img1)
cv2.imshow('img2',img2)
cv2.imshow('img3',img3)
cv2.imshow('img4',img4)
cv2.waitKey(0)
图片缩放
<code>import cv2
import numpy as np
img1 = cv2.imread('./media/shapan.jpg')
img2 = cv2.resize(img1,dsize=None,fx=0.25,fy=0.25,interpolation=cv2.INTER_LINEAR)
# x方向缩放 y方向缩放 插值方式
cv2.imshow('img1',img1)
cv2.imshow('img2',img2)
# cv2.imwrite('./media/shapan.jpg',img2)
cv2.waitKey(0)
图片矫正
import cv2
import numpy as np
img = cv2.imread('./media/liner_road.png')
w,h,_ = img.shape
potion = [
[415,50],
[506,50],
[60,560],
[872,560]
]
new_p = np.float32([
[0,0],
[h,0],
[0,w],
[h,w]
])
p = np.float32(potion)
# cv2.line(img,p[0].astype(np.int64).tolist(),p[1].astype(np.int64).tolist(),(0,0,255),2,cv2.LINE_AA)
# cv2.line(img,p[1].astype(np.int64).tolist(),p[3].astype(np.int64).tolist(),(0,0,255),2,cv2.LINE_AA)
# cv2.line(img,p[3].astype(np.int64).tolist(),p[2].astype(np.int64).tolist(),(0,0,255),2,cv2.LINE_AA)
# cv2.line(img,p[2].astype(np.int64).tolist(),p[0].astype(np.int64).tolist(),(0,0,255),2,cv2.LINE_AA)
mat = cv2.getPerspectiveTransform(p,new_p)
img2 = cv2.warpPerspective(img,mat,(h,w))
cv2.imshow('img',img)
cv2.imshow('img2',img2)
cv2.waitKey(0)
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。