天天看點

OpenCV做點好玩的!虛拟縮放

介紹

OpenCV 徹底改變了整個圖像處理領域。從圖像分類到對象檢測,我們不僅可以使用 OpenCV 庫做一些很酷的事情,而且還可以建構一流的應用程式。

今天我們要實作一個有趣的東西,它是手機或電腦中的一種功能,即圖像縮放。但在這裡,它将是實時對幀上所需的圖像進行虛拟縮放。

目錄

  1. 要求
  2. 目的
  3. 建構
  4. 結論

要求

對于這個項目,我們将使用 OpenCV 庫和另一個名為 Cvzone 的庫來使用虛拟縮放。

CVZone

它是一個建立在 OpenCV 和 MediaPipe 之上的庫。它使事情變得容易得多。

CVZone 具有一些非常有用的内置功能,例如手部跟蹤、面部标志檢測、姿勢估計等等。這些都可以通過幾行代碼來完成。

讓我們編寫一段代碼來看看使用 CVZone 的手部檢測器的示範。首先,安裝 requirements 。你可以使用以下指令安裝它,也可以逐個安裝。

– pip install -r requirements.txt

– pip install opencv-python==3.4.11.43

– pip install cvzone==1.5.3

現在讓我們檢測手。

import cv2
from cvzone.HandTrackingModule import HandDetector      
# Input from webcam
frame = cv2.VideoCapture(0)
frame.set(3, 1280)
frame.set(4, 720)

# initialize hand detector module with some confidence
handDetector = HandDetector(detectionCon=0.8)

# loop
while True:
# Read the frames from webcam
res, img = frame.read()

# detect the hands, by default it will detect two hands
hands = handDetector.findHands(img)

# show the output
cv2.imshow(“Sample CVZone output”, img)
cv2.waitKey(1)      

首先,讓我們導入所需的子產品,cv2,以及從 cvzone.HandTrackingModule 導入HandDetector*。*

然後我們将使用 OpenCV 的 Videocapture 功能從網絡攝像頭擷取輸入。設定視窗的高度和寬度,并以一定的檢測置信度初始化手部檢測器子產品。

然後在循環内部從網絡攝像頭讀取輸入幀并将其傳遞給手部檢測器子產品内部的方法,即 findHands。顯示圖像。

OpenCV做點好玩的!虛拟縮放

使用 OpenCV 進行虛拟縮放

與此類似,我們可以使用 CVZone 實作面部地标檢測、姿勢估計等。

目标

我們的目标是建構一個螢幕上有圖像的項目,使用 OpenCV 進行虛拟縮放,并使用我們的手勢,即如果雙手的食指和拇指向上并且兩根手指彼此遠離,就放大,如果雙手的食指和拇指向上并且兩根手指彼此靠近,則縮小該圖像或對象。牢記這一點,我們将制定一些步驟。

步驟

初始化來自網絡攝像頭的輸入。

設定輸出視窗的高度和寬度。

初始化手部檢測器子產品。

分别聲明計算距離、縮放範圍、中心X和中心Y的4個變量。

讀取輸入幀。

檢測雙手。

讀取用于縮放操作的圖像。

檢查是否檢測到兩隻手。

檢查食指和拇指是否向上。

計算兩隻手之間的距離,并将圖像調整到兩隻手的中心。

計算新的高度和寬度,然後調整圖像大小。

顯示輸出。

OpenCV做點好玩的!虛拟縮放

使用 OpenCV 進行虛拟縮放

建構

如上一節所述安裝所需的庫。現在讓我們開始吧。

首先,導入所需的子產品。這裡我們隻需要 cv2 和 cvzone 的手部檢測器子產品。

導入庫後,使用 cv2.VideoCapture(0) 從網絡攝像頭擷取輸入,其中 0 是網絡攝像頭 ID。

然後設定輸出視窗的寬度和高度。這裡是 1280 x 720。

import cv2
from cvzone.HandTrackingModule import HandDetector      
# Input from webcam
frame = cv2.VideoCapture(0)
frame.set(3, 1280)
frame.set(4, 720)      

現在,我們将初始化手檢測子產品(handDetector),檢測置信度為 0.8,并将在 while 循環中用于檢測手。

聲明 4 個變量,一個是初始存儲距離,它是None,一個是縮放範圍,初始是0,另外 2 個用于捕捉縮放對象的中心 X 和中心 Y,并設定一些随機值。

這裡代碼中的變量分别是 distStart、zoom_range、cx、cy。

# initialize hand detector module
handDetector = HandDetector(detectionCon=0.8)
distStart = None
zoom_range = 0
cx, cy = 500, 500      

開始一個while循環,從現在開始,一切操作都應該在這個循環中。

從網絡攝像頭讀取輸入,并使用上面初始化的手部檢測器子產品,我們可以調用方法 findHands 将幀作為輸入傳遞。此方法會在架構中找到手,預設它可以檢測架構中的兩隻手并傳回手的清單。

我們可以從中通路每隻檢測到的手(這裡:一隻手為hands[0],另一隻手為hands[1]),并且它還傳回圖像。然後我們将使用 OpenCV 的 imread() 函數讀取螢幕上要縮放的圖像。最好圖像大小應低于 (250, 250),否則你可以使用 cv2.resize(img, (250,250)) 調整其大小。這裡圖像大小為 (225, 225)。

while True:
    # Read the input frame
    res, img = frame.read()
    # Detect the hands
    hands, img = handDetector.findHands(img)
    # Image to be zoomed
    new_img = cv2.imread('resized_test.jpg')      

現在,我們需要檢查架構中是否有兩隻手,然後我們将檢查食指和拇指是否向上,這可以使用手檢測子產品中的 FingerUp() 方法輕松完成。

在下面的第一個 if 語句之後的代碼中,我們将使用兩個列印語句 print(handDetector.fingersUp(hands[0])) ,如果食指和拇指向上,則這将列印一個包含 5 個元素的清單,結果清單顯示一隻手将是 [1, 1, 0, 0, 0],另一隻手類似地執行 print(handDetector.fingersUp(hands[1]))。

請參考下圖。

# if two hands are detected
if len(hands) == 2:
    print("Start Zoom...")
    print(handDetector.fingersUp(hands[0]))
    print(handDetector.fingersUp(hands[1]))      
OpenCV做點好玩的!虛拟縮放

使用 OpenCV 進行虛拟縮放

然後是重要的部分,現在我們需要檢查雙手的食指和拇指是否向上。我們将再次使用 if 語句(在第一個 if 語句中:if handDetector.fingersUp(hands[0]) == [1, 1, 0, 0, 0] 和 handDetector.fingersUp(hands[1]) == [ 1, 1, 0, 0, 0]:) 然後求兩隻手之間的距離,具體來說就是食指兩點之間的距離。

在下面的代碼中,findDistance() 方法将找到距離,這裡我們将兩隻手的中心作為參數與架構一起傳遞。findDistance() 方法将傳回三個項目距離,一個包含位置 4 和 5 的中心 X 和中心 Y 的元組以及圖像。

如果僅當 distStart 為 None 時才執行條件,則将獲得的距離配置設定給我們之前聲明的第三個變量 distStart。然後,計算新距離并從舊距離 distStart 中減去它,并執行除以 2 (向下取整)以獲得縮放範圍。然後将中心坐标配置設定給變量cx,cy。然後,如果架構中沒有兩隻手,則将 distStart 變量重置為 None。

OpenCV做點好玩的!虛拟縮放

使用 OpenCV 進行虛拟縮放

if handDetector.fingersUp(hands[0]) == [1, 1, 0, 0, 0] and handDetector.fingersUp(hands[1]) == [1, 1, 0, 0, 0]:
        # print("Start Zoom...")
        lmList1 = hands[0]['lmList']
        lmList2 = hands[1]['lmList']
        # point 8 is tip of the index finger
        if distStart is None:
            # length, info, img = handDetector.findDistance(lmList1[8], lmList2[8], img)
            # draw the connection points between right hand index and thum finger to left hand
            length, info, img = handDetector.findDistance(hands[0]['center'], hands[1]['center'], img)
            # print(length)
            distStart = length      
# length, info, img = handDetector.findDistance(lmList1[8], lmList2[8], img)
length, info, img = handDetector.findDistance(hands[0][‘center’], hands[1][‘center’], img)
# info gives center x and center y
# calculate the zoom range
zoom_range = int((length – distStart) // 2)
# calculate the center point so that we can place the zooming image at the center
cx, cy = info[4:] print(zoom_range)

else:
distStart = None      

然後擷取要放大的圖像的高度和寬度,并計算圖像的新高度和寬度。這有點棘手,要獲得新的高度和寬度,我們需要将圖像之前的高度和寬度添加到縮放範圍并執行向下取整除法,然後乘以 2。

然後我們可以動态找到放置縮放的位置圖像(這裡:img[cy – newH // 2:cy + newH // 2, cx – newW // 2:cx + newW // 2])。

但是還有一個問題,如果縮放後的圖像低于視窗邊距,則會出錯,為了解決這個問題,我們将使用 try 和 except。然後顯示輸出。

try:
    h, w, _ = new_img.shape      
# new height and new width
newH, newW = ((h + zoom_range) // 2) * 2, ((w + zoom_range) // 2) * 2
new_img = cv2.resize(new_img, (newW, newH))

# we want the zooming image to be center and place it approx at the center
img[cy – newH // 2:cy + newH // 2, cx – newW // 2:cx + newW // 2] = new_img

except:
pass

# display output
cv2.imshow(‘output’, img)
cv2.waitKey(1)      

完整的代碼也可以在這個 GitHub 中找到:

​​https://github.com/BakingBrains/Virtual_Zoom_usinf_OpenCV.git​​

結論

這就是這篇關于使用 OpenCV 進行虛拟縮放的部落格的内容。如果你想即興發揮,讓它更有趣,你可以在螢幕上保留一些圖像,每次選擇一個并放大它,或者你可以建立不同的形狀,使用不同的手勢來讓它變大或變小。這就是我們如何使用 OpenCV 實作虛拟縮放。

參考:

繼續閱讀