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)圖像的輪廓。

本篇博客的目標(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)到圖片的位置如下圖所示。

一般情況下,我們描述一個矩形區(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)之和。


對于一個矩形區(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。

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)位置如下:

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