<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>mings-k.log</title>
        <link>https://velog.io/</link>
        <description>꾸준히, 열심히, 즐겁게</description>
        <lastBuildDate>Thu, 15 Feb 2024 07:30:24 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>mings-k.log</title>
            <url>https://velog.velcdn.com/images/mings-k/profile/8f4cfeea-ad81-4284-a9a0-dc2d8b067cd3/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. mings-k.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/mings-k" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[1차 저주파 통과 필터 전개]]></title>
            <link>https://velog.io/@mings-k/1%EC%B0%A8-%EC%A0%80%EC%A3%BC%ED%8C%8C-%ED%86%B5%EA%B3%BC-%ED%95%84%ED%84%B0-%EC%A0%84%EA%B0%9C</link>
            <guid>https://velog.io/@mings-k/1%EC%B0%A8-%EC%A0%80%EC%A3%BC%ED%8C%8C-%ED%86%B5%EA%B3%BC-%ED%95%84%ED%84%B0-%EC%A0%84%EA%B0%9C</guid>
            <pubDate>Thu, 15 Feb 2024 07:30:24 GMT</pubDate>
            <description><![CDATA[<p>칼만필터는 어렵지 않아 책을 통해 1차 저주파 통과 필터 내용을 보게 되었습니다.
책에 나온 공식은 아래와 같은데 
<img src="https://velog.velcdn.com/images/mings-k/post/e173cacd-4b8b-41dd-b6ff-bff746f8636f/image.png" alt="">
뭔가 의문이 듭니다...? </p>
<h3 id="회로이론을-통해-배운-저주파-통과-필터의-식과는-매우-다른데요">회로이론을 통해 배운 저주파 통과 필터의 식과는 매우 다른데요??</h3>
<p>그래서 어떻게 이 식이 1차 저주파 통과 필터라 불릴 수 있는지 공부를 조금 해봤습니다.
먼저 회로 이론에서 사용한 1차 저주파 통과 필터 회로는 아래와 같은 RC 회로입니다.
<img src="https://velog.velcdn.com/images/mings-k/post/bf1d1f01-9231-4ff6-9e10-9d763d69c6c0/image.png" alt="">
해당 회로를 풀어보면 식은 아래와 같이 전개됩니다. 
<img src="https://velog.velcdn.com/images/mings-k/post/b010ebf7-745a-4719-b315-f5136bd3f16e/image.png" alt="">
위 식이 회로이론을 통해 배운 1차 저주파 통과 필터의 식입니다. 
그렇다면 어떻게 이 식이 책에 나온 식이 될 수 있을까요?
바로 위 식을 컴퓨터에 적용하기 위한 Δt 간격의 차분 방정식으로 변환하면 됩니다.
변환 식은 아래와 같습니다.
<img src="https://velog.velcdn.com/images/mings-k/post/0de125db-d599-431a-8cdf-ffff90259d95/image.png" alt=""></p>
<p>이를 통해 책에서 나온 1차 저주파 통과 필터가 회로이론에서 배운 1차 저주파 통과 필터와 다르지 않다는 것을 알게 되었습니다!!</p>
<hr>
<blockquote>
<p>참고 자료</p>
</blockquote>
<ul>
<li><a href="https://stella47.tistory.com/102">1차 필터의 연속/이산 시간 영역에서의 변환과 구현</a></li>
<li><a href="https://ko.wikipedia.org/wiki/%EB%A1%9C%EC%9A%B0%ED%8C%A8%EC%8A%A4_%ED%95%84%ED%84%B0">wiki 로우패스 필터</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Flutter + Unity AR]]></title>
            <link>https://velog.io/@mings-k/Flutter-Unity-AR</link>
            <guid>https://velog.io/@mings-k/Flutter-Unity-AR</guid>
            <pubDate>Wed, 22 Nov 2023 08:41:27 GMT</pubDate>
            <description><![CDATA[<p>이전 글에서 apple의 정책상 background에서 카메라를 쓰지 못하는 것 같다는 말을 했었다. 그러나 background에서 실행시키지 않으면 의미가 없다는 생각을 하며 최선을 방안을 탐색하던 중 불쑥 나타난 그 이름 </p>
<h3 id="pip-mode">pip mode...</h3>
<p>그렇다면 pip mode란 무엇일까?</p>
<p>pip mode란 picture in picture mode로서 유튜브 프리미엄을 쓰는 사람들은 화면을 최소화 하여 다른 어플을 사용할 수 있는데 그때 사용되는 것이 pip mode이다. 즉, pip mode를 사용하면 프로젝트 초기에 구상했던 방안을 완성할 수 있다는 것이다.
그래서 Unity에서 pip mode를 사용하는 방법을 찾다가 
<img src="https://velog.velcdn.com/images/mings-k/post/200d484b-a807-4f9f-906d-be7cfd88472c/image.png" alt=""></p>
<h3 id="항상-관심이-있었던-flutter를-이용하면-어떨까">항상 관심이 있었던 flutter를 이용하면 어떨까?</h3>
<p>라는 생각을 하며 Unity의 정보를 flutte에 넘기는 방법을 찾았다.
그렇게 찾은 방법은 <a href="https://pub.dev/packages/flutter_unity_widget">flutter_unity_widget</a> . 
사실 이전에 flutter로 어플을 만들고 싶어서 unity의 3D 정보를 flutter로 가져오기 위해 flutter_unity_widget을 시도했으나 여러 오류를 겪으며 결국 사용을 실패했던 기억이 있었다. </p>
<p>아픈 기억을 가지고 두려움에 떨며 <a href="https://www.youtube.com/watch?v=icxfRM_qEnU&amp;t=491s">유튜브 튜토리얼</a>을 차근차근 따라한 결과!!</p>
<h2 id="실-패">실 패</h2>
<p><img src="https://velog.velcdn.com/images/mings-k/post/d41934d7-6b02-4281-8b61-8bcfbea4c727/image.png" alt=""></p>
<p>역시나 이전에 했던 방식으로 접근하니 과거에 안됐던 것이 될리가 없었다. 하지만 여기서 포기하면 성장은 없다.
이유를 찾아보다 도달한 결론은 <a href="https://pub.dev/">pub.dev</a>에 올라온 공식 정보를 따라해보자!! 였다. 기존에는 글을 통해 따라가는 것에 대한 두려움이 있어 넘겼지만, 더 이상 물러날 곳이 없기에 정석을 따르기로 했다. 처음부터 차근차근 따라해서 실행시킨 결과!!!</p>
<h2 id="실패-x-2">실패 X 2</h2>
<p>역시나 쉽지 않은 상대였다. 지금까지 계속 괴롭힌 Error가 
<img src="https://velog.velcdn.com/images/mings-k/post/15e9d8ec-d5dc-4c1f-ab9a-cc1ea70108a0/image.png" alt=""></p>
<h3 id="no-such-moduel-unity-framework">No such moduel &#39;Unity Framework&#39;</h3>
<p>이 오류가 항상 발목을 잡았다. 구글에 검색해보니 많은 사람들이 위 오류를 접한 것 같다. 그러나 해결책으로 써놓은 많은 답변들로도 이 오류를 물리칠 수 없었다. 그래서 &#39;최근 iOS는 지원을 안하나 보다&#39; 라고 위로하며 도망치려하던 중 발견한 공식 Discord!! 
해당 채널로 들어가니 많은 분들이 존재했고 거기서 위 오류를 질문하니 돌아오는 답변은</p>
<ul>
<li>혹시 flavors를 제대로 setting 하셨나요?</li>
</ul>
<p>허나 flavors가 뭔지도 모르는 초 뉴비인 나는 해당 setting 법을 물어봤다. 
그 결과 공식 문서의 거의 마지막 부분에 </p>
<h4 id="flavors">Flavors</h4>
<p>라는 곳이 있다는 것을 알게 되었다. 해당 부분의 요구에 맞게</p>
<ul>
<li><p>Runner 부분의 Configurations를 아래와 같이
<img src="https://velog.velcdn.com/images/mings-k/post/9e774de5-6835-4b9d-934b-0ca4ada3e7db/image.png" alt=""></p>
</li>
<li><p>Unity-iPhone 부분의 Configurations를
<img src="https://velog.velcdn.com/images/mings-k/post/2824c5dc-9c07-48d5-8f3f-f2a2b0360d74/image.png" alt="">
위와 같이 설정하고 
flutter에 공식 문서에서 제공한 코드인 </p>
</li>
</ul>
<pre><code>import &#39;package:flutter/material.dart&#39;;
import &#39;package:flutter/services.dart&#39;;
import &#39;package:flutter_unity_widget/flutter_unity_widget.dart&#39;;

void main() {
  runApp(MaterialApp(
    home: UnityDemoScreen()
  ));
}

class UnityDemoScreen extends StatefulWidget {

  UnityDemoScreen({Key key}) : super(key: key);

  @override
  _UnityDemoScreenState createState() =&gt; _UnityDemoScreenState();
}

class _UnityDemoScreenState extends State&lt;UnityDemoScreen&gt;{
  static final GlobalKey&lt;ScaffoldState&gt; _scaffoldKey =
      GlobalKey&lt;ScaffoldState&gt;();
  UnityWidgetController _unityWidgetController;

  Widget build(BuildContext context) {

    return Scaffold(
      key: _scaffoldKey,
      body: SafeArea(
        bottom: false,
        child: WillPopScope(
          onWillPop: () {
            // Pop the category page if Android back button is pressed.
          },
          child: Container(
            color: colorYellow,
            child: UnityWidget(
              onUnityCreated: onUnityCreated,
            ),
          ),
        ),
      ),
    );
  }

  // Callback that connects the created controller to the unity controller
  void onUnityCreated(controller) {
    this._unityWidgetController = controller;
  }
}</code></pre><p>를 넣고 실행시킨 결과 드디어 </p>
<h2 id="성공">성공!!!!!!!!!</h2>
<p>여기서 주의할 점은 Simulator에 어플을 실행시키면 여전히 오류가 나므로 실제 device에서 어플을 실행해야 하는 것 같다!! </p>
<p>다음 글은 flutter를 이용해서 pip mode를 이용하는 방법을 작성해 보겠다!!</p>
<center> 
    <font size=5>
        <b>
To Be Continued...
        </b>
    </font>
</center> ]]></description>
        </item>
        <item>
            <title><![CDATA[Unity iOS notification ]]></title>
            <link>https://velog.io/@mings-k/Unity-iOS-notification</link>
            <guid>https://velog.io/@mings-k/Unity-iOS-notification</guid>
            <pubDate>Sat, 11 Nov 2023 12:17:37 GMT</pubDate>
            <description><![CDATA[<p>지금까지 iOS LiDAR를 이용하여 거리를 측정하고 상단의 이미지를 추출하는 것을 진행하였다. 이번에는 거리에 따라 notification 즉 알림을 보내는 기능을 추가하는 방법에 대해 글을 쓰고자 한다.</p>
<hr>
<p>unity에서 notification을 사용하기 위해서는 우선 </p>
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/366444f1-d936-47e4-96fd-c417f987c9a5/image.png"width="80%" height="%">
</img>
</p>

<p>Mobile Notification 패키지를 import 해줘야한다. 해당 패키지를 다운하면 이제 android와 iOS에서 notification을 사용할 수 있다. 이제 script를 이용하여 사용을 해주면 되는데 기본적인 내용은
<a href="%22https://docs.unity3d.com/Packages/com.unity.mobile.notifications@1.0/manual/index.html%22">이곳</a>에서 볼 수 있으며, 유튜브 강의는 <a href="%22https://www.youtube.com/watch?v=KkpWtsljLCA&amp;t=115s%22">여기</a>를 참고하였다. 먼저 notification을 사용하기 위한 기본적은 script를 작성할 필요가 있는데 해당 내용은 </p>
<pre><code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Notifications.iOS;


public class iosNotificationController : MonoBehaviour
{

    //notification 사용하기 위함
    public IEnumerator&lt;string&gt; RequestAuthorization()
    {
        using (var req = new AuthorizationRequest(AuthorizationOption.Alert | AuthorizationOption.Badge, true))
        {
            while (!req.IsFinished)
            {
                yield return null;
            }
        }
    }

    public void SendNotification(string title, string body, string subtitle, int fireTimeInSeconds)
    {
        var timeTrigger = new iOSNotificationTimeIntervalTrigger()
        {
            TimeInterval = new System.TimeSpan(0, 0, fireTimeInSeconds),
            Repeats = false
        };

        var notification = new iOSNotification()
        {
            Identifier = &quot;hello_world_notification&quot;,
            Title = title,
            Body = body,
            Subtitle = subtitle,
            ShowInForeground = true,
            ForegroundPresentationOption = (PresentationOption.Alert | PresentationOption.Sound),
            CategoryIdentifier = &quot;default_category&quot;,
            ThreadIdentifier = &quot;thread1&quot;,
            Trigger = timeTrigger

        };

        iOSNotificationCenter.ScheduleNotification(notification);

    }


    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

    }
}

</code></pre><p>위와 같이 작성하였다. </p>
<pre><code>var timeTrigger = new iOSNotificationTimeIntervalTrigger()
        {
            TimeInterval = new System.TimeSpan(0, 0, fireTimeInSeconds),
            Repeats = false
        };</code></pre><p>이 부분에서 TimeInterval이 int라 가장 빠르게 동작하는 시간이 1초라 좀 더 빨리는 할 수 없을까 double로 변경하려 했으나 아직 제대로 못해서 그런지 double로 하면 오류가 나서 일단은 1초로 진행하기로 하고 위 코드 그대로 진행하였다. 
이제 기본적은 코드는 작성하였으니 사용하기 위한 코드가 필요하다. 사용하기 위한 코드는
이전에 만들었던 코드에서 </p>
<pre><code>// notification 불러오기
    [SerializeField]
    private iosNotificationController iosNotificationController;</code></pre><p>위 코드로 이전 script를 가져온 후 void Start() 부분에 notification 사용 승인을 질문할 </p>
<pre><code>StartCoroutine(iosNotificationController.RequestAuthorization());
</code></pre><p>코드를 넣었다. 
<a href="%22https://velog.io/@mings-k/Unity-AR-iOS-LiDAR-%ED%99%9C%EC%9A%A9%22">이전 글</a>에서 작성한 것을 사용하여 1.3m 보다 가까워졌을 때 빨간 표기와 함께 notification도 동작하길 바라며 void Update()에 </p>
<pre><code>// first는 제목부분, warning은 body부분, subtitle은 말그대로, 1은 TimeInterval 시간이다.
iosNotificationController.SendNotification(&quot;first&quot;, &quot;warning&quot;, &quot;subtitle&quot;, 1);</code></pre><p>을 넣으니 Update의 속도가 TimeInterval인 1초 보다 빨라 notification문구가 나오지 않았고, 앱을 종료하면 그제서야 나오는 상황이 나타났다. (이 이유를 몰라서 하루를 썼다...)
해당 문제를 해결하기 위해 Update가 아닌 FixedUpdate()를 이용하였다.
FixedUpdate는 매 프레임마다 실행되는 Update와 달리 원하는 주기를 설정하여 해당주기에 따라 Update시킬 수 있기에 원하는 주기를 1초 보다 크게 한다면 동작에 문제가 없을 것이라 판단하였다. FixedUpdate의 주기를 변경하기 위해서는 project setting의 player Setting에 들어가야 한다. 그 후 </p>
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/92da7a5f-35a0-4ff2-bf6c-cb3e6148bcb9/image.png"width="80%" height="%">
</img>
</p>
위 사진과 같이 Time의 가장 상단인 Fixed Timestep을 변경하면 원하는 주기를 설정할 수 있다.

<h4 id="위-사진과-같이-작성하면-주기는-11초가-된다">위 사진과 같이 작성하면 주기는 1.1초가 된다.</h4>
<p>주기를 설정한 후 iosNotificationController를 FixedUpdate에 사용하기 위해 </p>
<pre><code>// notification을 실행시키기 위한 trigger 
    static int trigger;</code></pre><p>static을 이용하여 trigger라는 전역변수를 만들고 1.3m보다 가까워졌을 때 </p>
<pre><code>if (hitDis &lt; 1.3f)
                {
                    trigger = 0;
                    color[i].material.color = Color.red;

                    Debug.Log(&quot;거리가 가까워짐&quot;);
                    trigger = 1;


                }</code></pre><p>다음과 같이 trigger가 1이 되도록 했다. 
이후 </p>
<pre><code>private void FixedUpdate()
    {
        if(trigger == 1)
        {
            iosNotificationController.SendNotification(&quot;first&quot;, &quot;warning&quot;, &quot;subtitle&quot;, 1);
            trigger = 0;
        }
    }</code></pre><p>다음과 같이 동작 후 초기화를 해주니 원하는 동작이 실행되었다!!
원래는 실시간성이 가장 중요하여 1초 보다 빠른 반응이 필요하지만 아직 해당 부분은 좀 더 공부가 필요해 보인다. </p>
<p>원하는 프로젝트를 만들기 위해 남은 task는 </p>
<blockquote>
<ol>
<li>여전히 존재하는 classification 실행 시의 화면 딜레이</li>
<li>임시로 적용한 classification model의 정확성 문제</li>
<li>최적의 화면 추출 위치 설정 </li>
<li>Backgroud 실행</li>
</ol>
</blockquote>
<p>이 있다. 그런데 여기서 Background 실행 방법을 찾아보던 중 iOS의 정책상 해당 어플을 Background에서 실해하는 것이 불가능한 듯한 글을 보았다... 만약 불가능하다면 아쉽지만 정책이니 4번 task를 제외한 task를 진행할 예정이다...ㅠㅠ
아직 남은 task가 있으니 열심히 연구해 볼 예정이다!!</p>
<p>실행 결과 (사진 클릭 시 유튜브 영상으로 이동합니다.)
<a href="https://youtube.com/shorts/55HESruIwcg"><img src="https://velog.velcdn.com/images/mings-k/post/1754320e-e2be-447a-92f7-c3b41d332ab8/image.jpeg" alt="Video Label"></a></p>
<center> 
    <font size=5>
        <b>
To Be Continued...
        </b>
    </font>
</center> 
]]></description>
        </item>
        <item>
            <title><![CDATA[tqdm 사용]]></title>
            <link>https://velog.io/@mings-k/tqdm-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@mings-k/tqdm-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Sun, 05 Nov 2023 07:15:20 GMT</pubDate>
            <description><![CDATA[<h4 id="tqdm을-사용하며-기존에-알고-있던-방식가-약간-다른-방식을-사용하게-되어-기억에-남기고자-글을-쓰게되었다">tqdm을 사용하며 기존에 알고 있던 방식가 약간 다른 방식을 사용하게 되어 기억에 남기고자 글을 쓰게되었다.</h4>
<hr>
<p>공식 <a href="https://github.com/yhenon/pytorch-retinanet">RetinaNet</a>을 학습할 일이 생겨 학습을 진행하며 <a href="https://tqdm.github.io/">tqdm</a>으로 학습 진행 상황을 시각화 하려는데 기존에는</p>
<pre><code>images, labels in enumerate(train_load)</code></pre><p>와 같은 형태의 코드에서 </p>
<pre><code>for images, labels in tqdm(train_load):</code></pre><p>와 같은 형태로 변경하여 학습을 진행하면 학습 시 게이지바가 등장하였는데 
이번에 진행할 코드는 </p>
<pre><code> for iter_num, data in enumerate(dataloader_train):</code></pre><p>로 image와 label을 직접적으로 추출하는 방식이 아닌 코드였다.
위 내용에서 </p>
<pre><code> for iter_num, data in tqdm(dataloader_train,leave=True):</code></pre><p>를 사용하니 ValueError: too many values to unpack (expected 2)  오류가 등장하였다. 
위 문제를 해결하기 위해 검색을 한 끝에</p>
<pre><code>for iter_num, data in enumerate(tqdm(dataloader_train,leave=True)):</code></pre><p>으로 코드를 바꾸는 정상적으로 학습이 잘 진행되었다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Unity AR iOS LiDAR 활용]]></title>
            <link>https://velog.io/@mings-k/Unity-AR-iOS-LiDAR-%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@mings-k/Unity-AR-iOS-LiDAR-%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Sat, 28 Oct 2023 14:11:29 GMT</pubDate>
            <description><![CDATA[<p>이전 글에서 <a href="%22https://www.youtube.com/watch?v=dWfDnyBVyxc&amp;t=626s&amp;ab_channel=%EC%88%9C%EC%88%9C%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4%22">순순스튜디오</a>님의 영상을 활용하여 iOS의 LiDAR의 거리값을 가져오는 방법에 대해 적었다. 이번에는 여러 위치의 LiDAR 거리 값을 가져오고 거리가 특정값보다 작을 경우 빨간색으로 나타내는 방법에 대한 글이다.</p>
<hr>
<p>이전의 경우 화면 가운데 위치의 LiDAR값만 가져왔었다. 그러나 좀 더 넓은 범위의 정보를 가져올 필요가 있었다. 초기 구성은 다음과 같다. </p>
 <p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/92233f47-f9ab-4da9-b5aa-b3ba317d5c49/image.jpeg"width="50%" height="%">
</p>
사진의 파란 위치가 LiDAR 포인트를 가져올 위치이다. 총 11개 point의 위치를 가져와야 하는데 이전처럼 하나하나 위치를 지정해서 코드를 짜는 것은 매우 비효율적이라 판단했다. 그래서 

 <p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/a615357f-dece-404b-b4ac-2f06f5b4dffa/image.jpeg"width="70%" height="%">
</p>
위와 같이 가운데를 기준으로 가로X축, 세로Y축으로 설정하고 for문을 작성하기로 하였다.
<br>
여러 위치에 대해 한번에 변수를 선언하기 위해 List형태인

<pre><code>/위치를 가질 변수 
    public List&lt;Vector2&gt; posVec = new List&lt;Vector2&gt;();</code></pre><p>다음과 같이 작성하였으며, 해당 변수에 값 대입은 </p>
<pre><code>//화면에 표기할 obj 위치 지정
        // i는 point 갯수 지정 
        for (int i = 0; i &lt; 11; i++)
        {
            // z는 point의 높이 설정
            for (float z = 0.5f; z &gt; 0.2; z = z - 0.1f)
            {
                if (z == 0.5f)
                {
                    //j는 x축 위치 설정 
                    for (float j = 0.1f; j &lt; 1; j = j + 0.2f)
                    {
                        // 화면 넓이를 이용하여 point 위치를 지정 
                        posVec[i] = new Vector2(Screen.width * j, Screen.height * z);
                        i++;
                    }

                }

                else if (z == 0.4f)
                {

                    for (float j = 0.2f; j &lt; 1; j = j + 0.2f)
                    {
                        posVec[i] = new Vector2(Screen.width * j, Screen.height * z);
                        i++;
                    }
                }
                else if (z == 0.3f)
                {
                    for (float j = 0.3f; j &lt; 1; j = j + 0.4f)
                    {
                        posVec[i] = new Vector2(Screen.width * j, Screen.height * z);
                        i++;
                    }
                }

            }
        }</code></pre><p>위와 같이 11개의 포인트 위치를 for문으로 작성하였다. 
각 point에 표시될 모양 또한 List 형태인</p>
<pre><code>// 화면의 LiDAR 사용 위치에 표시될 object
    public List&lt;Transform&gt; obj = new List&lt;Transform&gt;();</code></pre><p>로 선언하였으며</p>
<p><img src="https://velog.velcdn.com/images/mings-k/post/f9eefd3e-8f76-4ada-91a5-318a50a88fab/image.png" alt="">
다음과 같이 구성된 obj의 pivot 11개를 
<img src="https://velog.velcdn.com/images/mings-k/post/b1ed2cd7-8956-4f52-8779-d55d11215c74/image.png" alt=""></p>
<p>다음과 같이 연결해주었다.
해당 방법은 </p>
<p><a href="%22https://www.youtube.com/watch?v=dWfDnyBVyxc&amp;t=626s&amp;ab_channel=%EC%88%9C%EC%88%9C%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4%22">순순스튜디오</a>님의 영상에서 확인할 수 있었다. 
이제 각 point의 거리 값을 가져와야 하는데,
이전 처럼 </p>
<pre><code> void Update()
    {
        if (m_RaycastManager.Raycast(_centerVec, s_Hits))
        {
            Quaternion tRot = Quaternion.Euler(90f, 0, 0);
            // s_Hits의 위치를 저장 
            var hitPose = s_Hits[0].pose;
            // s_Hits의 거리를 저장
            float hitDis = s_Hits[0].distance;
            // 가져온 거리를 화면에 표시 
            c_resouceText.text = hitDis.ToString(&quot;#.##&quot;) + &quot;m&quot;;

            _pivot.localScale = new Vector3(hitDis, hitDis, hitDis);
            _pivot.position = Vector3.Lerp(_pivot.position, hitPose.position, 0.2f);
            //디버깅을 위해 rotation값을 Quaternion.Lerp에 넣어 자연스럽게 회전하게 만듦 
            _pivot.rotation = Quaternion.Lerp(_pivot.rotation, hitPose.rotation, 0.2f);

            //s_Hits의 값 초기화
            s_Hits.Clear();
        }
    }
}</code></pre><p>일일이 작성하기는 너무 많은 양이므로 </p>
<pre><code>// LiDAR의 정보를 저장할 list
    static List&lt;List&lt;ARRaycastHit&gt;&gt; Hits = new List&lt;List&lt;ARRaycastHit&gt;&gt;();</code></pre><p>다음과 같이 이중 List를 이용하였다.
11개의 List를 사용하기 위해 Start 부분에 </p>
<pre><code> for (int k = 0; k &lt; 11; k++)
        {
            List&lt;ARRaycastHit&gt; A = new List&lt;ARRaycastHit&gt;();
            Hits.Add(A);
        }</code></pre><p>for문을 이용하여 내용을 추가했다. </p>
<p>LiDAR 거리값을 가져오는 방식은 이전과 같으나 </p>
<pre><code>if (RaycastManager.Raycast(posVec[i], Hits[i]))
            {

                Quaternion tRot = Quaternion.Euler(90f, 0, 0);

                // s_Hits의 위치를 저장 
                var hitPose_1 = Hits[i];
                var hitPose = hitPose_1[0].pose;
                // s_Hits의 거리를 저장
                var hitDis_1 = Hits[i];
                float hitDis = hitDis_1[0].distance;

                //Debug.Log(i+&quot;의 거리&quot; + hitDis);


                obj[i].localScale = new Vector3(hitDis, hitDis, hitDis);
                obj[i].position = Vector3.Lerp(obj[i].position, hitPose.position, 0.2f);

                //디버깅을 위해 rotation값을 Quaternion.Lerp에 넣어 자연스럽게 회전하게 만듦
                obj[i].rotation = Quaternion.Lerp(obj[i].rotation, hitPose.rotation, 0.2f);
                // 거리가 1.3m보다 짧을 경우 원을 빨간색으로 변경 
                if (hitDis &lt; 1.3f)
                {
                    color[i].material.color = Color.red;
                }
                else
                {
                    color[i].material.color = Color.white;
                }
            }


            else
            {
                Quaternion tRot = Quaternion.Euler(90f, 0, 0);
                obj[i].localScale = new Vector3(0.5f, 0.5f, 0.5f);
                obj[i].rotation = Quaternion.Lerp(obj[i].rotation, tRot, 0.5f);
                obj[i].localPosition = Vector3.Lerp(obj[i].localPosition, Vector3.zero, 0.5f);

            }</code></pre><p>위와 같이 이중 List에서 값을 가져오는 형식으로 변경하였으며, 거리에 따라 표시되는 원의 색이 변하게 만들었다.</p>
<p>색에 대한 변수는 </p>
<pre><code>public List&lt;Renderer&gt; color = new List&lt;Renderer&gt;();</code></pre><p>Render 정보를 가져와서 내부의 색을 변경해주는 방식으로 작성했다!!
실행 결과 (사진 클릭 시 유튜브 영상으로 이동합니다.)
<a href="https://youtube.com/shorts/bfJk6tCvI88?feature=share"><img src="https://velog.velcdn.com/images/mings-k/post/3e5307f1-5281-4a05-96c1-85467861ade0/image.png" alt="Video Label"></a></p>
<p>제대로 작동하는 것을 확인할 수 있었다!!
이제 남은 문제점은 </p>
<blockquote>
<ol>
<li>여전히 존재하는 화면 딜레이</li>
<li>임시로 적용한 classification model의 정확성 문제</li>
<li>최적의 화면 추출 위치 설정 </li>
</ol>
</blockquote>
<p>이 있으며, 남은 문제점도 열심히 연구해 봐야겠다!!</p>
<center> 
    <font size=5>
        <b>
To Be Continued...
        </b>
    </font>
</center> ]]></description>
        </item>
        <item>
            <title><![CDATA[Unity AR 메모리 누수 현상 잡기]]></title>
            <link>https://velog.io/@mings-k/Unity-AR-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%88%84%EC%88%98-%ED%98%84%EC%83%81-%EC%9E%A1%EA%B8%B0</link>
            <guid>https://velog.io/@mings-k/Unity-AR-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%88%84%EC%88%98-%ED%98%84%EC%83%81-%EC%9E%A1%EA%B8%B0</guid>
            <pubDate>Sat, 28 Oct 2023 07:30:24 GMT</pubDate>
            <description><![CDATA[ <p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/e6efa747-325b-4884-b209-41db3d44d251/image.png"width="70%" height="%">
</p>

<hr>
<p> 현재 Unity를 이용하여 만든 어플의 메모리 사용량과 배터리 사용량을 확인할 필요가 있었다. 어플을 실행하고 Xcode의 
 <img src="https://velog.velcdn.com/images/mings-k/post/e1168f03-4d7c-4ba0-a3de-b13c3b759eb7/image.png" alt="">
부분을 클릭하니 원했던 정보를 확인할 수 있었다.</p>
<p> 확인하니 맨 위의 사진과 같이 memory가 끝도없이 상승하는 메모리 누수현상을 발견하였다. 어플을 실행했을 때 시간이 지난 후 튕기는 현상이 발생했었는데 아마 메모리가 계속 증가하다 한계치를 넘었을 때 튕기는 현상이 발생한 듯 하다. 이유를 곰곰이 생각하니
<a href="https://velog.io/@mings-k/Unity-AR-camera-%ED%99%94%EB%A9%B4-%EC%A0%95%EB%B3%B4-%EC%9D%BC%EB%B6%80%EB%B6%84%EC%9D%84-%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0">Unity AR camera 화면 정보 일부분을 추출하기</a> 에서 언급했던 튕기는 현상이 생각이 났고 코드를 돌아보니</p>
<pre><code>   private Texture2D CaptureImage()
    {
        int width = Screen.width;
        int height = Screen.height / 3;
        Texture2D Texture = new Texture2D(width, height, TextureFormat.RGB24, false);
        Texture.ReadPixels(new UnityEngine.Rect(0, 2 * height, width, height), 0, 0);
        Texture.Apply();
        return Texture;
    }</code></pre><center> 
    <font size=5>
        <b>
        ...?!
        </b>
    </font>
</center> 

<p>코드를 함수들로 변경하면서 이전에 말했던 update 부분에 </p>
<pre><code>Texture2D Texture = new Texture2D(width, height, TextureFormat.RGB24, false);</code></pre><p>코드를 넣어서 생성한 texture를 이용하는 것이 아니라 지속적으로 생성하여 메모리 누수 현상이 발생했던 것이다...
이 코드를</p>
<pre><code> private Texture2D CaptureImage()
    {

        Texture2D Texture = tex;
        int width = Screen.width;
        int height = Screen.height / 3;

        Texture.ReadPixels(new UnityEngine.Rect(0, 2 * height, width, height), 0, 0);
        Texture.Apply();
        return Texture;
    }</code></pre><p>이렇게 바꾸니 
 <p align="center">
&lt;img src=&quot;<a href="https://velog.velcdn.com/images/mings-k/post/96049990-9247-48d0-a2c2-8e297900e302/image.png&quot;width=&quot;70%&quot;">https://velog.velcdn.com/images/mings-k/post/96049990-9247-48d0-a2c2-8e297900e302/image.png&quot;width=&quot;70%&quot;</a> height=&quot;%&quot;&gt;</p>
</p>
문제 해결....
그래도 배운것이 있다면 정신을 잘 차리고 코드를 짜자...
<center> 
    <font size=5>
        <b>
To Be Continued...
        </b>
    </font>
</center> 
]]></description>
        </item>
        <item>
            <title><![CDATA[자연상수의 미분 ]]></title>
            <link>https://velog.io/@mings-k/%EC%9E%90%EC%97%B0%EC%83%81%EC%88%98%EC%9D%98-%EB%AF%B8%EB%B6%84</link>
            <guid>https://velog.io/@mings-k/%EC%9E%90%EC%97%B0%EC%83%81%EC%88%98%EC%9D%98-%EB%AF%B8%EB%B6%84</guid>
            <pubDate>Tue, 24 Oct 2023 14:55:31 GMT</pubDate>
            <description><![CDATA[<h4 id="ex의-미분은-ex이다-과거에-이유를-배웠으나-까먹었기에-다시-한번-상기하고자-글을-쓰게-되었다">$e^x$의 미분은 $e^x$이다. 과거에 이유를 배웠으나 까먹었기에 다시 한번 상기하고자 글을 쓰게 되었다.</h4>
<hr>
<p>먼저 $f(x)= e^x$인 함수를 도함수로 표기하면</p>
<p>$\displaystyle\lim_{
 Δx\rarr0}{f(x+Δx)-f(x)\over Δx}$ = $\displaystyle\lim_{
 Δx\rarr0}{e^{x+Δx} -e^{x}\over Δx}$ 이며,
 <br></p>
<p> $\displaystyle\lim_{
 Δx\rarr0}{e^{x+Δx} -e^{x}\over Δx}$  =  $\displaystyle\lim_{
 Δx\rarr0}{e^{x}(e^{Δx} -1)\over Δx}$ 이 된다. 
  <br> </p>
<p> 여기서 $\displaystyle\lim_{
 Δx\rarr0}{e^{x}(e^{Δx} -1)\over Δx}$의 $\displaystyle\lim_{
 Δx\rarr0}{(e^{Δx} -1)\over Δx}=1$ 이다. 
  <br></p>
  <center> 
    <font size=5>
        <b>
WHY?
        </b>
    </font>
</center> 
<br>

<p>$\displaystyle\lim_{
 Δx\rarr0}{(e^{Δx} -1)\over Δx}=1$ 이라 할때 </p>
<p> $(e^{Δx} -1) = t$라 하고,   $e^{Δx} = t +1\rarr Δx=ln(t+1)$ 이다.</p>
<p> 이 값을 $\displaystyle\lim_{
 Δx\rarr0}{(e^{Δx} -1)\over Δx}$에 대입하면 </p>
<p> $=\displaystyle\lim_{
 t\rarr0}{t\over ln(t+1)}$</p>
<p> $=\displaystyle\lim_{
 t\rarr0}{{1\over ln(t+1)}\over t}$</p>
<p>  $=\displaystyle\lim_{
 t\rarr0}{1\over{1\over t} ln(t+1)}$</p>
<p>   $=\displaystyle\lim_{
 t\rarr0}{1\over ln(t+1)^{1\over t}}$</p>
<p> 위 값은    $e=\displaystyle\lim_{
 t\rarr0}{ln(t+1)^{1\over t}}$ 에 의해 </p>
<p>   $\rarr\displaystyle{1\over ln(e)}$ 이 되며 결과적으로 1이 되기에 이 가정은 사실이 된다. </p>
<p>   그렇기에 최종적으로  </p>
<p> $\displaystyle\lim_{
 Δx\rarr0}{e^{x}(e^{Δx} -1)\over Δx}$의 값은 $e^{x}$가 되므로  </p>
<h3 id="ex의-미분은-ex이다">$e^x$의 미분은 $e^x$이다.</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[Unity AR classification 실행  ]]></title>
            <link>https://velog.io/@mings-k/Unity-AR-classification-%EC%8B%A4%ED%96%89</link>
            <guid>https://velog.io/@mings-k/Unity-AR-classification-%EC%8B%A4%ED%96%89</guid>
            <pubDate>Sat, 21 Oct 2023 09:03:42 GMT</pubDate>
            <description><![CDATA[<p>지금까지 Unity를 이용하여 원하는 카메라 화면의 일부를 추출하였고, 추출과 LiDAR를 동시에 실행하는 것 까지 진행했다. 이번에는 추출된 이미지를 Classification model을 사용하여 분류하는 작업에 대한 내용이다. </p>
<hr>
<p>먼저 Unity에서 classification model을 사용하기 위해 <a href="https://github.com/Unity-Technologies/barracuda-release">Barracuda package</a>를 사용하였다. 그리고 MobileNetv3에 custom dataset을 이용하여 학습한 후 onnx 파일로 출력하여 unity에 적용하였다. </p>
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/cdeabf0b-c550-47eb-ba60-ccc1e0a7a4f6/image.png
" width="50%" height="n%">
</p>
적용한 model의 정보는 위와 같다. 
Barracuda를 사용하기 위해 

<pre><code>using Unity.Barracuda;</code></pre><p>로 Barracuda를 적용하고 </p>
<pre><code>// Barracuda를 이용하여 사용할 model 선언 
    public NNModel classification;
    public Model model;
    public IWorker engine;</code></pre><p>위 코드를 이용하여 Model을 사용하기 위한 기본 선언을 해준다. 
label에 대한 정보는 &#39;\n&#39;을 기준으로 class를 분리한 text파일에 들어있으며 classs는 </p>
<blockquote>
<p>bus
car
motorcycle
train
truck</p>
</blockquote>
<p>총 5가지로 이루어져 있다. 
label에 대한 내용은 </p>
<pre><code>public TextAsset labelAsset;
private string[] labels;
// 화면에 text를 출력하기 위한 선언 
public TextMeshProUGUI lab;</code></pre><p>을 이용하여 선언하였다. </p>
<p><img src="https://velog.velcdn.com/images/mings-k/post/95ba4dc1-3e78-477b-9aca-da7a566be3e8/image.png" alt=""></p>
<p>최종으로 script에 다음과 같이 적용하였다.
Model을 적용하기 위한 코드는</p>
<pre><code>private void Awake()
    {
        // 화면에서 추출할 위치 지정 
        int width = Screen.width;
        int height = Screen.height / 3;
        // 화면 정보를 담을 공간 마련 
        tex = new Texture2D(width, height, TextureFormat.RGB24, false);
        // &#39;\n&#39;으로 분리된 label text값을 split  
        labels = labelAsset.text.Split(&#39;\n&#39;);

        model = ModelLoader.Load(classification);
        // 모델을 수행할 device 설정 
        WorkerFactory.Device device = WorkerFactory.Device.CPU;
        engine = WorkerFactory.CreateWorker(model, device);
    }

private void ExecuteML(Texture2D inputTexture)
    {
        int bestIndex = 0;
        float bestValue = 0;
        Tensor inputTensor = new Tensor(inputTexture, 3);
        engine.Execute(inputTensor);
        var output = engine.PeekOutput(&quot;modelOutput&quot;);
        // 가장 큰 값을 가지는 label 도출 
        for (int i = 0; i &lt; 5; i++)
        {
            if (output[0, 0, 0, i] &gt;= bestValue)
            {
                bestIndex = i;
                bestValue = output[0, 0, 0, i];
            }
        }
        // 화면에 classification 결과 label 출력 
        lab.text = labels[bestIndex];
        //Debug.Log(labels[bestIndex]);

    }</code></pre><p>위와 같다.
처음 object detection을 이용하려 하였으나 iPad에서 실행시키니 화면의 딜레이가 너무 심해서 classification을 사용하였다. 
그러나 현재 동작은 되지만 아직 해결해야할 문제점들이 있다.</p>
<blockquote>
<ol>
<li>여전히 존재하는 화면 딜레이</li>
<li>임시로 적용한 classification model의 정확성 문제</li>
<li>최적의 화면 추출 위치 설정 </li>
<li>LiDAR point 위치 및 data 활용 방법 고안</li>
</ol>
</blockquote>
<p>위 문제를 지속적으로 해결해 나갈 예정이며 classification의 결과 사진을 마지막으로 이번 글을 끝내고자 한다. </p>
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/a355e096-dab9-4ca9-851b-4d87dc1ab117/image.jpg
" width="50%" height="n%">
</p>

</p>
<center> 
    <font size=5>
        <b>
To Be Continued...
        </b>
    </font>
</center> 


]]></description>
        </item>
        <item>
            <title><![CDATA[Unity AR camera with iOS LiDAR]]></title>
            <link>https://velog.io/@mings-k/Unity-AR-camera-with-iOS-LiDAR</link>
            <guid>https://velog.io/@mings-k/Unity-AR-camera-with-iOS-LiDAR</guid>
            <pubDate>Mon, 16 Oct 2023 08:16:03 GMT</pubDate>
            <description><![CDATA[<hr>
<h4 id="본-게시글의-lidar-사용-부분은-youtube순순스튜디오님의-해당-영상에서-배운-내용을-활용하였습니다">본 게시글의 LiDAR 사용 부분은 <a href="https://www.youtube.com/@soonsoonstudio">Youtube순순스튜디오</a>님의 <a href="https://www.youtube.com/watch?v=dWfDnyBVyxc&amp;t=593s&amp;ab_channel=%EC%88%9C%EC%88%9C%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4">해당</a> 영상에서 배운 내용을 활용하였습니다.</h4>
<hr>
<p> 현재 진행중인 프로젝트의 필요내용은 아래와 같다.
 <p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/f98bdec5-9be6-4db4-a841-a4663f4cabdb/image.png
" width="100%" height="n%"></p>
</p>
 위 내용을 진행 위해서는 아래와 같이 이미지와 LiDAR를 동시에 사용해야한다. 앞서 작성했던 내용을 합치고 LiDAR를 이용하여 특정 위치의 거리값도 가져올 필요가 있었다. 순순스튜디오님의 영상에서 알려준 방식으로 LiDAR관련 구성을 하였으며 AR Session의 경우  
 <p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/272f992f-e5d3-431d-b51c-e9f60a8ff398/image.png
" width="%" height="n%">
</p>
위와같이 AR Plane Manager는 사용하지 않았다. 그 이유는 AR Plane Manager를 사용하니 LiDAR의 정확도가 다소 떨어지는 느낌을 받았기에 제거한 후 진행하였다. 먼저 Script의 경우 
앞의 
<b>
 <p align="center">
[Unity AR camera 화면 정보 일부분을 추출하기]
 </p>
</b>
에서 사용한 Script와 LiDAR의 정보를 가져오기 위한 아래 코드를 

<pre><code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.UI;
//TextMeshPro를 사용하기 위해 선언
using TMPro;

public class LiDARManager : MonoBehaviour
{
    public ARRaycastManager m_RaycastManager;
    // LiDAR의 정보를 저장할 list 
    static List&lt;ARRaycastHit&gt; s_Hits = new List&lt;ARRaycastHit&gt;();
    // center의 위치를 가질 변수
    public Vector2 _centerVec;
    // 화면의 LiDAR 사용 위치에 표시될 object
    public Transform _pivot;
    // LiDAR의 거리정보를 화면에 표시하기 위해
    public TextMeshProUGUI c_resouceText;




    void Start()
    {
        //화면의 중앙을 의미
        _centerVec = new Vector2(Screen.width * 0.5f, Screen.height * 0.5f);
    }


    void Update()
    {
        if (m_RaycastManager.Raycast(_centerVec, s_Hits))
        {
            Quaternion tRot = Quaternion.Euler(90f, 0, 0);
            // s_Hits의 위치를 저장 
            var hitPose = s_Hits[0].pose;
            // s_Hits의 거리를 저장
            float hitDis = s_Hits[0].distance;
            // 가져온 거리를 화면에 표시 
            c_resouceText.text = hitDis.ToString(&quot;#.##&quot;) + &quot;m&quot;;

            _pivot.localScale = new Vector3(hitDis, hitDis, hitDis);
            _pivot.position = Vector3.Lerp(_pivot.position, hitPose.position, 0.2f);
            //디버깅을 위해 rotation값을 Quaternion.Lerp에 넣어 자연스럽게 회전하게 만듦 
            _pivot.rotation = Quaternion.Lerp(_pivot.rotation, hitPose.rotation, 0.2f);

            //s_Hits의 값 초기화
            s_Hits.Clear();
        }
    }
}</code></pre><p>이용하였다. 화면에 글자를 표시하기 위해 Unity의 Canvas에 제공하는 TextMeshPro를 이용하였다. 화면에 출력될 Canvas의 화면은 
 <p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/991ab29c-ef15-4b9d-ab73-9f382f2dc18f/image.png
" width="40%" height="n%"></p>
</p>
위와 같이 구성하였으며 최종적으로 

 <p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/490e8900-0d93-4c7c-aff0-3dac05e443f4/image.png
" width="20%" height="n%">
</p>

<p>위와 같이 원하는 결과물을 얻을 수 있었다. 이후에는 추출한 상단 이미지를 딥러닝  Classification Model에 넣어 결과물을 얻는 작업을 진행할 예정이다!!</p>
<center> 
    <font size=5>
        <b>
To Be Continued...
        </b>
    </font>
</center> ]]></description>
        </item>
        <item>
            <title><![CDATA[Unity AR Raycast 사용하기]]></title>
            <link>https://velog.io/@mings-k/Unity-AR-Raycast-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@mings-k/Unity-AR-Raycast-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 15 Oct 2023 07:55:20 GMT</pubDate>
            <description><![CDATA[<hr>
<h4 id="본-게시글의-lidar-사용-부분은-youtube순순스튜디오님의-해당-영상에서-배운-내용을-정리하였습니다">본 게시글의 LiDAR 사용 부분은 <a href="https://www.youtube.com/@soonsoonstudio">Youtube순순스튜디오</a>님의 <a href="https://www.youtube.com/watch?v=85i87cBqre4&amp;list=PLATff1khpIscTMN2KXxagrTkBCwdzOeol&amp;index=5&amp;t=86s&amp;ab_channel=%EC%88%9C%EC%88%9C%EC%8A%A4%ED%8A%9C%EB%94%94%EC%98%A4">해당</a> 영상에서 배운 내용을 정리하였습니다.</h4>
<hr>
<p>iOS에서 제공하는 LiDAR를 활용하여 거리를 측정하기 위해 사용법을 찾던 도중 Unity의 AR Foundation 기능을 이용하면 사용이 가능하다는 것을 알게 되었다. AR Foundation을 사용했던 적이 전무했기에 인터넷과 유튜브를 헤매던 도중 가뭄의 단비같은 <a href="https://www.youtube.com/@soonsoonstudio">Youtube순순스튜디오</a>님의 유튜브를 알게되었으며 강의를 통해 알게된 Raycast에 대한 것을 정리하고자 한다. 
(해당 내용은 Raycast를 사용하여 터치한 부분에 공을 두는 것이다.)</p>
<p>먼저 iOS의 LiDAR는 비교적 최근 모델의</p>
<blockquote>
<ul>
<li>iPhone pro model</li>
</ul>
</blockquote>
<ul>
<li>iPad pro model</li>
</ul>
<p>에서 제공하고있다.</p>
<hr>
<p>Unity에서 AR 기능을 이용하기 위해 Unity project를 AR로 만들어준다.
그후 아래와 같이 구성된 초반 AR Session Origin의 AR Raycast Manager에 Raycast Prefab의 부분에 Ball prefeb을 추가한다. (LiDAR를 사용하기 위해서는 Raycast Manager가 중요하다.)</p>
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/8af4073e-d76e-4172-bf2f-4d0761ec8be8/image.png
" width="50%" height="n%">
</p>
Ball prefab의 구성은 3D object의 Sphere를 생성하고 그곳의 Component를 구성해야한다. (터치한 부분에 공을 놓기 위해서 Sphere를 두는 것이다.)

<p>기존의 Default Component에서</p>
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/378afbe5-c0f0-4ee2-83fd-5ecc889ebe62/image.png
" width="50%" height="n%">
</p>
Sphere Collider의 Is Trigger를 체크해준다. (체크를 하면 Collider 영역이 있더라도 Collider 영역을 무시해서 중첩할 수 있다.) 

<p>이를 통해 생성된 plane에 Ball을 중첩해서 생성할 수 있게된다.
 이렇게 생성한 Ball은 Prefab형태로 만들어야 하는데 간단하게 폴더를 생성 후 거기에 Drag and Drop을 하면 된다.</p>
<p>생성된 Prefab을 AR Raycast Manager의 Raycast Prefab에 넣어준다.
그 후 C# Script를 만들고 </p>
<pre><code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;

public class SetARBall : MonoBehaviour
{
    // 추가한 RaycastManager를 component로 연동
    public ARRaycastManager m_RaycastManager;
    // 충돌되는 점들을 저장할 list 생성
    static List&lt;ARRaycastHit&gt; s_Hits = new List&lt;ARRaycastHit&gt;();

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if(Input.touchCount &gt; 0)
        {
            Vector2 touchPosition = Input.GetTouch(0).position;
            // Raycast에서 touchPosition이 현재 터치한 포인트를, s_Hits가 포인트 저장, .planeWithinPolygon이 생성한 Plane위에 raycast를 생성 
            if (m_RaycastManager.Raycast(touchPosition, s_Hits, TrackableType.PlaneWithinPolygon))
            {
                var hitPose = s_Hits[0].pose;
                // raycast에 연결되어있는 ratcastPrefab object를 hitPose.position, hitPose.rotation에 맞춰서 생성)
                Instantiate(m_RaycastManager.raycastPrefab, hitPose.position, hitPose.rotation);
            }
        }

    }
}</code></pre><p>위 코드를 넣은 후 </p>
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/16e3127c-20db-4d65-b03a-e575dd051553/image.png
" width="70%" height="n%">
</p>
Script를 AR Session Origin을 넣고 사진과 같이 Raycast Manager에 AR Session Origin을 넣음으로 해당 Script가 동작하게 만들면 
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/08088db2-9818-44b4-b273-87295a3f553e/image.png
" width="70%" height="n%">
</p>
사진과 같이 터치한 부분에 공을 놓을 수 있다!!!

</p>
<center> 
    <font size=5>
        <b>
To Be Continued...
        </b>
    </font>
</center> 
]]></description>
        </item>
        <item>
            <title><![CDATA[Unity AR camera 화면 정보 일부분을 추출하기]]></title>
            <link>https://velog.io/@mings-k/Unity-AR-camera-%ED%99%94%EB%A9%B4-%EC%A0%95%EB%B3%B4-%EC%9D%BC%EB%B6%80%EB%B6%84%EC%9D%84-%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@mings-k/Unity-AR-camera-%ED%99%94%EB%A9%B4-%EC%A0%95%EB%B3%B4-%EC%9D%BC%EB%B6%80%EB%B6%84%EC%9D%84-%EC%B6%94%EC%B6%9C%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 13 Oct 2023 07:14:04 GMT</pubDate>
            <description><![CDATA[<p>Unity에서 ARkit을 활용하여 프로젝트를 진행하기 위해 AR camera를 이용한 휴대폰 화면의 상단 1/3 지점을 추출할 필요가 있었다. 
유니티의 기본 카메라가 아니라 AR camera의 정보를 가져오는 것이므로 어떤식으로 가져와야하나 인터넷을 돌아다니던 중 </p>
<pre><code>tex.ReadPixels(new UnityEngine.Rect(0, height, width, height), 0, 0);</code></pre><p>을 이용하면 카메라의 일부분을 추출할 수 있다는 정보를 얻어 실행에 옮겼다. </p>
<p>처음 완성한 코드는</p>
<pre><code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenCvSharp;
using UnityEngine.UI;

public class opencv : MonoBehaviour
{

    public RawImage img = default;

    void Start()
    {

        int width = Screen.width;
        int height = Screen.height;
        Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);
        tex.ReadPixels(new UnityEngine.Rect(0, 0, width, height), 0, 0);
        tex.Apply();

    }

    void Update()
    {

    }
}
</code></pre><p>위와 같았다. 그 결과는 rawimage에 검정화면만... 
생각해보니 위 코드를 Update가 아닌 Start에 넣었기에 시작 시 한 번만 화면을 읽기때문에 첫화면인 검정화면을 띄울 것이라 판단하여 Update에 위치한 </p>
<pre><code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenCvSharp;
using UnityEngine.UI;

public class opencv : MonoBehaviour
{

    public RawImage img = default;

    void Start()
    {
    }

    void Update()
    {

        int width = Screen.width;
        int height = Screen.height;
        Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);
        tex.ReadPixels(new UnityEngine.Rect(0, 0, width, height), 0, 0);
        tex.Apply();

    }
}</code></pre><p>위의 코드로 변경하였고 그 결과는 아래와 같았다.</p>
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/ab8827d0-15a8-4525-8bae-2eb0fde67088/image.PNG" width="50%" height="n%">
</p>
화면의 영상은 rawimage에 불러오지만 보이는 것과 같이 여러 이미지가 층층이 쌓인 형태로 보이며 대략 3초정도의 실행후에 튕기는 현상이 발생했다. 튕기는 현상의 원인은 Update위치에 tex를 선언하여 Update시 tex를 계속 생성했기 때문에 발생한 것이었다. 이후 

<pre><code>using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenCvSharp;
using UnityEngine.UI;

public class opencv : MonoBehaviour
{
    // 카메라 영상을 받을 위치 지정
    public RawImage img = default;
    // 카메라 영상을 담을 변수 지정
    private Texture2D tex;

    void Start()
    {
        //화면 위치 지정
        int width = Screen.width;
        int height = Screen.height / 3;
        // tex에 화면 정보를 담을 공간 마련 
        tex = new Texture2D(width, height, TextureFormat.RGB24, false);
    }

    void Update()
    {
        int width = Screen.width;
        int height = Screen.height / 3;

        // 상단 1/3 위치의 화면 정보 읽기 
        tex.ReadPixels(new UnityEngine.Rect(0, 2 * height, width, height), 0, 0);
        // 읽은 화면정보를 tex에 담기 
        tex.Apply();

        // tex에 담긴 Texture2D 정보를 img에 넣어 화면에 출력 
        img.texture = tex;
    }
}</code></pre><p>위의 코드로 변경하니 튕기는 문제는 해결되었다. 그러나 아직 남은 하나의 문제... 바로 여러 층이 쌓이는 현상이었다. 코드도 바꿔보고 여러 방법을 써봤으나 상황은 바뀌지 않았다. 그러다 문뜩 </p>
<p align="center">
'rawimage의 위치 때문인가?' 
</p>
는 생각이 들어 rawimage의 위치를 아래와 같이 바꾸니 제대로된 화면이 출력되었다.... 
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/85a90c4d-3c34-4166-b6d0-304894ab1b13/image.png" width="60%" height="50%">
</p>
rawimage가 상단 1/3 지점에 포함되어 있어 rawimage를 포함한 화면이 지속적으로 update 되는 문제였던 것이다.
상단 1/3 지점을 제대로 출력하는 사진을 마지막으로 글을 마친다!!
<p align="center">
<img src="https://velog.velcdn.com/images/mings-k/post/55943f2b-b936-4efd-aa7d-c48c113b29c2/image.jpeg" width="30%" height="50%">
</p>
<center> 
    <font size=5>
        <b>
To Be Continued...
        </b>
    </font>
</center> 
]]></description>
        </item>
    </channel>
</rss>