- ๋์กธ์ค ๋ฐ ์ฌํ ์น๋ฃ ํ์์ ๊ณ ์ ์์ฉ๊ฐ๊ฐ ํ๊ฐ ๋ฐฉ์์ ์ฃผ๊ด์ ์ธ ๊ด์ฐฐ์ ์์กดํ์ฌ ์ ํ๋๊ฐ ๋จ์ด์ง๋๋ค.
- ์ด๋ฅผ ๊ฐ์ ํ๊ณ ์ Kinect์ Unity๋ฅผ ํ์ฉํ ์ค์๊ฐ ๊ณ ์ ์์ฉ๊ฐ๊ฐ ํ๊ฐ ์์คํ ์ ๊ฐ๋ฐํ์ต๋๋ค.
- 20๊ฐ์ Skeleton point๋ฅผ ํ์ฉํ์ฌ ์ธ์ฒด์ ์์ง์์ ์ ๋์ ์ผ๋ก ๋ถ์ํ๊ณ ์ค์๊ฐ์ผ๋ก ๋ชจ๋ํฐ๋งํฉ๋๋ค.
- ์ฌ์ฉ์์ ์์ธ๋ฅผ ์ธก์ ํ๊ณ ์์ ๋ณํ๋ก ์ฆ๊ฐ์ ์ธ ํผ๋๋ฐฑ์ ์ ๊ณตํ์ฌ, ์ฌํ ์งํ ์ํ๋ฅผ ์ง๊ด์ ์ผ๋ก ํ์ ํ ์ ์์ต๋๋ค.
- Scikit-learn์ ํ์ฉํ์ฌ 4๊ฐ์ง ์์ธ ๋ฐ์ดํฐ์ ๋ํ ๋จธ์ ๋ฌ๋ ๋ถ์์ ์ํํ์ต๋๋ค.
- ์ด๋ฅผ ํตํด ํ์๋ค์ด ์์ ์ ์ฌํ ์ํ๋ฅผ ์๊ฐ์ ์ผ๋ก ํ์ธํ๋ฉฐ ์น๋ฃ์ ๋ํ ๋ชฐ์ ๋๋ฅผ ๋์ผ ์ ์๊ฒ ๋์์ต๋๋ค.
๋ด๋น ์ธ์ : 1๋ช
-
Kinect ์ผ์๋ฅผ ํตํด ํ์์ ์์ง์์ ๊ฐ์งํ๊ณ , Unity๋ฅผ ํตํด ์๋ฐํ๋ก ์๊ฐํํฉ๋๋ค.
-
ํ์๋ ์์ ์ ์์ธ ์ํ๋ฅผ ์ค์๊ฐ ํ์ธํ ์ ์์ต๋๋ค.
๋ฉ์ธ ํ๋ฉด
์์ ํ๋ฉด
-
ํ๋ฉด์ ๋ณ ์์์ ํตํด ์ฌ์ฉ์๊ฐ ์์ธ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ํํ๋์ง ์ฌ๋ถ๋ฅผ ํ์ธํฉ๋๋ค.
-
์์ธ ๊ฐ๋ ํ๋ณํ ์ ์์ต๋๋ค.
- ์ ์ ํ ๊ฐ๋ โ โญ ๋ ธ๋์
- ๊ฐ๋๊ฐ ๋ฎ์ โ โซ ๊ฒ์์
- ๊ฐ๋๊ฐ ๋์ โ ๐ด ๋นจ๊ฐ์
-
์ด 4๊ฐ์ง ์์ธ ์ธก์ ํ ์ ์์ต๋๋ค (์ํ, ์๋ค๋ฆฌ).
-
๊ฐ๋ ์ํ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋ํ๋ก ๋น๊ตํ๋ฉฐ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ์ ๋น๊ตํ ์ ์์ต๋๋ค.
์ฌ๋๋ค์ ๊ฐ๋ ์ ๋ณด๊ฐ ์ ์ฅ๋ csv ํ์ผ์ ๋ถ๋ฌ์ ๋ง๋ ๊ทธ๋ํ ํํ๋ก ๋ณด์ฌ์ค
-
Paired T-test๋ฅผ ํตํด ์คํ ๊ฒฐ๊ณผ ๋ถ์: - ๋์ ๋ฌ ์ํ์ ๊ฐ์ ์ํ ๋น๊ต - ์ ์ ์์ค p-value = 0.05 ๊ธฐ์ค - Right Arm(0.03), Left Arm(0.02) โ ์ ์๋ฏธํ ์ฐจ์ด ํ์ธ
์คํ ๊ฒฐ๊ณผ ํ
4. ๋จธ์ ๋ฌ๋ ๊ธฐ๋ฐ ์์ธ ๋ถ๋ฅ
-
Scikit-learn์ ํ์ฉํ์ฌ Decision Tree & Random Forest ๋ชจ๋ธ ์ ์ฉํ์ต๋๋ค.
-
์ต๊ณ ์ฑ๋ฅ 96%, ์ต์ ์ฑ๋ฅ 81% ๊ธฐ๋กํ์ต๋๋ค.
-
๋์ ๋จ๊ณ ์งํํ ๋ฐ์ดํฐ์๋ open์ ๋ผ๋ฒจ๋ง์ ํ๊ณ ๋์ ๊ฐ๊ณ ์งํํ ๋ฐ์ดํฐ์๋ close๋ก ๋ผ๋ฒจ๋ง์ ์งํ ํ ๋ถ๋ฅํ์ต๋๋ค.

๋จธ์ ๋ฌ๋ ์ฑ๋ฅ ์งํ
์ฑ๋ฅ ์ธก์ ์ ์ ๋ํฐ ๋ด๋ถ์ Profiler๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
1. ๋ฌธ์ ๋ฐ๊ฒฌ ๋ฐ ๋ถ์
- Kinect๊ฐ ์ฌ๋์ Skeleton Point๋ฅผ ์ ์์ ์ผ๋ก ์ธ์ํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ, ํ๋ ์ Peak(์ต๋ ๋ถํ ์ ์๊ฐ์ ์ธ ์ฑ๋ฅ ์ ํ) ๊ฐ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ์ต๋๋ค.
ํ๋ ์์
- ์ฑ๋ฅ ์ต์ ํ ํจ๊ณผ
| ํญ๋ชฉ | ๊ฐ์ ์ | ๊ฐ์ ํ | ํจ๊ณผ |
|---|---|---|---|
์ต๋ ๋ถํ ์คํ ์๊ฐ(KinectManager.Update() ) |
30.98ms | 25.62ms | โฌ 17% ๋จ์ถ |
| GC ํธ์ถ ํ์ | 98 | 64 | โฌ 35% ๊ฐ์ (๋ฉ๋ชจ๋ฆฌ ์ต์ ํ) |
| ์ค์๊ฐ ์๋ฐํ ์ ์ด ์์คํ FPS | 29.3 FPS | 33.3 FPS | โซ 15% ํฅ์ |
| ์ต์ ๋ถํ CPU ์ฌ์ฉ๋ | 51.7% | 47.5% | โฌ 4.2% ๊ฐ์ (์์ ์ฑ ์ฆ๊ฐ) |
- ๋ฌธ์ :
List.Contains()๋ฐList.Remove()ํธ์ถ๋ก ์ธํด O(N) ๊ฒ์ ๋ฐ์ โ ์ฑ๋ฅ ์ ํ. - ์ถ๊ฐ ๋ฌธ์ :
new์ฐ์ฐ์ ํตํด ๋ถํ์ํ ๊ฐ์ฒด ์์ฑ โ GC ํธ์ถ ์ฆ๊ฐ.
// ๊ธฐ์กด ์ฝ๋: O(N) ๊ฒ์์ผ๋ก CPU ๋ถํ ๋ฐ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ๋ฐ์
List<uint> allUsers = new List<uint>();
for (int i = allUsers.Count - 1; i >= 0; i--)
{
uint userId = allUsers[i]; // O(N)
RemoveUser(userId);
}- ํด๊ฒฐ:
HashSet<>์ฌ์ฉ์ผ๋ก ๊ฒ์ ์ฑ๋ฅ O(N) โ O(1) ๊ฐ์ . - ํจ๊ณผ: CPU ๋ถํ ๊ฐ์ & GC ๋ฐ์ ์ต์ํ.
private HashSet<uint> allUsers = new HashSet<uint>();
foreach (uint userId in allUsers)
{
RemoveUser(userId); // O(1)
}
allUsers.Clear(); // HashSet ๋น์ฐ๊ธฐ- ๋ฌธ์ :
FindObjectOfType<KinectManager>()๋ ์ฌ ๋ด ๋ชจ๋ ์ค๋ธ์ ํธ๋ฅผ ํ์ โ CPU ๋ถํ ์ฆ๊ฐ. - ์ถ๊ฐ ๋ฌธ์ :
Awake()์์ ์ค๋ณต ์ธ์คํด์ค ์์ฑ ๊ฐ๋ฅ.
public static KinectManager Instance
{
get
{
return FindObjectOfType<KinectManager>(); // ๋งค๋ฒ ๊ฒ์ ๋ฐ์ (๋นํจ์จ์ )
}
}
.
.
.
private void Awake()
{
instance = this;
DontDestroyOnLoad(gameObject);
}- ํด๊ฒฐ: ํ ๋ฒ๋ง
FindObjectOfType<KinectManager>()์ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์บ์ฑํ์ฌ ๋ถํ์ํ ํ์ ์ ๊ฑฐ. - ํจ๊ณผ: CPU ๋ถํ ๊ฐ์ & ์ค๋ณต ์ธ์คํด์ค ๋ฐฉ์ง.
// ์ต์ ํ๋ ์ฑ๊ธํค ์ ์ฉ: ํ ๋ฒ๋ง ๊ฒ์ํ๊ณ ์ธ์คํด์ค๋ฅผ ์บ์ฑ
private static KinectManager instance;
public static KinectManager Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<KinectManager>();
}
return instance;
}
}
.
.
.
private void Awake()
{
if (instance == null)
{
instance = this; // ์ฑ๊ธํค ์ด๊ธฐํ
DontDestroyOnLoad(gameObject); // ์ฌ ๋ณ๊ฒฝ ์ ์ธ์คํด์ค ์ ์ง
}
else
{
Destroy(gameObject); // ์ค๋ณต ์ธ์คํด์ค ๋ฐฉ์ง
}
}KinectManager.Update()์ ์ต๋ ๋ถํ ์คํ ์๊ฐ์ 17% ๋จ์ถ- GC ํธ์ถ ํ์๋ฅผ 35% ๊ฐ์ โ ๋ถํ์ํ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์ ๊ฑฐ
- ์ค์๊ฐ ์๋ฐํ ์ ์ด ์์คํ ์ FPS๋ฅผ 15% ํฅ์
- ์ต์ ๋ถํ ์ํฉ์์๋ CPU ๋ถํ๋ฅผ 4.2% ๊ฐ์ โ ์์ ์ ์ธ ์์คํ ๊ตฌํ
-
์ต์ Unity์์ Kinect-SDK ์ฌ์ฉ ์ ๋ค์๊ณผ ๊ฐ์ ์ค๋ฅ๊ฐ ๋ฐ์
'GUIText' is obsolete: 'GUIText has been removed. Use UI.Text instead.'
-
Unity์
GUIText๋ ๋ ์ด์ ์ง์๋์ง ์์ผ๋ฉฐ, ์ต์ Unity UI ์์คํ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ํ์
- UI.Text๋ก ๋ณ๊ฒฝ
- ๊ธฐ์กด ์ฝ๋ (GUIText ์ฌ์ฉ - ์ง์ ์ข ๋ฃ๋จ)
using UnityEngine;
public class Example : MonoBehaviour
{
public GUIText guiText; // ์ง์ ์ข
๋ฃ๋ ๋ฐฉ์
void Update()
{
guiText.text = "Score: " + Time.time;
}
}- Unity์ Canvas + UI.Text ์์คํ ์ ์ฉ
GUIText๋์Text์ฌ์ฉ ๋ฐ RectTransform ๊ธฐ๋ฐ UI ๋ฐฐ์น ๊ฐ๋ฅ
using UnityEngine;
using UnityEngine.UI; // UI ๋ค์์คํ์ด์ค ์ถ๊ฐ
public class Example : MonoBehaviour
{
public Text uiText; // UI.Text ์ฌ์ฉ
void Update()
{
if (uiText != null)
{
uiText.text = "Score: " + Time.time.ToString("F2");
}
}
}์ UI.Text๋ฅผ ์ฌ์ฉํด์ผ ํ๋๊ฐ?
- ์ ์ฐ์ฑ
UI.Text๋ Canvas ๊ธฐ๋ฐ์ผ๋ก ๋ค์ํ ํด์๋์ ํ๋ฉด ๋น์จ์ ์ง์ํฉ๋๋ค.- RectTransform์ผ๋ก ์์น์ ํฌ๊ธฐ๋ฅผ ์ฝ๊ฒ ์กฐ์ ํ ์ ์์ต๋๋ค.
- ์คํ์ผ๋ง
- ํฐํธ, ์์, ์ ๋ ฌ, ์๋์ฐ ๋ฑ ๋ค์ํ ํ ์คํธ ํจ๊ณผ ์ ๊ณตํฉ๋๋ค.
- ์ฑ๋ฅ
- Canvas ์์คํ ์ ๋ ๋๋ง ์ฑ๋ฅ์ด ์ต์ ํ๋์ด ์์ต๋๋ค.
- ๋ฏธ๋ ํธํ์ฑ
GUIText๋ ๋ ์ด์ ์ง์๋์ง ์์ผ๋ฉฐ,UI.Text๋ ์ง์์ ์ผ๋ก ์ ๋ฐ์ดํธ ๋ฉ๋๋ค.
- ์ค์๊ฐ Skeleton Point ์ธ์ ์ค ์ผ๋ถ ๊ฐ์ด ๋น์ ์์ ์ผ๋ก ํ๊ฑฐ๋ ๊ฐ์ง๋์ง ์๋ ๋ฌธ์ ๋ฐ์
- ์์ธ ๋ถ์:
- Skeleton ๋ฐ์ดํฐ๊ฐ ์ฐ์์ ์ผ๋ก ์ถ์ ๋์ง ์์
- ์ฅ์ ๋ฌผ์ ์ฌ๋์ด ๊ฐ๋ ค์ ธ ์ผ์๊ฐ ์ ๋๋ก ์ถ์ ๋์ง ์์
- ์ด์ ์ขํ๋ฅผ ํ์ฉํ์ฌ ์์ ์ ์ธ ๊ฐ ๋ฐํ
- ๊ธฐ์กด ์ฝ๋ (๋น์ ์์ ์ธ ์ธ์ ๊ฐ๋ฅ)
private Vector3 GetRightHandPosition()
{
KinectWrapper.NuiSkeletonPositionIndex joint = KinectWrapper.NuiSkeletonPositionIndex.HandRight;
KinectManager manager = KinectManager.Instance;
if (manager && manager.IsInitialized() && manager.IsUserDetected())
{
uint userId = manager.GetPlayer1ID();
return manager.GetJointPosition(userId, (int)joint); // ๋ถ์์ ํ ๊ฐ ๋ฐ์ ๊ฐ๋ฅ
}
return Vector3.zero;
}- ์ด์ ํ๋ ์์ ์์น(
previousRightHandPosition)๋ฅผ ์ ์ฅํ์ฌ ๊ฐ์ด ํ๋ ๋ฌธ์ ํด๊ฒฐ
private Vector3 GetRightHandPosition()
{
KinectWrapper.NuiSkeletonPositionIndex joint = KinectWrapper.NuiSkeletonPositionIndex.HandRight;
KinectManager manager = KinectManager.Instance;
Vector3 jointPos = Vector3.zero;
if (manager && manager.IsInitialized())
{
if (manager.IsUserDetected())
{
uint userId = manager.GetPlayer1ID();
if (manager.IsJointTracked(userId, (int)joint))
{
jointPos = manager.GetJointPosition(userId, (int)joint);
previousRightHandPosition = jointPos;
return jointPos;
}
}
}
Debug.LogWarning("Right hand joint not tracked. Using previous position.");
return previousRightHandPosition;
}- Skeleton Point๊ฐ ํ๋ ๋ฌธ์ ๋ฐฉ์ง
- ์ด์ ํ๋ ์ ๋ฐ์ดํฐ ํ์ฉํ์ฌ ์ฐ์์ฑ ์ ์ง
- ๋ณด๋ค ์์ ์ ์ธ Skeleton ํธ๋ํน ๊ตฌํ
-
๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฅํ์ผ๋ ์ฑ๋ฅ ์งํ๊ฐ ๋ฎ์
-
๋จธ์ ๋ฌ๋ ์ฑ๋ฅ ํ ์คํธ ๊ฒฐ๊ณผ:
- ์ต๊ณ ์ฑ๋ฅ: 0.95
- ์ต์ ์ฑ๋ฅ: 0.17 โ ์ฑ๋ฅ ํธ์ฐจ๊ฐ ์ฌํจ
-
์์ธ ๋ถ์
- 12๋ช ์ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ์๊ธฐ์ ๋งค์ฐ ์ ์ ๋ฐ์ดํฐ
- ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ๊ฐ ์ ๋ชป ๋์ด ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ์ฌ์ฉํ๊ธฐ์ ์ ์ ํ์ง ์์ ๋ฐ์ดํฐ์์ต๋๋ค.
- ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ ๊ณผ์ ์ฌ์ค๊ณ
- ๋ผ๋ฒจ๋ง ๊ธฐ์ค ์ฌ์ ์ ๋ฐ ์ ์ ๋ ๋ฐ์ดํฐ์ ํ์ฉ
- ๋ฐ์ดํฐ ์์ง๋ ์ฆ๊ฐํ์ฌ ์ ๋ขฐ์ฑ ํฅ์
- ์ต๊ณ ์ฑ๋ฅ 0.96 ๋ฐ ์ฑ๋ฅ ํธ์ฐจ ์์ ํ.
-
ํ์ฉ ๊ฐ๋ฅ์ฑ
- ์๊ฐํ๋ฅผ ํตํด ์ค์ ์ฌ๋ 12๋ช ์ ๋ฐ์ดํฐ๋ฅผ ์์ง.
- ํ์๋ค์ ์ฌํ ์น๋ฃ์ ๋ํ ์ฐธ์ฌ๋๋ฅผ ๋์ด๊ณ , ๋ฌผ๋ฆฌ ์น๋ฃ์ ์ข ์ฌํ์๋ ๊ต์๋๊ป ๋ฌธ์๋ฅผ ๋๋ ค ์ค์ ์์ ํ์ฅ์์ ์ฌ์ฉํ ์ ์๋ ๋๊ตฌ๋ก ๋ฐ์ ํ ๊ฐ๋ฅ์ฑ์ ๋ณด์ฌ์ค
-
ํํ ๋ฐํ
- 2024๋ ๋ ์๋ฃ์ ๋ณด๊ณตํํ, 2024 IEEE BHI ํํ ํฌ์คํฐ ๋ฐํํจ
-
ํ์ ์ ๋ฐํ
- ์์ฒํฅ๋ํ๊ต ์ 1ํ ์ตํฉ๋ํ ํ์ ์ ์ฅ๋ ค์ ์์
-
SW ๋ฑ๋ก
-
๋ ผ๋ฌธ ํฌ๊ณ (under reivew)
- C#: Kinect ๋ฐ์ดํฐ ์์ง ๋ฐ ๋ถ์์ ์ํ ํต์ฌ ์ธ์ด๋ก ์ฌ์ฉ
- Unity: ํ์์ ์์ง์์ ์๊ฐ์ ์ผ๋ก ํผ๋๋ฐฑํ๋ 3D ์๋ฎฌ๋ ์ด์ ๊ตฌํ
- Python, Scikit-learn: ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ํตํ ์์ง์ ๋ฐ์ดํฐ ๋ถ์ ๋ฐ ๋ถ๋ฅ
- Git: ๋ฒ์ ๊ด๋ฆฌ๋ฅผ ์ํด ์ฌ์ฉ
- Excel: ๋ฐ์ดํฐ ๋ถ์ ๋ฐ ์ ์์ฑ ๊ฒ์ฌ ๋๊ตฌ๋ก ์ฌ์ฉ