取經(jīng)之旅第 55 天,Python OpenCV 透視變換前置知識輪廓坐標(biāo)點(diǎn)

Python OpenCV 365 天學(xué)習(xí)計(jì)劃,與橡皮擦一起進(jìn)入圖像領(lǐng)域吧。本篇博客是這個系列的第 55 篇。
該系列文章導(dǎo)航參考:https://blog.csdn.net/hihell/category_10688961.html

學(xué)在前面

正式學(xué)習(xí)之前,先將上一篇 博客的內(nèi)容回顧一下,通過一系列的輪廓操作,得到了目標(biāo)圖像的輪廓。

20210320173715714[1].png

本篇博客的目標(biāo)將逐步實(shí)現(xiàn)對其進(jìn)行透視變換。

獲取輪廓的四個頂點(diǎn)坐標(biāo)

上篇博客已經(jīng)獲取到了輪廓坐標(biāo),但是每個坐標(biāo)對應(yīng)的位置是不確定的,需要通過計(jì)算將其明確出來。
輪廓坐標(biāo)從三維修改為二維

cv.drawContours(src, [screen_cnt], -1, (0, 0, 255), 2)

print(screen_cnt)
print(screen_cnt.shape)
print(screen_cnt.reshape(4, 2))

代碼運(yùn)行效果如下,圖片不同得到的數(shù)值不同。

[[[ 30  94]]
 [[ 17 273]]
 [[469 278]]
 [[462 106]]]
(4, 1, 2)
[[ 30  94]
 [ 17 273]
 [469 278]
 [462 106]]

坐標(biāo)轉(zhuǎn)換之后,對應(yīng)到圖片的位置如下圖所示。

20210320174124215[1].png

一般情況下,我們描述一個矩形區(qū)域,在 OpenCV 中,采用的是 左上,右上,右下,左下 順時(shí)針順序,所以接下來需要對這四個坐標(biāo)進(jìn)行轉(zhuǎn)換。

聲明一個函數(shù)進(jìn)行相應(yīng)的計(jì)算工作。

def change_points(input_points):
    pass

# 函數(shù)調(diào)用
change_points(screen_cnt.reshape(4, 2))

計(jì)算 4 個點(diǎn)橫縱坐標(biāo)之和

def change_points(input_points):
    s = input_points.sum(axis=1)
    print(s)

核心用到的是 numpy 中的 sum 函數(shù),注意 axis 軸參數(shù),0 表示豎向,1 表示橫向,這里的橫向就是該點(diǎn)的橫縱坐標(biāo)之和。

20210320174903730[1].png
20210320175002826[1].png

對于一個矩形區(qū)域,左上點(diǎn)與右下點(diǎn)分別是橫縱坐標(biāo)之和最小的點(diǎn)與最大的點(diǎn),基于此,繼續(xù)完善代碼。

下述代碼使用了 np.argmin()np.argmax() 函數(shù),可以通過搜索引擎進(jìn)行快速學(xué)習(xí)。

def change_points(input_points):
    s = input_points.sum(axis=1)
    p1 = input_points[np.argmin(s)]
    p3 = input_points[np.argmax(s)]
    print(p1,p3)

得到的數(shù)據(jù)如下:

[[ 30  94]
 [ 17 273]
 [469 278]
 [462 106]]
[30 94] [469 278]

左下點(diǎn)與右上點(diǎn)的計(jì)算方式為,使用 np.diff() 函數(shù),計(jì)算橫縱坐標(biāo)之差最小找到右上角的點(diǎn),橫縱坐標(biāo)之差最大找到左下角的點(diǎn)。對應(yīng)下圖可以輔助理解,左下點(diǎn) 300-100 = 200,右上點(diǎn) 100-400 = -300。

20210320175815245[1].png
def change_points(input_points):
    s = input_points.sum(axis=1)
    p1 = input_points[np.argmin(s)]
    p3 = input_points[np.argmax(s)]
    print(p1,p3)

    diff = np.diff(input_points,axis=1)
    p2 = input_points[np.argmin(diff)]
    p4 = input_points[np.argmax(diff)]
    print(p2,p4)

此時(shí),4 個坐標(biāo)都已經(jīng)獲取到,最后聲明一個空矩陣,賦值之后進(jìn)行返回。

def change_points(input_points):
    s = input_points.sum(axis=1)
    p1 = input_points[np.argmin(s)]
    p3 = input_points[np.argmax(s)]

    diff = np.diff(input_points, axis=1)
    p2 = input_points[np.argmin(diff)]
    p4 = input_points[np.argmax(diff)]

    # 聲明一個所有元素都為 0 的矩陣
    rect = np.zeros((4, 2), dtype="float32")
    rect[0] = p1
    rect[1] = p2
    rect[2] = p3
    rect[3] = p4
    print(rect)
    return rect
change_points(screen_cnt.reshape(4, 2))

坐標(biāo)數(shù)值與圖片對應(yīng)位置如下:


20210320180718263[1].png

橡皮擦的小節(jié)

希望今天的 1 個小時(shí)(貌似不太夠)你有所收獲,我們下篇博客見~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容