<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NTREXGO - 디바이스마트, 엔티렉스 컨텐츠 통합 사이트 &#187; 시스템</title>
	<atom:link href="http://www.ntrexgo.com/archives/tag/%ec%8b%9c%ec%8a%a4%ed%85%9c/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ntrexgo.com</link>
	<description>엔티렉스, 디바이스마트 컨텐츠 통합 사이트</description>
	<lastBuildDate>Thu, 03 Mar 2022 06:47:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>[67호]메타버스를 이용한 문서 보안 시스템</title>
		<link>http://www.ntrexgo.com/archives/40440</link>
		<comments>http://www.ntrexgo.com/archives/40440#comments</comments>
		<pubDate>Wed, 25 Aug 2021 00:00:35 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[ict]]></category>
		<category><![CDATA[공모전]]></category>
		<category><![CDATA[디바이스마트]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[메타버스]]></category>
		<category><![CDATA[문서보안]]></category>
		<category><![CDATA[시스템]]></category>
		<category><![CDATA[융합]]></category>
		<category><![CDATA[최우수상]]></category>
		<category><![CDATA[프로젝트]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=40440</guid>
		<description><![CDATA[디바이스마트매거진 67호 &#124; 더욱 함양된 보안성을 갖춘 문서 보안 시스템을 구축하기 위해 메타버스를 이용해보기로 했다. 메타버스를 이용한 보안 시스템의 취약성은 아직 발견된 것이 없으며, 컴퓨터와 휴대폰 두 개의 디바이스를 이용하여 보안 시스템을 구축하기 때문에 더 높은 보안 장벽을 갖는다는 장점이 있다. ]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-1.png" rel="lightbox[40440]"><img alt="67 ict_ 최우수상 메타버스 (1)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-1-620x203.png" width="620" height="203" /></a></p>
<p><span style="color: #ff6600;font-size: medium"><strong>2021 ICT 융합 프로젝트 공모전 최우수상</strong></span></p>
<p><span style="font-size: x-large"><strong>메타버스를 이용한 문서 보안 시스템</strong></span></p>
<p style="text-align: right">글 | 광운대학교 최예지, 최혁순</p>
<p>&nbsp;</p>
<p><span style="color: #0000ff"><strong>1.심사평</strong></span><br />
<strong>칩센</strong> 우선 Leap Motion과 unity을 통한 가상현실을 이용하는 것이 실제로는 처음 보고, 매우 흥미로웠습니다. 일반적인 실제 사용의 단계라면 어쩌면 번거로울 수도 있겠으나, 작품의 기획 의도인 강화된 보안이 필요한 경우에는 매우 유용한 기술로 판단됩니다. 다단계의 보안 단계를 만들고, AWS를 이용하여 떨어져 있는 다중의 사용자들 간에 보안 적용된 특정 정보 (작품에서는 문서)의 접근 권한을 만들어주는 것 또한 익숙하지 않은 저에게는 매우 놀라웠습니다. 세부적인 기술 내역에 대하여 저도 검토해봐야겠다는 생각이 드는 작품입니다. 다만 소프트웨어적인 구현만으로 이루어진 점은 개인적으로 조금 아쉽고, 동일한 보안 해제 방식을 통해 특정 목적을 가진 기기를 컨트롤할 수 있는 형태라면 기술의 범위가 충분히 확장될 수 있지 않을까 합니다.</p>
<p><strong>펌테크</strong> 날로 중요시되는 컴퓨터 보안에 메타버스 개념을 접목한 독창적이고 색다른 형태의 작품으로 핵심요소인 소프트웨어 개발에 따른 각각의 SDK, 개발툴 등을 작품의 성격에 맞게 효율적으로 구성하였으며 전체적으로 작품의 기획의도, 기술 구현도, 완성도 등에서 우수한 작품이라고 생각됩니다.</p>
<p><strong>위드로봇</strong> Leap motion을 이용한 제스처로 보안을 처리한 아이디어가 돋보이는 작품입니다. 공모전의 성격을 감안하여 LeapMotion을 대치할 수 있는 기술까지 같이 연구가 진행되었다면 더욱 훌륭한 연구가 되었을 것 같습니다.</p>
<p><strong>뉴티씨</strong> 매우 독특한 발상으로 잘 만들어진 작품입니다. 스마트폰에만 의존하는 보안 시스템에서 발전하여 Cloud server를 활용하여 보다 높은 수준의 보안 시스템을 구현한 예가 될 수 있습니다. 작품의 모양이나 시스템의 표현 방법이나 사용 방법 등을 대폭 개선하면, 좋은 제품으로 탄생할 수도 있을 것 같습니다. 아파트 현관이나 특정 사무실의 보안 시스템도 그런 식으로 만드는 것도 방법인 것 같습니다. 앞으로 기대가 됩니다.</p>
<p><span style="color: #0000ff"><strong>2. 작품 개요</strong></span><br />
개인 휴대폰을 이용한 문서 공유, 개인 정보 저장, 신상 정보를 이용한 거래 등의 서비스들이 늘어나고 있다. 등본이나 각종 증명서, 회사 기업 자료 등 중요한 문서 파일을 휴대폰에 저장하기도 하고, 회원가입 정보나 여러 사이트의 비밀번호, 개인 정보를 휴대폰에 저장하기도 하며, 인터넷 뱅킹, 휴대폰 결제와 같은 개인정보를 이용한 서비스들을 휴대폰을 통해 사용한다. 이러한 휴대폰 속 개인정보를 이용한 서비스들과 휴대폰에 저장하는 개인정보, 주요 문서들이 늘어남에 따라 이를 악용한 범죄 또한 늘어나고 있다. 이러한 범죄에 우리가 노출됨에 있어 가장 큰 문제는 오직 핸드폰의 보안에만 의존하고 있다는 점이다. 휴대폰에 저장된 대부분의 주요 문서나 개인 정보가 오직 핸드폰의 보안 또는 어플 자체의 보안에만 의존하고 있다. 우리는 이러한 문제점을 인식하고 더욱 함양된 보안성을 갖춘 문서 보안 시스템을 구축하기 위해 메타버스를 이용해보기로 했다. 메타버스를 이용한 보안 시스템의 취약성은 아직 발견된 것이 없으며, 컴퓨터와 휴대폰 두 개의 디바이스를 이용하여 보안 시스템을 구축하기 때문에 더 높은 보안 장벽을 갖는다는 장점이 있다. 이러한 장점을 가진 메타버스 중 우리는 Leap Motion과 Unity를 이용해 시스템을 구축하기로 했다. Leap Motion은 손의 움직임을 인식하는 장치로 이를 이용하면 오직 손의 움직임만을 이용하여 잠금을 해제하는 보안장치를 만들 수 있기 때문에 잠금을 해제하는 기록을 데이터로 남기기 어려워 보안에 유리하다. 또한 Unity를 이용한 3D 가상현실을 만들어 여기에 Leap Motion을 적용한다면, 보안 장치를 사용하는 사용자가 아닌 이상 보안 장치 해제 방식을 파악하기 어려워 보안에 유리하다. 우리는 이러한 장점을 이용하여 Leap Motion, Unity를 이용한 메타버스 문서 보안 시스템을 제작하기로 했다.</p>
<p><span style="color: #0000ff"><strong>3. 작품 설명</strong></span><br />
<span style="color: #33cccc"><strong>3.1. 주요 동작 및 특징</strong></span><br />
시스템은 Leap Motion을 이용한 1차 보안과 Unity와 앱을 이용한 2차 보안, 1차 보안과 2차 보안 사이의 서버 통신으로 이루어져 있다.<br />
Leap Motion을 이용해 손의 동작을 감지하고 정해진 동작이 수행되면 웹 서버인 AWS DynamoDB로 동작이 수행됨을 알리는 정보가 넘어간다. 서버 통신을 통해 Leap Motion을 이용한 1차 보안이 해제됨을 감지한 AWS DynamoDB는 이 정보를 핸드폰에 설치된 어플로 넘긴다. 어플에서 정보를 받으면 Unity와 앱을 이용한 2차 보안이 실행되고, 2차 보안에서 정해진 순서대로 번호를 터치하게 되면 문서의 잠금이 해제된다.</p>
<p><span style="color: #993366"><strong>Leap Motion을 이용한 1차 보안</strong></span><br />
Leap Motion에 정해진 동작을 수행하면 그 동작에 해당하는 마법진이 생성되고, 정해진 손짓을 통해 생성된 마법진을 뒤로 보낼 수 있다. 정해진 동작을 순서대로 수행하면 그 동작에 해당하는 4종류의 마법진이 순서대로 생성되고, 이 4종류의 마법진을 정해진 손짓을 통해 순서대로 뒤로 보내 circle에 통과시키면 보안이 해제된다. 이때 4종류의 마법진을 정해진 순서대로 circle에 통과시키지 않으면 보안 잠금이 해제되지 않는다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-2.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40500" alt="67 ict_ 최우수상 메타버스 (2)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-2.png" width="500" height="322" /></a></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>[코드 가-1] 위 사진에 해당하는 코드</strong></p>
<p>if ((frame.Hands[1].GrabStrength == 1.0) &amp;&amp; (frame.Hands[1].PinchStrength == 1.0)) //왼손 grab 후 pinch<br />
{<br />
count += 1;<br />
if (count &gt; 3)<br />
count = 0;<br />
}<br />
if (count == 0)<br />
{<br />
if (frame.Hands[0].PinchStrength == 1.0 &amp;&amp; frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 손가락 pinch<br />
{<br />
fstone.state = 1;<br />
}<br />
if (frame.Hands[0].PinchStrength &lt; 1.0 &amp;&amp; frame.Hands[1].PinchStrength &lt; 1.0 &amp;&amp; fstone.state == 1) //윗줄 후 왼손, 오른손 no pinch<br />
{<br />
GameObject realplz = Instantiate(fstobj) as GameObject; // 첫 번째 오브젝트 생성</p>
<p>realplz.transform.position = new Vector3(0, 0.5f,0.5f);<br />
fstone.state = 0;<br />
}<br />
}<br />
</div>
<p>그림 가-1과 같이 양 손을 pinch 후 떼어내면 마법진이 생성된다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-3.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40501" alt="67 ict_ 최우수상 메타버스 (3)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-3.png" width="497" height="616" /></a></p>
<p>&nbsp;</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>[코드 가-2] 위 사진에 해당하는 코드 </strong></p>
<p>if ((frame.Hands[1].GrabStrength == 1.0) &amp;&amp; (frame.Hands[1].PinchStrength == 1.0)) //왼손 grab 후 pinch{<br />
count += 1;<br />
if (count &gt; 3)<br />
count = 0;<br />
}<br />
if (count == 0){<br />
if (frame.Hands[0].PinchStrength == 1.0 &amp;&amp; frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 손가락 pinch{<br />
fstone.state = 1;<br />
}<br />
if (frame.Hands[0].PinchStrength &lt; 1.0 &amp;&amp; frame.Hands[1].PinchStrength &lt; 1.0 &amp;&amp; fstone.state == 1) //윗줄 후 왼손, 오른손 no pinch{<br />
GameObject realplz = Instantiate(fstobj) as GameObject; // 첫 번째 오브젝트 생성<br />
realplz.transform.position = new Vector3(0, 0.5f,0.5f);<br />
fstone.state = 0;<br />
}<br />
}<br />
else if (count == 1){<br />
if (frame.Hands[0].PinchStrength == 1.0 &amp;&amp; frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 pinch{<br />
second.state = 1;<br />
}<br />
if (frame.Hands[0].PinchStrength &lt; 1.0 &amp;&amp; frame.Hands[1].PinchStrength &lt; 1.0 &amp;&amp; second.state == 1) //윗 줄 후 왼손, 오른손 no pinch{<br />
GameObject realplz = Instantiate(scdobj) as GameObject; //두 번째 오브젝트 생성<br />
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);<br />
second.state = 0;<br />
}<br />
}<br />
else if (count == 2)<br />
{<br />
if (frame.Hands[0].PinchStrength == 1.0 &amp;&amp; frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 pinch{<br />
third.state = 1;<br />
}<br />
if (frame.Hands[0].PinchStrength &lt; 1.0 &amp;&amp; frame.Hands[1].PinchStrength &lt; 1.0 &amp;&amp; third.state == 1) //윗 줄 후 왼손, 오른손 no pinch{<br />
GameObject realplz = Instantiate(thdobj) as GameObject; //세 번째 오브젝트 생성<br />
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);<br />
third.state = 0;<br />
}<br />
else if (count == 3)<br />
{<br />
if (frame.Hands[0].PinchStrength == 1.0 &amp;&amp; frame.Hands[1].PinchStrength == 1.0) //왼손, 오른손 pinch{<br />
fourth.state = 1;<br />
}<br />
if (frame.Hands[0].PinchStrength &lt; 1.0 &amp;&amp; frame.Hands[1].PinchStrength &lt; 1.0 &amp;&amp; fourth.state == 1) //윗 줄 후 왼손, 오른손 no pinch{<br />
GameObject realplz = Instantiate(fthobj) as GameObject; //네 번째 오브젝트 생성<br />
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);<br />
fourth.state = 0;<br />
}<br />
}<br />
</div>
<p>왼손 grab 후 오른손 pinch 한 번 할 때마다 object, 즉 마법진이 변경된다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-4.png" rel="lightbox[40440]"><img class="alignnone size-large wp-image-40502" alt="67 ict_ 최우수상 메타버스 (4)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-4-481x620.png" width="481" height="620" /></a></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>[코드 가-3] 위 사진에 해당하는 코드</strong></p>
<p>if (HandPalmYam &gt; -2f &amp;&amp; HandPalmYam &lt; 3.5f &amp;&amp; (frame.Hands[1].GrabStrength==1.0 )) //왼손 grab 후 오른손 흔듦{<br />
Debug.Log(&#8220;앞&#8221;);<br />
this.transform.Translate(0, 2 * Time.deltaTime,0); //오브젝트 앞으로 이동<br />
}<br />
if ((frame.Hands[1].GrabStrength == 1.0) &amp;&amp; (frame.Hands[0].GrabStrength == 1.0)) //양손 grab<br />
Destroy(gameObject); //오브젝트 사라짐<br />
</div>
<p>&nbsp;</p>
<p>왼손 grab 후 오른손 흔들면 object, 즉 마법진이 앞으로 이동하다가 circle에 닿으면 사라지게 된다. 이때, 마법진 4종류가 정해진 순서대로 circle에 닿아야만 잠금이 해제된다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-5.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40503" alt="67 ict_ 최우수상 메타버스 (5)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-5.png" width="498" height="295" /></a></p>
<p>Object, 즉 마법진은 계속해서 회전하고 있다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-7.png" rel="lightbox[40440]"><img class="alignnone size-large wp-image-40505" alt="67 ict_ 최우수상 메타버스 (7)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-7-620x98.png" width="620" height="98" /></a></p>
<p>코드 가-5에 의해 object, 즉 마법진이 circle에 닿으면 사라지게 된다. 또한 4종류의 마법진이 정해진 순서대로 circle에 닿아야만 보안이 해제된다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-8.png" rel="lightbox[40440]"><img class="alignnone size-large wp-image-40506" alt="67 ict_ 최우수상 메타버스 (8)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-8-620x206.png" width="620" height="206" /></a></p>
<p><span style="color: #993366"><strong>1차 보안과 2차 보안 사이의 서버 통신</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-9.png" rel="lightbox[40440]"><img class="alignnone size-large wp-image-40507" alt="67 ict_ 최우수상 메타버스 (9)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-9-620x396.png" width="620" height="396" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-10.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40508" alt="67 ict_ 최우수상 메타버스 (10)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-10.png" width="559" height="356" /></a></p>
<p>Leap Motion을 이용한 1차 보안이 해제됨을 알리는 정보가 AWS DynamoDB로 넘어간다. AWS DynamoDB는 받은 정보를 다시 2차 보안에 사용되는 앱에 넘기고, 앱은 정보를 받으면 보안 해제 시스템이 작동된다. 2차 보안 앱은 1차 보안이 해제되기 전까지는 실행되지 않고, 로딩창에 머무르게 된다. 1차 보안이 해제되었다는 정보를 넘겨받아야 실행이 되는 구조이다.<br />
[그림 나-2]는 DynamoDB에서 leapmotion의 데이터가 초기설정 값인 0000이었지만, 1차 보안을 해제한 후 1234로 바뀐 모습이다.<br />
private void Start() //AWS에서 계정에 대한 인증과 권한을 부여받는 코드이다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>{<br />
UnityInitializer.AttachToGameObject(this.gameObject);<br />
credentials = new CognitoAWSCredentials(&#8220;ap-northeast-2:ceafc145-14a2-4c03-b397-22368bc8ab4f&#8221;, RegionEndpoint.APNortheast2);<br />
DBclient = new AmazonDynamoDBClient(credentials, RegionEndpoint.APNortheast2);<br />
context = new DynamoDBContext(DBclient);<br />
}</p>
[DynamoDBTable("character_info")]
public class Character<br />
{<br />
[DynamoDBHashKey] // Hash key.<br />
public string id { get; set; }<br />
[DynamoDBProperty]
public int item { get; set; }<br />
}</p>
<p>public void FindItem() //DB에서 캐릭터 정보 받기<br />
{<br />
context.LoadAsync&lt;Character&gt;(&#8220;leapmotion&#8221;, (AmazonDynamoDBResult&lt;Character&gt; result) =&gt;<br />
{<br />
// id가 leapmotion인 캐릭터 정보를 DB에서 받아옴<br />
if (result.Exception != null)<br />
{<br />
Debug.LogException(result.Exception);<br />
// 정보를 받아오지 못했을 때의 예외처리</p>
<p>return;<br />
}<br />
c = result.Result;<br />
Debug.Log(c.item); //찾은 캐릭터 정보 중 아이템 정보 출력<br />
}, null);<br />
}</p>
<p>void Update()<br />
{</p>
<p>FindItem();<br />
if (c!=null) //앱 실행 후 초기화되는 aws에서 정보를 받아오는 변수이므로 받아온 정보가 null값인지를 먼저 확인한다.<br />
{<br />
if (c.item == 1234)<br />
{<br />
GameObject.Destroy(this.gameObject);<br />
SceneManager.LoadScene(&#8220;realA&#8221;);<br />
}<br />
}<br />
</div>
사용자가 4번에 걸쳐서 원을 서클에 통과시키면, 4개의 원이 지정된 패턴과 일치하는지를 판별 후, 맞다면 AWS에 접속하여 DynamoDB의 leapmotion이라는 데이터의 값을 1234로 변경해준다.</p>
<p><span style="color: #993366"><strong>Unity와 앱을 이용한 2차 보안</strong></span><br />
AWS DynamoDB로 전달된 1차 보안이 해제됨을 알리는 정보는 만들어둔 핸드폰에 전달된다. 정보를 받은 핸드폰은 앱을 실행시킨다. 실행된 앱에서 정해진 물체에 카메라를 가져가면 키패드가 생성되고, 생성된 키패드에 비밀번호를 순서대로 입력하면 2차 보안이 해제되어 문서를 열람할 수 있게 된다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-11.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40509" alt="67 ict_ 최우수상 메타버스 (11)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-11.png" width="580" height="433" /></a></p>
<p>AR 키패드 화면으로 넘어왔지만, 지정된 물체를 비추지 않아, 키패드가 나타나지 않는 모습이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-12.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40510" alt="67 ict_ 최우수상 메타버스 (12)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-12.png" width="574" height="414" /></a><br />
지정된 물체를 비추고 나서, 키패드가 나타나는 모습이다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>if (count == 4) //사용자가 키패드를 누른 횟수를 센다<br />
{<br />
Debug.Log(&#8220;full&#8221;);<br />
for (int i = 0; i &lt; 4; i++)<br />
{<br />
if (answer[i] != realanswer[i]) //입력 비밀번호랑 정답 비밀번호랑 비교<br />
{<br />
SceneManager.LoadScene(&#8220;retry&#8221;);<br />
break;<br />
}</p>
</div>
기본적으로 앱은 AWS와 계속해서 통신을 하고 DynamoDB의 leapmotion 데이터의 값을 반복해서 불러들이는 작업을 하고, 받아온 값이 최초 설정값인 0000이 아닌 1234일 때, 씬을 변경하여 앱을 실행시키는 역할을 한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-13.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40511" alt="67 ict_ 최우수상 메타버스 (13)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-13.png" width="579" height="399" /></a></p>
<p><span style="color: #33cccc"><strong>3.2. 전체 시스템 구성</strong></span><br />
위 시스템은 Leap Motion을 이용한 1차 보안과 Unity와 앱을 이용한 2차 보안, 1차 보안과 2차 보안 사이의 서버 통신으로 이루어져 있다.<br />
Leap Motion을 이용해 손의 동작을 감지하고 정해진 동작이 수행되면 웹 서버인 AWS DynamoDB로 동작이 수행됨을 알리는 정보가 넘어간다. 서버 통신을 통해 Leap Motion을 이용한 1차 보안이 해제됨을 감지한 AWS DynamoDB는 이 정보를 핸드폰에 설치된 어플로 넘긴다. 어플에서 정보를 받으면 Unity와 앱을 이용한 2차 보안이 실행되고, 2차 보안 앱에서 지정된 물체를 비추게 되면 키패드가 나타나고, 키패드에 비밀번호를 입력하게 되면 2차 보안이 해제되면서 문서의 잠금이 해제된다. 따라서 키패드를 거치기 전, 지정된 물체를 알고 있어야 하고, 그것을 비추어야만 비밀번호를 입력할 수 있다는 점에서 2차 보안 속에 한 단계의 보조 보안단계가 더 있다고 볼 수 있다.</p>
<p><span style="color: #33cccc"><strong>3.3. 개발 환경</strong></span><br />
위 시스템은 Leap Motion을 이용한 1차 보안과 Unity와 앱을 이용한 2차 보안, 1차 보안과 2차 보안 사이의 서버 통신으로 이루어져 있다. 먼저 Leap Motion을 이용한 1차 보안에서 Leap Motion과 Unity를 이용하며, 이를 위해 Leap Motion SDK와 개발 Tool로 Unity 2D, Unity 3D를 사용하였다. 또한 Unity 개발 언어로 C#을 이용하였으며 3D 가상 현실 환경을 구축하기 위해 Asset store를 사용하였다. 또한 개발 언어를 위한 Tool로 Visual Studio를 사용하였다. 다음으로 1차 보안과 2차 보안 사이의 서버 통신을 위한 시스템으로 AWS와 DynamoDB를 사용하였다. 마지막으로 App과 Unity를 이용한 2차 보안에서 App 개발과 보안 환경 구축을 위해 개발 Tool로 Unity 2D, Unity 3D를 사용하였다. 또한 Unity 개발 언어로 C#을 이용하였으며 3D 가상 현실 환경을 구축하기 위해 Asset store와 Vuforia를 사용하였다. 또한 개발 언어를 위한 Tool로 Visual Studio를 사용하였다.</p>
<p><strong><span style="color: #993366">Leap Motion을 이용한 1차 보안</span></strong><br />
생체 움직임 감지를 위해 Leap Motion을 사용하였으며, Leap Motion을 사용하기 위해 Leap Motion SDK를 사용하였다. Leap Motion 이용을 위한 증강 현실을 구현하기 위한 개발 Tool로 Unity 2D와 Unity 3D를 사용하였으며, Unity 개발 언어로 C#을 사용하고, 개발 언어를 사용하기 위한 Tool로 Visual Studio를 사용하였다. 3D 증강 현실 구현을 위해 Asset Store를 사용하였으며, AR엔진으로 Vuforia를 이용하였다.</p>
<p><span style="color: #993366"><strong>1차 보안과 2차 보안 사이의 서버 통신</strong></span><br />
1차 보안에서의 정보를 서버로 옮기고, 서버에 저장된 정보를 다시 휴대폰 앱으로 전송하기 위한 웹 서버를 구축하였다. 이때 AWS를 사용하여 웹서버를 구축하였다. 웹 서버로 통신한 정보를 저장하기 위해 DynamoDB를 데이터베이스로 사용하였다.</p>
<p><span style="color: #993366"><strong>Unity와 App을 이용한 2차 보안</strong></span><br />
증강 현실을 이용한 App 개발을 위한 개발 Tool로 Unity 2D와 Unity 3D를 사용하였으며, Unity 개발 언어로 C#을 사용하고, IDE로 Visual Studio를 사용하였다. 3D 증강 현실 구현을 위해 Asset Store를 사용하였으며, AR엔진으로 Vuforia를 이용하였다.</p>
<p><span style="color: #0000ff"><strong>4. 단계별 제작 과정</strong></span><br />
시스템은 ‘Leap Motion을 이용한 1차 보안’과 ‘Unity와 앱을 이용한 2차 보안’, ‘1차 보안과 2차 보안 사이의 서버 통신’으로 단계를 나누어 제작하였다.</p>
<p><span style="color: #33cccc"><strong>4.1. Leap Motion을 이용한 1차 보안</strong></span><br />
이 단계에서는 먼저 Leap Motion을 Unity와 연동시킨 뒤 Leap Motion의 동작 인식 감도를 확인하였다. 이후 Unity를 이용해 Leap Motion을 이용하기 위한 3D 가상 현실과 보안 시스템을 구축하였고, 가상 현실과 보안 시스템을 제어하기 위한 코드를 작성하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-1.jpg" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40498" alt="67 ict_ 최우수상 메타버스 (1)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-1.jpg" width="567" height="401" /></a></p>
<p>그림 4-1-1과 같이 Leap Motion을 이용하기에 앞서 Leap Motion을 Unity에 연동시키고, Unity에서의 Leap Motion 작동 여부와 실제 작동 환경을 테스트하였다. 이후 Leap Motion의 손동작 인식 감도를 확인하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-14.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40512" alt="67 ict_ 최우수상 메타버스 (14)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-14.png" width="569" height="380" /></a><br />
다음으로 그림 4-4-2와 같이 Leap Motion이 사용되는 가상 현실을 Unity를 통해 구축하였다. 배경과 바닥을 3D object와 asset을 이용하여 구현했으며, 손동작에 따라 생성되고 작동될 3D object를 만들었다. 마지막으로 코드 3-1-가-1,2,3,4,5와 같이 Leap Motion에 감지된 동작에 따라 실행될 기능에 대해 코드를 작성하였다. 왼손 grab 후에 pinch 한 번 할 때마다 object가 바뀌고, 양손을 pinch 후에 떼면 object가 생성되는 코드, 왼손 grab 후 오른손을 흔들면 object가 앞으로 이동하는 코드, 양손 grab시에 object가 사라지는 코드, object가 회전하는 코드, object가 circle에 닿으면 사라지는 코드, object가 정해진 순서대로 circle에 닿으면 그 정보를 관리자 object에 전달하는 코드를 작성하였다.</p>
<p><span style="color: #33cccc"><strong>4.2. 1차 보안과 2차 보안 사이의 서버 통신</strong></span><br />
이 단계에서는 먼저 1차 보안을 담당하는 노트북과 2차 보안을 담당하는 핸드폰 App사이의 서버 통신을 위한 웹서버를 구축하였다. 이후 노트북의 정보가 구축한 웹서버로 전달되는지 여부를 확인하였다. 다음으로 웹서버에 저장된 데이터 베이스가 휴대폰 App으로 전달되는지 여부를 확인하였다. 마지막으로 1차 보안이 해제됨을 알리는 정보를 웹 서버에 전달하고 웹 서버는 이를 데이터 베이스에 저장하여 2차 보안을 담당하는 휴대폰 App으로 전달하는 코드를 작성하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-15.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40513" alt="67 ict_ 최우수상 메타버스 (15)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-15.png" width="571" height="297" /></a></p>
<p>그림 4-2-1과 같이 웹서버를 구축하였다. DynamoDB에 leapmotion 데이터가 저장되어 있는 모습을 볼 수 있다.</p>
<p>&nbsp;</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-16.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40514" alt="67 ict_ 최우수상 메타버스 (16)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-16.png" width="569" height="112" /></a></p>
<p>그림 4-2-2와 같이 1차 보안과 웹 서버 사이의 서버 통신이 원활하게 이루어지는지 확인하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-17.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40515" alt="67 ict_ 최우수상 메타버스 (17)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-17.png" width="568" height="108" /></a></p>
<p>그림 4-2-3과 같이 웹 서버에 저장된 데이터 베이스가 2차 보안을 담당하는 휴대폰 App으로 잘 전달되는지 여부를 확인하였다. DynamoDB의 데이터 leapmotion의 정보를 잘 받았는지 확인하는 콘솔로그 창이다.<br />
코드 4-2-1과 같이 1차 보안이 해제됨을 알리는 정보를 웹 서버에 전달하고 웹 서버는 이를 데이터 베이스에 저장하여 2차 보안을 담당하는 휴대폰 App으로 전달하는 코드를 작성하였다.</p>
<p><span style="color: #00ccff"><strong>4.3. Unity와 App을 이용한 2차 보안</strong></span><br />
이 단계에서는 노트북에서 Unity를 이용하여 2차 보안의 가상 현실을 만든 뒤, 순서대로 정해진 비밀번호를 입력하면 문서 보안이 해제되는 코드를 작성하였다. 이후 제작한 App을 휴대폰에 복제하였다. 마지막으로 제작한 App이 구축한 웹 서버를 통해 1차 보안이 해제됨을 알리는 데이터 베이스를 전달하면 App이 실행되도록 하는 코드를 작성하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-18.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40516" alt="67 ict_ 최우수상 메타버스 (18)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-18.png" width="566" height="368" /></a></p>
<p>그림 4-3-1과 같이 Unity를 이용하여 2차 보안에 사용할 가상 현실을 제작했다.<br />
그림 4-3-2와 같이 앞서 노트북으로 만든 App을 휴대폰에 빌드하여 휴대폰으로 App이용이 가능하게 만들었다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-19.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40517" alt="67 ict_ 최우수상 메타버스 (19)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-19.png" width="283" height="350" /></a></p>
<p><strong> <span style="color: #0000ff">5. 사용한 제품 리스트</span></strong></p>
<p>‘Leap Motion을 이용한 1차 보안’과 ‘Unity와 앱을 이용한 2차 보안’, ‘1차 보안과 2차 보안 사이의 서버 통신’으로 나누어져 있다. 이 중 Leap Motion을 이용한 1차 보안 단계에서 Leap Motion Controller제품을 사용하였다.</p>
<p><span style="color: #0000ff"><strong>6. 회로도</strong></span><br />
작품의 전체 회로도는 그림 6-1과 같다. Leap Motion과 노트북이 1차 보안을 위해 연결되어 있으며, 2차 보안인 휴대폰 App과 웹 서버를 통해 연결되어 있다.</p>
<p><del><a href="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-20.png" rel="lightbox[40440]"><img class="alignnone size-full wp-image-40518" alt="67 ict_ 최우수상 메타버스 (20)" src="http://www.ntrexgo.com/wp-content/uploads/2021/08/67-ict_-최우수상-메타버스-20.png" width="564" height="269" /></a></del></p>
<p><span style="color: #0000ff"><strong>7. 소스코드</strong></span><br />
<span style="color: #33cccc"><strong>7.1. Leap Motion을 이용한 1차 보안 코드</strong></span><br />
<span style="color: #993366"><strong>Leap Motion Hand model 코드</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>void Update(){<br />
controller = new Controller();<br />
Frame frame = controller.Frame();<br />
List&lt;Hand&gt; hands = frame.Hands;<br />
Frame previous = controller.Frame(1);<br />
Hand previous_leapHand = previous.Hands[0];<br />
Vector handOrigin = frame.Hands[0].PalmPosition;<br />
Vector previoushandOrigin = previous_leapHand.PalmPosition;<br />
if ((frame.Hands[1].GrabStrength == 1.0) &amp;&amp; (frame.Hands[1].PinchStrength == 1.0)){<br />
count += 1;<br />
if (count &gt; 3)<br />
count = 0;<br />
}<br />
if (count == 0) {<br />
if (frame.Hands[0].PinchStrength == 1.0 &amp;&amp; frame.Hands[1].PinchStrength == 1.0)<br />
{<br />
fstone.state = 1;<br />
}<br />
if (frame.Hands[0].PinchStrength &lt; 1.0 &amp;&amp; frame.Hands[1].PinchStrength &lt; 1.0 &amp;&amp; fstone.state == 1) {<br />
GameObject realplz = Instantiate(fstobj) as GameObject;</p>
<p>realplz.transform.position = new Vector3(0, 0.5f,0.5f);<br />
fstone.state = 0;<br />
}<br />
}<br />
else if (count == 1){<br />
if (frame.Hands[0].PinchStrength == 1.0 &amp;&amp; frame.Hands[1].PinchStrength == 1.0){<br />
second.state = 1;<br />
}<br />
if (frame.Hands[0].PinchStrength &lt; 1.0 &amp;&amp; frame.Hands[1].PinchStrength &lt; 1.0 &amp;&amp; second.state == 1){<br />
GameObject realplz = Instantiate(scdobj) as GameObject;</p>
<p>realplz.transform.position = new Vector3(0, 0.5f, 0.5f);<br />
second.state = 0;<br />
}<br />
}<br />
else if (count == 2) {<br />
if (frame.Hands[0].PinchStrength == 1.0 &amp;&amp; frame.Hands[1].PinchStrength == 1.0){<br />
third.state = 1;<br />
}<br />
if (frame.Hands[0].PinchStrength &lt; 1.0 &amp;&amp; frame.Hands[1].PinchStrength &lt; 1.0 &amp;&amp; third.state == 1){<br />
GameObject realplz = Instantiate(thdobj) as GameObject;<br />
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);<br />
third.state = 0;<br />
}<br />
else if (count == 3){<br />
if (frame.Hands[0].PinchStrength == 1.0 &amp;&amp; frame.Hands[1].PinchStrength == 1.0){<br />
fourth.state = 1;<br />
}<br />
if (frame.Hands[0].PinchStrength &lt; 1.0 &amp;&amp; frame.Hands[1].PinchStrength &lt; 1.0 &amp;&amp; fourth.state == 1){<br />
GameObject realplz = Instantiate(fthobj) as GameObject;<br />
realplz.transform.position = new Vector3(0, 0.5f, 0.5f);<br />
fourth.state = 0;<br />
}<br />
}<br />
strength1 = frame.Hands[0].GrabStrength;<br />
strength2 = frame.Hands[1].GrabStrength;<br />
Debug.Log(&#8220;왼손??&#8221; + strength2);<br />
Debug.Log(&#8220;오른손??&#8221; + strength1);<br />
}<br />
}<br />
</div>
<p><span style="color: #993366"><strong>Leap Motion New Behavior 코드</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>Controller controller;<br />
float HandPalmPitch;<br />
float HandPalmRoll;<br />
float HandPalmYam;<br />
float HandWristRot;<br />
Rigidbody rb;<br />
void Start(){<br />
}<br />
void Update(){<br />
controller = new Controller();<br />
Frame frame = controller.Frame();<br />
List&lt;Hand&gt; hands = frame.Hands;<br />
if (frame.Hands.Count &gt; 0){<br />
Hand fristHand = hands[0];<br />
}<br />
HandPalmPitch = hands[0].PalmNormal.Pitch;<br />
HandPalmRoll = hands[0].PalmNormal.Roll;<br />
HandPalmYam = hands[0].PalmNormal.Yaw;<br />
HandWristRot = hands[0].WristPosition.Pitch;<br />
Debug.Log(&#8220;Pitch : &#8221; + HandPalmPitch);<br />
Debug.Log(&#8220;Roll : &#8221; + HandPalmRoll);<br />
Debug.Log(&#8220;Yam : &#8221; + HandPalmYam);<br />
if (HandPalmYam &gt; -2f &amp;&amp; HandPalmYam &lt; 3.5f &amp;&amp; (frame.Hands[1].GrabStrength==1.0 )){<br />
Debug.Log(&#8220;앞&#8221;);<br />
this.transform.Translate(0, 2 * Time.deltaTime,0);<br />
}<br />
this.transform.Rotate(0, 30, 0);<br />
if ((frame.Hands[1].GrabStrength == 1.0) &amp;&amp; (frame.Hands[0].GrabStrength == 1.0))<br />
Destroy(gameObject);<br />
}<br />
}<br />
</div>
<p><span style="color: #993366"><strong>Leap Motion 관리자 object 코드</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>using System.Collections;<br />
using System.Collections.Generic;<br />
using UnityEngine;<br />
public class c1direc : MonoBehaviour{<br />
GameObject director;<br />
void Start(){<br />
director = GameObject.Find(&#8220;director&#8221;);<br />
}<br />
void Update(){<br />
if (this.transform.position.z &gt; 3){<br />
director.GetComponent&lt;director&gt;().arr[director.GetComponent&lt;director&gt;().ind] = 0;<br />
director.GetComponent&lt;director&gt;().ind += 1;<br />
}<br />
}<br />
}<br />
</div>
<p><span style="color: #33cccc"><strong>7.2. 1차 보안과 2차 보안 사이의 서버 통신 코드</strong></span><br />
<span style="color: #993366"><strong>Leap Motion 서버 통신 director 코드</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>public class director : MonoBehaviour<br />
{<br />
int count;<br />
public int [] arr = { -1, -1, -1, -1 };<br />
int[] arranswer = { 0, 1, 2, 3 };<br />
DynamoDBContext context;<br />
AmazonDynamoDBClient DBclient;<br />
CognitoAWSCredentials credentials;<br />
Character c;<br />
public Camera a;<br />
private void Start()<br />
{<br />
UnityInitializer.AttachToGameObject(this.gameObject);<br />
credentials = new CognitoAWSCredentials(&#8220;ap-northeast-2:ceafc145-14a2-4c03-b397-22368bc8ab4f&#8221;, RegionEndpoint.APNortheast2);<br />
DBclient = new AmazonDynamoDBClient(credentials, RegionEndpoint.APNortheast2);<br />
context = new DynamoDBContext(DBclient);<br />
}<br />
[DynamoDBTable("character_info")]
public class Character<br />
{<br />
[DynamoDBHashKey] // Hash key.<br />
public string id { get; set; }<br />
[DynamoDBProperty]
public int item { get; set; }<br />
}<br />
private void CreateCharacter() //캐릭터 정보를 DB에 올리기<br />
{<br />
Character c1 = new Character<br />
{<br />
id = &#8220;leapmotion&#8221;,<br />
item = 1234,<br />
};<br />
context.SaveAsync(c1, (result) =&gt;<br />
{<br />
if (result.Exception == null)<br />
Debug.Log(&#8220;Success!&#8221;);<br />
else<br />
Debug.Log(result.Exception);<br />
});<br />
}<br />
void Update() //써클을 통과한 원이 지정된 패턴과 일치하는지 확인 후, 일치하면 서버에 정보를 보냄<br />
{</p>
<p>for(int i = 0; i &lt;= 3; i++)<br />
{<br />
if (arr[i] == arranswer[i])<br />
{<br />
count += 1;<br />
}<br />
else if (arr[i] != arranswer[i])<br />
break;<br />
}<br />
if (count== 4)<br />
{<br />
CreateCharacter();<br />
Debug.Log(&#8220;카운트!!!!!!!!!!!!!!!!!111&#8243;);<br />
}<br />
</div>
<p><span style="color: #33cccc"><strong>7.3. Unity와 App을 이용한 2차 보안 코드</strong></span><br />
<span style="color: #993366"><strong>서버와 통신을 하는 direc코드</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>private void Start() //AWS에 접속해서 인증받고 권한을 받아오는 단계<br />
{<br />
UnityInitializer.AttachToGameObject(this.gameObject);<br />
credentials = new CognitoAWSCredentials(&#8220;ap-northeast-2:ceafc145-14a2-4c03-b397-22368bc8ab4f&#8221;, RegionEndpoint.APNortheast2);<br />
DBclient = new AmazonDynamoDBClient(credentials, RegionEndpoint.APNortheast2);<br />
context = new DynamoDBContext(DBclient);</p>
<p>}</p>
[DynamoDBTable("character_info")]
public class Character<br />
{<br />
[DynamoDBHashKey] // Hash key.<br />
public string id { get; set; }<br />
[DynamoDBProperty]
public int item { get; set; }<br />
}<br />
public void FindItem() //DB에서 캐릭터 정보 받기<br />
{<br />
context.LoadAsync&lt;Character&gt;(&#8220;leapmotion&#8221;, (AmazonDynamoDBResult&lt;Character&gt; result) =&gt;<br />
{<br />
// id가 leapmotion인 캐릭터 정보를 DB에서 받아옴<br />
if (result.Exception != null)<br />
{<br />
Debug.LogException(result.Exception);<br />
return;<br />
}<br />
c = result.Result;<br />
Debug.Log(c.item); //찾은 캐릭터 정보 중 아이템 정보 출력<br />
}, null);<br />
}<br />
void Update()<br />
{</p>
<p>FindItem();<br />
if (c!=null) //앱 실행 후 초기화되는 aws에서 정보를 받아오는 변수이므로 받아온 정보가 null값인지를 먼저 확인한다.<br />
{<br />
if (c.item == 1234)<br />
{</p>
<p>GameObject.Destroy(this.gameObject);<br />
SceneManager.LoadScene(&#8220;realA&#8221;);<br />
} }}<br />
</div>
<p><span style="color: #993366"><strong>입력한 비밀번호를 확인하는 director 코드</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>public class director : MonoBehaviour<br />
{<br />
public int[] answer = new int[4] { -1, -1, -1, -1 }; //입력받을 비밀번호를 저장할 배열<br />
int[] realanswer = new int[4] { 2, 1, 3, 0 }; //원래 비밀번호 정답<br />
public int count = 0;<br />
int point = 0;<br />
void Start()<br />
{<br />
a.enabled = true;<br />
iinteraction = GameObject.Find(&#8220;iinteraction&#8221;);<br />
interaction1 = GameObject.Find(&#8220;interaction1&#8243;);<br />
interaction2 = GameObject.Find(&#8220;interaction2&#8243;);<br />
interation3 = GameObject.Find(&#8220;interation3&#8243;);<br />
}<br />
// Update is called once per frame<br />
void Update()<br />
{<br />
Debug.Log(count);<br />
if (count == 4) //네개의 비밀번호를 입력받으면 일치하는 비밀번호인지 확인하는 코드<br />
{<br />
Debug.Log(&#8220;full&#8221;);<br />
for (int i = 0; i &lt; 4; i++)<br />
{<br />
if (answer[i] != realanswer[i])<br />
{<br />
SceneManager.LoadScene(&#8220;retry&#8221;);<br />
break;<br />
}<br />
}<br />
}<br />
if (point ==4)<br />
SceneManager.LoadScene(&#8220;EndScene&#8221;);<br />
}<br />
</div>
<p><span style="color: #993366"><strong>어떤 키패드가 눌렸는지 확인하는 interaction1 코드</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>void Start()<br />
{ director = GameObject.Find(&#8220;director&#8221;);<br />
mat = GetComponent&lt;Renderer&gt;().material;<br />
mat.SetFloat(&#8220;_Mode&#8221;, 2);<br />
mat.SetInt(&#8220;_SrcBlend&#8221;, (int)UnityEngine.Rendering.BlendMode.SrcAlpha);<br />
mat.SetInt(&#8220;_DstBlend&#8221;, (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);<br />
mat.SetInt(&#8220;_ZWrite&#8221;, 0);<br />
mat.DisableKeyword(&#8220;_ALPHATEST_ON&#8221;);<br />
mat.EnableKeyword(&#8220;_ALPHABLEND_ON&#8221;);<br />
mat.DisableKeyword(&#8220;_ALPHAPREMULTIPLY_ON&#8221;);<br />
mat.renderQueue = 3000;<br />
defaultColor = new Color32(255, 255, 255, 255);<br />
selectedColor = new Color32(255, 0, 0, 255);</p>
<p>mat.color = defaultColor;<br />
}<br />
void Update()<br />
{<br />
if (die == 1)<br />
{<br />
Destroy(gameObject);<br />
}<br />
}<br />
void touchBegan() //키패드의 어떤 숫자가 눌렸는지 확인하는 코드<br />
{<br />
director.GetComponent&lt;director&gt;().count+=1;<br />
director.GetComponent&lt;director&gt;().answer[director.GetComponent&lt;director&gt;().count-1] = 1;<br />
</div>
<p><span style="color: #0000ff"><strong>8. 참고 문헌</strong></span><br />
[1] https://bit.ly/3wcnOow<br />
[2] https://bit.ly/2QNPyjk<br />
[3] https://bit.ly/31u0aWz<br />
[4] https://amzn.to/39rTzQU<br />
[5] https://bit.ly/3wfrber<br />
[6] https://amzn.to/3dneDJx<br />
[7] https://bit.ly/31y7Abi</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/40440/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[66호]20대 주거환경을 위한 외·내부 환기 제어 시스템</title>
		<link>http://www.ntrexgo.com/archives/40667</link>
		<comments>http://www.ntrexgo.com/archives/40667#comments</comments>
		<pubDate>Wed, 23 Jun 2021 00:00:42 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[ict]]></category>
		<category><![CDATA[공모전]]></category>
		<category><![CDATA[디바이스마트]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[미세먼지]]></category>
		<category><![CDATA[시스템]]></category>
		<category><![CDATA[장려상]]></category>
		<category><![CDATA[제어]]></category>
		<category><![CDATA[환기]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=40667</guid>
		<description><![CDATA[디바이스마트매거진 66호 &#124; 집안의 미세먼지 농도를 확인할 수 있고 내부의 미세먼지가 외부보다 높은 경우 자동으로 창문을 열 수 있는 시스템이다. ]]></description>
				<content:encoded><![CDATA[<p><strong><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-1.png" rel="lightbox[40667]"><img class="alignnone size-large wp-image-40678" alt="66_ict_환기제어 (1)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-1-620x175.png" width="620" height="175" /></a></strong></p>
<p><span style="font-size: medium"><strong>2020 ICT 융합 프로젝트 공모전 장려상</strong></span></p>
<p><span style="font-size: x-large"><span style="color: #0000ff"><strong>20대 주거환경을 위한 </strong></span><span style="color: #0000ff"><strong>외·내부 환기 제어 시스템</strong></span></span></p>
<p style="text-align: right">글 | 항공대학교 이종민</p>
<p><span style="color: #ff9900"><strong>1. 심사평</strong></span><br />
<strong>칩센</strong> 우선 보고서를 통하여 작품에 대하여 조금 더 설명해주었으면 좋았겠다는 생각은 들지만, 주제로 삼은 작품명의 &#8220;20대 주거 환경을 위한~&#8221;으로 시작하는 부분이 매우 인상적입니다. 공기 청정이 필요한 이유를 단순히 외부에서 발현한 공기질의 저하가 아닌, 20대가 사는 주거환경에서는 왠지 실내의 공기질이 더 나쁠 수도 있겠다는 생각이 들었습니다. 작품명을 아주 잘 정하신거 같습니다. 그리고 다른 유사 작품들과의 차이점, 두 개의 장치(실내/외)가 서로 통신하여 연동하도록 한 부분은 매우 기발한 발상으로 보입니다. 스마트폰 또는 인터넷을 통해 추출된 지역의 정보보다는 실제로 필요한 것은 내가 머무르고 있는 실내 공간과 외부 공간의 공기질의 차이가 더 중요하다는 생각이 들기 때문입니다. 전반적으로 데모 작품이 구성이나 제작이 매우 깔끔하게 된 듯 합니다.</p>
<p><strong>펌테크</strong> 실생활과 접목된 실용성을 지닌 작품으로 생각됩니다. 전체적으로 꼼꼼하게 잘 기획되었고, 간결하게 잘 구성한 완성도 높은 작품이라고 생각합니다.</p>
<p><strong>위드로봇</strong> 아이디어가 좀 더 추가되면 좋은 작품이 될 것 같습니다.</p>
<p><span style="color: #ff9900"><strong>2. 배경</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-2.png" rel="lightbox[40667]"><img class="alignnone size-large wp-image-40679" alt="66_ict_환기제어 (2)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-2-620x275.png" width="620" height="275" /></a></p>
<p>미세먼지 농도가 심각하다는 것은 아마 우리 모두가 알고 있을 것이다. 그리고 실제로 미세먼지로 인한 두통, 기침, 폐암, 그리고 직업 능률 감소로까지 이어지고 있다. 네이버 키워드 검색량을 확인해보면 미세먼지라는 것이 큰 문제이고 많은 사람들이 관심을 가지고 있다는 것을 확인할 수 있다.</p>
<p><span style="color: #33cccc"><strong>2.1. 현재상황</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-3.png" rel="lightbox[40667]"><img class="alignnone size-full wp-image-40680" alt="66_ict_환기제어 (3)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-3.png" width="584" height="287" /></a><br />
미세먼지 문제를 해결하기위한 공기기청정기는 2018년 기준으로 2조원 시장을 가지고 있고 미니 공기청정기 시장은 약 1000억원의 시장을 형성하고 있다. 하지만 미니 공기청정기는 단지 필터와 펜으로 이루어진 공기청정기로 사람들이 어느정도 공기가 오염되었는지 확인할 수 없다. 또한 미니 공기청정기를 분해해보면 공기청정기의 필터가 역할을 제대로 하지 못하고 펜이 약한 경우가 대부분이다. 배경에서 말했듯이 대부분의 사람들은 초미세먼지로 인해 창문을 열고 살지 않고 있다 하지만 기사에 따르면 집안의 먼지농도와 밖의 미세먼지 농도를 비교 했을 때 밖의 미세먼지 농도가 높다고 한다. 이러한 상황에는 공기청정기를 계속 틀기보다 창문을 여는 것이 더 효과적인 방법이 될 수 있다. 그래서 저는 이 두가지 문제점을 해결하기 위한 제품을 만들려고 했다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-4.png" rel="lightbox[40667]"><img class="alignnone size-full wp-image-40681" alt="66_ict_환기제어 (4)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-4.png" width="611" height="452" /></a></p>
<p><span style="color: #33cccc"><strong>2.2. 제품의 특징</strong></span><br />
집안의 미세먼지 농도를 확인할 수 있고 내부의 미세먼지가 외부보다 높은 경우 자동으로 창문을 열 수 있는 시스템을 만들었다. 그렇게 함으로써 20대의 주거환경에 필수적인 공기 오염도를 현저히 줄일 수 있고 전기료 감소로 인한 경제적 이익을 취할 수 있다고 생각한다.</p>
<p><span style="color: #33cccc"><strong>2.3. 제품 상세 특징 및 스펙</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-5.png" rel="lightbox[40667]"><img class="alignnone size-large wp-image-40682" alt="66_ict_환기제어 (5)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-5-549x620.png" width="549" height="620" /></a></p>
<p>아두이노 나노 기반인 PCB를 제작하려고 한다. 이 공기청정기는 여러가지 특징이 있다. 브레드 보드를 사용하지 않고 PCB 형태로 제작 되기 때문에 회로가 안정화되어 있고 LED, 미세먼지, 온습도 센서를 통한 정보를 LCD에서 바로 확인을 할 수 있다.<br />
또한 다양한 센서 정보를 다른 쪽 아두이노에 블루투스 통신을 통해서 정보를 보내 내부와 외부의 미세먼지 농도를 비교하여 창문 개폐를 위한 서브모터를 작동시킨다.</p>
<p><span style="color: #33cccc"><strong>2.4. 제품 작동 알고리즘</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-6.png" rel="lightbox[40667]"><img class="alignnone size-large wp-image-40683" alt="66_ict_환기제어 (6)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-6-620x328.png" width="620" height="328" /></a></p>
<p>미세먼지에 따른 LED표시, 미세먼지에 농도에 따라 AUTO 펜 제어, 그리고 미세먼지 농도 심각 시 부저가 울리는 것이다. 그리고 그러한 정보를 LCD에 표현하는 것이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-7.png" rel="lightbox[40667]"><img class="alignnone size-large wp-image-40684" alt="66_ict_환기제어 (7)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-7-620x298.png" width="620" height="298" /></a></p>
<p>외부장치와 내부장치를 구성하여, HC-06 두개를 페어링하여 외부 미세먼지 농도에 대한 정보를 아두이노에 블루투스 통신을 통해서 보내 창문을 개폐여부를 결정하는 것이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-8.png" rel="lightbox[40667]"><img class="alignnone size-large wp-image-40685" alt="66_ict_환기제어 (8)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-8-620x270.png" width="620" height="270" /></a></p>
<p>블루투스 통신의 경우 일련의 String 형식으로 값이 전달이 된다. 따라서 여러가지 정보를 보내기가 매우 어려운 사항이다. 따라서 이번 프로젝트에서는 미세먼지 농도를 포함해서, 온도, 습도, 조도의 정보를 블루투스 통신을 통해서 받아야하기 때문에 센서값별로 일련의 String을 파싱하는 소프트웨어 알고리즘이 필요하다. 그 부분을 코딩으로 구현</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-9.png" rel="lightbox[40667]"><img class="alignnone size-large wp-image-40686" alt="66_ict_환기제어 (9)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-9-620x192.png" width="620" height="192" /></a></p>
<p>미세먼지 센서의 값은 정확한 농도를 표현을 하는 것이 아닌 전압을 읽어서 가져오는 것이다. 시리얼 통신을 통해 고정밀 미세저측정기를 통해서, 캘리브레이션 할 수 있는 이동평균 개념을 적용해서 센서값 기복에 대한 부분을 해결했다.</p>
<p><span style="color: #33cccc"><strong>2.5. 회로도 및 부분별 하드웨어 원리</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-10.png" rel="lightbox[40667]"><img class="alignnone size-large wp-image-40687" alt="66_ict_환기제어 (10)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-10-620x206.png" width="620" height="206" /></a></p>
<p>캐패시터는 다양한 용도로 사용된다. 노이즈를 막기위해서 맥류신호를 평활하기 위한 평활용으로 사용되었다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-11.png" rel="lightbox[40667]"><img class="alignnone size-full wp-image-40688" alt="66_ict_환기제어 (11)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-11.png" width="613" height="367" /></a></p>
<p>전원 순단 시 및 IC의 구동 스피드가 급격히 빨라짐에 따라, 부하전류가 증가한 경우, 전원으로부터의 라인 전압이 강하하여, IC의 오동작을 초래하는 경우가 있다. 이를 방지하기 위해, 전원 라인 정상 시에 콘덴서가 축적해 놓은 전기를 IC 측에 공급하여 전원 라인 전압을 일시적으로 유지한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-12.png" rel="lightbox[40667]"><img class="alignnone size-full wp-image-40689" alt="66_ict_환기제어 (12)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-12.png" width="619" height="254" /></a></p>
<p>아두이노에 전원을 공급하기위해서는 5v전원을 공급해주어야한다. 하지만 모터의 경우 5v를 공급하게 되면 최대 파워를 낼 수 가 없다 그래서 12v전원은 모터에 아두이노에는 전압을 강압시켜 5v를 공급 시켜주기 위해 레귤레이터를 사용하였다. 전원 공급의 경우 12v로 일정한 정전압을 보내므로 스위칭 레귤레이터가 아닌 리니어 레귤레이터를 사용하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-13.png" rel="lightbox[40667]"><img class="alignnone size-full wp-image-40690" alt="66_ict_환기제어 (13)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-13.png" width="612" height="450" /></a></p>
<p>12v와 0.7A가 사용되는 모턴팬을 동작시키기 위해 Mosfet을 사용하여, 아두이노 신호에 따라 입력된 12V 전원부에서 전류를 공급할 수 있도록 구성을 하였다</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-14.png" rel="lightbox[40667]"><img class="alignnone size-full wp-image-40691" alt="66_ict_환기제어 (14)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-14.png" width="612" height="408" /></a></p>
<p>경고음을 알리기 위한 용도로서 부저를 사용하였다. 부저 또한 코일성분을 가지고 있기에 직접적으로 아두이노에 연결을 하는 것은 좋지 않으며, 아두이노에서 출력하는 전류의 한계로 소리가 매우 작은 측면을 가지고 있다. 따라서 부저의 경우에는 트랜지스터를 사용하여 전류증폭을 통해 더 큰 경고음을 울릴 수 있도록 회로를 구성하였으며, 다이오드(FLYING WEEL 다이오드)를 사용하여, 역기전력를 방지하고자 구성하였다.</p>
<p><span style="color: #ff9900"><strong>3. 최종 결과물</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-1.jpg" rel="lightbox[40667]"><img class="alignnone size-full wp-image-40677" alt="66_ict_환기제어 (1)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-1.jpg" width="611" height="438" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-15.png" rel="lightbox[40667]"><img class="alignnone size-full wp-image-40692" alt="66_ict_환기제어 (15)" src="http://www.ntrexgo.com/wp-content/uploads/2021/06/66_ict_환기제어-15.png" width="612" height="360" /></a></p>
<p><span style="color: #ff9900"><strong>4.아두이노 소스코드</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>// 해당 소스코드는 외부데이터(미세먼지 / 온도 / 습도 / 조도) 측정하고, 내부 데이터와 비교하여<br />
// 외부환기에 대한 부분을 담당하는 부분이다.</p>
<p>#include &#8220;SoftwareSerial.h&#8221;<br />
#include &lt;Adafruit_NeoPixel.h&gt;<br />
#include &#8220;DHT.h&#8221;<br />
#include &lt;Servo.h&gt;<br />
#include &lt;LiquidCrystal_I2C.h&gt;</p>
<p>// 블루통신 관련해서 필요한 변수 정리<br />
const int maxIndex = 10;<br />
byte blockData[maxIndex]; //block 값 저장<br />
int arrIndex = 0; // 배열 arrIndex</p>
<p>byte refined_humidity = 0;<br />
byte refined_temperature = 0;<br />
byte refined_value = 0;<br />
byte refined_dust_data = 0;</p>
<p>byte refined_humidity2 = 0;<br />
byte refined_temperature2 = 0;<br />
byte refined_value2 = 0;<br />
byte refined_dust_data2 = 0;</p>
<p>/*미세먼지센서 변수들*/<br />
#define measurePin A1 //Connect dust sensor to Arduino A0 pin<br />
#define ledPower 6 //Connect 3 led driver pins of dust sensor to Arduino D4<br />
#define SampleTime 30 //먼지센서 30회 샘플링</p>
<p>int samplingTime = 280;<br />
int deltaTime = 40;<br />
int sleepTime = 9680;<br />
float voMeasured = 0;<br />
float calcVoltage = 0;<br />
float dustDensity = 0;</p>
<p>//조도센서&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
#define cds A0</p>
<p>//서보 모터 오브젝트 생성<br />
Servo myservo;</p>
<p>// 온습도 센서를 디지털 4번 핀에 연결합니다.<br />
#define DHTPIN 8<br />
#define DHTTYPE DHT11</p>
<p>//네오픽셀 연결 핀<br />
#define PIN1 4<br />
//네오픽셀 LED개수<br />
#define NUMPIXELS 4<br />
Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800);<br />
int delayval = 10;</p>
<p>DHT dht(DHTPIN, DHTTYPE);<br />
SoftwareSerial Serial1(2, 3); // rx,tx</p>
<p>// 서보모터 변수<br />
int val1 = 0;<br />
int val2 = 0;</p>
<p>// LCD의 경우, 고유 주소를 가지고 있는데 대부분의 LCD는 2개의 주소 중 하나로 세팅되어 있다.<br />
// 0x3F, 0&#215;27 이렇게 두가지 주소가 있다.<br />
LiquidCrystal_I2C lcd(0&#215;27, 16, 2);</p>
<p>//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>void GetData();<br />
void get_data_print2();<br />
void data_print1();<br />
void LED_R1();<br />
void LED_B1();<br />
void LED_G1();<br />
void window_open_close(int out, int in);<br />
int dust_val(); // 먼지 값받아오는 함수</p>
<p>void setup () {</p>
<p>// 시리얼통신<br />
Serial.begin(9600);<br />
// 블루투스 통신<br />
Serial1.begin(9600);<br />
//서보 모터 10번핀<br />
myservo.attach(10);<br />
myservo.write(100);<br />
// 조도센서<br />
pinMode(cds, INPUT);<br />
// 미세먼지센서<br />
pinMode(ledPower, OUTPUT);<br />
pinMode(measurePin, INPUT);<br />
//온도습도센서 시작<br />
dht.begin();<br />
// 네오픽셀 시작<br />
pixels1.begin(); // This initializes the NeoPixel library.</p>
<p>lcd.init();<br />
lcd.backlight();<br />
lcd.clear();<br />
}</p>
<p>void loop () {</p>
<p>// 블루투스 통신을 통해 내부데이터를 받아서 파싱을 하고, 각 변수에 저장</p>
<p>if (Serial1.available()) {<br />
GetData();<br />
}<br />
if (arrIndex != 0 &amp;&amp; arrIndex &lt; 9) {<br />
Serial.println(&#8220;내부데이터 변수 저장&#8221;);</p>
<p>if (blockData[0] == 104)<br />
refined_humidity2 = blockData[1];<br />
if (blockData[2] == 116)<br />
refined_temperature2 = blockData[3];<br />
if (blockData[4] == 99)<br />
refined_value2 = blockData[5];<br />
if (blockData[6] == 100)<br />
refined_dust_data2 = blockData[7];<br />
} else {</p>
<p>Serial.println(&#8220;내부데이터 변수 이상으로 미저장 or 블루투스 미연결&#8212;&#8211;&#8221;);<br />
}</p>
<p>// 습도와 온도값을 측정하고, 제대로 측정되었는지 확인해줍니다.<br />
byte humidity = dht.readHumidity();<br />
byte temperature = dht.readTemperature();</p>
<p>refined_humidity = constrain(humidity, 0, 100);<br />
refined_temperature = constrain(temperature, 0, 100);</p>
<p>// 조도센서 값<br />
int value = analogRead(cds);<br />
refined_value = map(value, 0, 1023, 100, 0);</p>
<p>// 먼지센서 값<br />
int dust_data = dust_val(); // 먼지량을 받아옴<br />
refined_dust_data = map(dust_data, 0, 1023, 0, 100);</p>
<p>// 미세먼지 농도에 따라 색변화와 부저를 활용하여 경고음 제공하기.</p>
<p>if (refined_dust_data &gt; 65) {<br />
delay(10);<br />
LED_R1();<br />
} else if (refined_dust_data &lt;= 65 &amp;&amp; refined_dust_data &gt; 50 ) {<br />
delay(10);<br />
LED_RB1();<br />
} else if (refined_dust_data &lt;= 50 &amp;&amp; refined_dust_data &gt; 25) {<br />
delay(10);<br />
LED_B1();<br />
} else {<br />
LED_G1();<br />
}</p>
<p>// 내부데이터와 외부데이터를 비교하여, 창문개폐 진행<br />
// 내부 공기청정기팬의 경우에는 외부,내부 미세먼지 농도에 상관없이, 내부 미세먼지가 25 이상인 경우에는 자동으로 작동이된다.<br />
// 창문개폐의 경우는<br />
// 1) 외부 창문이 열리는 경우<br />
// 외부의 미세먼지농도가 내부보다 낮을 때,<br />
// 외부 미세먼지 농도가 높은 경우에는 창문을 열리지 않고, 내부 팬에 의해서 공기정화가 진행이 된다.<br />
// 내부 미세먼지 농도가 25 이상일 때, 동작한다.<br />
window_open_close(refined_dust_data, refined_dust_data2);</p>
<p>lcd.clear();<br />
lcd.setCursor(0, 0);<br />
lcd.print(&#8220;out dust :&#8221;);<br />
lcd.print(refined_dust_data);<br />
lcd.setCursor(0, 1);<br />
if(refined_dust_data2 ==0){<br />
lcd.print(&#8220;BT disconnected&#8221;);<br />
}else{<br />
lcd.print(&#8220;inner dust :&#8221;);<br />
lcd.print(refined_dust_data2);<br />
}</p>
<p>get_data_print2();<br />
data_print1();<br />
}</p>
<p>//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
void LED_R1() {<br />
for (int i = 0; i &lt; NUMPIXELS; i++) {<br />
pixels1.setPixelColor(i, pixels1.Color(255, 0, 0)); // Moderately bright green color.<br />
pixels1.show(); // This sends the updated pixel color to the hardware.<br />
delay(delayval); // Delay for a period of time (in milliseconds).<br />
}<br />
}</p>
<p>void LED_G1() {</p>
<p>for (int i = 0; i &lt; NUMPIXELS; i++) {<br />
pixels1.setPixelColor(i, pixels1.Color(0, 255, 0)); // Moderately bright green color.<br />
pixels1.show(); // This sends the updated pixel color to the hardware.<br />
delay(delayval); // Delay for a period of time (in milliseconds).<br />
}<br />
}</p>
<p>void LED_B1() {<br />
for (int i = 0; i &lt; NUMPIXELS; i++) {<br />
pixels1.setPixelColor(i, pixels1.Color(0, 0, 255)); // Moderately bright green color.<br />
pixels1.show(); // This sends the updated pixel color to the hardware.<br />
delay(delayval); // Delay for a period of time (in milliseconds).<br />
}<br />
}</p>
<p>void LED_RB1() {<br />
for (int i = 0; i &lt; NUMPIXELS; i++) {<br />
pixels1.setPixelColor(i, pixels1.Color(255, 0, 120)); // Moderately bright green color.<br />
pixels1.show(); // This sends the updated pixel color to the hardware.<br />
delay(delayval); // Delay for a period of time (in milliseconds).<br />
}<br />
}</p>
<p>//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
int dust_val() //센서의 노이즈 값으로인해 여러번 데이터를 받은뒤 평균 먼지량을 구함<br />
{<br />
int dust = 0;<br />
for (int i = 0; i &lt; SampleTime; i++)<br />
{<br />
digitalWrite(ledPower, LOW); // power on the LED 0.028초부터 led가 가장 밝음으로 최소샘플링 타임으로 결정<br />
delayMicroseconds(samplingTime);</p>
<p>voMeasured = analogRead(measurePin); // read the dust value<br />
delayMicroseconds(deltaTime);<br />
digitalWrite(ledPower, HIGH); // turn the LED off<br />
delayMicroseconds(sleepTime);<br />
//////////////////////////////////////////// dust vlaue 받아오기<br />
calcVoltage = voMeasured * (5.0 / 1024.0);<br />
dustDensity = calcVoltage / 0.005; //(0.17 * calcVoltage &#8211; 0.1) * 1000;<br />
/////////////////////value 의 미세한 변화를 수식으로 먼지량으로 변환<br />
if (dustDensity &lt; 0) { // value 의 값이 마이너스일경우 오류 임으로 0을 대입<br />
dustDensity = 0;<br />
}<br />
dust += dustDensity;<br />
}<br />
return (dust / SampleTime)+50; // 센싱한값의 평균을 return<br />
}</p>
<p>void GetData() {<br />
Serial.println();<br />
Serial.println(&#8220;데이터 가져오기 시작 &#8220;);<br />
char temp;<br />
arrIndex = 0;</p>
<p>temp = (char)Serial1.read();<br />
Serial.println(&#8220;&#8221;);<br />
Serial.print(temp);</p>
<p>// 전송 시작 확인<br />
// 블루투스 시작을 알리는 문자를 s로 설정 !!!<br />
if (temp != &#8216;s&#8217;) {<br />
while (temp != &#8216;e&#8217; ) {<br />
temp = (char)Serial1.read();<br />
}<br />
return;<br />
}<br />
String stringTemp;</p>
<p>while (true) {<br />
// Serial.print(&#8220;arrIndex : &#8220;);<br />
// Serial.println(arrIndex);</p>
<p>if (Serial1.available()) {<br />
temp = (char)Serial1.read();<br />
Serial.print(temp);</p>
<p>if (arrIndex &gt; 10) {<br />
// Serial.println(&#8220;내부데이터 변수 이상 &#8212;&#8212;&#8212;-&#8221;);<br />
break;<br />
}</p>
<p>// &#8216;_&#8217; 라는 문자를 통해 구분을 지어준다. 구분을 지어주는 표시라고 생각을 하면된다. &#8212;&#8212;&#8212;&#8211;<br />
if (temp != &#8216;_&#8217;) {</p>
<p>// &#8216;e&#8217; 라는 문자가 나오게 되면 블루투스 통신이 끝났다는 의미이다.<br />
if (temp == &#8216;e&#8217;) {<br />
break;<br />
}</p>
<p>if (isAlpha(temp)) { //temp라는 변수가 문자인지 확인을 한다.</p>
<p>blockData[arrIndex] = temp;<br />
arrIndex++;</p>
<p>} else if (isDigit(temp)) { //temp라는 변수가 숫자인지 확인을 한다.<br />
stringTemp += temp;</p>
<p>} else {<br />
// 원하지 않는 데이터 값<br />
Serial.println(&#8220;upload failed. error: not digit or alpha&#8221;);<br />
arrIndex = 0;<br />
return;<br />
}<br />
}</p>
<p>else if (temp == &#8216;_&#8217;) {<br />
if (stringTemp == &#8220;&#8221;)<br />
continue; // 아래의 것들을 건너뛴다.<br />
blockData[arrIndex] = stringTemp.toInt();<br />
//변수 초기화<br />
stringTemp = &#8220;&#8221;;<br />
arrIndex++;<br />
}<br />
}<br />
}<br />
Serial.println(&#8220;끝&#8221;);<br />
Serial.println(&#8220;&#8221;);<br />
delay(30);<br />
}</p>
<p>// int out은 외부미세먼지농도, int in 내부미세먼지농도<br />
void window_open_close(int out, int in) {</p>
<p>// 내부미세먼지농도가 낮아서 공기정화를 할 필요없는 경우<br />
if(in &lt; 3){<br />
return;}<br />
if (in &lt; 25) {<br />
Serial.println(&#8220;내부 공기가 매우 깨끗합니다.&#8221;);<br />
val1 = 100;<br />
if (val1 != val2) {<br />
myservo.write(val1); // 창문이 닫힘.<br />
val2 = val1;<br />
delay(10);<br />
}<br />
return;<br />
}<br />
// 내부미세먼지농도가 안좋은 경우<br />
else {<br />
if (out &lt; in) {<br />
Serial.println(&#8220;환기를 위해 창문 open. &#8220;);<br />
val1 = 0;<br />
if (val1 != val2) {<br />
myservo.write(val1); // 창문이 닫힘.<br />
val2 = val1;<br />
delay(10);<br />
}<br />
delay(10);<br />
} else {<br />
Serial.println(&#8220;외부 미세먼지 농도가 높아, 창문 close. &#8220;);<br />
val1 = 100;<br />
if (val1 != val2) {<br />
myservo.write(val1); // 창문이 닫힘.<br />
val2 = val1;<br />
delay(10);<br />
}<br />
delay(10);<br />
}<br />
}<br />
}</p>
<p>void data_print1() {<br />
Serial.print(&#8220;외부센서데이터 : &#8220;);<br />
Serial.print(&#8220;humidity : &#8220;);<br />
Serial.print(refined_humidity);<br />
Serial.print(&#8221; temp :&#8221;);<br />
Serial.print(refined_temperature);<br />
Serial.print(&#8221; cds : &#8220;);<br />
Serial.print(refined_value);<br />
Serial.print(&#8221; dust : &#8220;);<br />
Serial.println(refined_dust_data);<br />
delay(300);<br />
}</p>
<p>void get_data_print2() {<br />
Serial.print(&#8220;내부센서데이터 : &#8220;);<br />
Serial.print(&#8220;humidity : &#8220;);<br />
Serial.print(refined_humidity2);<br />
Serial.print(&#8221; temp :&#8221;);<br />
Serial.print(refined_temperature2);<br />
Serial.print(&#8221; cds : &#8220;);<br />
Serial.print(refined_value2);<br />
Serial.print(&#8221; dust : &#8220;);<br />
Serial.println(refined_dust_data2);<br />
delay(300);<br />
아두이노 코드 2 &#8211; 내부 담당 코드<br />
#include &#8220;SoftwareSerial.h&#8221;<br />
#include &lt;Adafruit_NeoPixel.h&gt;<br />
#include &#8220;DHT.h&#8221;<br />
// I2C LCD를 쉽게 제어하기 위한 라이브러리를 추가해줍니다.<br />
#include &lt;LiquidCrystal_I2C.h&gt;</p>
<p>/*미세먼지센서 변수들*/<br />
#define measurePin A1 //Connect dust sensor to Arduino A0 pin<br />
#define ledPower 6 //Connect 3 led driver pins of dust sensor to Arduino D4<br />
#define SampleTime 30 //먼지센서 30회 샘플링</p>
<p>int samplingTime = 280;<br />
int deltaTime = 40;<br />
int sleepTime = 9680;<br />
float voMeasured = 0;<br />
float calcVoltage = 0;<br />
float dustDensity = 0;<br />
// 정제된 변수값<br />
byte refined_humidity = 0;<br />
byte refined_temperature = 0;<br />
byte refined_value = 0;<br />
byte refined_dust_data = 0;</p>
<p>//조도센서&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
#define cds A0</p>
<p>//부저 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
#define buzzer 7</p>
<p>//모터팬 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
#define fan 9</p>
<p>// 온습도 센서를 디지털 4번 핀에 연결합니다.<br />
#define DHTPIN 8<br />
#define DHTTYPE DHT11</p>
<p>//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>//네오픽셀 연결 핀<br />
#define PIN1 4</p>
<p>//네오픽셀 LED개수<br />
#define NUMPIXELS 4<br />
Adafruit_NeoPixel pixels1 = Adafruit_NeoPixel(NUMPIXELS, PIN1, NEO_GRB + NEO_KHZ800);<br />
int delayval = 10;<br />
int color_value=0;</p>
<p>DHT dht(DHTPIN, DHTTYPE);<br />
SoftwareSerial Serial1(2, 3); // rx,tx</p>
<p>// LCD의 경우, 고유 주소를 가지고 있는데 대부분의 LCD는 2개의 주소 중 하나로 세팅되어 있다.<br />
// 0x3F, 0&#215;27 이렇게 두가지 주소가 있다.<br />
LiquidCrystal_I2C lcd(0&#215;27, 16, 2);</p>
<p>//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
void SendData();<br />
void LED_RB1();<br />
void setup () {</p>
<p>// 시리얼통신<br />
Serial.begin(9600);<br />
// 블루투스 통신<br />
Serial1.begin(9600);<br />
// 조도센서<br />
pinMode(cds, INPUT);<br />
// 미세먼지센서<br />
pinMode(ledPower, OUTPUT);<br />
pinMode(measurePin, INPUT);<br />
//온도습도센서 시작<br />
dht.begin();<br />
// 12V 모터팬<br />
pinMode(fan, OUTPUT);<br />
// 네오픽셀 시작<br />
pixels1.begin(); // This initializes the NeoPixel library.</p>
<p>// 부저 // #define buzzer 7<br />
pinMode(buzzer, OUTPUT);<br />
lcd.init();<br />
lcd.backlight();<br />
lcd.clear();<br />
}<br />
int dust_val(); // 먼지 값받아오는 함수<br />
void loop () {</p>
<p>// 습도와 온도값을 측정하고, 제대로 측정되었는지 확인해줍니다.<br />
byte humidity = dht.readHumidity();<br />
byte temperature = dht.readTemperature();</p>
<p>refined_humidity = constrain(humidity, 0, 100);<br />
refined_temperature = constrain(temperature, 0, 100);</p>
<p>// 조도센서 값<br />
int value = analogRead(cds);<br />
refined_value = map(value, 0, 1023, 100, 0);<br />
color_value=map(refined_value, 10, 100, 0, 255);</p>
<p>// 먼지센서 값<br />
int dust_data = dust_val(); // 먼지량을 받아옴<br />
refined_dust_data = map(dust_data, 0, 1023, 0, 100);</p>
<p>Serial.print(&#8221; temp : &#8220;);<br />
Serial.print(refined_temperature);<br />
Serial.print(&#8220;&#8216;c &#8220;);<br />
Serial.print(&#8221; humidity : &#8220;);<br />
Serial.print(refined_humidity);<br />
Serial.print(&#8220;% &#8220;);<br />
Serial.print(&#8221; cds : &#8220;);<br />
Serial.print(refined_value);<br />
Serial.print(&#8221; dust : &#8220;);<br />
Serial.println(refined_dust_data);</p>
<p>lcd.clear();<br />
lcd.setCursor(0, 0);<br />
lcd.print(&#8220;hm:&#8221;);<br />
lcd.print(refined_humidity);<br />
lcd.print(&#8221; tp:&#8221;);<br />
lcd.print(refined_temperature);<br />
lcd.setCursor(0, 1);<br />
lcd.print(&#8220;cds :&#8221;);<br />
lcd.print(refined_value);<br />
lcd.print(&#8221; dust :&#8221;);<br />
lcd.print(refined_dust_data);</p>
<p>// 미세먼지 농도에 따라 색변화와 부저를 활용하여 경고음 제공하기.</p>
<p>if (refined_dust_data &gt; 68) {<br />
analogWrite(fan,150);<br />
delay(10);<br />
LED_R1();<br />
tone(buzzer, 1000);<br />
} else if (refined_dust_data &lt;= 68 &amp;&amp; refined_dust_data &gt; 50 ) {<br />
analogWrite(fan,150);<br />
noTone(buzzer);<br />
delay(10);<br />
LED_RB1();<br />
} else if (refined_dust_data &lt;= 50 &amp;&amp; refined_dust_data &gt; 25) {<br />
analogWrite(fan, 120);<br />
noTone(buzzer);<br />
delay(10);<br />
LED_B1();<br />
} else {<br />
analogWrite(fan, 0);<br />
noTone(buzzer);<br />
LED_G1();<br />
}</p>
<p>SendData();<br />
}</p>
<p>//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>void LED_R1() {<br />
for (int i = 0; i &lt; NUMPIXELS; i++) {<br />
pixels1.setPixelColor(i, pixels1.Color(color_value, 0, 0)); // Moderately bright green color.<br />
pixels1.show(); // This sends the updated pixel color to the hardware.<br />
delay(delayval); // Delay for a period of time (in milliseconds).<br />
}<br />
}</p>
<p>void LED_RB1() {<br />
for (int i = 0; i &lt; NUMPIXELS; i++) {<br />
pixels1.setPixelColor(i, pixels1.Color(color_value, 0, color_value/2)); // Moderately bright green color.<br />
pixels1.show(); // This sends the updated pixel color to the hardware.<br />
delay(delayval); // Delay for a period of time (in milliseconds).<br />
}<br />
}</p>
<p>void LED_G1() {</p>
<p>for (int i = 0; i &lt; NUMPIXELS; i++) {<br />
pixels1.setPixelColor(i, pixels1.Color(0, color_value, 0)); // Moderately bright green color.<br />
pixels1.show(); // This sends the updated pixel color to the hardware.<br />
delay(delayval); // Delay for a period of time (in milliseconds).<br />
}<br />
}</p>
<p>void LED_B1() {<br />
for (int i = 0; i &lt; NUMPIXELS; i++) {<br />
pixels1.setPixelColor(i, pixels1.Color(0, 0, color_value)); // Moderately bright green color.<br />
pixels1.show(); // This sends the updated pixel color to the hardware.<br />
delay(delayval); // Delay for a period of time (in milliseconds).<br />
}<br />
}</p>
<p>void rain_color1() {</p>
<p>for (int i = 0; i &lt; NUMPIXELS; i++) {<br />
int a = random(0, 255);<br />
int b = random(0, 255);<br />
int c = random(0, 255);</p>
<p>pixels1.setPixelColor(i, pixels1.Color(a, b, c)); // Moderately bright green color.<br />
pixels1.show(); // This sends the updated pixel color to the hardware.<br />
delay(delayval); // Delay for a period of time (in milliseconds).<br />
}<br />
}<br />
//int dust_val() //센서의 노이즈 값으로인해 여러번 데이터를 받은뒤 평균 먼지량을 구함<br />
{<br />
int dust = 0;<br />
for (int i = 0; i &lt; SampleTime; i++)<br />
{<br />
digitalWrite(ledPower, LOW); // power on the LED 0.028초부터 led가 가장 밝음으로 최소샘플링 타임으로 결정<br />
delayMicroseconds(samplingTime);</p>
<p>voMeasured = analogRead(measurePin); // read the dust value<br />
delayMicroseconds(deltaTime);<br />
digitalWrite(ledPower, HIGH); // turn the LED off<br />
delayMicroseconds(sleepTime);<br />
////////////////////////////////// dust vlaue 받아오기<br />
calcVoltage = voMeasured * (5.0 / 1024.0);<br />
dustDensity = calcVoltage / 0.005; //(0.17 * calcVoltage &#8211; 0.1) * 1000;<br />
////////////value 의 미세한 변화를 수식으로 먼지량으로 변환<br />
if (dustDensity &lt; 0) { // value 의 값이 마이너스일경우 오류 임으로 0을 대입<br />
dustDensity = 0;<br />
}<br />
dust += dustDensity;<br />
}<br />
return dust / SampleTime; // 센싱한값의 평균을 return<br />
}</p>
<p>void SendData() {<br />
Serial1.print(&#8220;s_&#8221;);<br />
Serial1.print(&#8220;h_&#8221;);<br />
Serial1.print(refined_humidity);<br />
delay(3);<br />
Serial1.print(&#8220;_t_&#8221;);<br />
Serial1.print(refined_temperature);<br />
delay(3);<br />
Serial1.print(&#8220;_c_&#8221;);<br />
Serial1.print(refined_value);<br />
delay(3);<br />
Serial1.print(&#8220;_d_&#8221;);<br />
delay(3);<br />
Serial1.print(&#8220;_e&#8221;);<br />
delay(200);<br />
}<br />
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/40667/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[8호] 위드로봇 무료강좌 기술자료 – 4차</title>
		<link>http://www.ntrexgo.com/archives/6994</link>
		<comments>http://www.ntrexgo.com/archives/6994#comments</comments>
		<pubDate>Fri, 29 Jul 2011 06:36:27 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[스페셜 컬럼]]></category>
		<category><![CDATA[8호]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[비전]]></category>
		<category><![CDATA[소개]]></category>
		<category><![CDATA[시스템]]></category>
		<category><![CDATA[위드로봇]]></category>
		<category><![CDATA[임베디드]]></category>
		<category><![CDATA[핫뉴수]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=6994</guid>
		<description><![CDATA[디바이스마트 매거진 8호 &#124; 비전 시스템(vision system)은 카메라를 통해 얻은 영상에서부터 얻고자 하는 정보를 처리하는 장치로 카메라 - 이미지 그래버 - PC 형태로 구성되는 것이 일반적이다. ]]></description>
				<content:encoded><![CDATA[<h3><span style="color: #008000"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith006.jpg" rel="lightbox[6994]"><img class=" wp-image-7021 alignleft" alt="08SCwith006" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith006-300x225.jpg" width="194" height="146" /></a></span></h3>
<p><strong><span style="color: #008000;font-size: 1.17em;line-height: 19px">4차 릴레이 무료강좌 기술자료</span></strong></p>
<h2><strong>임베디드</strong><strong>비전 시스템 소개</strong></h2>
<p>&nbsp;</p>
<p style="text-align: left">글 | 위드로봇(주) 김도윤 대표</p>
<p>&nbsp;</p>
<p><strong style="font-size: 13px;line-height: 19px"><span style="color: #008000;text-decoration: underline">시작글</span></strong></p>
<p>위드로봇 연구실 확장 이전 기념 릴레이 무료 강좌 4차 교육이 2011년 1월 8일 토요일에 성수동 위드로봇 본사에서 진행 되었습니다. 임베디드 비전 시스템에 대한 주제로 진행된 이번 강좌의 강의 내용을 참석하지 못한 디바이스마트 매거진 구독자들을 위해 간단히  소개하고자 합니다.</p>
<p><strong><span style="color: #008000">서 론</span></strong></p>
<p>비전 시스템(vision system)은 카메라를 통해 얻은 영상에서부터 얻고자 하는 정보를 처리하는 장치로 카메라 &#8211; 이미지 그래버 &#8211; PC 형태로 구성되는 것이 일반적이다. 이때 PC의 사양은 통상적으로 해당 시점에서 가장 고성능의 부품들로 구성된다. 이는 영상 데이터가 현재 기술 대비 아직도 실시간으로 처리하기에 힘들고, 많은 비전 어플리케이션들이 하드 데드라인(Hard deadline)을 가지는 실시간성을 요구하기 때문이다. 위드로봇에서 수행한 많은 영상 처리 과제들도 쿼드 코어를 가지는 i7 프로세서를 사용하는 PC 1대로도 실시간 처리가 안되어 PC 3대를 기가비트 이더넷으로 연결한 구조로 구성하여 실시간성을 맞추는 시스템을 만들곤 한다.<br />
비즈니스 관점에서는 시스템의 신뢰성을 높이고 시스템을 구성하는 요소를 줄여 성능을 높이고 생산 단가를 줄이는 것이 중요하다. 위 세 가지 요소(카메라, 이미지 그래버, PC)들은 각각 다음과 같이 발전하고 있다.</p>
<p>●카메라: CCD 이미지 센서에 비해 CMOS 이미지 센서가 대량 생산에 유리하기에 기술 개발은 CMOS 이미지 센서쪽에 편중되어 진행되고 있다. 이 덕분에 고해상도, 고속 CMOS 이미지 센서가 지속적으로 출시되고 있으며, CCD 센서에 비해 단점으로 여겨지는 dark current, 저조도에서의 응답 특성이 점차 개선되어 CCD 이미지 센서를 맹렬히 추격하고 있다. 특히 최근에 많은 관심을 끌고 있는 wide dynamic range 카메라는 명암 차이가 심한 지역에서도 어두운 부분과 밝은 부분의 디테일을 잘 표현하기에 영상 처리 센서를 제조하는 제조사들이 공을 들여 개발을 거듭하고 있다. 아울러 적정 해상도, 응답 특성을 기준으로 놓고 보면, CMOS 센서 기술이 발전하면서 점점 더 작은 크기의 이미지 센서 크기로도 담당할 수 있게 되어 가격이 저렴해지는 효과가 있다. 최근 640 x 480 VGA 급 CMOS 이미지 센서는 $2까지 가격이 떨어졌고, 렌즈까지 포함해도 $4 수준인 경우가 많다. 기존 CCTV용 카메라 셋트를 구성하려면 $100이 넘는데, CMOS 이미지 센서로 영상을 취득하는 부분을 구성하면 1/20 가격으로 카메라를 구성할 수 있게 된 것이다.</p>
<p>● 이미지 그래버는 통상적으로 아날로그 신호로 전달되는 영상 신호를 디지털 신호로 바꾸기 위해 존재했었는데 앞서 소개한 CMOS 이미지 센서들은 디지털 신호를 바로 출력하여 마이크로 프로세서에 연결할 수 있는 인터페이스를 내장하고 있다. ITU BT.601, 656과 같은 규약이 그것이다. 주로 8비트 내지 10비트의 데이터 라인과 함께 수평 라인, 수직 라인을 표시하는 동기 신호 및 각 픽셀의 전송을 알리는 픽셀 클럭 신호를 가지고 있다. 최근 출시되는 범용 마이크로 프로세서에서는 이러한 BT.601/656 포맷을 지원하는 인터페이스 블록을 내장하고 있는 경우도 있어 이러한 마이크로 프로세서를 사용하면 CMOS 이미지 센서 출력을 바로 마이크로 프로세서에 연결할 수 있다. BT.601/656 인터페이스는 PCB 상에서 영상을 전달하거나 근거리(10~20cm 이내)내에서 영상을 전송하는 목적으로 만들어진 인터페이스이므로 이 보다 더 긴 거리로 영상을 전송하려면 별도의 인터페이스가 필요하다. 최근에 널리 사용되는 기술은 Camera link, 기가비트 이더넷, USB 3.0을 들 수 있다. 이 중에서 가장 최근에 출시된 USB 3.0은 5Gbit가 넘는 넓은 대역폭에 기존 USB 2.0과의 하위 호환성을 무기로 빠른 속도로 영상 전송 인터페이스 시장을 잠식할 것으로 예상된다.</p>
<p>● PC는 본질적으로 영상 처리 알고리즘을 동작시키기 위한 장치이므로 성능만 따라준다면 전통적인 임베디드 프로세서로 대치 가능하다. 아쉽게도 현존하는 기술로는 PC가 가장 손쉽게 접할 수 있는 고성능 프로세서를 장착한 시스템이기에 PC를 능가하는 임베디드 프로세서를 접하기는 어렵다. 하지만 특정 영상 처리 알고리즘을 소프트웨어가 아닌 하드웨어를 통해 구현하고, 이를 하나의 칩으로 만든 형태로 시스템을 구성하면 PC에 비해 낮은 클록으로 동작하는 임베디드 프로세서에서도 실시간성을 확보할 수 있어 굳이 PC를 사용하지 않더라도 비전 시스템을 구성할 수 있게 된다. 대표적인 예로 차량에 장착하여 전방의 상황을 실시간으로 SD 카드에 저장하는 차량용 블랙박스를 들 수 있다. 640&#215;480 해상도의 컬러 이미지를 실시간으로 압축하여 저장하는 연산량은 저사양 PC에서도 버거울 정도로 많은 컴퓨팅 파워를 요구한다. 이를 현장에서는 MPEG2 또는 H.264와 같은 특정 압축 알고리즘을 전담하는 임베디드 프로세서와 인터페이스를 담당하는 임베디드 프로세서 두 개를 하나의 칩으로 만들어 해결하였다. 이러한 프로세서는 설계는 어렵지만 일단 설계가 완성되면 대량 생산이 가능해지기 때문에 생산 원가를 대폭 줄일 수 있다. 통상적으로 이러한 프로세서는 $5 이내에서 공급되기에 $150이 넘는 PC 세트에 비해 가격 우월성, 저전력, 시스템 크기 등에서 큰 장점을 가진다.</p>
<div id="attachment_7020" class="wp-caption aligncenter" style="width: 568px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith005.jpg" rel="lightbox[6994]"><img class=" wp-image-7020 " alt="그림1. ITU BT 601 인터페이스 타이밍" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith005-620x146.jpg" width="558" height="131" /></a><p class="wp-caption-text">그림1. ITU BT 601 인터페이스 타이밍</p></div>
<p>위에서 살펴본 바와 같이 이미지 센서 기술 발전으로 인한 영상 장치 가격의 하락, 별도의 이미지 그래버 없이 영상을 바로 마이크로 프로세서로 전달할 수 있는 인터페이스 등장, 그리고 마이크로 프로세서의 성능 개선을 통한 컴퓨팅 능력의 향상은 영상 처리 기술이 공장 자동화와 같이 한정된 산업 분야를 벗어나 모바일 기기, 차량, 게임, 서비스 로봇, 사용자 인터페이스 등과 같이 실생활 곳곳에서 다양한 형태로 응용되는 기반을 마련하였다[1]. 이처럼 영상 처리 시스템의 기반이 기존 고성능, 고가의 컴퓨터에서 휴대폰이나 디지털 카메라와 같은 저가형 임베디드 시스템으로 전환되면서 임베디드 비전 시스템, 임베디드 컴퓨터 비전이라는 개념이 등장하기 시작하였고, 관련 학회에서도 이러한 용어를 사용하기 시작하였다[2][3].</p>
<p>이러한 새로운 개념이 등장하면 해외에서는 뜻을 같이 하는 단체를 결정하여 주도권을 쥐고 많은 부분의 표준을 선도한다. 이런 부분은 국내 연구진, 산업체들이 항상 한 발 늦어 아쉬운 부분인데 임베디드 비전 분야도 얼마전 15개의 해외 기업 주도로 임베디드 비전 연합(Embedded Vision Alliance, www.embedded-vision.com)을 출범하였다. 참여하고 있는 기업을 살펴 보면 BDTI, 자일링스, 아날로그 디바이스, 앱티컬(Aptical), 애브넷 일렉트로닉스 마케팅, CEVA, 코그니뷰, 프리스케일, 매스웍스, 내쇼날 인스트루먼트(NI), 엔비디아(NVIDIA), 텍사스 인스트루먼트(TI), 도쿄 일렉트론 디바이스, Ximea 그리고 XMOS 등이다. 아직은 초기 단계여서 홈페이지에서 많은 정보를 제공하고 있지는 않지만 쟁쟁한 업체들이 참여한 만큼 해당 분야에서 큰 영향력을 미칠 것으로 예상된다.</p>
<p>임베디드 비전 분야가 등장하면서 이전 영상 처리 시스템에서는 별로 고려하지 않던 제약 사항들이 새롭게 등장하는데, 대표적인 것이 성능, 가격, 크기 등이다. 이 중 이번 원고에서는 임베디드 비전 시스템의 성능에 대해 살펴보도록 하겠다.</p>
<p><strong><span style="color: #008000">임베디드 비전 시스템의 성능 개선 방향</span></strong></p>
<p>반복해서 강조하지만 영상정보는 한 장의 이미지만 해도 수백 KB가 넘는 데이터를 가지고 있어 연산량은 매우 방대하다. 따라서 연산 속도가 PC에 비해 절대적으로 느린 임베디드 프로세서에서는 성능 저하가 발생한다. 임베디드 환경이 가지는 여러 제약사향을 만족시키면서 실시간성을 확보하기 위해 전용/범용 하드웨어 구성 및 소프트웨어 프로그램에 대한 연구가 진행되고 있다. DSP(Digital Signal Processor)를 내장하여 코프로세서(Co-processor)처럼 활용하는 방법이 있으며, DSP에 전통적으로 강점을 지녔던 TI(Texas Instrument)가 많은 시도를 하고 있다. TI의 Davinci 제품군은 범용 프로세서로 ARM Cortex-A8을 사용하고, 전용 프로세서로 TI C6000 계열 DSP를 내장한 원칩 임베디드 프로세서이다.</p>
<p>외부에서 봤을 때에는 ARM 프로세서처럼 보이게 되어 기존 ARM 시스템과 호환성을 높였고 내부적으로는 DSP가 코프로세서처럼 동작하게 하여 다양한 영상 처리를 두 개의 프로세서를 통해 처리가 가능하도록 구성한 시스템이다. 두 개의 프로세서 프로그래밍을 돕기 위해 SYS/LINK라는 기능이 지원되며 이를 이용하면 ARM쪽 프로세스와 DSP쪽 프로세스간의 프로세스 통신 및 데이터 교환이 가능하다. 2011년 기준으로 가장 최신 Davinci 제품군은 DM814x 시리즈이며, Cortex-A8 667MHz와 C674x DSP가 내장되어 있다. TI에서 전략적으로 임베디드 비전 분야 시장을 보고 출시한 제품이며 2012년 상반기에 출시될 예정이다. 현재 엔지니어링 샘플이 출시되어 있다.</p>
<div id="attachment_7019" class="wp-caption aligncenter" style="width: 568px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith004.jpg" rel="lightbox[6994]"><img class=" wp-image-7019 " alt="TI사의 DM814x 블록 다이어그램" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith004-620x389.jpg" width="558" height="350" /></a><p class="wp-caption-text">TI사의 DM814x 블록 다이어그램</p></div>
<p>또 다른 접근 방법은 FPGA(Field-programmable Gate Array)를 이용하는 것이다. FPGA 단어 자체가 낯선 분들을 위해 간단히 소개하면 하드웨어 기술 언어(HDL)을 이용하여 수행하고자 하는 연산을 하드웨어 로직으로 구성할 수 있는 디바이스이다. 통상적으로 ASIC으로 가기 위한 전단계로 많이 사용되지만 영상 처리 알고리즘에 최적화된 하드웨어를 빠르게 구현할 수 있다는 점에서 꾸준히 영상 처리 전문가들에게 관심을 받아왔다. FPGA를 이용하여 영상 처리 알고리즘을 구현하면 비종속적인 연산을 동시에 수행할 수 있어 병렬 처리가 가능해진다.</p>
<p>이는 전통적인 범용 프로세서에서 for loop를 돌릴 경우 파이프 라인 처리 속도 이상은 기대할 수 없는 반면, 극단적인 예를 들다면, for loop문이 필요 없이 한 번에 연산을 처리할 수 있다는 이야기가 된다. 특히 특정 비전 알고리즘은 FPGA와 궁합이 매우 잘 맞는다. Optical flow, 얼굴 검출 등은 연산의 구조가 서로 관련성이 적고, 여러 영상 화소 데이터값은 동시 참조가 빈번하여 FPGA 특성을 잘 활용하면 범용 프로세서에서 처리한 것에 비해 대폭적인 성능 향상을 기대할 수 있는 분야이다. 실제로 이와 같은 특징을 잘 활용하여 얼굴 인식 분야에서는 얼굴 인식 알고리즘을 FPGA 또는 ASIC까지 진행하여 원칩으로 나온 제품들이 많이 있다. 이러한 전용 칩은 동시 연산이 가능하기에 VGA 영상을 초당 300장 이상 처리할 수 있는 제품들도 있어 동적 응답 특성이 중요한 응용 분야에서 널리 활용될 것으로 기대된다.</p>
<p>앞서 언급한 ARM+DSP 조합이 범용 프로세서 두 개를 구성하고 소프트웨어를 잘 구성하여 임베디드 비전 시스템의 성능 향상을 꾀하는 방법이라면 범용 프로세서 + FPGA 조합은 하드웨어 구성으로 성능 향상을 꾀하는 방법이다. 후자 방식이 시스템 크기도 커지고 소비 전력도 상대적으로 많이 소비되며 VHDL 또는 Verilog로 추가 코딩을 해야 하기 때문에 디버깅이 어렵다는 단점이 있다. 하지만 시스템의 보완이 상대적으로 우월하며 실시간 측면에서는 훨씬 이점이 있기에 주어진 조건에 맞춰 개발자들은 적절한 방법을 선택하여 개발하고 있다.</p>
<p>마지막으로 시도하는 방식은 GPU(Graphics Processor Unit)을 이용하는 것이다. GPU는 원래 모니터에 2D/3D 그래픽을 출력하는데 있어 빠른 처리를 위해 매트릭스 연산을 빨리 수행할 수 있도록 특화된 프로세서이다. 부동 소수점의 병렬 처리 기능이 강화되어 있으며 하드웨어 구조가 범용 프로세서에 비해 매우 단순하여 집적도를 늘리기 쉽다. 그 결과 범용 프로세서의 집적도를 넘어서서 연산 성능으로만 보면 GPU가 CPU를 능가하게 되었다. 이런 기능을 그래픽 연산뿐만 아니라 범용 연산에도 처리할 수 있도록 하는 GPGPU(General-Purpose computing on Graphics Processor Unit)가 도입되면서 최근에는 슈퍼 컴퓨터들이 GPU로 만들어지고 있다. 앞서 소개한 임베디드 비전 얼라이언스 참여 기업 목록을 보면 그래픽 카드 칩셋 제조사로 유명한 엔비디아가 참여하고 있는 것을 확인할 수 있다. 이는 GPU의 임베디드 비전 분야 활용을 보여주는 단적인 예이다. 엔비디아는 CUDA(Compute Unified Device Architecture)라는 하드웨어 코어 및 프로그래밍 방법론을 제공하고 있다. CUDA 코어에는 매 클록 당 부동 소수점 연산이 가능한데 GF100 그래픽 카드의 경우 이러한 CUDA 코어를 512개 가지고 있다. 추가로 스트리밍 멀티 프로세서(SM)을 16개, SM 1개당 4개의 특수 기능 유닛(SFU)를 가지고 있어 범용 프로세서 대비 30배 이상 빠른 연산을 수행할 수 있다. 실제로 위드로봇에서는 CPU에서 동작하던 알고리즘을 GPU로 이식하는 과제를 수행하였는데 인텔 CPU 대비 38배 빠르게 수행할 수 있는 결과를 얻었었다.</p>
<div id="attachment_7018" class="wp-caption aligncenter" style="width: 418px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith003.jpg" rel="lightbox[6994]"><img class=" wp-image-7018 " alt="그림3. CUDA 코어의 내부 구조" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith003.jpg" width="408" height="485" /></a><p class="wp-caption-text">그림3. CUDA 코어의 내부 구조</p></div>
<p>문제는 내부 캐시 메모리가 한정적이어서 모든 이미지를 GPU가 접근 가능한 영역에 올릴 수 없다는 것이 단점이다. 따라서 메모리 억세스를 최소화하면서 해당 알고리즘을 구현할 수 있도록 변경해야 하는데 이 부분이 GPU 프로그램의 핵심이 된다.<br />
이와 같은 GPU 장점으로 임베디드 프로세서에 GPU를 이식하는 시도가 계속되고 있으며, 첫 번째 제품이 최근 스마트 폰에 도입되어 선전하고 있는 테그라 프로세서이다. 올해 시제품이 출시될 것으로 보이는 테그라3의 경우 쿼드 코어 프로세서 + 듀얼 GPU 기반으로 출시가 된다면 임베디드 비전 분야에서는 가장 화려한 스펙을 가진 디바이스가 될 것으로 예상된다.</p>
<div id="attachment_7017" class="wp-caption aligncenter" style="width: 568px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith002.jpg" rel="lightbox[6994]"><img class=" wp-image-7017 " alt="그림4. CUDA 코어의 내부 구조" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/08SCwith002-620x357.jpg" width="558" height="321" /></a><p class="wp-caption-text">그림4. CUDA 코어의 내부 구조</p></div>
<p><strong><span style="color: #008000">핵심은 무엇인가?</span></strong></p>
<p>앞서 소개한 내용 구성 요소 모두가 중요하긴 하다. 하지만 최근 프로세서의 패키징이 작아지고 AP(application processor) 공급이 대규모 설계 쪽으로 치중되는 현상이 심해지면서 아마추어들이 취미 삼아 하드웨어를 만들기에는 점점 어려워지고 있다. 이는 소규모 회사에게도 마찬가지여서 Davinci 시스템이건, FPGA 기반 시스템이건, Tegra3 GPU 기반의 시스템이건 프로젝트를 가동하기가 매우 부담스러워졌다. 이러다 보니 해당 프로세서를 조그마한 모듈로 만들고 이를 대량 생산하여 공급하는 업체들이 자리 잡을 시장이 형성되고 있다. 이 이야기는 임베디드 비전 시스템을 구성하는데 있어 하드웨어는 굳이 자체적으로 제작하지 않아도 시장에서 구할 수 있는 분위기가 조성되고 있다는 뜻이다.</p>
<p>반면 소프트웨어는 조금 사정이 다르다. 시중에 나와있는 상용 영상처리 라이브러리는 모두 PC 기반이며, 임베디드용은 거의 찾기가 어렵다. 그나마 컴퓨터 비전 연구자들이 모여 공개 소프트웨어로 진행한 OpenCV가 임베디드 비전 분야에서는 대안책처럼 여겨지고 있다.</p>
<p>주어진 환경에서 목적하는 작업을 수행하는 알고리즘은 매번 프로젝트마다 달라지고, 또한 프로젝트마다 주어진 환경이 달라지기에 기존에 사용했던 알고리즘을 그대로 사용할 가능성은 희박하다. 이러한 분위기에서는 환경에 알맞게 변화하는 카멜레온처럼 알고리즘을 주어진 환경 및 하드웨어에 최적화하는 기술을 핵심이 된다. 이를 위해서는 해당 알고리즘의 기본 원리에서부터 구현까지 온전히 다 알고 있어야 한다. 최근 스마트 폰 보급이 늘어나면서 스마트 폰에서 다양한 영상 처리를 하려는 시도가 늘어나고 있다. 이 역시 임베디드 비전 분야라고 볼 수 있는데, 이 분야의 개발자들과 이야기를 하다 보면 “나는 비전 전문가가 아니라서… 알고리즘에는 관심 없고 일단 함수 레벨에서 가져다 쓰면 되지”라는 이야기를 종종 듣곤 한다.</p>
<p>예를 들면 2D 바코드로 유명한 QR code는 최근 보급이 많이 되어 스마트 폰에서 다양한 어플리케이션들이 만들어 지고 있는데 그 수 많은 어플리케이션들이 단 2종류의 QR 코드 디코더를 쓰고 있다. 스마트 폰 어플리케이션 개발자가 수 만명이라면 이러한 임베디드 비전 알고리즘을 구현할 수 있는 개발자는 수 십명 수준이라는 것이다. 어느 쪽이 개발자로서 수명이 길고 대접을 받을 수 있을까?</p>
<p>항상 핵심은 단순하고 간단하다. 가장 밑바탕이 되는, 그리고 가장 어려워 보이는 것이 핵심이다. 그리고 그 핵심이 가장 오래 간다. 많은 개발자들이 개발자로서의 수명이 짧다고 한탄하는 것, 제대로 대접받지 못하는 것은 물론 시스템 구조적인 문제도 있겠지만 보다 쉽고 빨리 할 수 있는 방향으로 가다 보니 본질에 해당하는 핵심 부분을 건드리지 못해서는 아닐까 생각해 본다. 짧은 저자의 식견으로는 임베디드 비전 분야의 핵심은 ARM 프로세서를 잘 사용하는 것도, ARM 프로세서 하드웨어를 잘 설계하는 것도 아닌 비전 알고리즘을 얼마나 잘 이해하고 실제 구현할 수 있느냐라고 생각한다.</p>
<p>앞서 DSP, FPGA, GPU 등의 다양한 하드웨어를 소개했었다. 하지만 자신이 풀고자 하는 문제의 특성을 정확하게 파악하지 않으면 아무리 좋은 하드웨어를 사용한다고 해도 생각보다 빨라지지 않는 것을 경험할 수 있으며 꽤나 많은 시간을 들여도 개선되지 않는 것을 경험하게 될 것이다. 예를 들면 어떤 필터 알고리즘을 구현한다면, 부동 소수점 연산을 고정 소수점 연산으로 바꾸는 것만으로도 8배 이상 빨라지거나 심지어는 20배 이상 빨라지는 것을 경험할 수 있다.</p>
<p>이 때 고정 소수점 연산으로 변환하기 위해서는 알고리즘의 각 부분은 명확하게 이해해야지 오류 없이 변환이 가능하다. 또한 GPU의 경우 일반 프로세서에서 순차적으로 수행하는 형태로 작성된 알고리즘은 그다지 빨라지는 효과를 볼 수 없다. 알고리즘을 이해하여 병렬적인 부분을 만들어 내야지만 대폭적인 성능 개선을 볼 수 있다. 이러한 부분은 책이나 강의로 전달될 수 있는 부분이 아니라 많은 시간을 들여 노력을 해야 얻을 수 있는 노하우이다. 역설적으로 그러기에 누구나 할 수 있는 분야가 아니게 되고 그렇기에 더욱 값어치가 있다.<br />
임베디드 비전 시스템의 알고리즘을 공부하고 싶은 분은 다음 내용을 추천한다.</p>
<p>● OpenCV(http://sourceforge.net/projects/opencvlibrary/): 현존하는 가장 좋은 임베디드 비전 알고리즘을 학습하기에 좋은 소스이다. PC에서 동작하는 것을 기본으로 하고 있지만, cxcore 부분을 잘 이식하면 non-OS의 임베디드에서도 잘 동작한다. 단순히 영상 처리 함수들을 불러다 쓰는데만 만족하지 않고 해당 소스들을 하나씩 공부하다 보면 누구보다도 월등한 실력을 가진 임베디드 비전 개발자가 될 수 있다. 꽤 방대한 양이니 단숨에 끝날 것이라고는 기대하지 마시길.</p>
<p>● TI Fast Run-Time Support Library(http://focus.ti.com/docs/toolsw/folders/print/sprc060.html): 임베디드 비전 분야에서는 DSP쪽에 강세인 Texas Instruments 자료에 많이 의존하게 된다. FastRTS라고 알려진 수학 함수라이브러리는 일반 라이브러리에 비해 3배 이상 빠른 연산을 보장한다. 실제로 필자도 MARU 휴머노이드 프로젝트를 할 때 FastRTS의 도움을 많이 받았다. 부동 소수점 연산 수학 함수들이 DSP에 최적화되어 있는데 어떻게 하면 DSP에 최적화되는지 구조를 볼 수 있다. 폼페이지 접속하면 소스와 설명서를 내려 받을 수 있는데, 대부분의 TI 문서가 그렇듯이 무지막지한 양을 자랑한다.</p>
<p>● BLAS/LAPACK(http://www.netlib.org/lapack/): FOTRAN에서 시작한 수학 연산 라이브러리로 거의 대부분의 수학 연산 알고리즘을 확인할 수 있다.</p>
<p>● TI DSPLIB(http://focus.ti.com/docs/toolsw/folders/print/sprc265.html): TI DSP 하드웨어 플랫폼에 최적화된 라이브러리이다. ANSI-C 로 작성되어 있으니 꼭 TI가 아니더라도 한 번 살펴보면 다른 DSP쪽에 어떻게 활용할 것인지 알 수 있다.</p>
<p>● TI IMGLIB(http://focus.ti.com/docs/toolsw/folders/print/sprc264.html) : 2D 이미지 처리에 관련된 기본 함수가 TI DSP에 최적화되어 있다.</p>
<p>● IPP(http://software.intel.com/en-us/articles/intel-integrated-performance-primitives-intel-ipp-domain-library-migration-faq/): 인텔 프로세서에 최적화된 라이브러이다. OpenCV도 IPP의 전신인 IPL을 기반으로 작성되어 있다. 각종 이미지 연산에 관련된 최적화된 함수를 확인할 수 있다.</p>
<p><strong><span style="color: #008000">마감하며</span></strong><br />
위드로봇㈜ 연구소를 성수동으로 이전하는 기념으로 시작한 공개 강좌 내용을 디바이스마트 매거진에 글로 옮긴지 벌써 네 번째이자 마지막이 되었다. 볼품없는 글을 예쁘게 다듬어주신 디바이스마트 디자인 팀 및 신종헌 팀장님께 감사 드리며, 다시 기회가 주어진다면 좀 더 알찬 내용으로 다시 한 번 독자분들을 찾아 뵙겠다는 이야기로 마무리한다.</p>
<p>&nbsp;</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p><span style="text-decoration: underline"><strong>참고 문헌</strong></span></p>
[1] 진승훈, 전재욱, “Embedded Computer Vision 관련 연구 동향,“ 로봇학회지 제7권 제 1호, pp7-15<br />
[2] http://www.movesinstitute.org/~kolsch/pubs/EmbeddedCV.html<br />
[3] Mathias Kolsch, Branislav Kisacanin, “Embedded Computer Vision and Smart Cameras,” Tutorial Paper on Embedded Systems Conference(ESC), 2007</p>
<p><span style="font-size: 13px;line-height: 19px"></div></span></p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p><strong><span style="text-decoration: underline">그림 출처</span></strong></p>
<p>그림 1 Micron 홈페이지<br />
그림 2 TI 홈페이지<br />
그림 3, 4 nVidia 홈페이지</p>
<p><span style="font-size: 13px;line-height: 19px"></div></span></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/6994/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
