【python-opencv】opencv基礎操做之三

opencv_3javascript

 

 

 
3 仿射變換
 
3.0 仿射變化基礎
 

什麼是仿射變換?
仿射變換就是圖像的線性變換加上平移,用一幅圖表示,就是css

avatar

由 image1 到 image2 的轉換通過了三個操做:
1.旋轉 (線性變換)
2.縮放操做(線性變換)
3.平移 (向量加)html

若是沒有了第3個平移的操做,那它就是線性變換。前兩個筆記已經整理了圖像的旋轉、縮放和平移的各個方法,接下來會介紹仿射變換的矩陣表示和使用方法。html5

仿射變化的矩陣形式java

圖像的變換要對圖像的每個像素點進行操做,假設其中的一個像素點的座標是(x,y),咱們用矩陣形式表示: $${X}=\begin{bmatrix} {x}\\ {y}\\ \end{bmatrix}\tag{1}$$ 咱們一般使用$2\times3$矩陣來表示仿射變化。 $${A}=\begin{bmatrix} {a_{00}} & {a_{01}}\\ {a_{10}} & {a_{11}}\\ \end{bmatrix}_{2\times2}\tag{2}$$python

$$B=\begin{bmatrix} {b_{00}}\\ {b_{10}}\\ \end{bmatrix}_{2\times1}\tag{3}$$$${M}=\begin{bmatrix} {A} & {B} \end{bmatrix} = \begin{bmatrix} {a_{00}} & {a_{01}} & {b_{00}}\\ {a_{10}} & {a_{11}} & {b_{10}}\\ \end{bmatrix}_{2\times3}\tag{4} $$

矩陣${A}、{B}$就是變換矩陣。
通過仿射變換後的點的矩陣座標是${T}$,咱們已經知道放射變換就是線性變換加上平移,用矩陣表示的話就是 $${T}={A}\cdot\begin{bmatrix} {x}\\ {y}\\ \end{bmatrix}+{B}\tag{5} $$ 也能夠寫成 $${T}={M}\cdot\begin{bmatrix} {x, y, 1} \end{bmatrix}^{T}\tag{6} $$ 計算可得: $${T}=\begin{bmatrix} {a_{00}\cdot{x}+a_{01}\cdot{y}+b_{00}}\\ {a_{10}\cdot{x}+a_{11}\cdot{y}+b_{10}}\\ \end{bmatrix}\tag{7} $$jquery

下面使用代碼linux

In [1]:
import cv2
import requests
import time
from PIL import Image
from io import BytesIO
import numpy as np
from matplotlib import pyplot as plt

%matplotlib inline
# set None proxy
import os
os.environ['no_proxy'] = '*' 
In [2]:
# get file(of Internet picture)
class InternetPicture:
    def __init__(self, url):
        # attribute
        self.url = url
        self.img = None
        # initial method
        self.get() # self表明類的實例, 而非類自己,因此self.get(self)--> self.get()
        self.show()
        self.info()

    # get Internet Picture
    def get(self):
        for i in range(5): # 多獲取幾回,增長成功率
            start=time.time()
            file = requests.get(self.url)
            img = cv2.imdecode(np.fromstring(file.content, np.uint8), 1)    #file.content 是讀取的遠程文件的字節流
            print(i + 1, ' time of Requesting Time:', time.time()-start)
        self.img = img
        print('get a file of:', type(img))
    
    # show image
    def show(self):
        #using plt draw picture
        plt.figure() # 設置畫布
        plt.imshow(cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB))
        plt.show()
    
    def info(self):
        # using cv2 to read Internet file of picture
        color_img = self.img
        gray_img = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY)

        # 獲取信息:行,列,通道,像素數目,圖像數據類型
        print('獲取信息:行,列,通道,像素數目,圖像數據類型')
        print(color_img.shape, color_img.size, color_img.dtype)
        print(gray_img.shape, gray_img.size, gray_img.dtype)
        print('self.img: get a numpy image')
        print('self.show(): show a numpy image using plt')

        # using PIL.Image to read Internet file of picture
        ## image = Image.open(BytesIO(file.content))
        ## image.show()
In [3]:
# draw a cvMat using plt.
def draw(image):
        plt.figure() # 設置畫布
        plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
        plt.show()
 
3.1 圖像平移的代碼

以前有講過
實例代碼android

In [4]:
# 實例化類,並獲取一個網絡圖像
url = 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=672015163,3441564657&fm=26&gp=0.jpg'
instance = InternetPicture(url)
 
1  time of Requesting Time: 0.05405902862548828
2  time of Requesting Time: 0.04230785369873047
3  time of Requesting Time: 0.05769944190979004
4  time of Requesting Time: 0.04853630065917969
5  time of Requesting Time: 0.04676055908203125
get a file of: <class 'numpy.ndarray'>
 
 
獲取信息:行,列,通道,像素數目,圖像數據類型
(500, 500, 3) 750000 uint8
(500, 500) 250000 uint8
self.img: get a numpy image
self.show(): show a numpy image using plt
In [5]:
img = instance.img
rows, cols, _ = img.shape
M = np.float32([[1, 0, 200], [0, 1, 100]])  
dst = cv2.warpAffine(img, M, (cols, rows))      
draw(dst)
 
 

在代碼:css3

M = np.float32([[1, 0, 200], [0, 1, 100]])

中。將這個二維矩陣的值帶入${T}$,獲得通過仿射變換後的點的座標是$(x+200,y+100)$,即將整個圖像平移$(200,100)$

再次強調一下:圖片的高度(y方向)是rows,寬度(x方向)是cols,請勿混淆。

 
3.2 圖像旋轉的代碼

以前有講過
實例代碼

In [6]:
# 實例化類,並獲取一個網絡圖像
url = 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=672015163,3441564657&fm=26&gp=0.jpg'
instance = InternetPicture(url)

# 旋轉就完事兒了
img = instance.img
rows, cols, _ = img.shape
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 0.5)  
dst = cv2.warpAffine(img, M, (cols, rows))      
draw(dst)
 
1  time of Requesting Time: 0.03540825843811035
2  time of Requesting Time: 0.06493616104125977
3  time of Requesting Time: 0.04896807670593262
4  time of Requesting Time: 0.043243408203125
5  time of Requesting Time: 0.043845176696777344
get a file of: <class 'numpy.ndarray'>
 
 
獲取信息:行,列,通道,像素數目,圖像數據類型
(500, 500, 3) 750000 uint8
(500, 500) 250000 uint8
self.img: get a numpy image
self.show(): show a numpy image using plt
 
 

大部分同上相似,只是其中的${M}$矩陣不一樣。

M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 0.5) # 第一個參數是中心點的座標

參數1:圖片的旋轉中心
參數2:旋轉角度
參數3:縮放比例,該例中0.5表示咱們縮小一半

 
3.3 圖像仿射

那麼如何經過仿射變換任意變換圖形呢?
咱們須要源圖像和目標圖像上分別一一映射的三個點來定義仿射變換

In [7]:
# 實例化類,並獲取一個網絡圖像
url = 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=672015163,3441564657&fm=26&gp=0.jpg'
instance = InternetPicture(url)

# 仿射
img = instance.img
rows, cols, _ = img.shape

# 變換前的三個點
pts1 = np.float32([[0, 0], [cols - 1, 0], [0, rows - 1]])
# 變換後的三個點
pts2 = np.float32([[cols * 0.2, rows * 0.1], [cols * 0.9, rows * 0.2], [cols * 0.1, rows * 0.9]])

# 獲得變換矩陣
M = cv2.getAffineTransform(pts1, pts2)
dst = cv2.warpAffine(img, M, (cols, rows))
draw(dst)
 
1  time of Requesting Time: 0.03268003463745117
2  time of Requesting Time: 0.03764843940734863
3  time of Requesting Time: 0.03796219825744629
4  time of Requesting Time: 0.0615692138671875
5  time of Requesting Time: 0.0556941032409668
get a file of: <class 'numpy.ndarray'>
 
 
獲取信息:行,列,通道,像素數目,圖像數據類型
(500, 500, 3) 750000 uint8
(500, 500) 250000 uint8
self.img: get a numpy image
self.show(): show a numpy image using plt
 
相關文章
相關標籤/搜索