跳轉到

📚 手部偵測與體感互動

什麼是體感互動?

(26秒, 資料來源:1)


建議先備課程

在學習本課程前,建議先體驗過 「人臉偵測與臉部特徵」 ,在學習概念銜接上會較為平順。

kinect體感作品參考

筆者於2014年實作的kinect體感作品--機器娃娃

機器娃娃





📙 手與手勢偵測(3)

攝影機程式


運作流程

computuer_vision_flow


範例程式 攝影機程式 - - - - - - - (手與手勢偵測 1/3 新檔)
from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')

while True :
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)
    顯示影像(陣列)




手部特徵點


偵測流程

hand_detection_flow



手部關鍵點


hand-landmarks

(資料來源:2)


範例程式 手部特徵點 - - - - - - - (手與手勢偵測 2/3 接續)
from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')
偵測器 = 設置HandAndGesture()

while True :
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)

    結果 = 偵測器.process(陣列)
    if 結果:
        標記Hand(陣列, 結果)
    顯示影像(陣列)        




左右手與手勢



手勢偵測


手勢 中文說明
"None" 無手勢
"Closed_Fist" 握拳(石頭)
"Open_Palm" 開掌(布)
"Pointing_Up" 食指向上
"Thumb_Down" 拇指向下(倒讚)
"Thumb_Up" 拇指向上(讚)
"Victory" 勝利(剪刀)
"ILoveYou" 我愛你(伸出拇指、食指與小指)





範例程式 左右手與手勢 - - - - - - - (手與手勢偵測 3/3 接續)
from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')
偵測器 = 設置HandAndGesture()

while True :
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)

    結果 = 偵測器.process(陣列)
    if 結果:
        標記Hand(陣列, 結果)
         = 取出Hand(結果)
        print(.handedness)    
        print(.gesture)

    顯示影像(陣列)       




📗 幾何形狀互動(2)

直線互動


直線

line_point


範例程式 直線互動 - - - - - - - (幾何形狀互動 1/2 新檔)
from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')
偵測器 = 設置HandAndGesture()

while True :
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)
    結果 = 偵測器.process(陣列)

    if 結果:
         = 取出Hand(結果)
        手指1 = .特徵點(索引=8)
        手指2 = .特徵點(索引=4)

        畫直線(image=陣列,
            pt1=手指1,
            pt2=手指2)
        畫圓形(image=陣列,
            center=手指1,
            radius=5,
            color=(0,0,255),
            thickness=-1)
        畫圓形(image=陣列,
            center=手指2,
            radius=5,
            color=(0,0,255),
            thickness=-1)

    顯示影像(陣列)




矩形互動


矩線

rectangle_point


範例程式 矩形互動 - - - - - - - (幾何形狀互動 1/2 接續)
from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')
偵測器 = 設置HandAndGesture()

while True :
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)
    結果 = 偵測器.process(陣列)

    if 結果:
        手清單 = 取出Hand清單(結果)
        if len(手清單) == 2:
            手指1 = 手清單[0].特徵點(索引=8)
            手指2 = 手清單[1].特徵點(索引=8)

            畫矩形(image=陣列,
                pt1=手指1,
                pt2=手指2)
            畫圓形(image=陣列,
                center=手指1,
                radius=5,
                color=(0,0,255),
                thickness=-1)
            畫圓形(image=陣列,
                center=手指2,
                radius=5,
                color=(0,0,255),
                thickness=-1)

    顯示影像(陣列)



練習 圓形互動
請利用手部的兩點,決定圓心與半徑,做出圓形互動的效果
circle_point
圓形互動實作影片(Py4t練功坊)
進階範例 數位花繩
將兩手相對應的指頭靠近後,會產生直線連結
進階範例 數位花繩


(1分11秒, 資料來源:3)

Leap Motion體感作品參考

筆者於2015年實作的leap motion體感作品--用手控制機器娃娃頭部

用手控制機器娃娃頭部





📘 圖像互動(2)

模糊控制



模糊處理(平滑處理),影像去噪

blur_comparison


卷積核與卷積運算

average_blur_kernel

(資料來源:4)


範例程式 模糊控制 - - - - - - - (圖像互動 1/2 新檔)
from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')
偵測器 = 設置HandAndGesture()
kernel = 30

while True :
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)
    結果 = 偵測器.process(陣列)

    if 結果:
        kernel -= 2    
    else:
        kernel += 2        
    kernel = max(1, min(30,kernel))    
    陣列 = 模糊(陣列, 核心=kernel)  

    顯示影像(陣列)




掌中球


背景透明圖

alpha_channel_effect

(資料來源:5)


兩點對應


two_point_transform_basketball


範例程式 掌中球 - - - - - - - (圖像互動 2/2 新檔)
# 需匯入basketball.png(視覺便利貼:png->匯入)

from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')
偵測器 = 設置HandAndGesture()
png陣列 = 讀取png影像('basketball.png')

while True :
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)
    結果 = 偵測器.process(陣列)
    if 結果:
         = 取出Hand(結果)
        手指1 = .特徵點(索引=4)
        手指2 = .特徵點(索引=20)
        籃球1 = (30,300)
        籃球2 = (630,300)

        轉換png陣列 = 兩點transform(
            來源影像=png陣列,
            來源pt1=籃球1,
            來源pt2=籃球2,
            目標影像=陣列,
            目標pt1=手指1,
            目標pt2=手指2)
        貼上png(陣列,轉換png陣列)

    顯示影像(陣列)  




📘 鍵盤互動(2)

記事本自動化


什麼是PyAutoGui?

what_is_pyautogui



範例程式 記事本自動化 - - - - - - - (鍵盤互動 1/2 新檔)
import pyautogui
import os
import time

# 開啟 記事本
os.startfile('notepad.exe')
time.sleep(1)

# key in 文字
for i in 'How are you?' :
    pyautogui.press(i)
    pyautogui.press('enter')





體感小恐龍



結合手勢與自動化程式,來玩小恐龍遊戲。


範例程式 體感小恐龍 - - - - - - - (鍵盤互動 2/2 新檔)
from 視覺模組 import *
import pyautogui
import os
import time

攝影機 = 設置影像擷取(後端='DSHOW')
偵測器 = 設置HandAndGesture()
延遲計數器 = 0 

# 產生影像視窗
陣列 = 擷取影像(攝影機)
顯示影像(陣列)

# 開啟chrome(若開啟失敗,請手動開啟並輸入網址)
os.startfile('chrome.exe')
time.sleep(1)

# 輸入小恐龍網址
for c in 'chrome://dino':
    pyautogui.press(c)
pyautogui.press('enter')

while True :
    延遲計數器 -= 1
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)
    結果 = 偵測器.process(陣列)
    if 結果 and 延遲計數器 < 0:
         = 取出Hand(結果)
        if .gesture == "Open_Palm":
            print('空白鍵', end=' ')
            pyautogui.press('space')
            延遲計數器 = 5
    顯示影像(陣列)


(1分11秒, 資料來源:6)






📗 3D互動(3)

攝影機與3D貼圖


3D程式流程與攝影機流程,要如何合併?

event_loop


computuer_vision_flow


範例程式 攝影機與3D貼圖 - - - - - - - (3D互動 1/3 新檔)
from 模擬3D模組 import *
from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')
舞台 = 模擬3D引擎(1600,800)

螢幕 = 新增方形平面()
螢幕.縮放 = [6.4, 4.8, 1]

def 當更新時(dt):
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)
    螢幕.多維陣列貼圖 = 陣列

模擬主迴圈()




地球與星空



加入地球與星空的物件及貼圖

範例程式 地球與星空 - - - - - - - (3D互動 2/3 接續)
# 需匯入地球.jpg(3D便利貼:材質->匯入)
# 需匯入星空.jpg(3D便利貼:材質->匯入)

from 模擬3D模組 import *
from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')
舞台 = 模擬3D引擎(1600,800)

螢幕 = 新增方形平面()
螢幕.縮放 = [6.4, 4.8, 1]
螢幕.位置x = -4

地球 = 新增球體()
地球.縮放 = 5
地球.位置x = 3
地球.材質貼圖 = '地球.jpg'

星空 = 新增內面貼圖球體()
星空.縮放 = 100
星空.材質貼圖 = '星空.jpg'

def 當更新時(dt):
    地球.旋轉y -= 0.4
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)
    螢幕.多維陣列貼圖 = 陣列

模擬主迴圈()




旋轉縮放互動



結合手勢來控制地球

旋轉:一手做出「石頭」的手勢,另一手的拇指食指調整速度

旋轉:一手做出「布」的手勢,另一手的拇指食指調整大小


範例程式 旋轉縮放互動 - - - - - - - (3D互動 3/3 接續)
# 需匯入地球.jpg(3D便利貼:材質->匯入)
# 需匯入星空.jpg(3D便利貼:材質->匯入)

from 模擬3D模組 import *
from 視覺模組 import *

攝影機 = 設置影像擷取(後端='DSHOW')
偵測器 = 設置HandAndGesture()
舞台 = 模擬3D引擎(1600,800)

螢幕 = 新增方形平面()
螢幕.縮放 = [6.4, 4.8, 1]
螢幕.位置x = -4

地球 = 新增球體()
地球.縮放 = 5
地球.位置x = 3
地球.材質貼圖 = '地球.jpg'

星空 = 新增內面貼圖球體()
星空.縮放 = 100
星空.材質貼圖 = '星空.jpg'

def 當更新時(dt):
    地球.旋轉y -= 0.4
    陣列 = 擷取影像(攝影機)
    陣列 = 左右翻轉(陣列)
    結果 = 偵測器.process(陣列)
    if 結果:
         = 取出Hand(結果)
        手清單 = 取出Hand清單(結果)
        if .gesture == 'Closed_Fist':
            if len(手清單) == 1:
                地球.旋轉y -= 2
            else:
                手指距離 = abs(手清單[1].y(索引=8)-手清單[1].y(索引=4))
                地球.旋轉y -= 手指距離 / 20
                畫直線(image=陣列,
                    pt1=手清單[1].特徵點(索引=8),
                    pt2=手清單[1].特徵點(索引=4))
        elif .gesture == 'Open_Palm':
            地球.旋轉y -= 2
            if len(手清單) == 2:
                手指距離 = abs(手清單[1].y(索引=8)-手清單[1].y(索引=4))
                地球.縮放 =手指距離 / 20
                畫直線(image=陣列,
                    pt1=手清單[1].特徵點(索引=8),
                    pt2=手清單[1].特徵點(索引=4))                            
    螢幕.多維陣列貼圖 = 陣列            
模擬主迴圈()






  1. 《Nintendo Switch 運動》介紹影片(新增高爾夫球)(香港), by Nintendo HK官方頻道 , youtube連結 

  2. mediapipe , https://developers.google.com/mediapipe/solutions/vision/hand_landmarker 

  3. Leap Motion With Windows, by Leap Motion , youtube連結 

  4. Computer Vision for Beginners: Part 2, https://towardsdatascience.com/computer-vision-for-beginners-part-2-29b3f9151874 

  5. Export with ALPHA Channel to make your video Transparent - Premiere Pro, by storysium, https://youtu.be/s3r5Ezzv3Rs 

  6. 「關鍵報告」虛擬螢幕 GOOGLE手勢傳感勾雛型, by 東森新聞 CH51 , youtube連結