์ด์ ๊ธ์์ CVZone ์ MediaPipe ํจํค์ง๋ค์ ์ค์นํ๊ณ , ์น์บ ์ ๋ถ๋ฌ์ ์์ ์ถ์ ํ๋ ๊ฒ๊น์ง ๋ค๋ค๋ดค์ต๋๋ค.
https://vrworld.tistory.com/12
MediaPipe๋ฅผ ์ด์ฉํ์ฌ Hand Tracking & ์ ๋์ ์ธ์ ์ฝ๊ฒ ํ ์คํธ ํ๊ธฐ
๊ตฌํ ๋๊ธฐ ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์์ AR ํ๋ก์ ํธ๋ฅผ ์งํํ๊ณ , ๋ค๋ฅธ AR ํ๋ก์ ํธ๋ฅผ ๋ง์ด ๋ณด๋ฉด์ ๋๋ ๊ฒ ํ ๊ฐ์ง ์๋ค๋ฉด ๋๊ฐ ์ฌ์ฉ์ํํ ์ ๋ ฅ์ ๋ฐ์ ๋ ์ค๋งํธํฐ ํฐ์น๋ก ๋ฐ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์๋ค. ์ด๋ฐ ์ ์
vrworld.tistory.com
์ด๋ฒ ๊ธ์ ์์ฝํ๋ฉด ์๋ 5๊ฐ์ง๋ก ์ ๋ฆฌํ ์ ์์ต๋๋ค.
1. ์น์บ ์ผ๋ก ๊ฐ์งํ ์์ 21๊ฐ ๋๋๋งํฌ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ต๋๋ค.
2. ๋๋๋งํฌ ๋ฐ์ดํฐ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค์ด ํด๋น ๊ฐ์ UDP ์์ผ์ ํตํด Unity๋ก ์ ์กํฉ๋๋ค.
3. ์ ์ก๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Unity ๋ด์์๋ "์"์ ๋ง๋ญ๋๋ค.
4. ์ค์๊ฐ์ผ๋ก ์น์บ ์์ ์ถ์ ํ ์์ด Unity ๋ด์์ ๋ง๋ "์"์ด ์ฐ๋๋ฉ๋๋ค.
5. Unity ๋ด์์ ์ฐ๋๋ "์" ์ผ๋ก ์ค๋ธ์ ํธ ๋ค๊ณผ ์ํธ์์ฉ(Interaction)ํ ์ ์๊ฒ ๋ฉ๋๋ค.
21๊ฐ์ ๋๋๋งํฌ ๋ฐ์ดํฐ
์ฐ๋ฆฌ๊ฐ ์ด์ ์ PyCharm ํ๊ฒฝ์์ MediaPipe ํจํค์ง๋ฅผ ๋ค์ด๋ฐ์์ ๊ฑด๋ฐ, ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ์ถ์ ํ ์์ ๋๋๋งํฌ๋ฅผ ๊ฐ์งํ๊ฒ ๋๋๋ฐ ๊ฐ ์๋ง๋ค 21๊ฐ์ ๋๋๋งํฌ ๋ฐ์ดํฐ๋ฅผ ํ๋ ์๋ง๋ค ์ถ๋ก ํ๊ฒ ๋ฉ๋๋ค.
# ์น์ผ์์ ํ๋ ์ ๊ฐ์ ธ์ค๊ธฐ
success, img = cap.read()
# Hands
hands, img = detector.findHands(img)
data = []
# 21๊ฐ์ ๋๋๋งํฌ ๊ฐ๋ค์ UDP ํ๋กํ ์ฝ์ ์ฌ์ฉํ์ฌ Unity์ ๋ณด๋.
# Landmark values - (x,y,z) * 21
if hands:
# Get the first hand detected
hand = hands[0]
# Get the landmark list
lmList = hand['lmList']
print(lmList)
for lm in lmList:
data.extend([lm[0], height - lm[1], lm[2]])
print(data)
sock.sendto(str.encode(str(data)), serverAddressPort)
์ฝ๋์ ํ๋ฆ์ while ๋ฐ๋ณต๋ฌธ์ผ๋ก ์น์บ ์ ํ๋ ์๋ง๋ค๊ฐ ๊ฐ์ ธ์ค๊ณ , fineHands() ๋ฉ์๋๋ฅผ ํตํด ์น์บ ์์ ์์ ๊ฐ์งํฉ๋๋ค.
if ๋ฌธ์ ํตํด ๋ง์ฝ ์์ ๊ฐ์งํ๋ค๋ฉด, ์์ ๋๋๋งํฌ ๋ฆฌ์คํธ๋ฅผ ์ถ๋ ฅํฉ๋๋ค. (lmList)
๋ํ, ์ฐ๋ฆฌ๊ฐ ๋ฐ์์จ ๋๋๋งํฌ ๋ฆฌ์คํธ ๋งํผ ๋ฐ๋ณตํ์ฌ Unity์ ๋ณด๋ผ ๋ฐ์ดํฐ๋ฅผ "data" ๋ณ์์ ์ฐจ๊ณก์ฐจ๊ณก ๋ฃ์ด์ฃผ๊ฒ ๋๋ ๊ฑฐ์ฃ .
์ฌ๊ธฐ์ data.extend() ๋ถ๋ถ์ lm[0], lm[1], lm[2] ๋ ๊ฐ๊ฐ x, y, z ๊ฐ์ ๊ฐ๋ฆฌํต๋๋ค.
height - lm[1]๋ OpenCV ์ Unity ๊ฐ Y ๋ฐฉํฅ์ด ์๋ก ๋ฐ๋์ด๊ธฐ์ Height(์ธ๋ก ํด์๋)์์ Y๊ฐ์ ๋นผ์ค์ผ๋ก์จ ์ฌ๋ฐ๋ฅธ ๋ฐ์ดํฐ๋ฅผ Unity์ ๋ณด๋ด์ฃผ๊ธฐ ์ํจ๋ Key Point๊ฐ ๋ ์ ์์ต๋๋ค.
์คํ ํ๋ฉด์ ๋๋ค. ์ค์๊ฐ์ผ๋ก ๋๋๋งํฌ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๊ณ ์์ต๋๋ค. ํ์ดํ ๋ชจ์์ ์์ธํ ๋ณด์๋ฉด lmList ๋ณ์์ Data ๋ณ์ ์์๋ก ์ ์๋ ์ถ๋ ฅ๋๊ณ ์๋๋ฐ, Data ๋ณ์์ Helight๋งํผ Y ๊ฐ์ด ๊ฐ์ํ์ฌ ์๊ณ , Unity์ ๋ณด๋ด๊ธฐ ์ํด ๊ฐ๊ฐ์ ๋๊ดํธ๋ ์ฌ๋ผ์ง ๊ฑธ ํ์ธํ ์ ์์ต๋๋ค.
from cvzone.HandTrackingModule import HandDetector
import socket
# Parameters
width, height = 1280, 720
# IP WebCam
cap = cv2.VideoCapture("http://Your IP Address/video")
# ์ผ๋ฐ WebCam ์ ์ฌ์ฉํ ๊ฒฝ์ฐ
#cap = cv2.VideoCapture(0)
cap.set(3, width)
cap.set(4, height)
# ์์ ๊ฐ์ง
detector = HandDetector(maxHands=1, detectionCon=0.8)
# ๋คํธ์ํฌ
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
serverAddressPort = ("127.0.0.1", 5052)
while True:
# ์น์ผ์์ ํ๋ ์ ๊ฐ์ ธ์ค๊ธฐ
success, img = cap.read()
# Hands
hands, img = detector.findHands(img)
data = []
# 21๊ฐ์ ๋๋๋งํฌ ๊ฐ๋ค์ UDP ํ๋กํ ์ฝ์ ์ฌ์ฉํ์ฌ Unity์ ๋ณด๋.
# Landmark values - (x,y,z) * 21
if hands:
# Get the first hand detected
hand = hands[0]
# Get the landmark list
lmList = hand['lmList']
print(lmList)
for lm in lmList:
data.extend([lm[0], height - lm[1], lm[2]])
print(data)
sock.sendto(str.encode(str(data)), serverAddressPort)
img = cv2.resize(img, (0,0), None, 0.5, 0.5)
cv2.imshow("Image", img)
if cv2.waitKey(1) == ord("q"): # q ๋๋ฅผ ์ ์น์ผ ์ข ๋ฃ
break
์ ์ ์ฒด ์ฝ๋์ ๋ํ ์ค๋ช
์
๋๋ค. ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
1. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ํฌํธ:
- `import cv2`: OpenCV ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ํฌํธํฉ๋๋ค. OpenCV๋ ์์ ์ฒ๋ฆฌ์ ์ปดํจํฐ ๋น์ ์์
์ ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์
๋๋ค.
- `from cvzone.HandTrackingModule import HandDetector`: cvzone ํจํค์ง์์ HandDetector ๋ชจ๋์ ์ํฌํธํฉ๋๋ค. ์ด ๋ชจ๋์ ์์ ๊ฐ์งํ๊ณ ์ถ์ ํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- `import socket`: ์์ผ ํต์ ์ ์ํ socket ๋ชจ๋์ ์ํฌํธํฉ๋๋ค.
2. ๋งค๊ฐ๋ณ์ ์ค์ :
- `width, height = 1280, 720`: ์์์ ๊ฐ๋ก์ ์ธ๋ก ํด์๋๋ฅผ ์ง์ ํฉ๋๋ค. ์ด ๊ฐ์ ์น์บ ์ ํด์๋ ์ค์ ์ ์ฌ์ฉ๋ฉ๋๋ค.
3. IP ์น์บ ์ค์ :
- `cap = cv2.VideoCapture("http://Your IP Address//video")`: IP ์น์บ ์ผ๋ก๋ถํฐ ์์์ ๋ฐ์์ค๊ธฐ ์ํด `cv2.VideoCapture` ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค. `"http://Your IP Address//video"`์ ์น์บ ์ ์ฃผ์๋ฅผ ๋ํ๋ด๋ฉฐ, ํด๋น ์ฃผ์์์ ์์์ ๋ฐ์์ต๋๋ค.
4. ์น์บ ์ค์ :
- `cap.set(3, width)`: ์น์บ ์ ๊ฐ๋ก ํด์๋๋ฅผ ์ค์ ํฉ๋๋ค.
- `cap.set(4, height)`: ์น์บ ์ ์ธ๋ก ํด์๋๋ฅผ ์ค์ ํฉ๋๋ค.
5. ์ ๊ฐ์ง ๊ฐ์ฒด ์์ฑ:
- `detector = HandDetector(maxHands=1, detectionCon=0.8)`: `HandDetector` ๊ฐ์ฒด๋ฅผ ์์ฑํฉ๋๋ค. `maxHands`๋ ๊ฐ์งํ ์์ ์ต๋ ์๋ฅผ ์ง์ ํ๋ฉฐ, `detectionCon`์ ์์ ๊ฐ์งํ๊ธฐ ์ํ ์ ๋ขฐ๋ ์๊ณ๊ฐ์ ์ค์ ํฉ๋๋ค.
6. ๋คํธ์ํฌ ์ค์ :
- `sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)`: UDP ์์ผ์ ์์ฑํฉ๋๋ค. `socket.AF_INET`์ IPv4๋ฅผ ์ฌ์ฉํ๊ณ , `socket.SOCK_DGRAM`์ ๋ฐ์ดํฐ๊ทธ๋จ ์์ผ์ ์์ฑํฉ๋๋ค.
- `serverAddressPort = ("127.0.0.1", 5052)`: UDP ์๋ฒ์ ์ฃผ์์ ํฌํธ๋ฅผ ์ง์ ํฉ๋๋ค.
7. ์์ ์ฒ๋ฆฌ ๋ฃจํ:
- `while True:`: ๋ฌดํ ๋ฃจํ๋ฅผ ์์ํฉ๋๋ค.
- `success, img = cap.read()`: ์น์บ ์์ ํ๋ ์์ ์ฝ์ด์ต๋๋ค. `success`๋ ํ๋ ์ ์ฝ๊ธฐ๊ฐ ์ฑ๊ณตํ๋์ง ๋ฅผ ๋ํ๋ด๋ ๋ถ๋ฆฌ์ธ ๊ฐ์ด๊ณ , `img`๋ ์ฝ์ด์จ ํ๋ ์ ์ด๋ฏธ์ง์
๋๋ค.
8. ์ ๊ฐ์ง:
- `hands, img = detector.findHands(img)`: `HandDetector` ๊ฐ์ฒด์ `findHands()` ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ ๊ฐ์งํฉ๋๋ค. `img`์๋ ์ ๊ฐ์ง ๊ฒฐ๊ณผ๊ฐ ๊ทธ๋ ค์ง ์ด๋ฏธ์ง๊ฐ ๋ฐํ๋๊ณ , `hands`์๋ ๊ฐ์ง๋ ์์ ๋ํ ์ ๋ณด๊ฐ ๋ด๊ธด ๋ฆฌ์คํธ๊ฐ ๋ฐํ๋ฉ๋๋ค.
9. ์์ ๋๋๋งํฌ ๊ฐ ์ ์ก:
- `if hands:`: ์์ด ๊ฐ์ง๋์๋ค๋ฉด ์๋ ์ฝ๋๋ฅผ ์คํํฉ๋๋ค.
- `hand = hands[0]`: ์ฒซ ๋ฒ์งธ๋ก ๊ฐ์ง๋ ์์ ์ ํํฉ๋๋ค. - `lmList = hand['lmList']`: ์ ํ๋ ์์ ๋๋๋งํฌ ๋ฆฌ์คํธ๋ฅผ ๊ฐ์ ธ์ต๋๋ค.
- `for lm in lmList:`: ๊ฐ ๋๋๋งํฌ์ ๋ํด ๋ฐ๋ณตํฉ๋๋ค.
- `data.extend([lm[0], height - lm[1], lm[2]])`: `data` ๋ฆฌ์คํธ์ ๋๋๋งํฌ์ x, y, z ์ขํ ๊ฐ์ ์ถ๊ฐํฉ๋๋ค. y ์ขํ๋ ํ๋ฉด ์์์ ๋ค์งํ ์์ผ๋ฏ๋ก `height - lm[1]`๋ก ๋ณํํฉ๋๋ค.
- `sock.sendto(str.encode(str(data)), serverAddressPort)`: `data` ๊ฐ์ ๋ฌธ์์ด๋ก ๋ณํํ๊ณ , ํด๋น ๊ฐ์ ๋ฐ์ดํธ๋ก ์ธ์ฝ๋ฉํ์ฌ UDP ์์ผ์ ํตํด Unity๋ก ์ ์กํฉ๋๋ค.
10. ์์ ์ถ๋ ฅ:
- `img = cv2.resize(img, (0,0), None, 0.4, 0.4)`: ์ถ๋ ฅํ ์์์ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํฉ๋๋ค.
- `cv2.imshow("Image", img)`: `img`์ ์ ์ฅ๋ ์ด๋ฏธ์ง๋ฅผ "Image"๋ผ๋ ์ฐฝ์ ์ถ๋ ฅํฉ๋๋ค.
11. ์ข
๋ฃ ์กฐ๊ฑด:
- `if cv2.waitKey(1) == ord("q"):`: ์ฌ์ฉ์๊ฐ "q" ํค๋ฅผ ๋๋ฅด๋ฉด ๋ฃจํ๋ฅผ ์ข
๋ฃํฉ๋๋ค.
- `cv2.waitKey(1)`: ์ฌ์ฉ์์ ํค ์
๋ ฅ์ 1๋ฐ๋ฆฌ์ด ๋์ ๋๊ธฐํ๊ณ , ์
๋ ฅ์ด ์์ผ๋ฉด ํด๋น ํค์ ์ ๋์ฝ๋ ๊ฐ์ ๋ฐํํฉ๋๋ค.
- `ord("q")`: ๋ฌธ์ "q"์ ์ ๋์ฝ๋ ๊ฐ์ ๋ฐํํฉ๋๋ค.
- `break`: ๋ฃจํ๋ฅผ ์ข
๋ฃํฉ๋๋ค. ์ด ์ฝ๋๋ IP ์น์บ ์ผ๋ก๋ถํฐ ์ค์๊ฐ์ผ๋ก ์์์ ๋ฐ์์ ์์ ๊ฐ์งํ๊ณ , ๊ฐ์ง๋ ์์ ๋๋๋งํฌ ๊ฐ์ Unity๋ก ์ ์กํ๋ ์์
์ ์ํํฉ๋๋ค.
UDP ์์ผ์ ์ด์ฉํ์ฌ ๋๋๋งํฌ ๋ฐ์ดํฐ๋ฅผ Unity์ ์ ์ก
https://www.youtube.com/watch?v=RQ-2JWzNc6k
์ด์ Unity ๋ด์์ ๋ฐ์ดํฐ๋ฅผ ์ ์ก๋ฐ์ UDP ๊ด๋ จ ์คํฌ๋ฆฝํธ๊ฐ ํ์ํฉ๋๋ค.
UDP ๊ด๋ จ ์คํฌ๋ฆฝํธ๋ ์ง๊ธ๊น์ง ์ฐธ๊ณ ํ๋ ํํ ๋ฆฌ์ผ ์์๊ฒ์์์ ์ฌ์ดํธ๋ฅผ ๋ค์ด๊ฐ ๊ฐ๋จํ ํ์๊ฐ์ ํ ๋ฌด๋ฃ๋ก ๋ค์ด๋ฐ์ ์ ์์ต๋๋ค.
UDP ๊ด๋ จ ์คํฌ๋ฆฝํธ๋ฅผ ๋ค์ด๋ฐ๊ณ , Unity ์๋ํฐ๋ก ์ฎ๊ฒจ์ฃผ์ ๋ค์, ๋ฐ์ดํฐ ์ ๋ณด๋ฅผ ๋ฐ์ ๋น ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค์ด ์คํฌ๋ฆฝํธ๋ฅผ ์ฒจ๋ถํด ์ฃผ์ธ์.
์ง๊ธ๊น์ง ๊ณผ์ ์ ๋ง์น ํ, ํ๋ก์ ํธ๋ฅผ ์คํํ๋ฉด ์๊น PyCharm ์ฝ์ ์ฐฝ์์ ํ์ธํ๋ ๋๋๋งํฌ ๋ฐ์ดํฐ๋ค์ด Unity ๋ด์์๋ ์ ์์ ์ผ๋ก ์ฎ๊ฒจ์ง ๊ฑธ ํ์ธํ ์ ์์ต๋๋ค.
Unity์์ ์ ์ก ๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ค์๊ฐ ์ํธ์์ฉ ๊ตฌํ
์ด์ ์ด ์ ์ก๋ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Unity ๋ด์์ ์ ๋ชจ๋ธ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค. ์ ๋ชจ๋ธ ๋ง๋๋ ๊ณผ์ ์ ํ๋ํ๋ ์ ์ด ๋๊ฐ๊ธฐ์๋ ๊ธ์ ์์ด ๋ง์์ ธ ์ฝ๋ ์ค๋ช ๊ณผ ํต์ฌ์ ์ธ ๋ถ๋ถ๋ง ์ง๊ณ , ๋๋จธ์ง๋ ์ ํํ ๋ฆฌ์ผ ๋งํฌ๋ฅผ ๋ฐ๋ผ๊ฐ์ ์ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ฐ๋ผ ํด ๋ณด์๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
HandTracking.cs ์ฝ๋๋ฅผ ์์ฑํ์ฌ Unity์์ ์ฐ๋ฆฌ๊ฐ ๋ฐ์์จ ์์ ๋๋๋งํฌ ๋ฐ์ดํฐ๋ฅผ ์ด์ฉํ์ฌ ์ ๋ชจ๋ธ์ ํํํ๊ฒ ๋ฉ๋๋ค.
21๊ฐ์ง์ ๋ํ ๋๋๋งํฌ Point๋ค๊ณผ ๋ฐ์์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํ UDP ์์ผ์ HandTracking ์ปดํฌ๋ํธ์ ์ฐ๊ฒฐํด ์ค๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HandTracking : MonoBehaviour
{
// Start is called before the first frame update
public UDPReceive udpReceive;
public GameObject[] handPoints;
void Start()
{
}
// Update is called once per frame
void Update()
{
// UDP ํ๋กํ ์ฝ๋ก ์ ์ก๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์จ๋ค.
string data = udpReceive.data;
// ๊ฐ์ง๊ณ ์จ ๋ฐ์ดํฐ์์ ๋๊ดํธ([ ])๋ฅผ ๋บ๋ค.
data = data.Remove(0, 1);
data = data.Remove(data.Length-1, 1);
// ์ผํ๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถํ
string[] points = data.Split(',');
for ( int i = 0; i < 21; i++)
{
float x = 5 - float.Parse(points[i * 3])/100;
float y = float.Parse(points[i * 3 + 1]) / 100;
float z = float.Parse(points[i * 3 + 2]) / 100;
handPoints[i].transform.localPosition = new Vector3(x, y, z);
}
}
}
|
c |
- ๋ณ์ ์ ์ธ:
- public UDPReceive udpReceive;: UDPReceive ์คํฌ๋ฆฝํธ์ ์ ๊ทผํ๊ธฐ ์ํ ๋ณ์๋ฅผ ์ ์ธํฉ๋๋ค. ์ด ์คํฌ๋ฆฝํธ๋ UDP ํ๋กํ ์ฝ์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๊ธฐ๋ฅ์ ๋ด๋นํฉ๋๋ค.
- public GameObject[] handPoints;: ์ ๋ชจ๋ธ์ ๋๋๋งํฌ ์์น๋ฅผ ๋ํ๋ด๋ ๊ฒ์ ์ค๋ธ์ ํธ ๋ฐฐ์ด์ ์ ์ธํฉ๋๋ค. ์ด ๋ฐฐ์ด์ ์ ๋ชจ๋ธ์ ๊ฐ ๋๋๋งํฌ์ ๋ํ ์์น๋ฅผ ์ค์ ํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
- UDP ๋ฐ์ดํฐ ์์ :
- string data = udpReceive.data;: UDPReceive ์คํฌ๋ฆฝํธ์์ ๋ฐ์์จ UDP๋ก ์ ์ก๋ ๋ฐ์ดํฐ๋ฅผ ๋ฌธ์์ด ํํ๋ก data ๋ณ์์ ์ ์ฅํฉ๋๋ค.
- ๋ฐ์ดํฐ ๊ฐ๊ณต:
- data = data.Remove(0, 1);: data ๋ฌธ์์ด์์ ์ฒซ ๋ฒ์งธ ๋ฌธ์์ธ ๋๊ดํธ [๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
- data = data.Remove(data.Length-1, 1);: data ๋ฌธ์์ด์์ ๋ง์ง๋ง ๋ฌธ์์ธ ๋๊ดํธ ]๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
- string[] points = data.Split(',');: data ๋ฌธ์์ด์ ์ผํ ,๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ถํ ํ์ฌ ๋ฌธ์์ด ๋ฐฐ์ด์ธ points์ ์ ์ฅํฉ๋๋ค.
- ๋๋๋งํฌ ์์น ์
๋ฐ์ดํธ:
- for (int i = 0; i < 21; i++): 21๊ฐ์ ๋๋๋งํฌ์ ๋ํด ๋ฐ๋ณตํฉ๋๋ค.
- float x = 5 - float.Parse(points[i * 3])/100;: x ์ขํ ๊ฐ์ ๊ฐ์ ธ์์ float ํ์ผ๋ก ๋ณํํ๊ณ , ๋ฒ์๋ฅผ ์กฐ์ ํฉ๋๋ค.
- float y = float.Parse(points[i * 3 + 1]) / 100;: y ์ขํ ๊ฐ์ ๊ฐ์ ธ์์ float ํ์ผ๋ก ๋ณํํ๊ณ , ๋ฒ์๋ฅผ ์กฐ์ ํฉ๋๋ค.
- float z = float.Parse(points[i * 3 + 2]) / 100;: z ์ขํ ๊ฐ์ ๊ฐ์ ธ์์ float ํ์ผ๋ก ๋ณํํ๊ณ , ๋ฒ์๋ฅผ ์กฐ์ ํฉ๋๋ค.
- handPoints[i].transform.localPosition = new Vector3(x, y, z);: handPoints ๋ฐฐ์ด์์ i๋ฒ์งธ ์ธ๋ฑ์ค์ ํด๋นํ๋ ์์ ๋๋๋งํฌ ์์น๋ฅผ ์ ๋ฐ์ดํธํฉ๋๋ค. localPosition ์์ฑ์ ์ฌ์ฉํ์ฌ ์์น๋ฅผ ์ง์ ํฉ๋๋ค.
์ด์ ๋๋๋งํฌ 21๊ฐ์ง Point๋ค์ ๋ง๋ค์๋ค๋ฉด ๊ฐ๊ฐ์ Point๋ค์ ์์์ (Origin)๊ณผ ๋์ฐฉ์ (Destination)์ ์ ํด ๋ผ์ธ(Line)์ ๊ทธ๋ ค์ค "์"์ ํํ๋ฅผ ๋ง๋ค์ด ์ฃผ๊ฒ ๋ฉ๋๋ค.
LineCode.cs๋ ์์์ ๊ณผ ๋์ฐฉ์ Point๋ค์ ๋ฐ์์ Update() ํจ์๋ฅผ ๊ฑฐ์ณ ํ๋ ์๋ง๋ค ๋ผ์ธ์ ์์น๋ฅผ ์ ๋ฐ์ดํธํ์ฌ ๊ทธ๋ ค์ฃผ๊ฒ ๋ฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LineCode : MonoBehaviour
{
LineRenderer lineRenderer;
public Transform origin;
public Transform destination;
// Start is called before the first frame update
void Start()
{
lineRenderer = GetComponent<LineRenderer>();
lineRenderer.startWidth = 0.1f;
lineRenderer.endWidth = 0.1f;
}
// Update is called once per frame
void Update()
{
lineRenderer.SetPosition(0, origin.position);
lineRenderer.SetPosition(1, destination.position);
}
}
|
cs |
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ํฌํธ:
- using System.Collections;: Unity์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Collections์ ์ฌ์ฉํฉ๋๋ค.
- using System.Collections.Generic;: Unity์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Generic Collections์ ์ฌ์ฉํฉ๋๋ค.
- using UnityEngine;: Unity์ ๊ธฐ๋ณธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ UnityEngine์ ์ฌ์ฉํฉ๋๋ค.
- ๋ณ์ ์ ์ธ:
- LineRenderer lineRenderer;: LineRenderer ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ๋ณ์๋ฅผ ์ ์ธํฉ๋๋ค.
- Transform ๋ณ์ ์ ์ธ:
- public Transform origin;: ์์์ ์ ๋ํ๋ด๋ Transform ๋ณ์๋ฅผ ์ ์ธํฉ๋๋ค.
- public Transform destination;: ๋์ฐฉ์ ์ ๋ํ๋ด๋ Transform ๋ณ์๋ฅผ ์ ์ธํฉ๋๋ค.
- Start ํจ์:
- void Start(): ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋ ๋ ํ ๋ฒ ํธ์ถ๋๋ Start ํจ์์ ๋๋ค.
- lineRenderer = GetComponent<LineRenderer>();: LineRenderer ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ ธ์ lineRenderer ๋ณ์์ ํ ๋นํฉ๋๋ค.
- lineRenderer.startWidth = 0.1f;: ๋ผ์ธ์ ์์์ ๋๋น๋ฅผ ์ค์ ํฉ๋๋ค.
- lineRenderer.endWidth = 0.1f;: ๋ผ์ธ์ ๋์ฐฉ์ ๋๋น๋ฅผ ์ค์ ํฉ๋๋ค.
- Update ํจ์:
- void Update(): ํ๋ ์๋ง๋ค ํธ์ถ๋๋ Update ํจ์์ ๋๋ค.
- lineRenderer.SetPosition(0, origin.position);: ๋ผ์ธ์ ์์์ ์ origin์ ์์น๋ก ์ค์ ํฉ๋๋ค. origin.position์ ์์์ ์ 3D ์ขํ๋ฅผ ๋ํ๋ ๋๋ค.
- lineRenderer.SetPosition(1, destination.position);: ๋ผ์ธ์ ๋์ฐฉ์ ์ destination์ ์์น๋ก ์ค์ ํฉ๋๋ค. destination.position์ ๋์ฐฉ์ ์ 3D ์ขํ๋ฅผ ๋ํ๋ ๋๋ค.
์คํ ์์
IP WebCam ํด๋ํฐ ํ๋ฉด ์นด๋ฉ๋ผ๋ฅผ ์ด์ฉํ๊ธฐ์ "์"์ด ์ข์ฐ ๋ฐ์ ๋์์ง๋ง, ์ ์์ ์ผ๋ก ์ค๋ธ์ ํธ๋ค๊ณผ ์ํธ์์ฉํ๊ณ ์๋ ๋ชจ์ต์ ํ์ธํ ์ ์์ต๋๋ค.