Day13 虛擬試身室


🟡 先看看程式的效果

今天的程式是一個互動式的虛擬試衣間系統,使用了電腦視覺和姿態估計技術來實現實時的虛擬試衣效果。它的主要功能是將預先準備好的服裝圖片(上衣和褲子)疊加到攝像頭捕捉的人體影像上,讓使用者可以在螢幕上看到自己穿著不同服裝的樣子。

Today’s program is an interactive virtual fitting room system that utilizes computer vision and pose estimation technology to achieve real-time virtual try-on effects. Its main function is to overlay pre-prepared clothing images (tops and pants) onto the human image captured by the camera, allowing users to see themselves wearing different outfits on the screen.


🟡 學習目標

電腦視覺應用:使用 OpenCV 來處理圖像和視頻流。
人體姿態估計:利用 MediaPipe 庫進行人體姿態估計,這可以讓我們準確地定位人體的關鍵點。
圖像疊加:使用 cvzone 庫來實現圖像疊加效果,將服裝圖片疊加到攝像頭捕捉的影像上。
實時處理:程式能夠實時處理視頻流,並根據檢測到的人體姿態動態調整服裝的位置和大小。
動態縮放:根據檢測到的肩膀寬度來動態調整服裝大小,使其更符合使用者的體型。
全屏顯示:使用 OpenCV 的視窗功能來創建全屏顯示,提供更好的使用體驗。
參數調整:程式中包含了一些可調整的參數,如服裝位置的微調(topXAdjust, topYAdjust 等),這允許更精細的控制。
事件處理:程式會持續運行直到使用者按下 Esc 鍵,這展示了如何處理鍵盤輸入。


🟡 程式碼

請先下載 “Day13 虛擬校服試身室” 資料夾內的程式以及圖檔。
請按此下載

'''

Python + AI in 21 days
https://jasonworkshop.com/python

Designed by Jason Workshop

[請勿修改以上內容]

---

預備工作:

首先,請確保已安裝 opencv-python, mediapipe 模組
如不確定可直接在 Windows 的 cmd prompt 執行以下指定
pip install opencv-python mediapipe

'''

import cv2
import cvzone
import mediapipe as mp

# 讀取服裝圖檔及修正參數
top = cv2.imread("uniform01.png", cv2.IMREAD_UNCHANGED)
topXAdjust = 0
topYAdjust = 0
bottom = cv2.imread("bottom01.png", cv2.IMREAD_UNCHANGED)
bottomXAdjust = -10
bottomYAdjust = 20

mp_drawing = mp.solutions.drawing_utils
mp_pose = mp.solutions.pose

x = [0 for i in range(32)]
y = [0 for i in range(32)]

# 取得螢幕解析度
screen_width, screen_height = 1920, 1080

# --------------------------------------------------------------------------------

def detect_position():
    # 計算服裝大小比例
    tscale=round((results.pose_landmarks.landmark[11].x - results.pose_landmarks.landmark[12].x), 2) # 用左肩 X - 右肩 X 求出大小比例值
    # print (tscale)

    if tscale > 0:
        # txc, tyc = 服裝中心 X, Y 坐標
        txc=round((results.pose_landmarks.landmark[11].x - results.pose_landmarks.landmark[12].x) / 2 + results.pose_landmarks.landmark[12].x, 2)
        tyc=round((results.pose_landmarks.landmark[11].y - results.pose_landmarks.landmark[12].y) / 2 + results.pose_landmarks.landmark[12].y, 2)
        # print(txc, " , ", tyc)

        # 改變服裝大小
        top2 = cv2.resize(top, (0,0), None, tscale*4.2, tscale*4.2)
        # print(top2.shape[0]) # Height
        # print(top2.shape[1]) # Width

        # 改變服裝位置
        imgResult = cvzone.overlayPNG(image, top2, [int(txc * 1280 - top2.shape[1] / 2) + topXAdjust, int(tyc * 720 - top2.shape[0] * 0.20) + topYAdjust])

        # --------------------------------------------------------------------------------

        # bxc, byc = 服裝中心 X, Y 坐標
        bxc=round((results.pose_landmarks.landmark[23].x - results.pose_landmarks.landmark[24].x) / 2 + results.pose_landmarks.landmark[24].x, 2)
        byc=round((results.pose_landmarks.landmark[23].y - results.pose_landmarks.landmark[24].y) / 2 + results.pose_landmarks.landmark[24].y, 2)

        # 改變服裝大小
        bottom2 = cv2.resize(bottom, (0,0), None, tscale*7, tscale*7)

        # 改變服裝位置
        imgResult = cvzone.overlayPNG(image, bottom2, [int(bxc * 1280 - bottom2.shape[1] / 2) + bottomXAdjust, int(byc * 720 - bottom2.shape[0] * 0.20) + bottomYAdjust])

# --------------------------------------------------------------------------------

# 創建一個視窗
cv2.namedWindow('JCCSSYL Dressing Room', cv2.WINDOW_NORMAL)

# 設定視窗屬性為全屏
cv2.setWindowProperty('JCCSSYL Dressing Room', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

# 調整視窗大小以符合解析度
cv2.resizeWindow('JCCSSYL Dressing Room', screen_width, screen_height)

# Webcam input
pose = mp_pose.Pose(min_detection_confidence = 0.7, min_tracking_confidence =0.5)
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) # Capture width = 640
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) #Capture height = 480

while cap.isOpened():
    success, image = cap.read()
    if not success:
        break

    # Flip the image horizontally for a later selfie-view display
    image = cv2.flip(image, 1)

    # To improve performance, optionally mark the image as not writeable to pass by reference
    image.flags.writeable = True
    results = pose.process(image)

    if results.pose_landmarks:
        detect_position()
        # 顯示骨架
        # mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)

    cv2.imshow('JCCSSYL Dressing Room', image)

    # 取得畫面大小
    # print(image.shape)

    # 按 Esc 關閉程式及視窗
    if cv2.waitKey(5) & 0xFF == 27:
        cv2.destroyAllWindows()
        break

pose.close()
cap.release()

🟡 小小挑戰一下

大家可以嘗試進行一些修改或改良喔! 例如:
✌️嘗試修改成女裝的虛擬試身室吧。

😁 明天見!

按這裏回到 Python + AI 的 21 天挑戰