Python+OpenCV如何實(shí)現(xiàn)自動(dòng)海報(bào)場(chǎng)景替換,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
十余年的馬尾網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。營(yíng)銷型網(wǎng)站的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整馬尾建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。成都創(chuàng)新互聯(lián)從事“馬尾網(wǎng)站設(shè)計(jì)”,“馬尾網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
現(xiàn)存在一個(gè)問題,就下面圖片中的兩本書而言,怎樣快速讓中間邊的書本與左邊書本對(duì)齊(最終效果能實(shí)現(xiàn)兩張圖片重疊(最終結(jié)果為右圖)),進(jìn)行的圖像轉(zhuǎn)變可旋轉(zhuǎn)、平移、縮放、形變。
主要內(nèi)容就是介紹利用 Opencv 來怎樣解決上面的問題,解決這個(gè)問題需要三步
確定至少四組對(duì)應(yīng)點(diǎn)坐標(biāo)
找到一個(gè)轉(zhuǎn)換矩陣;
把找到的轉(zhuǎn)換矩陣應(yīng)用到 Moving Image(需要移動(dòng)的圖片) 上,實(shí)現(xiàn)圖像對(duì)齊
圖片旋轉(zhuǎn)、平移、縮放等操作的主要目的,就是要最終實(shí)現(xiàn)兩圖像中點(diǎn)對(duì)點(diǎn)一一映射關(guān)系,圖像映射本質(zhì)上就是像素點(diǎn)轉(zhuǎn)換
圖中標(biāo)記了其中四組對(duì)應(yīng)點(diǎn),分別標(biāo)為不同的顏色,分別標(biāo)為紅、橙、黃和綠四種顏色;比如這里的 和 是就是一組對(duì)應(yīng)點(diǎn),圖片經(jīng)過轉(zhuǎn)換之后 點(diǎn) 必須映射到 點(diǎn)位置。
涉及圖片中點(diǎn)坐標(biāo)變換,都需要借助于 矩陣 運(yùn)算,這里探究的圖像維度都屬于二維,坐標(biāo)只需要 即可
面向此類轉(zhuǎn)換問題,Homography 轉(zhuǎn)換 ( 3 × 3 矩陣) 可用于解決此類轉(zhuǎn)化問題,用來解決點(diǎn)對(duì)點(diǎn)映射問題,Homography 矩陣可寫作下列方式:
則 、 作為對(duì)應(yīng)點(diǎn),則 Homography 的的應(yīng)用 如下:
而矩陣 H 參數(shù)的確定至少需要 4 組對(duì)應(yīng)點(diǎn),因此在計(jì)算 H 時(shí)至少要找到 4 組對(duì)應(yīng)點(diǎn);找到的對(duì)應(yīng)點(diǎn)組數(shù)越多,計(jì)算得到的 H 會(huì)越精確,最終的轉(zhuǎn)換效果也就會(huì)越好。
下面用 Opencv + Python 來實(shí)現(xiàn)上面圖片中的書籍的對(duì)齊,
import cv2
import numpy as np
if __name__ =='__main__':
#圖片讀取
img_src = cv2.imread("D:/book2.jpg")
position_src = np.array([[141,131],[480,159],[493,630],[64,601]],dtype = float)
img_dst = cv2.imread("D:/book1.jpg")
position_dst = np.array([[318,256],[543,372],[316,670],[73,473]],dtype = float)
#計(jì)算轉(zhuǎn)換矩陣
h,status = cv2.findHomography(position_src,position_dst)
#對(duì)圖片進(jìn)行仿射變換
out_img = cv2.warpPerspective(img_src,h,(img_dst.shape[1],img_dst.shape[0]))
#Display images;
cv2.imshow("Source image",img_src)
cv2.imshow("Destination Image",img_dst)
cv2.imshow("Warped Source Image",out_img)
cv2.waitKey(0)
這里事先已經(jīng)確定好對(duì)應(yīng)的四個(gè)點(diǎn)的坐標(biāo),然后把這四個(gè)點(diǎn)的坐標(biāo)帶入 cv2.findHomography() 計(jì)算出轉(zhuǎn)換矩陣,最后把矩陣應(yīng)用到兩圖像中,得到最終的轉(zhuǎn)換結(jié)果,
這里提醒一點(diǎn),warpPerspective 函數(shù)進(jìn)行對(duì)圖像像素進(jìn)行矩陣變換時(shí),隱藏了一個(gè)參數(shù) Interpolator ,默認(rèn)為線性插值,功能是防止像素點(diǎn)像素值缺失
上面小案例不方便的一點(diǎn)需要確定對(duì)應(yīng)四個(gè)點(diǎn)的坐標(biāo),這個(gè)步驟是比較繁瑣的,下面案例將在程序中加入交互功能,實(shí)現(xiàn)某個(gè)圖片的自動(dòng)標(biāo)記點(diǎn)收集、標(biāo)記點(diǎn)點(diǎn)轉(zhuǎn)換:
首先需要準(zhǔn)備兩張圖片,其中一張為海報(bào),一張為需要替換的海報(bào);關(guān)于確定點(diǎn)的坐標(biāo)時(shí),被替換的圖片的坐標(biāo)非常好確定,只需知道圖片的長(zhǎng)寬即可;
但的海報(bào)圖像區(qū)域四個(gè)點(diǎn)是不好確定的, 這里利用 Opencv 的鼠標(biāo)回調(diào)函數(shù),監(jiān)視鼠標(biāo)響應(yīng),根據(jù)用戶點(diǎn)擊來收集 PIck 得到的坐標(biāo);
def mouse_handler(event,x,y,flags,data):
if event ==cv2.EVENT_LBUTTONDOWN:
cv2.circle(data['im'],(x,y),3,(0,0,255),5,16)
cv2.namedWindow("Image",0)
cv2.imshow("Image",data['im'])
if len(data['points']) <4:
data['points'].append([x,y])
def get_four_points(im):
data = {}
data['im'] = im.copy()
data['points'] = []
# Set the callback function for any mouse event
cv2.namedWindow("Image", 0)
cv2.imshow('Image',im)
#請(qǐng)注意你標(biāo)記點(diǎn)的數(shù)據(jù),是順時(shí)針,需要與pst_src 方向一致
cv2.setMouseCallback("Image",mouse_handler,data)
cv2.waitKey(0)
# Convert array to np.array
#豎直方向堆疊起來;;;
points = np.vstack(data['points']).astype(float)
return points
坐標(biāo)確定以后,接下來就很簡(jiǎn)單了,跟上個(gè)案例一樣,計(jì)算變換矩陣,矩陣應(yīng)用到圖像旋轉(zhuǎn),最終更換海報(bào)內(nèi)容也就輕松完成啦
需要注意一點(diǎn),坐標(biāo) Pick 點(diǎn)的順序須與記錄替換圖像頂點(diǎn)順序一致,否則轉(zhuǎn)換圖會(huì)有偏差,案例完整代碼如下:
if __name__ =='__main__':
img_src = cv2.imread("D:/first-image.jpg")
size = img_src.shape
# 取得四個(gè)坐標(biāo)
pst_src = np.array(
[
[0,0],[size[1]-1,0],
[size[1]-1,size[0]-1],
[0,size[0]-1]
],dtype=float
)
#Read the destination image
img_dst = cv2.imread("D:/times-square.jpg")
print("Click on four corners of bllboard and the press ENTER")
four_point = get_four_points(img_dst)
# Calculate Homography between source and destination points
h,status = cv2.findHomography(pst_src,four_point)
im_temp = cv2.warpPerspective(img_src,h,(img_dst.shape[1],img_dst.shape[0]))
cv2.fillConvexPoly(img_dst,four_point.astype(int),0,16)
#add wraped source image to destination image
img_dst = img_dst + im_temp
cv2.namedWindow("Image", 0)
cv2.imshow("Image",img_dst)
cv2.waitKey(0)
看完上述內(nèi)容,你們掌握Python+OpenCV如何實(shí)現(xiàn)自動(dòng)海報(bào)場(chǎng)景替換的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!