안경잡이개발자

728x90
반응형

  최근 Teensy Board는 개발 과정에 있어서 아두이노(Arduino) IDE를 사용합니다. 이처럼 아두이노 기반의 Teensy 개발 환경을 Teensyduino라고 합니다. Teensy를 이용하면 Raw HID 데이터 송수신과 같은 같은 기능을 손쉽게 이용할 수 있습니다. 만약 Teensyduino가 설치되어 있지 않다면 다음의 경로를 통해서 설치할 수 있습니다.

 

  ▶ Teensy 프로젝트 시작: https://ndb796.tistory.com/353

 

Teensy 프로젝트 시작하기

Teensy는 Teensyduino를 이용하여, 아두이노 IDE 상에서 프로그램을 작성할 수 있도록 지원하고 있습니다. 기본적으로 HalfKay 부트로더(Bootloader)가 동작하고 있을 때, Teensy Loader 프로그램이 Teensy Board..

ndb796.tistory.com

 

  기본적인 Raw HID 소스코드는 [예제] - [Teensy] - [USB Raw HID] - [Basic]으로 가면 됩니다.

 

 

  그러면 다음과 같은 기본적인 소스코드가 나옵니다. USB Type을 [Raw HID]로 설정한 뒤에, 컴파일을 진행하고 업로드(Upload)를 수행하면 됩니다.

 

 

  업로드를 진행하고, 시리얼 모니터(Serial Monitor)를 실행하면 다음과 같이 호스트(Host) PC로 데이터를 보내는 것을 확인할 수 있습니다.

 

 

  그러면 이제 호스트(Host) PC에서도 적절한 프로그램을 실행하여, USB와 통신할 수 있어야 합니다. 현재 예제는 기본적인 Raw HID 예제이며, Teensy 공식 홈페이지에서 Host PC 전용 프로그램도 제공하고 있습니다. 다음의 경로에서 다운로드를 받을 수 있습니다.

 

  ▶ Teensy 공식 홈페이지: https://www.pjrc.com/teensy/rawhid.html

 

 

  결과적으로 Teensy를 연결한 상태에서 Raw HID Host 전용 프로그램을 실행하면 다음과 같이 데이터를 받아오는 것을 알 수 있습니다.

 

 

  또한 Host PC 쪽에서도 입력을 수행하면 그 데이터가 Teensy Device 쪽으로도 전송되는 것을 확인할 수 있습니다. 이처럼 Host PC와 데이터를 주고 받으면서, 원하는 데이터가 왔을 때 특정한 작업을 수행하는 등의 처리가 가능합니다.

 

 

  Teensy를 더 자유롭게 이용하기 위해서 SD 카드(Card) 예제와 합쳐서 사용해보는 등의 기능도 구현을 해보면 좋을 것 같네요. 이후 게시글에서 다루어 보겠습니다.

728x90
반응형

728x90
반응형

  최근에 데이터셋을 직접 구축하여, 내가 만든 데이터셋으로 학습(Training)을 해야 하는 일이 생겼다.

 

  PyTorch에서는 ImageFolder라는 라이브러리를 제공한다. 이는 다음과 같은 계층적인 폴더 구조를 가지고 있는 데이터셋을 불러올 때 사용할 수 있다. 다시 말해 다음과 같이 각 이미지들이 자신의 레이블(Label) 이름으로 된 폴더 안에 들어가 있는 구조라면, ImageFolder 라이브러리를 이용하여 이를 바로 불러와 객체로 만들면 된다.

 

dataset/
	0/
		0.jpg
		1.jpg
        	...
	1/
		0.jpg
		1.jpg
		...
	...
	9/
		0.jpg
		1.jpg
		...

 

  한 번 연습을 위해서 기존에 존재하는 CIFAR-10 데이터셋을 불러와서, 이를 계층적인 폴더 구조가 되도록 이미지를 저장하는 소스코드를 만들어 보자. 그 다음에 다시 ImageFolder 라이브러리로 동일한 CIFAR-10 데이터셋을 불러오면 성공이다.

 

  먼저 다음과 같이 기본적으로 PyTorch에서 제공하고 있는 CIFAR-10 데이터셋을 불러와보자.

 

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import matplotlib.image as image
import numpy as np

transform_train = transforms.Compose([
    transforms.ToTensor(),
])

train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=4)

 

  CIFAR-10의 경우 10개의 레이블로 구성된 데이터셋이므로, 각 레이블의 이미지가 몇 번 등장했는지를 기록해주는 변수를 선언하자.

 

import os

num_classes = 10
number_per_class = {}

for i in range(num_classes):
    number_per_class[i] = 0

 

  이후에 이미지 Torch 객체레이블 정수 값이 들어왔을 때, 이를 실제 폴더에 저장해주는 함수를 작성하자.

 

def custom_imsave(img, label):
    path = 'dataset/' + str(label) + '/'
    if not os.path.exists(path):
        os.makedirs(path)
    
    img = img.numpy()
    img = np.transpose(img, (1, 2, 0))
    image.imsave(path + str(number_per_class[label]) + '.jpg', img)
    number_per_class[label] += 1

 

  이제 만들어진 도구들을 이용하여 CIFAR-10 데이터셋에서 데이터를 배치 단위로 읽으며, 배치에 포함된 각 이미지를 하나씩 정확한 폴더에 저장될 수 있도록 하자.

 

def process():
    for batch_idx, (inputs, targets) in enumerate(train_loader):
        print("[ Current Batch Index: " + str(batch_idx) + " ]")
        for i in range(inputs.size(0)):
            custom_imsave(inputs[i], targets[i].item())

process()

 

  이후에 한 번 0번 레이블(비행기)의 첫 번째 이미지를 출력하도록 해보자. 정상적으로 잘 출력된다.

 

from PIL import Image
from matplotlib.pyplot import imshow

img = Image.open('dataset/0/0.jpg')
imshow(np.asarray(img))

 

 

  이제 ImageFolder 라이브러리를 이용해서, 우리가 저장한 이미지들을 이용해 다시 PyTorch 데이터셋 객체로 불러올 수 있는지 확인해보도록 하자.

 

from torchvision.datasets import ImageFolder

train_dataset = ImageFolder(root='./dataset', transform=transform_train)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=4)

 

  이미지 출력용 함수는 다음과 같다. PyTorch의 경우 [Batch Size, Channel, Width, Height]의 구조를 가지고 있어서, 이를 matplotlib로 출력하기 위해서는 [Width, Height, Channel]의 순서로 변경해주어야 한다.

 

def custom_imshow(img):
    img = img.numpy()
    plt.imshow(np.transpose(img, (1, 2, 0)))
    plt.show()

 

  이제 이미지를 하나씩 출력하도록 해보자.

 

def process():
    for batch_idx, (inputs, targets) in enumerate(train_loader):
        custom_imshow(inputs[0])

process()

 

  실행 결과, 다음과 같이 정상적으로 데이터셋이 구성되었다는 사실을 알 수 있다.

 

728x90
반응형

728x90
반응형

  실험을 하면서 자주 쓰는 코드인데, 따로 정리를 해놓지 않아서 매 번 입력을 하고 있다. 그래서 정리하려고 한다. 일단 Dataset 객체를 불러올 때는 데이터를 전처리하는 부분이 들어간다. PyTorch의 경우 ToTenser() 함수를 불러오면, 이미지가 자동으로 [0, 1]의 값으로 변경된다. 예를 들어 CIFAR-10 학습용 데이터셋을 불러오는 코드는 다음과 같다.

 

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np

transform_train = transforms.Compose([
    transforms.ToTensor(),
])

train_dataset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=128, shuffle=True, num_workers=4)

 

  이렇게 불러온 이미지는 실제로 Tensor 객체로 존재하며, 각 원소의 값이 0부터 1 사이의 값이다. 그렇기 때문에 이를 화면에 출력하고자 한다면, 이 값을 다시 0부터 255 사이의 값으로 늘려야 하는 건지 궁금할 수 있다. 다행히도 파이썬의 matplotlib는 기본적으로 0부터 1사이의 값이라고 해도 알아서 인식하여 정상적인 이미지로 출력해준다. 하지만 별도로 OpenCV 등에서 활용하고자 한다면, 추가적인 전처리가 필요할 수 있다.

 

  또한 기본적으로 PyTorch는 이미지 데이터셋을 [Batch Size, Channel, Width, Height] 순서대로 저장하기 때문에, 이를 matplotlib로 출력하기 위해서는 각 이미지를 [Width, Height, Channel] 형태로 변경해 줄 필요가 있다. 그것은 numpy 라이브러리의 transpose() 함수를 이용하여 해결할 수 있다.

 

def custom_imshow(img):
    img = img.numpy()
    plt.imshow(np.transpose(img, (1, 2, 0)))
    plt.show()

 

  그럼 이제 이렇게 정의된 imshow() 함수를 이용하여 데이터셋의 이미지를 배치당 하나씩 출력해보자.

 

def process():
    for batch_idx, (inputs, targets) in enumerate(train_loader):
        custom_imshow(inputs[0])

process()

 

  실행 결과는 다음과 같다.

 

728x90
반응형

728x90
반응형

※ UEFI와 BIOS ※

 

  UEFI통합 확장 펌웨어 인터페이스(Unified Extensible Firmware Interface)의 줄임말입니다. UEFI를 이해하기 전에, 먼저 BIOS에 대해서 이해해야 합니다. BIOS란 기본 입출력 시스템 (Basic Input Output System)의 약자로, 일반적인 컴퓨터의 메인보드에 탑재되어 있는 펌웨어 소프트웨어입니다.

  ① 하드웨어② BIOS③ 부트 로더④ 운영체제(OS)⑤ 어플리케이션(App)

  일반적인 컴퓨터는 바로 위와 같이 계층적인 구조로 동작합니다.

 

  가장 먼저 우리가 컴퓨터의 전원을 눌러 전원을 공급하면, BIOS가 실행되어 컴퓨터의 하드웨어가 정상적인지 진단합니다. 이러한 하드웨어 검사를 흔히 POST(Power On Self Test)라고도 부릅니다. 흔히 컴퓨터를 조립할 때 메인 메모리(RAM) 없이 부팅을 하려고 하면 경고음이 몇 번 울리는 것 등이 그 예시입니다.

  이후에 부트 매니저(Boot Manager)가 실행됩니다. 흔히 컴퓨터 시작 직후에 [F2]를 연타하여 BIOS에 진입한 이후에 부트 디바이스를 설정할 수 있는데, 이러한 작업을 지원하는 것이 부트 매니저입니다. 이어서 선택한 부트 디바이스의 부트 로더가 실행됩니다. 여기에서 부트 로더(Boot Loader)란, 운영체제가 구동되기 이전에 미리 실행되어 운영체제가 올바르게 동작하기 위해 필요한 작업을 수행하는 소프트웨어를 말합니다. 예를 들어 윈도우(Windows) OS가 설치된 컴퓨터의 경우에는 윈도우가 1순위로 설정되어 실행되는 것을 떠올리시면 됩니다.

 

  UEFIBIOS를 대체하기 위해 등장한 시스템입니다. UEFI를 이용하는 경우 보안 부팅(Secure Booting)이 가능하며, BIOS에 비해서 더욱 큰 디스크 용량을 지원하고, 더욱 고급스러운 GUI를 제공하는 경우가 많습니다. 그래서 최근에 출시되는 컴퓨터 메인보드에는 기본적으로 UEFI가 탑재되어 출시되고 있습니다. 사용자 입장에서도 손쉽게 하드웨어를 조작할 수 있도록 해줍니다.

 

  사실 UEFI 자체는 명세서(Specification)입니다. 따라서 UEFI 규격에 맞게 개발된 펌웨어는 다양하게 존재할 수 있습니다. Tiano는 UEFI 규격을 따르는 최초의 오픈 소스 프로젝트인데, 이러한 Tiano에서 실질적으로 UEFI 구현체로 내보인 것이 바로 EDK입니다. 최근에는 EDK II 버전이 사용되고 있습니다. 즉 EDK II는 크로스 플랫폼을 지원하는 펌웨어 개발 환경(Firmware Development Environment)입니다. 기본적으로 UEFI 명세를 잘 따르고 있습니다.

 

  UEFI는 영문 위키(Wiki)에서도 잘 소개되고 있습니다.

 

  https://en.wikipedia.org/wiki/Unified_Extensible_Firmware_Interface

 

※ UEFI의 부팅 과정(Boot Flow) ※

 

  UEFI의 Boot Flow에 대해서 소개하고 있는 Tianocore 튜토리얼 페이지의 문서는 다음과 같습니다.

 

  https://github.com/tianocore/tianocore.github.io/wiki/PI-Boot-Flow

 

  UEFI의 부팅 과정은 크게 7단계로 구성됩니다.

728x90
반응형

728x90
반응형

※ VirtualBox 설치 ※

 

  개발 혹은 실습을 할 때, 윈도우(Windows) 10 운영체제의 컴퓨터에 리눅스 운영체제의 가상 환경을 갖추어야 하는 경우가 종종 있다. 이번 포스팅에서는 오라클(Oracle)에서 무료로 제공하는 소프트웨어인 VirtualBox를 이용하여 리눅스 가상 환경을 갖추어 보도록 하겠다.

 

  ▶ VirtualBox 웹 사이트: https://www.virtualbox.org/

 

  바로 다운로드 버튼을 눌러서 다운로드를 진행하자.

 

 

  저자의 경우 호스트(Host) 운영체제가 윈도우(Windows)라서, 다음과 같이 [Windows hosts] 링크를 클릭하였다.

 

 

  이제 VirtualBox 설치 프로그램을 실행하여, 설치를 진행하면 된다. 기본적인 설정 그대로 설치하는 것을 권장한다.

 

 

  다음과 같이 [Next]를 눌러 설치를 진행한다.

 

 

 

  기본적으로 가상 머신(Virtual Machine)을 설치하는 경우, 네트워크 인터페이스 또한 설정하는 경우가 많기 때문에 설치 과정 중에서 일시적으로 인터넷 연결이 끊길 수 있다.

 

 

  이제 [Install] 버튼을 눌러서 설치를 진행한다.

 

 

  설치 자체는 몇 분 이내로 적은 시간이 소요된다.

 

 

  설치가 완료된 이후에는 Oracle VirtualBox를 실행할 수 있도록 한다.

 

 

  실행된 VirtualBox의 형태는 다음과 같다.

 

 

※ 리눅스 설치 ※

 

  이제 리눅스를 설치해보자.

 

  ▶ 우분투 이미지 파일(ISO) 웹 사이트: http://releases.ubuntu.com/16.04/

 

 

  [새로 만들기(N)] 버튼을 클릭하여 새롭게 가상 머신을 생성한다.

 

 

  자신의 가상 머신에 이름을 붙이자. 아무렇게나 붙여도 된다.

 

 

  이제 메모리를 할당해야 한다. 저는 제 호스트 PC에 16GB의 메모리가 있기 때문에 2GB만큼 가상 머신에 할당하도록 하였다. 너무 과도하게 많은 메모리를 할당하는 경우, 설치 도중에 가상 머신이 갑자기 종료되거나 기타 다른 문제가 발생할 수 있다.

 

 

  이어서 가상 머신에서 사용할 데이터 저장 목적의 하드 디스크를 추가할 수 있다. 일반적으로 새로운 가상 하드 디스크를 만들어 사용한다. 당연히 컴퓨터에 남은 하드 디스크 용량이 많아야 문제가 없을 것이다.

 

 

  기본적인 하드 디스크 파일 종류인 VDI (VirtualBox Disk Image)를 선택하여 만들어 주자.

 

 

  저자의 경우 SSD의 용량이 많이 남아 있었기 때문에, 고정 크기로 가상 하드 디스크를 만들었다.

 

 

  일단 기본 설정 그대로 10GB로 설정하여 만들어주자.

 

 

  이제 하나의 가상 머신이 만들어 졌으므로, [설정(S)] 탭으로 이동하여 우분투 이미지를 적용해주자.

 

 

  [저장소]에서 광학 드라이브(D)로 아까 전에 다운로드 받았던 우분투 ISO 파일을 선택해주면 된다.

 

 

  다음과 같이 정상적으로 선택되었다.

 

 

  이제 [시작]을 누르면, 우분투 ISO 파일을 이용하여 우분투로 부팅이 진행된다.

 

 

  당연히 현재 가상 머신의 하드 디스크에는 실제로 우분투가 설치가 되어 있는 것은 아니므로, ISO 파일을 이용하여 이제 실제 우분투를 하드 디스크에 설치하면 된다. 따라서 [Install Ubuntu] 버튼을 클릭하여 우분투를 설치해준다.

 

 

  또한 우분투 설치 과정에서 자동으로 Update 파일 다운로드를 진행할 것인지 물어보는데, 어차피 나중에 대부분 설치해도 괜찮기 때문에 바로 [Continue]를 눌러서 설치를 진행해도 괜찮다.

 

 

  또한 우분투 OS를 설치할 떄는 기본적으로 디스크를 비운 뒤에 우분투 OS가 설치된다. 다만 여기에서 말하는 디스크란 가상 머신의 디스크 이므로, 그냥 [Install Now]를 눌러서 설치를 진행하면 된다.

 

 

  이후에 디스크 파티션 관련 내용이 나오는데 그냥 [Continue]를 눌러서 진행할 수 있다.

 

 

  이후에 기본적인 날짜 설정을 위해 위치를 물어본다. 서울(Seoul)을 선택하도록 하자.

 

 

  이후에 기본적인 언어(Language), 그리고 우분투 OS에서 사용할 관리자 계정의 비밀번호를 설정한 뒤에 설치를 진행하면 다음과 같은 화면이 나오면서 설치됩니다.

 

 

  설치가 완료되고 나면 재시작 메시지가 나오는데, 재시작이 된 이후에는 다음과 같이 우분투가 정상적으로 실행된다.

 

 

  우분투가 실행이 되면, 관리자 계정(root)으로 로그인을 해준다.

 

 

  성공적으로 우분투가 실행된 모습이다.

 

 

※ 흔히 발생하는 문제 1: 해상도 ※

 

  VirtualBox를 실행한 경우, 해상도가 굉장히 낮은 상태로 유지되는 경우가 있다. 이럴 때는 [장치] - [게스트 확장 CD 이미지 삽입]을 클릭한다. 이후에 소프트웨어를 설치하자. 이 과정에서 루트 계정으로 로그인을 요구할 수 있다.

 

 

  설치가 완료된 이후에는 재부팅을 해주자.

 

 

  이제 창의 크기에 맞게 VirtualBox의 해상도가 자동으로 조절되는 것을 확인할 수 있다.

 

 

※ 흔히 발생하는 문제 2: 클립보드 (복사, 붙여넣기) ※

 

  VirtualBox의 가상 머신은 기본적으로 호스트 OS와 클립보드를 공유하지 않는다. 즉, 호스트 OS에서 복사된 텍스트를 게스트 OS에 붙여넣을 수 없다. 이를 위해서는 추가적인 [설정]이 필요하다.

 

 

  이후에 다음과 같이 [일반] - [클립보드 공유(S)] 부분의 값을 "양방향"으로 해준다.

 

 

  이후에 다시 가상 머신을 부팅하면, 호스트 OS에서 복사된 텍스트를 Ubuntu OS에서 [Ctrl + Shift + V]을 통하여 붙여넣기 할 수 있다. 하지만, 이렇게 해도 붙여넣기가 안 될 수도 있다. 그럴 때는 가상 머신을 삭제하고, 다시 생성하여 [클립보드 공유] 기능을 먼저 활성화 한 뒤에, 그 이후에 [게스트 확장 CD 이미지 삽입]을 해주면 해결 될 수도 있다.

 

기본적으로 설치할 소프트웨어들

 

  일반적으로 깃(Git)과 같은 유틸리티는 많이 사용되기 때문에 미리 설치하는 것이 좋다. 이 때 우분투에서 매 번 sudo 명령을 입력하기 귀찮으면, sudo -s를 입력하여 root 계정의 권한으로 접속하도록 하자.

 

  sudo apt install git

 

※ 기타 사항 

 

  또한 터미널(Terminal) 상에서 현재 폴더를 GUI로 열고 싶다면, 노틸러스(Nautilus) 명령을 이용하면 된다. 다음의 명령을 입력하여 GUI 화면으로 폴더를 열 수 있다.

 

  nautilus .

728x90
반응형

728x90
반응형

  특정 분야의 개발을 진행하다 보면, 이전 버전의 Visual Studio가 필요할 때가 있다. 예를 들자면, 저자의 경우 펌웨어 개발 과정에서 Visual Studio 2015 with Update 3 버전에서의 개발 환경과 C 컴파일러가 필요했다.

 

  하지만, 2020년 현재를 기준으로 Visual Studio 2017 이전 버전을 설치하는 것은 귀찮은 과정이며, 권장되지도 않는다. 그래서 가능하다면, 최신 버전의 Visual Studio를 이용하는 것이 좋다. 그래도 저자와 같이 어쩔 수 없이 이전 버전을 설치해야 하는 경우에는 다음의 과정을 따르도록 하자.

 

  ▶ Visual Studio 다운로드: https://my.visualstudio.com/Downloads

 

  위 사이트에 접속하면, 아래와 같이 모든 제품군을 검색하여 설치할 수 있다. Visual Studio Community 2015를 검색한 뒤에 원하는 업데이트 버전을 골라 설치할 수 있다.

 

 

  설치 프로그램 자체도 옛날 버전의 프로그램이다. 더불어 설치 시간이 매우 오래 걸리는 편이다. 저자의 경우 전체적으로 30분 가량의 시간이 소요되었다. 맨 처음에는 환경 설정(Configuration)만으로도 몇 분의 시간이 소요된다.

 

 

  이후에 Visual Studio를 설치할 경로를 설정할 수 있다. 저자는 기본 설정(Default)으로 설치를 진행했다.

 

 

  다음과 같이 필요한 패키지들이 설치되는 것을 확인할 수 있다.  

 

 

  설치가 완료되면 [LAUNCH] 버튼을 눌러서 Visual Studio를 실행할 수 있다.

 

 

  결과적으로 다음과 같이 Visual Studio가 실행되는 것을 알 수 있다.

 

 

  [New Project]에서 [Visual C++]로 하나의 프로젝트를 만들어 볼 수 있다. 기본적으로 C++ 개발 도구(Tools)가 설치되어 있지 않다면, C++ 개발 도구를 설치하라는 화면이 나온다.

 

 

  C++ 개발 도구가 설치된 이후에 [Empty Project]로 새로운 프로젝트를 생성할 수 있다.

 

 

  하나의 C언어 소스코드 파일을 작성한 뒤에 실행해보았더니, 잘 동작하였다.

 

 

728x90
반응형