主頁 >  其他 > Python計算機視覺——影像到影像的映射(作業三)

Python計算機視覺——影像到影像的映射(作業三)

2021-04-11 10:27:15 其他

第三章 影像到影像的映射

  • 序言
  • 一、單應性變換
    • 1.1 直接線性變換演算法
    • 1.2 仿射變換
  • 二、影像扭曲
    • 2.1 影像中的影像
      • 使用仿射變換放置影像
      • 使用ginput函式獲取 tp 中的齊次坐標值
    • 2.2 分段仿射扭曲

序言

??本章講解了影像之間的變換,以及一些計算變換的應用,這些應用可以用于影像扭曲變換和影像配準,

運行環境:

  1. python3.8
  2. PyCharm2020.3

一、單應性變換

??單應性變換 是將一個平面內的點映射到另一個平面內的二維投影變換,在這里,平面是指影像或者三維中的平面表示,單應性變換具有很強的實用性,比如影像配準,影像糾正和紋理扭曲,以及創建全景影像,我們將頻繁的使用單應性變換,本質上,單應性變換H,按照下面的方程映射二維中的點(齊次坐標意義下): [ x ′ y ′ w ′ ] = [ h 1 h 2 h 3 h 4 h 5 h 6 h 7 h 8 h 9 ] [ x y z ] \begin{bmatrix} x^{'} \\ y^{'} \\ w^{'}\end{bmatrix}=\begin{bmatrix}h_1 & h_2 & h_3 \\ h_4 & h_5 & h_6 \\ h_7 & h_8 & h_9\end{bmatrix}\begin{bmatrix}x \\ y \\ z\end{bmatrix} ???xyw????=???h1?h4?h7??h2?h5?h8??h3?h6?h9????????xyz????或者 x ′ = H x x^{'}=Hx x=Hx對于影像平面內(甚至是三維中的點,后面我們會介紹到)的點,齊次坐標是個非常有用的表示方式,點的齊次坐標是依賴于其尺度定義的,所以,x=[x,y,w]=[ax,ay,aw]=[x/w,y/w,1]都表示同一個二維點,因此,單應性矩陣H也僅依賴尺度定義,所以,單應性矩陣具有8個獨立的自由度,我們通常使用w=1來歸一化點,這樣,點具有唯一的影像坐標x和y,這個額外的坐標是的我們可以簡單地使用一個矩陣來表示變換,

??我們創建 homography.py 檔案,用下面的函式可以實作對點進行歸一化和轉換齊次坐標的功能:

from numpy import *

def normallize(points):
    """在齊次坐標意義下,對點集進行歸一化,是最后一行為1"""
    for row in points:
        row /= points[-1]
    return points

def make_homog(points):
    """將點集(dim×n的陣列)轉換為齊次坐標表示"""

    return vstack((points,ones((1, points.shape[1]))))

??進行點和變換的處理時,我們會按照列優先的原則存盤這些點,因此,n個二維點集將會存盤為齊次坐標意義下的一個3×n陣列,這種格式使得矩陣乘法和點的變換操作更加容易,對于其他的例子,比如對于聚類和分類的特征,我們將使用典型的行陣列來存盤資料,

??在這些投影變換中,有一些特別重要的變換,比如,仿射變換 [ x ′ y ′ 1 ] = [ a 1 a 2 t x a 3 a 4 t y 0 0 1 ] [ x y 1 ] \begin{bmatrix}x^{'} \\ y^{'} \\ 1\end{bmatrix}=\begin{bmatrix}a_1 & a_2 & t_x \\ a_3 & a_4 & t_y \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x \\ y \\ 1\end{bmatrix} ???xy1????=???a1?a3?0?a2?a4?0?tx?ty?1???????xy1???? x ′ = [ A t 0 1 ] x x^{'}=\begin{bmatrix}A & t \\ 0 & 1\end{bmatrix}x x=[A0?t1?]x保持了w=1,不具有投影變換所具有的強大變形能力,反射變換包括一個可逆矩陣A和一個平移向量t=[tx,ty],仿射變換可以用于很多應用,比如 影像扭曲

相似變換: [ x ′ y ′ 1 ] = [ s cos ? ( θ ) ? s sin ? ( θ ) t x s sin ? ( θ ) s cos ? ( θ ) t y 0 0 1 ] [ x y 1 ] \begin{bmatrix}x^{'} \\ y^{'} \\ 1\end{bmatrix}=\begin{bmatrix}s\cos(\theta) & -s\sin(\theta) & t_x \\ s\sin(\theta) & s\cos(\theta) & t_y \\ 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x \\ y \\ 1\end{bmatrix} ???xy1????=???scos(θ)ssin(θ)0??ssin(θ)scos(θ)0?tx?ty?1???????xy1???? x ′ = [ s R t 0 1 ] x x^{'}=\begin{bmatrix}sR & t \\ 0 & 1\end{bmatrix}x x=[sR0?t1?]x是一個包含尺度變化的二維剛體變換,上式中的向量s指定了變換的尺度,R是角度為θ的旋轉矩陣,t=[tx,ty]在這里也是一個平移向量,如果s=1,那么該變換能夠保持距離不變,此時,變換稱為剛體變換,相似變換可以用于很多應用,比如影像配準,

??下面讓我們來一起探討如何設計用于估計單應性矩陣的演算法,然后看一下使用仿射變換進行影像扭曲,使用相似變換進行影像匹配,以及使用完全投影變換進行創建全景影像的一些例子:

1.1 直接線性變換演算法

??單應性矩陣可以有兩幅影像(或者平面)中對應點對計算出來,前面已經提到過,一個完全射影變換具有8個自由度,根據對應點約束,每個對應點對可以寫出兩個方程,分別對應于x和y坐標,因此,計算單應性矩陣H需要4個對應點對,

??DLT(Direct Linear Transformation,直接線性變換)是給定4個點或者更多對應點對矩陣,來計算單應性矩陣H的演算法,將單應性矩陣H作用在對應點上,重新寫出該方程,我們可以得到下面的方程: [ ? x 1 ? y 1 ? 1 0 0 0 x 1 x 1 ′ y 1 x 1 ′ x 1 ′ 0 0 0 ? x 1 ? y 1 ? 1 x 1 y 1 ′ y 1 y 1 ′ y 1 ′ ? x 2 ? y 2 ? 1 0 0 0 x 2 x 2 ′ y 2 x 2 ′ x 2 ′ 0 0 0 ? x 2 ? y 2 ? 1 x 2 y 2 ′ y 2 y 2 ′ y 2 ′ . . . . . . . . . . . . ] [ h 1 h 2 h 3 h 4 h 5 h 6 h 7 h 8 h 9 ] = 0 \begin{bmatrix} -x_1& -y_1&-1& 0&0&0&x_1x_1^{'}&y_1x_1^{'}&x_1^{'} \\ 0&0&0&-x_1&-y_1&-1&x_1y_1{'}&y_1y_1{'}&y_1^{'} \\ -x_2&-y_2&-1&0&0&0&x_2x_2^{'}&y_2x_2^{'}&x_2^{'} \\ 0&0&0&-x_2&-y_2&-1&x_2y_2^{'}&y_2y_2^{'}&y_2^{'} \\ &...&&...&&...&&... \end{bmatrix}\begin{bmatrix}h_1 \\ h_2\\ h_3\\ h_4 \\ h_5\\h_6\\ h_7\\ h_8\\ h_9\end{bmatrix}=0 ????????x1?0?x2?0??y1?0?y2?0...??10?10?0?x1?0?x2?...?0?y1?0?y2??0?10?1...?x1?x1?x1?y1?x2?x2?x2?y2??y1?x1?y1?y1?y2?x2?y2?y2?...?x1?y1?x2?y2????????????????????????h1?h2?h3?h4?h5?h6?h7?h8?h9?????????????????=0或者Ah=0,其中A是一個具有對應點對二倍數量行數的矩陣,將這些對應點對方程的系數堆疊到一個矩陣紅,我們可以使用SVD演算法找到H的最小二乘解,下面是演算法代碼,我們也將其加入到 homography.py 檔案里:

def H_from_points(fp, tp):
    """使用線性DLT方法,計算單應性矩陣H,使fp映射到tp,點自動進行歸一化"""

    if fp.shape != tp.shape:
        raise RuntimeError('number of points do not match')

    # 對點進行歸一化(對數值計算很重要)
    # --- 映射起始點 ---
    m = mean(fp[:2], axis=1)
    maxstd = max(std(fp[:2], axis=1)) + 1e-9
    C1 = diag([1 / maxstd, 1 / maxstd, 1])
    C1[0][2] = -m[0] / maxstd
    C1[1][2] = -m[1] / maxstd
    fp = dot(C1, fp)

    # --- 映射對應點 ---
    m = mean(tp[:2], axis=1)
    maxstd = max(std(tp[:2], axis=1)) + 1e-9
    C2 = diag([1 / maxstd, 1 / maxstd, 1])
    C2[0][2] = -m[0] / maxstd
    C2[1][2] = -m[1] / maxstd
    tp = dot(C2, tp)

    # 創建用于線性方法的矩陣,對于每個對應對,在矩陣中會出現兩行數值
    nbr_correspondences = fp.shape[1]
    A = zeros((2 * nbr_correspondences, 9))
    for i in range(nbr_correspondences):
        A[2 * i] = [-fp[0][i], -fp[1][i], -1, 0, 0, 0,
                    tp[0][i] * fp[0][i], tp[0][i] * fp[1][i], tp[0][i]]
        A[2 * i + 1] = [0, 0, 0, -fp[0][i], -fp[1][i], -1,
                        tp[1][i] * fp[0][i], tp[1][i] * fp[1][i], tp[1][i]]

    U, S, V = linalg.svd(A)
    H = V[8].reshape((3, 3))

    # 反歸一化
    H = dot(linalg.inv(C2), dot(H, C1))

    # 歸一化,然后回傳
    return H / H[2, 2]

??上面的函式的第一步操作是檢查點對兩個陣列中點的數目是否相同,如果不相同,函式將會拋出例外資訊,這對于寫出穩健的代碼來說非常有用,

??代碼先對這些點進行歸一化操作,使其均值為0,方差為1,因為演算法的穩定性取決于坐標的表示情況和部分數值計算的問題,所以歸一化操作非常重要,接下來我們使用對應點對來構造矩陣A,最小二乘解即為矩陣SVD分解后所得矩陣V的最后一行,該行經過變換后得到矩陣H,然后對這個矩陣進行處理和歸一化,回傳輸出,

1.2 仿射變換

??由于仿射變換具有6個自由度,因此我們需要三個對應點來估計矩陣H,通過將最后兩個元素設定為0,即h7=h8=0,仿射變換可以用上面的DLT演算法估計得出,

??下面的函式使用對應點來計算放射變換矩陣,我們繼續將其添加到 homography.py 檔案中,

def Haffine_from_points(fp, tp):
    """計算H仿射變換,使得tp是fp經過仿射變換H得到的"""

    if fp.shape != tp.shape:
        raise RuntimeError('number of points do not match')

    # 對點進行歸一化(對數值計算很重要)
    # --- 映射起始點 ---
    m = mean(fp[:2], axis=1)
    maxstd = max(std(fp[:2], axis=1)) + 1e-9
    C1 = diag([1 / maxstd, 1 / maxstd, 1])
    C1[0][2] = -m[0] / maxstd
    C1[1][2] = -m[1] / maxstd
    fp_cond = dot(C1, fp)

    # --- 映射對應點 ---
    m = mean(tp[:2], axis=1)
    C2 = C1.copy()  # 兩個點集,必須都進行相同的縮放
    C2[0][2] = -m[0] / maxstd
    C2[1][2] = -m[1] / maxstd
    tp_cond = dot(C2, tp)

    # 因為歸一化后點的均值為0,所以平移量為0
    A = concatenate((fp_cond[:2], tp_cond[:2]), axis=0)
    U, S, V = linalg.svd(A.T)

    # 如Hartley和Zisserman著的Multiplr View Geometry In Computer,Scond Edition所示,
    # 創建矩陣B和C
    tmp = V[:2].T
    B = tmp[:2]
    C = tmp[2:4]

    tmp2 = concatenate((dot(C, linalg.pinv(B)), zeros((2, 1))), axis=1)
    H = vstack((tmp2, [0, 0, 1]))

    # 反歸一化
    H = dot(linalg.inv(C2), dot(H, C1))

    return H / H[2, 2]

??同樣的,類似于DLT演算法,這些點需要經過預處理和去處理化操作,


二、影像扭曲

??對影像塊應用仿射變換,我們將其稱為影像扭曲(或者 仿射扭曲),該操作不僅經常在計算機圖形學中,而且經常出現在計算機視覺演算法總,扭曲的操作可以使用SciPy工具包中的ndimage包來簡單完成,命令:

transform_im = ndimage.affine_transform(im, A, b, size)

??使用上面所示的一個線性變換A和一個平移向量b來對影像塊應用放射變換,選項引數 size 可以用來指定輸出影像的大小,

??我們可以運行下列代碼來研究該函式是如何作業的:

from numpy import *
from matplotlib.pyplot import *
from scipy import ndimage
from PIL import Image

# 解決中文亂碼
rcParams['font.sans-serif'] = 'SimHei'
rcParams['axes.unicode_minus'] = False

im = array(Image.open('image/image1.jpg').convert('L'))
H = array([[1.4,0.05,-100],[0.05,1.5,-100],[0,0,1]])
im2 = ndimage.affine_transform(im, H[:2,:2],(H[0,2],H[1,2]))

gray()
subplot(121)
imshow(im)
title("原始影像")
axis('off')
subplot(122)
imshow(im2)
title("扭曲后的影像")
axis('off')
show()

運行結果:
在這里插入圖片描述
??從運行結果可以看出,原始影像(左)和扭曲后的影像(右)的差別,扭曲后的影像中丟失的像素用零來填充,

2.1 影像中的影像

??仿射扭曲的一個簡單例子是,將影像或者影像的一部分放置在另一幅影像中,是的他們能夠和指定的區域或者標記物對齊,

??將函式 image_in_image() 添加到 wary.py 檔案中,該函式的輸入引數為兩幅影像和一個坐標,該坐標為將第一幅影像放置到第二幅影像中的角點坐標:

import homography
from scipy import ndimage
from numpy import *

def image_in_image(im1, im2, tp):
    """使用仿射變換將im1放置在im2上,使im1影像的角和tp盡可能的靠近
        tp是齊次表示的,并且是按照從左上角逆時針計算的"""

    # 扭曲的點
    m, n = im1.shape[:2]
    fp = array([[0, m, m, 0], [0, 0, n, n], [1, 1, 1, 1]])

    # 計算仿射變換,并且將其應用于影像im1中
    H = homography.Haffine_from_points(tp, fp)
    im1_t = ndimage.affine_transform(im1, H[:2, :2],
                                     (H[0, 2], H[1, 2]), im2.shape[:2])
    alpha = (im1_t > 0)

    return (1 - alpha) * im2 + alpha * im1_t

??將扭曲的影像和第二幅影像融合,就創建 alpha 影像,該影像定義了每個像素從各個影像中獲取的像素值成分多少,這里基于以下事實:扭曲的影像是在扭曲區域邊界之外以 0 來填充的影像,來創建一個二值的 alpha 影像,嚴格意義上,需要在第一幅圖象中的潛在 0 像素上加上一個小的數值,或者合理的處理這些 0 像素,

注意:我們使用的影像坐標是齊次坐標意義下的,

使用仿射變換放置影像

??我們試著使用該函式將一幅影像插入另一幅影像,

import warp
from numpy import *
from matplotlib.pyplot import *
from PIL import Image

# 將im1仿射扭曲到im2的指定位置
im1 = array(Image.open('image/1.jpg').convert('L'))
im2 = array(Image.open('image/image3.jpg').convert('L'))

figure()
gray()
subplot(121)
imshow(im1)
axis('equal')
axis('off')
subplot(122)
imshow(im2)
axis('equal')
axis('off')

# 選定一些目標點
tp = array([[862, 1019, 1019, 866], [905, 911, 1107, 1096], [1, 1, 1, 1]])

# 呼叫的warp.py的image_in_image函式,從而實作仿射變換
im3 = warp.image_in_image(im1, im2, tp)

figure()
imshow(im3)
axis('equal')
axis('off')
show()

運行結果:
在這里插入圖片描述

在這里插入圖片描述
??從運行結果上看,圖片將原本右下角的一個公告去給替換了,因為 tp 中的齊次坐標是對應公告牌的坐標,所以將其放置到該位置,那么,

使用ginput函式獲取 tp 中的齊次坐標值

??其中,tp 中選取的點的坐標值可以通過手工確定,也可以通過 PyLab 類別庫中的 ginput() 函式獲得,可以使用下面的代碼實作點齊次坐標的獲取:

from PIL import Image
from pylab import *
import numpy as np

im = array(Image.open('image/image3.jpg'))
imshow(im)

print('Please click 4 point')
points = ginput(4)

# 轉整數
int_points = np.int_(points)

# 行列互換操作
new_points = list(map(list, zip(*int_points)))

print('you clicked x:', new_points[1])
print('you clicked y:', new_points[0])
show()

運行結果:

選取點的順序運行結果

??然后就可以用 x 的坐標替換掉 tp 中的第一個引數串列,用 y 替換掉 tp 中的第而個引數串列:

# tp = array([[264, 538, 540, 264], [40, 36, 605, 605], [1, 1, 1, 1]])
# 替換成
tp = array([[862, 1019, 1019, 866], [905, 911, 1107, 1096], [1, 1, 1, 1]])

注意:運行上述代碼選取點時,要按照上圖的給的順序點擊,不然可能會出現圖片位置錯誤、圖片旋轉等一些問題!因為 image_in_image() 函式中的 tp 是按照從左上角逆時針計算的,

??函式 Haffine_from_points() 會回傳給定對應點對的最優仿射變換,在上面的例子中,對應點對為影像和公告牌的角點,如果透視效應比較弱,那么這種方法會回傳很好的結果,

??對于三個點,仿射變換可以將一幅影像進行扭曲,使這三對對應點對可以完美地匹配上,這是因為,仿射變換具有 6 個自由度,三個對應點對可以給出 6 個約束條件(對于這三個對應點對,x 和 y 坐標必須都要匹配),所以,如果你真的打算使用仿射變換將影像放置到公告牌上,可以將影像分成兩個三角形,然后對它們分別進行扭曲影像操作,代碼如下:

from warp import *
from numpy import *
from matplotlib.pyplot import *
from PIL import Image

im1 = array(Image.open('image/1.jpg').convert('L'))
im2 = array(Image.open('image/image3.jpg').convert('L'))

# 選取 im1 角上的一些點
m, n = im1.shape[:2]
fp = array([[0, m, m, 0], [0, 0, n, n], [1, 1, 1, 1]])

# 選定一些目標點
tp = array([[862, 1019, 1019, 866], [905, 911, 1107, 1096], [1, 1, 1, 1]])

# 第一個三角形
tp2 = tp[:, :3]
fp2 = fp[:, :3]

# 計算 H
H = Haffine_from_points(tp2, fp2)
im1_t = ndimage.affine_transform(im1, H[:2, :2],
                                 (H[0, 2], H[1, 2]), im2.shape[:2])

# 三角形的 alpha 影像
alpha = alpha_for_triangle(tp2, im2.shape[0], im2.shape[1])
im3 = (1 - alpha) * im2 + alpha * im1_t

# 第二個三角形
tp2 = tp[:, [0, 2, 3]]
fp2 = fp[:, [0, 2, 3]]

# 計算 H
H = Haffine_from_points(tp2, fp2)
im1_t = ndimage.affine_transform(im1, H[:2, :2],
                                 (H[0, 2], H[1, 2]), im2.shape[:2])

# 三角形的 alpha 影像
alpha = alpha_for_triangle(tp2, im2.shape[0], im2.shape[1])
im4 = (1 - alpha) * im3 + alpha * im1_t

figure()
gray()
subplot(121)
imshow(im3)
axis('equal')
axis('off')
subplot(122)
imshow(im4)
axis('equal')
axis('off')
show()

運行結果:
在這里插入圖片描述
??這里我們簡單地為每個三角形創建了 alpha 影像,然后將所有的影像合并起來,該三角形的 alpha 影像可以簡單地通過檢查像素的坐標是否能夠寫成三角形頂點坐標的凸組合來計算得出,如果坐標可以表示成這種形式,那么該像素就位于三角形的內部,上面的例子使用了下面的函式 alpha_for_triangle(),將其添加到 warp.py 檔案中,

def alpha_for_triangle(points, m, n):
    """對于帶有由 points 定義角點的三角形,創建大小為 (m, n) 的alpha 圖
    (在歸一化的齊次坐標意義下)"""

    alpha = zeros((m, n))
    for i in range(min(points[0]), max(points[0])):
        for j in range(min(points[1]), max(points[1])):
            x = linalg.solve(points, [i, j, 1])
            if min(x) > 0:  # 所有系數都大于零
                alpha[i, j] = 1
    return alpha

??這樣顯卡可以極其快速地操作上面的代碼,Python 語言的處理速度比你的顯卡(或者 C/C++ 實作)慢很多,但是對于我們來說已經夠用了,

2.2 分段仿射扭曲

??正如上面的例子所示,三角形影像塊的仿射扭曲可以完成角點的精確匹配,讓我們看一下對應點對集合之間最常用的扭曲方式:分段仿射扭曲,給定任意影像的標記點,通過將這些點進行三角剖分,然后使用仿射扭曲來扭曲每個三角形,我們可以將影像和另一幅影像的對應標記點扭曲對應,對于任何圖形和影像處理庫來說,這些都是最基本的操作,下面我們來演示一下如何使用 Matplotlib 和 SciPy 來完成該操作,

為了三角化這些點,我們經常使用狄洛克三角剖分方法,在 Matplotlib(但是不在 PyLab 庫中)中有狄洛克三角剖分,我們可以用下面的方式使用它:

from numpy import *
from matplotlib.pyplot import *
from scipy.spatial import Delaunay

x, y = array(random.standard_normal((2, 100)))
tri = Delaunay(np.c_[x, y]).simplices

figure()
for t in tri:
    t_ext = [t[0], t[1], t[2], t[0]] # 將第一個點加入到最后
    plot(x[t_ext], y[t_ext], 'r')

plot(x, y, '*')
axis('off')

figure()
plot(x, y, '*')
axis('off')
show()

運行結果:

??運行結果顯示了一些實體點和三角剖分的結果,狄洛克三角剖分選擇一些三角形,使三角剖分中所有三角形的最小角度最大(三角剖分中的邊實際上是泰森圖的對偶圖),函式 delaunay() 有 4 個輸出,其中我們僅需要三角形串列資訊(第三個輸出),在 warp.py 檔案中創建用于三角剖分的函式:

from scipy.spatial import Delaunay

def triangulate_points(x, y):
    """二維點的 Delaunay 三角剖分"""

    # centers, edges, tri, neighbors = Delaunay(x, y)
    tri = Delaunay(np.c_[x, y]).simplices
    return tri

??函式輸出的是一個陣列,該陣列的每一行包含對應陣列 x 和 y 中每個三角形三個點的切片,

??現在將該演算法應用于一個例子,在該例子中,在 5×6 的網格上使用 30 個控制點,將一幅影像扭曲到另一幅影像中的非平坦區域,圖 3-5b 所示的是將一幅影像扭曲到“turning torso”的表面,目標點是使用 ginput() 函式手工選取出來的,將結果保存在 turningtorso_points.txt 檔案中;

??然后我們使用下面簡短的腳本將這些操作統一起來:

 # -*- coding: utf-8 -*-
from pylab import *
from PIL import Image
from PCV.geometry import warp

# 打開影像,并將其扭曲
fromim = array(Image.open('image/sunset_tree.jpg'))
x, y = meshgrid(range(5), range(6))
x = (fromim.shape[1]/4) * x.flatten()
y = (fromim.shape[0]/5) * y.flatten()

# 三角剖分
tri = warp.triangulate_points(x, y)

# 打開影像和目標點
im = array(Image.open('image/turningtorso1.jpg'))
tp = loadtxt('turningtorso1_points.txt') # destination points

figure()
subplot(1, 4, 1)
axis('off')
imshow(im)

# 將點轉換成齊次坐標
fp = array(vstack((y, x, ones((1, len(x))))), 'int')
tp = array(vstack((tp[:, 1], tp[:, 0], ones((1, len(tp))))), 'int')

# 扭曲三角形
im = warp.pw_affine(fromim, im, fp, tp, tri)

# 繪制影像
subplot(1, 4, 2)
axis('off')
imshow(fromim)
warp.plot_mesh(fp[1], fp[0], tri)
subplot(1, 4, 3)
axis('off')
imshow(im)
subplot(1, 4, 4)
axis('off')
imshow(im)
warp.plot_mesh(tp[1], tp[0], tri)
show()

??再通過下面的輔助函式(將其添加到 warp.py 檔案中)來繪制出影像中的這些三角形:

def plot_mesh(x,y,tri):
    """ 繪制三角形"""
    for t in tri:
        t_ext = [t[0], t[1], t[2], t[0]] # 將第一個點加入到最后
        plot(x[t_ext],y[t_ext],'r')

運行結果:
在這里插入圖片描述

??使用狄洛克三角剖分標記點進行分段仿射扭曲:第一張為帶有標記物的目標影像;第二張為帶有三角剖分的影像;第三張為扭曲后的影像;第四張為帶有三角剖分的扭曲影像,

如果運行教材上的代碼報錯:ModuleNotFoundError: No module named ‘matplotlib.delaunay’
import matplotlib.delaunay as md 改成 from scipy.spatial import Delaunay
并將 triangulate_points() 函式中的 centers, edges, tri, neighbors = Delaunay(x, y) 改成 tri = Delaunay(np.c_[x,y]).simplices

使用狄洛克三角剖分標記點進行分段仿射扭曲使用的 turningtorso1_points.txt 檔案可以從該網站上下載: Programming Computer Vision with Python

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/274729.html

標籤:其他

上一篇:影像到影像的映射——實驗3

下一篇:2021-04-10 粵嵌單片機興趣課(一)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more