图像比例放缩是指将给定的图像在x、y轴方向按比例分别缩放 f x f_x fx倍和 f y f_y fy倍,从而获得一幅新的图像。如果 f x f_x fx= f y f_y fy,即在x轴和y轴方向缩放的比率相同,该比例缩放称为图像的全比例放缩。如果 f x ≠ f y f_x \neq f_y fx=fy,图像的比例放缩为改变原始图像的像素间的相对位置,产生几何畸变。比例放缩后图像中的像素在原图像中可能找不到对应的像素点,则此时需要进行插值处理,常见的插值处理方法为最邻近插值法和双线性插值法。
比例放缩前后 P 0 ( x , y ) 和 P ( x , y ) P_0(x,y)和P(x,y) P0(x,y)和P(x,y)之间的关系用矩阵形式可表示为
[ x y 1 ] = [ f x 0 0 0 f y 0 0 0 1 ] ⋅ [ x 0 y 0 1 ] \left[ \begin{matrix} x\\ y\\ 1 \end{matrix} \right] = \left[ \begin{matrix} f_x&0&0\\ 0&f_y&0\\ 0&0&1 \end{matrix} \right]· \left[ \begin{matrix} x_0\\ y_0\\ 1 \end{matrix} \right] ⎣⎡xy1⎦⎤=⎣⎡fx000fy0001⎦⎤⋅⎣⎡x0y01⎦⎤
在Opencv中,使用函数cv2.resize() 实现对图像的缩放,该函数的具体形式为:
d s t = c v 2. r e s i z e ( s r c , d s i z e , f x , f y , i n t e r p o l a t i o n ) dst=cv2.resize(src,dsize,fx,fy,interpolation) dst=cv2.resize(src,dsize,fx,fy,interpolation)
cv.resize(img,None,fx=2,fy=2,interpolation=cv.INTER_LINEAR)
将变换后图像中的原像素点的最邻近像素的灰度值赋给原图像的方法。当图像按全比例放大两倍,放大后图像中的(0,0)像素,对应于原图像的(0,0)像素;放大后图像中的(0,1)像素,对应于原图像的(0,0.5)像素,但该像素不存在,则近似为原图像(0,0)的像素;放大后图像中的(0,2)像素,对应于原图像的(0,1)像素;放大后图像中的(0,3)像素,对应于原图像的(0,1.5)像素,但该像素不存在,则近似为原图像(0,1)的像素,以此类推。
#p代表垂直放缩比例
#q代表水平放缩比例
def Inter_Neareast(self,img,q,p):
h,w=img.shape[:2]
print(h,w)
new_img=[]
# q=int(new_h/h)
# p=int(new_w/w)
for i in range(h*q):
for j in range(w*p):
new_img.append(
int(img[int(i/q),int(j/p)])
)
new_img=np.array(new_img).reshape(h*q,w*p)
print(new_img.shape[:2])
return new_img
使用自定义最邻近插值函数和Opencv最邻近插值实现图像的比例放缩:
当求出的分数地址与像素点不一致时,求出其与周围4个像素点的距离比,根据该比率,由4个邻域的像素灰度值进行双线性插值。简化后的插值点(x,y)处的灰度值可由下式计算:
g ( x , y ) = ( 1 − q ) × [ ( 1 − p ) × f ( [ x ] , [ y ] ) + p × f ( [ x ] + 1 , [ y ] ) ] + q × [ ( 1 − p ) × f ( [ x ] , [ y ] + 1 ) + p × f ( [ x ] + 1 , [ y ] + 1 ) ] g(x,y)=(1-q) \times \left[(1-p)\times f([x],[y])+p\times f([x]+1,[y])\right]+q \times \left[(1-p)\times f([x],[y]+1)+p\times f([x]+1,[y]+1)\right] g(x,y)=(1−q)×[(1−p)×f([x],[y])+p×f([x]+1,[y])]+q×[(1−p)×f([x],[y]+1)+p×f([x]+1,[y]+1)]
其中[x]、[y]分别代表不大于x、y的整数,f(x,y)为像素点(x,y)插值前的灰度值,g(x,y)代表像素点(x,y)插值后的灰度值,p代表x-[x],q代表y-[y]。
#p代表垂直放缩比例
#q代表水平放缩比例
def Inter_Linear(self,img,p,q):
h,w=img.shape[:2]
# q=int(new_h/h)
# p=int(new_w/w)
new_img=[]
for i in range(w*p):
for j in range(h*q):
dstx=i/p-int(i/p)
dsty=j/q-int(j/q)
new_img.append(
int((1-dsty)*((1-dstx)*img[int(i/p),int(j/q)]+dstx*img[min(int(i/p)+1,h-1),int(j/q)])+
dsty*((1-dstx)*img[int(i/p),min(int(j/q)+1,w-1)]+dstx*img[min(int(i/p)+1,h-1),min(int(j/q)+1,w-1)]))
)#列表会溢出,溢出时选择最大序号
new_img=np.array(new_img).reshape(h*q,w*p)
return new_img
注意:f([x]+1,[y])、f([x]+1,[y]+1)、f([x],[y]+1)会出现溢出,当溢出时,我们默认选择f(x,y)的 x m a x x_{max} xmax或者 y m a x y_{max} ymax,即图像高度和图像宽度。