Numpy平移,旋转,镜像操作

一、图像平移

 二、图像水平镜像

 三、图像垂直镜像

 四、图像缩放

 五、图像旋转(顺时针)

 正确代码:

import cv2
import math
import numpy as np

class Img:
    def __init__(self,image,rows,cols,center=[0,0]):
        self.src=image #原始图像
        self.rows=rows #原始图像的行
        self.cols=cols #原始图像的列
        self.center=center #旋转中心,默认是[0,0]

    def Move(self,delta_x,delta_y):      #平移
        #delta_x>0左移,delta_x<0右移
        #delta_y>0上移,delta_y<0下移
        self.transform=np.array([[1,0,delta_x],[0,1,delta_y],[0,0,1]])

    def Zoom(self,factor):               #缩放
        #factor>1表示缩小;factor<1表示放大
        self.transform=np.array([[factor,0,0],[0,factor,0],[0,0,1]])

    def Horizontal(self):                #水平镜像
        self.transform=np.array([[1,0,0],[0,-1,self.cols-1],[0,0,1]])

    def Vertically(self):                #垂直镜像
        self.transform=np.array([[-1,0,self.rows-1],[0,1,0],[0,0,1]])

    def Rotate(self,beta):               #旋转
        #beta>0表示逆时针旋转;beta<0表示顺时针旋转
        self.transform=np.array([[math.cos(beta),-math.sin(beta),0],
                                 [math.sin(beta), math.cos(beta),0],
                                 [    0,              0,         1]])

    def Process(self):
        self.dst=np.zeros((self.rows,self.cols),dtype=np.uint8)
        for i in range(self.rows):
            for j in range(self.cols):
                src_pos=np.array([i-self.center[0],j-self.center[1],1])
                [x,y,z]=np.dot(self.transform,src_pos)
                x=int(x)+self.center[0]
                y=int(y)+self.center[1]

                if x>=self.rows or y>=self.cols or x<0 or y<0:
                    self.dst[i][j]=255
                else:
                    self.dst[i][j]=self.src[x][y]

if __name__=='__main__':
    src=cv2.imread('.\jay.bmp',0)
    rows = src.shape[0]
    cols = src.shape[1]
    cv2.imshow('src', src)

    img=Img(src,rows,cols,[248,231])
    img.Vertically() #镜像
    img.Process()
    '''
    img.Rotate(-math.radians(30)) #旋转
    img.Process()
    img.Move(-50,-50) #平移
    img.Process()
    img.Zoom(0.5) #缩放
    img.Process()
    '''
    cv2.imshow('dst', img.dst)
    cv2.waitKey(0)

旋转易错点:

                       

           原始图                                    beta=-30°

  再Rotate的函数中,我们的transform矩阵完全是按照beta>0时为为逆时针旋转。但是我们需要注意到 时process:self.dst[i][j]=self.src[x][y];相当于又一次取反。最终,当beta>0时,我们是顺时针旋转

  这个时候你可能产生疑问,我直接写成:self.dst[x,y]=self.src[i,j]不就是逆时针的了????

结果如下:

 原因分析:可能是因为在遍历过程中dst的元素无法全部访问到,会保留默认的像素值为0的点。

六、旋转延拓

  上述方法的旋转之后的图像大小与原图像大小相等,接下来我们来看一个完全保留旋转后图像的方法:

import cv2
import math
import numpy as np
def XRotate(image, angle):
    h, w = image.shape
    anglePi = angle * math.pi / 180.0
    cosA = math.cos(anglePi)
    sinA = math.sin(anglePi)
    X1 = math.ceil(abs(0.5 * h * cosA + 0.5 * w * sinA))
    X2 = math.ceil(abs(0.5 * h * cosA - 0.5 * w * sinA))
    Y1 = math.ceil(abs(-0.5 * h * sinA + 0.5 * w * cosA))
    Y2 = math.ceil(abs(-0.5 * h * sinA - 0.5 * w * cosA))
    hh = int(2 * max(Y1, Y2))
    ww = int(2 * max(X1, X2))
    emptyImage2 = np.zeros((hh, ww), np.uint8)
    for i in range(hh):
        for j in range(ww):
            x = cosA * i + sinA * j - 0.5 * ww * cosA - 0.5 * hh * sinA + 0.5 * w
            y =  cosA * j- sinA * i+ 0.5 * ww * sinA - 0.5 * hh * cosA + 0.5 * h
            x = int(x)
            y = int(y)
            if x > -1 and x < h and y > -1 and y < w :
 
                emptyImage2[i, j] = image[x, y]*255
 
    return emptyImage2
 
 
# image = cv2.imread("e:\\lena.bmp")
iXRotate12 = XRotate(img[:,:,1], 30)
cv2.imshow('image', img)
cv2.imshow('iXRotate12', iXRotate12)
cv2.waitKey(0)

   代码解释:X1, X2, Y1, Y2的求解是考虑到了beta的正负;其次在两层的for循环里,cosA * i + sinA * j代表我们的transform矩阵是顺时针旋转;- 0.5 * ww * cosA - 0.5 * hh * sinA + 0.5 * w代表的是:根据图像中心进行旋转;同样的,由于我们 emptyImage2[i, j] = image[x, y]*255 操作,我们transform虽然是按照顺时针生成,但是最终结果会相反一下,为逆时针。

 

                          

 原始图像                                                       旋转之后

 

posted @ 2021-08-21 20:49  为红颜  阅读(2774)  评论(0编辑  收藏  举报