图像处理之几何变换(python实现)


通过几何变换不仅可以产生某种特殊的效果,而且可以简化图像处理过程和分析程序。图像的几何变换最重要的特征是仅改变像素的位置,而不改变图像的像素值。图像的几何变换按变换性质可分为五项的位置变换(平移、镜像、旋转)、图像的形状变换(放大、缩小、错切)等基本变换,以及图像的复合变换。

1.图像比例放缩

图像比例放缩是指将给定的图像在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=fx000fy0001x0y01
在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)

  • dst代表输出图像
  • src代表输入图像
  • dsize代表输出图像大小
  • fx代表水平方向的缩放比例
  • fy代表垂直方向的缩放比例
  • interpolation代表插值方式,常见插值方式有cv2.INTER_NEAREST(最近邻域插值 )、cv2.INTER_LINEAR(双线性插值)、cv2.INTER_CUBIC(三次样条插值)

示例代码

cv.resize(img,None,fx=2,fy=2,interpolation=cv.INTER_LINEAR)

1.1最邻近插值法

将变换后图像中的原像素点的最邻近像素的灰度值赋给原图像的方法。当图像按全比例放大两倍,放大后图像中的(0,0)像素,对应于原图像的(0,0)像素;放大后图像中的(0,1)像素,对应于原图像的(0,0.5)像素,但该像素不存在,则近似为原图像(0,0)的像素;放大后图像中的(0,2)像素,对应于原图像的(0,1)像素;放大后图像中的(0,3)像素,对应于原图像的(0,1.5)像素,但该像素不存在,则近似为原图像(0,1)的像素,以此类推。

1.1.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

1.1.2实现结果图

使用自定义最邻近插值函数和Opencv最邻近插值实现图像的比例放缩:
最邻近插值法

1.2双线性插值法

当求出的分数地址与像素点不一致时,求出其与周围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)=(1q)×[(1p)×f([x],[y])+p×f([x]+1,[y])]+q×[(1p)×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]。

1.2.1自定义函数

    #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,即图像高度和图像宽度。

1.2.2实现结果图

使用自定义双线性插值函数和Opencv双线性插值实现图像的比例放缩:
双线性插值

猜你喜欢

转载自blog.csdn.net/m0_53192838/article/details/127460630