利用OpenCV建立視差圖像

2021-02-08 OpenCV學堂

點擊上方↑↑↑「OpenCV學堂」關注我

來源:公眾號 小白學視覺 授權


我們都看過3D電影,他們看起來都很酷,這給了我們一個想法,使用一些工具通過改變看圖像視角,模擬觀眾的頭部移動。

效果如何?
我們都熟悉"視差"這一術語,它是描述對象在左右眼中的位置差距,視差的大小這取決於我們離它有多遠。

視差

因此,如果我們能在2D圖像中獲得與不同圖像層的相同效果,那麼我們可以在這些圖像中產生類似的感覺,並產生我們想要的酷效果。

讓我們分解一下這個過程

深度圖

因此,首先,我們需要將圖像分解為不同的圖層,並且,我們需要一個2D圖像的深度圖。深度圖只是一個黑白圖像,其中圖像的白色顯示對象與鏡頭的接近度。獲得基本圖層後,我們需要從每個圖層中畫出缺失的部分。最後,我們將單個圖像分解成不同的圖層。現在,我們可以顯示不同的圖層,這些圖層看起來與原始圖像相同。現在,我們可以使用相機進行人臉檢測,並測量用戶頭部的移動,然後移動這些圖層並進行匹配。

讓我們看看如何編寫此工具的代碼

因此,首先,我們需要導入一些文件,建議使用版本 4.1.0.25 的 OpenCV。

import os, sysimport numpy as npimport pygame as pgimport cv2

現在,我們需要加載圖像和深度圖,並調整它們的大小以匹配大小。現在,我們將提供一個深度圖、代碼,但你可以生成自己的模型MiDaS。

img = cv2.imread('moon.jpg', flags=cv2.CV_8UC4)depth_map = cv2.imread('moon_depth_map.png')depth_map = cv2.cvtColor(depth_map,cv2.COLOR_RGB2GRAY)img = cv2.resize(img, depth_map.shape[:2])


現在,在加載深度貼圖後,我們可以通過按不同閾值對深度貼圖不同圖層創建蒙版。在製作一個圖層時,我們需要兩個蒙版,一個是該圖層,另一個是上一層的第二個蒙版,用於畫上一個圖層的缺失部分。我們將在循環之外取最後一個圖層,以便提取此層中的所有剩餘部分。

   layers = []     prev_thres = 255div=30     for thres in range(255 - div, 0, -div):           ret, mask = cv2.threshold(depth_map, thres, 255,          cv2.THRESH_BINARY)           ret, prev_mask = cv2.threshold(depth_map, prev_thres, 255, cv2.THRESH_BINARY)            prev_thres = thres           inpaint_img = cv2.inpaint(img, prev_mask, 10, cv2.INPAINT_NS)   layer = cv2.bitwise_and(inpaint_img, inpaint_img, mask = mask)    layers.append(conv_cv_alpha(layer, mask))         mask = np.zeros(depth_map.shape, np.uint8)    mask[:,:] = 255    ret, prev_mask = cv2.threshold(depth_map, prev_thres, 255, cv2.THRESH_BINARY)     inpaint_img = cv2.inpaint(img, prev_mask, 10, cv2.INPAINT_NS)    layer = cv2.bitwise_and(inpaint_img, inpaint_img, mask = mask)layers.append(conv_cv_alpha(layer, mask))     layers = layers[::-1]

我們已經反轉了圖層,因此我們可以按最後一個層排列到第一層的順序排列它們。當我們將圖層添加到列表中時,我們使用的是函數[conv_cv_alpha],這將添加 alpha 值(使 RGB 到 RGBA),並使用蒙版使圖層的某些部分透明。

def conv_cv_alpha(cv_image, mask):        b, g, r = cv2.split(cv_image)        rgba = [r, g, b, mask]        cv_image = cv2.merge(rgba,4)                  return cv_image

現在來了人臉檢測和顯示圖像的部分。對於人臉檢測,我們將使用哈卡卡德。現在,我們將加載 haar 級聯進行人臉檢測,並創建一個函數,該函數將從圖像中返回人臉。

face_cascade = cv2.CascadeClassifier( 'haarcascade_frontalface_default.xml')   
def get_face_rect(img): gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) face_rects = face_cascade.detectMultiScale(gray_img, 1.3, 5) if len(face_rects) == 0: return () return face_rects[0]

現在,我們必須顯示圖像,將根據用戶的頭移動。我們將使用OpenCV讀取凸輪,然後使用 Pygame將每個幀呈現在彼此的頂部。為了計算每一層的移位,我們將計算從框架中心的頭部移位,然後縮小頭移位以獲得一個小的移位值。之後,我們將每個圖層的索引值相乘,以獲得相應圖層的移位值,還可以乘以一些常量值,以獲得更好的結果。

我們將創建一個比原始圖像稍小的 Pygame 窗口並加載相機。我們使用了比例,因此您更改其值以使最終結果變大。

scale = 1off_set = 20width, height = layers[0].get_width(), layers[0].get_height()        win = pg.display.set_mode((int((width - off_set)*scale), int((height - off_set)*scale)))    pg.display.set_caption('Parallax_image')scaled_layers = []    for layer in layers:              scaled_layers.append(pg.transform.scale(layer, (int(width*scale), int(height*scale))))cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)

我們將設置一些常量。你可以玩這些常量來獲得不同的結果。

x_transform = True     y_transform = False    sens = 50              show_cam = False       shift_x = 0    shift_y = 0    run = True

最後,主循環渲染所有圖層。

while run:    for event in pg.event.get():        if event.type==pg.QUIT:            run = False    ret, frame = cap.read()    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)    initial_pos = (frame.shape[0]/2, frame.shape[1]/2)    face_rect = get_face_rect(frame)    if len(face_rect) != 0:        x,y,w,h, = face_rect        face_rect_frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (255,255,0), 3)        shift_x = (initial_pos[0] - (x + w/2))/(sens*scale)        shift_y = (initial_pos[1] - (y + h/2))/(sens*scale)    win.fill((255, 255, 255))                     for i, layer in enumerate(scaled_layers):        new_x = -off_set/2        new_y = -off_set/2        if x_transform:            new_x = 0 + shift_x*i        if y_transform:            new_y = 0 + shift_y*i        win.blit(layer, (new_x, new_y))            face_rect_frame = cv2.resize(face_rect_frame, (100, 100))   if show_cam:       win.blit(conv_cv_pygame(face_rect_frame), (0, 0))   pg.display.update()cap.release()cv2.destroyAllWindows()pg.quit()

就是這裡,最終結果。


最終結果


不同圖像的演示

我已經創建了一個更高級版本的這個工具,你可以只選擇圖像,它會自動創建視差圖像,深度地圖將自動生成。

代碼連結:https://github.com/strikeraryu/Parallax_Image

相關焦點

  • Python中如何利用Opencv打開視頻或圖像並用PyQt控制項顯示
    OpenCV是一個基於BSD許可(開源)發行的跨平臺計算機視覺庫,可以運行在Linux、Windows、Android和Mac OS作業系統上,使用起來十分方便,把它與PyQt結合起來,就可以順利的操作視頻、圖像了。具體安裝請自行百度,這裡介紹使用方法。
  • opencv-python獲取圖像:面向對象與面向過程
    獲取圖像的方式有:1,讀取本地圖片,2,調用筆記本自帶攝像頭或usb攝像頭,3,調用網絡攝像頭。這裡需要注意以下,opencv讀取圖片默認通道為BGR的格式,當在其他UI用戶界面顯示圖像時注意轉換一下通道順序,例如BGR轉換成RGB:Image1=cv2.cvtColor(image, cv2.COLOR_BGR2RGB)下面讀取一張圖片並顯示
  • OpenCV 4.5 發布!
    9.12.https://github.com/opencv/opencv/wiki/ChangeLog#version450在我愛計算機視覺公眾號後臺回復「opencv」,即可收到包含4.5版本的OpenCV各版本的下載。
  • 什麼是「視差」
    從目標看兩個點之間的夾角,叫做這兩個點的視差角,兩點之間的距離稱作基線。只要知道視差角度和基線長度,就可以計算出目標和觀測者之間的距離。視差簡介要學會利用角度、利用視差。別忘了:如果兩眼之間沒有3CM的距離,那麼你永遠無法享受3D!科學應用測量學⑴視差是在光學實驗的調整過程中,隨著眼睛的晃動(觀察位置稍微改變),標尺與被測物體之間產
  • 使用OpenCv和Dlib進行打哈欠檢測
    Dlib: Dlib是一個Python庫,包含了數據挖掘、數據結構、機器學習、圖像處理等工具。打哈欠檢測與應用打哈欠檢測就是使用OpenCV和Dlib來檢測打哈欠(由於疲勞或無聊而張大嘴巴深吸氣)。可廣泛應用於自駕車、駕駛員疲勞檢測、駕駛員睡意檢測、駕駛員意識檢測等領域。
  • opencv教程-光流法
    opencv裡的光流法有兩種,稀疏光流法 和 稠密光流法。簡單理解的話光流就是一個向量,包含在一定時間間隔內x方向位置的變化、y方向位置的變化,所以其三個主要因素就是dx,dy,dt。主要輸入:prevImg:前一張灰度圖nextImg:當前圖片prevPts:要匹配的點(比如拐點、角點),float主要輸出:nextPts:根據prevPts以及當前圖像計算的新點status:nextPts與prevPts是否匹配狀態,1為匹配,0為不匹配err:光流點匹配的錯誤信息
  • 手把手:使用OpenCV進行面部合成— C++ / Python
    所以,為了將圖片I過渡合成到圖片J,我們需要先在兩張圖片之間建立對應像素點。換句話說,對於圖片I中的每一個像素點 ,我們需要在圖片J中找到對應像素點 。假設我們已經神奇般地找到了所有對應點,我們可以用兩個步驟將圖片混合。第一步,我們需要計算合成圖片中像素點 的位置。可以由以下方程算出
  • OpenCV黑魔法之隱身衣 | 附源碼
    為什麼捕獲背景圖像使用'循環' ?因為背景是靜態的,我們不能簡單地使用一個幀嗎?當然,但是與多幀圖像相比,捕獲的圖像有點暗。這是因為相機剛剛開始捕捉幀,因此它的參數還不穩定。因此,使用for循環捕獲靜態背景的多個圖像就可以完成這個任務。多幀平均也可以降低噪聲。
  • ICEVE精選 | Lytro CTO Kurt Akeley:虛擬實境中的視差
    視差應用於各個方面,舉一個尤其有趣的例子:從地球上觀察星星。利用地球公轉的運動規律,當地球轉到太陽不同方位時可以明顯觀察到星星排列的不同,那麼具體星星的排列發生了什麼樣的變化,就是傳統意義上的視差所研究的內容。
  • 如何用OpenCV製作一個低成本的立體相機
    我們準備好生成視差圖和3D視頻了嗎?二、立體相機標定和校正的重要性為了理解標定和校正的重要性,我們試著用剛DIY好的立體相機捕獲到的圖像生成一個沒有標定和校正過的視差圖。左圖是立體相機捕獲到的左右圖像;右圖是用沒有標定過的左右圖像生成的視差圖。我們觀察到,使用未校準的立體相機生成的視差圖非常嘈雜且不準確。為什麼會這樣?
  • Python 圖像處理 OpenCV (15):圖像輪廓
    本篇文章是關於圖像處理輪廓方面的,下面開始正文,希望能幫到各位。Q:什麼是輪廓?A:輪廓是一系列相連的點組成的曲線,代表了物體的基本外形,相對於邊緣,輪廓是連續的,邊緣並不全部連續。gray_img, 127, 255, 0)# 尋找輪廓contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)print(len(contours[0]))這段代碼先用 threshold() 對圖像進行降噪處理
  • 使用Python+OpenCV進行面部合成
    原文 http://www.learnopencv.com/face-morph-using-opencv-cpp-python/
  • 談談OpenCV中的四邊形
    因為這些點是矩形區域拍攝圖像後識別得到的圖形的邊界點,所以我們要抽象出來這個矩形,也就是我們要反映出這個矩形。問題是在拍照的時候攝像頭可能不是正對著圖形的,那麼矩形就必然在圖像上反映為一個四邊形, 如下圖所示。那怎麼得到這個四邊形的四個頂點呢?使用經典圖像處理的算法的話可以使用OpenCV提供了幾個和矩形相關的函數接口。另一類就是使用機器學習類算法檢測定位四個角點。
  • 圖像特徵點、投影變換與圖像拼接
    事實上,不僅僅是在數字圖像處理時代人們使用投影變換,在平常的生活中人們早就在利用投影變換了。比如,你很可能了解甚至親眼見過3D繪畫,藝術家利用透視原理在地上作畫,從而在某一個視角觀看時可以有非常逼真的3D效果。
  • 圖像特徵點、投影變換與圖像拼接
    事實上,不僅僅是在數字圖像處理時代人們使用投影變換,在平常的生活中人們早就在利用投影變換了。比如,你很可能了解甚至親眼見過3D繪畫,藝術家利用透視原理在地上作畫,從而在某一個視角觀看時可以有非常逼真的3D效果。
  • 基於python+opencv的圖像目標區域自動提取
    檢測矩形並提取坐標需要對圖像進行預處理、邊緣檢測、提取輪廓、檢測凸包、角點檢測。由於執行該函數時會直接修改圖像,因此我們複製一份圖像之傳給cv2.findContours();同時,OpenCV提供了cv2.drawContour()函數繪可以把輪廓疊加到另一張圖片上。下面的代碼使用cv2.findContours()函數對mask圖片提取輪廓,並調用cv2.drawContour()把輪廓疊加在原始圖像。
  • KeyPose:從立體圖像估計透明物體3D姿態
    給定透明物體的RGB-D圖像, ClearGrasp使用深度神經網絡推測物體表面法線、透明表面的掩模和遮擋邊界,用於優化場景中所有透明曲面的初始深度估計(上圖中最右側).這種方法非常有前景的, 並且允許利用依賴於深度的姿勢估計的方法處理透明物體的場景.但是修復可能很難辦, 特別是完全使用合成的圖像進行訓練時,可能會導致深度的錯誤。
  • 緬甸羅興亞人問題的視差——歷史、現狀與癥結分析
    人們關注羅興亞人問題的來龍去脈時,受不同來源素材的影響,會不自覺地站在某個立場上,而這些立場往往有較大的歧異性,這便形成了羅興亞人問題的視差。本文擬從不同視角出發,梳理對羅興亞人的產生、詞義和境遇的分歧,分析視差碰撞下羅興亞人問題的危機現狀和走勢,進而梳理和分析其癥結所在。
  • 從泊松方程的解法,聊到泊松圖像融合
    至此,不難理解,離散數據(例如圖像)上的微分操作完全可以轉換為卷積操作。當數組維度更高,變成二維數組呢?也就是處理圖像的拉普拉斯算子: Poisson Image Editing背景知識儲備好了後,讓我們把目光拉回到論文《Poisson Image Editing》上。在圖像融合任務中,前景放置在背景上時,需要保證兩點:重點關注兩個詞:內容平滑、邊界一致。平滑是什麼?可以理解成圖像前景、背景梯度相同。邊界一致是指什麼?
  • PS教程 利用Photoshop製作個性文字圖像!
    網上那些個性的文字圖像,大家是不是都愛上了呢,可能苦於不知道怎麼去製作,現在福利來啦,筆者跟大家把製作過程搜羅來啦,大家記得學習哦!利用Photoshop製作個性文字圖像!完成效果原圖素材3、現在開始打【小字體】了,主要是把文字圍繞在打字身邊,其它地方用小字填充,儘量別複製,否則複製多的地方會出現平鋪一樣的紋理現象,如果遇到圖像面積比較大,那用複製也行,但是記得要改字體和大小。