1. SSD1306 OLED Display소개 

 

SSD1306 OLED Display는 1인치 이하의 소형 Display장치로서 사용하는 방법이 간단하고 가격도 저렴하기 때문에 아두이노 환경에서 간단한 사항을 표시하는 용도로 인기가 많은 장치이다.  OLED 방식이므로 반응속도도 빠르고  백라이트가 필요없어 얇은 두께가 가능하고 명암비가 높아 선명하다는 장점이 있는데도 2~3000원 정도면 구입할 수 있을 정도로 저렴하기도 하다.  

 

 

2. 1.SSD1306 OLED Display 주요 사양 

 

  • 공급 전압 : 3.3V / 5V
  • 온도 범위 : -30 ℃ ~ 70 ℃
  • 해상도 : 128 x 64 또는 128 x 32 pixel이 많이 사용됨 
  • 시각 : 160 ° 이상
  • 캐릭터 색상 : 단색 (흰색,청색, 또는 노란색 등)  
  • 초 저전력 소비 :  0.06w
  • 통신 인터페이스 : IIC / SPI
  • 밝기와 명암비는 프로그램 명령으로 제어 가능
  • 드라이버 IC : SSD1306

 

3. 아두이노와의 연결 

 

연결단자가 I2C연결방식인 경우 다음과 같이 연결하면 된다. 

 

VCC -> 5V, GND->GND 단자를 연결하고 SCL단자는 아두이노 Analog 5번에, SDA 단자는 A4핀에 연결하면 된다   

 

4. 라이브러리 설치 

 

SSD1306 장치를 지원하기 위한 라이브러리는 여러 종류가 있으나  Adafruit_SSD1306 라이브러리를 많이 사용한다. 

 

아두이노 IDE 라이브러리 메니저에서 SSD1306f를 검색하여 설치해 준다. 

컴파일을 하게 되면 이에 관련된 또다른 라이브러리를 찾을 수 없다는 에러 메세지가 나오는 경우가 있는데 에러 메세지에 따라  Adafruit_GFX 또는 Adafruit_busIO 라이브러리를 추가로 설치해 주어야 하는 경우도 있다. 

 

 

5. 샘플프로그램 

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000);
  display.clearDisplay();

  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 10);
  // Display static text
  display.println("Hello, world!");
  display.display(); 
}

void loop() {
  
}

9 line에서 정의한 display장치를 14 line에서 시작한다. 

19 ~26 Line : display장치를 초기화한 후 Text Size와 위치를 지정한 후 println 명령으로 출력하고 하면 된다.  

 

만약 display가 표시되지 않을 경우 14 LIne의 주소를 0x3D로 수정하여 테스트해 본다.  

 

단순한 문자열 출력이외의 다양한 그래픽 처리 예제는 예제 -> Adafruit SSD1306메뉴에서 찾아볼 수 있다 

 

6. 구매좌표 

 

 

2056.0₩ 17% OFF|NEW 0.96 Inch IIC Serial White/Blue/Yellow OLED Display Module 128X64 I2C SSD1306 12864 LCD Screen Board for

Smarter Shopping, Better Living! Aliexpress.com

www.aliexpress.com

 

 

1359.0₩ 13% OFF|Blue/White OLED LCD Display 0.91 Inch 128x32 IIC I2C Serial DIY Module SSD1306 Driver IC 0.91

Smarter Shopping, Better Living! Aliexpress.com

www.aliexpress.com

 

 

1. 미디어파이프(Mediapipe)를 활용한 AI Web페이지 개발하기

 

미디어파이프는 사용하기 편하게 라이브러리 형태로 모듈화되어 제공되는데 지원가능한 환경이나 언어가 매우 다양해 Andoid, iOS, C++, Python, JavaScript, Coral 등이 지원된다. 이중에서 JavaScript언어 지원기능을 사용하면 미디어파이프 AI기능이 포함된 Web 페이지를 손쉽게 개발할 수 있다. 

 

미디어파이프에서 JavaScript 방식으로 제공하는 모듈들은 다음과 같다. 

Solution NPM Package Example
Face Mesh @mediapipe/face_mesh mediapipe.dev/demo/face_mesh
Face Detection @mediapipe/face_detection mediapipe.dev/demo/face_detection
Hands @mediapipe/hands mediapipe.dev/demo/hands
Holistic @mediapipe/holistic mediapipe.dev/demo/holistic
Objectron @mediapipe/objectron mediapipe.dev/demo/objectron
Pose @mediapipe/pose mediapipe.dev/demo/pose
Selfie Segmentation @mediapipe/selfie_segmentation mediapipe.dev/demo/selfie_segmentation

 이외에 다음과 같은 추가 모듈이 제공된다. 

 

2.설치 

 

위의 모듈들은 NPM 패키지형태로 제공되는데 이를 자체 웹서버에 설치하려면 npm install명령으로 가능하다. 즉 손모양인식을 위한 hands모듈은 "npm install @mediapipe/hands."라는 명령어로 설치하면 된다. 그러나 웹서버가 인터넷환경에서 운영될 것이라면 굳이 자체 서버에 설치할 필요도 없이 구글에서 제공하는 사이트를 링크걸어 사용하면 된다. 

<head>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils@0.1/drawing_utils.js" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/holistic@0.1/holistic.js" crossorigin="anonymous"></script>
</head>

 

 

3.샘플 웹페이지 

 

-HTML 코드 

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/control_utils/control_utils.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/drawing_utils/drawing_utils.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/@mediapipe/hands/hands.js" crossorigin="anonymous"></script>
</head>

<body>
  <div class="container">
    <video class="input_video"></video>
    <canvas class="output_canvas" width="1280px" height="720px"></canvas>
  </div>
</body>
</html>

5~8 line : 세가지 유티리티 모듈과 손동작 인식 AI 모델기능인 hands.js를 링크하는 것 만으로 필요한 미디어파이프 기능을 모두 사용할 수 있다  

 

-CSS 

body {
  bottom: 0;
  font-family: 'Titillium Web', sans-serif;
  color: white;
  left: 0;
  margin: 0;
  position: absolute;
  right: 0;
  top: 0;
  transform-origin: 0px 0px;
  overflow: hidden;
}

.container {
  position: absolute;
  background-color: #596e73;
  width: 100%;
  max-height: 100%;
}

.input_video {
  display: none;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  &.selfie {
    transform: scale(-1, 1);
  }
}


.output_canvas {
  max-width: 100%;
  display: block;
  position: relative;
  left: 0;
  top: 0;
}

 

-JavaScript

<script type="module">
const videoElement = document.getElementsByClassName('input_video')[0];
const canvasElement = document.getElementsByClassName('output_canvas')[0];
const canvasCtx = canvasElement.getContext('2d');

function onResults(results) {
  canvasCtx.save();
  canvasCtx.clearRect(0, 0, canvasElement.width, canvasElement.height);
  canvasCtx.drawImage(
      results.image, 0, 0, canvasElement.width, canvasElement.height);
  if (results.multiHandLandmarks) {
    for (const landmarks of results.multiHandLandmarks) {
      drawConnectors(canvasCtx, landmarks, HAND_CONNECTIONS,
                     {color: '#00FF00', lineWidth: 5});
      drawLandmarks(canvasCtx, landmarks, {color: '#FF0000', lineWidth: 2});
    }
  }
  canvasCtx.restore();
}

const hands = new Hands({locateFile: (file) => {
  return `https://cdn.jsdelivr.net/npm/@mediapipe/hands/${file}`;
}});
hands.setOptions({
  maxNumHands: 2,
  minDetectionConfidence: 0.5,
  minTrackingConfidence: 0.5
});
hands.onResults(onResults);

const camera = new Camera(videoElement, {
  onFrame: async () => {
    await hands.send({image: videoElement});
  },
  width: 1280,
  height: 720
});
camera.start();
</script>

24~28 Line :  손동작 인식 AI모델을 실행할 때 option으로  인식할 최대 손모양 갯수, 최소 신뢰도 값을 지정한다. 

6 ~ 19 Line : 손동작 인식 AI모델 실행결과에 따른 처리 

12 ~ 16 Line : 인식된 손가락 Landmark 좌표를 이용하여 원하는 기능의 동작을 프로그램할 수 있다. 

9~10 Line의 촬영이미지 Display 부분을 삭제하면 다음과 같이 인식된 손가락 모양만 표시된다. 

 

4.  테스트 사이트 

 

다음 링크에 접속하면 Codepen 기능을 이용하여 구글에서 제공하는 데모 프로그램을 동작시켜 볼 수 있고, 여기에서 내용을 수정해 가면서 작동되는 내용을 즉석에서 테스트 확인해 볼 수도  있다.  

 

 

 

MediaPipe - Hands

...

codepen.io

 

1. 미디어파이프(Mediapipe)를 활용한 AI기능 개발  

 

미디어파이프는 구글에서 주로 인체를 대상으로하는 비전인식기능들을  AI모델 개발과 기계학습까지 마친 상태로 제공하는 서비스이다. 다양한 프로그램언어에서 사용하기 편하게 라이브러리 형태로 모듈화되어 제공되며 사용방법 또한 풍부하게 제공되기 때문에 몇가지 간단한 단계로 미디어파이프에서 제공하는 AI기능을 활용한 응용 프로그램개발이 가능하다. 여기에서는 Python언어로 손가락 동작을 인식하는 AI프로그램을 개발하는 과정에 대해 정리한다. 

 

2. 미디어파이프 설치 

 

Python 개발환경이 설치되어 있다면 단순히 mediapipe 모듈을 설치하기만 하면 된다. 즉, "pip install mediapipe" 명령을 입력하여 설치하기만 하면  Python프로그램에서 "import mediapipe"문장으로 호출하여 Mediapipe 기능을  전부 사용할 수 있다. 물론 부가적인 영상처리 등을 위해서는 OpenCV나 numPy 등의 모듈 정도는 기본적으로 설치되어 있어야 한다.  

단 Jetson Nano나  라즈베리파이 등 aarch64 Linux systems기종에 대해서는 아직 pip insall이 지원되지 않고 다음 안내에 따라 설치해 주어야 한다.

 

 

GitHub - jiuqiant/mediapipe_python_aarch64

Contribute to jiuqiant/mediapipe_python_aarch64 development by creating an account on GitHub.

github.com

 

3. 미디어파이프 기본 가이드 

 

설치 후 미디어파이프의 기능별 사용 안내는 다음 링크에서 확인할 수 있다.  

 

그리고 각자의 컴퓨터에 미디어파이프 모듈을 직접 설치하여 개발하기 전에 구글 Colab환경으로 접속하여 코드를 돌려가며 테스트할 수 있는 환경도 제공된다. 

MediaPipe on Google Colab

 

4. 샘플 python 프로그램 

 

Python에서 Hands 인식기능을 이용하여 손가락 동작을 인식하는 샘플 프로그램인데 몇줄 되지 않는다. 이중에서도 실제 AI 모델을 가동시켜 손모양을 인식하는 작업은  20번째 line의 results = hands.process(image) 하나의 명령으로 실행되는 것이다.   

import cv2
import mediapipe as mp

mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands

cap = cv2.VideoCapture(0)

with mp_hands.Hands(
    max_num_hands=1,
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5) as hands:

    while cap.isOpened():
        success, image = cap.read()
        if not success:
            continue
        image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)

        results = hands.process(image)

        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

        if results.multi_hand_landmarks:
            for hand_landmarks in results.multi_hand_landmarks:
                finger1 = int(hand_landmarks.landmark[4].x * 100 )
                finger2 = int(hand_landmarks.landmark[8].x * 100 )
                dist = abs(finger1 - finger2)
                cv2.putText(
                    image, text='f1=%d f2=%d dist=%d ' % (finger1,finger2,dist), org=(10, 30),
                    fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=1,
                    color=255, thickness=3)

                mp_drawing.draw_landmarks(
                    image, hand_landmarks, mp_hands.HAND_CONNECTIONS)

        cv2.imshow('image', image)
        if cv2.waitKey(1) == ord('q'):
            break

cap.release()

 

2~5  Line : mediapipe 모듈을 import하고 약식으로 사용할 명칭을 지정한다. mediapipe.solutions.hands모듈이 손동작인식을 위한 모듈이다. 

7 Line : OpenCV로 웹캠을 읽어 입력데이터 소스로 지정한다. 

 

9~12 Line :  hands 손가락 인식모듈의  작동 option을 지정한다. 

    -max_num_hands=1,   : 인식할 손모양의 갯수, 생략하면 2가 지정된다. 

    -min_detection_confidence=0.5,  : 성공적인 것으로 간주되는 최소 신뢰도 값. 0.0 ~1.0사이로서 기본값은 0.5이다.

    -min_tracking_confidence=0.5 :손 랜드마크가 성공적으로 추적된 것으로 간주되는 최소 신뢰도 값. 0.0 ~1.0 사이로서 기본값은 0.5이다. 이 값을 높이면 시간이 더 소요되지만 좀 더 정확한 작동이 보장된다. 

 

18 Line :  OpenCV 영상은 BGR 형식인데 MediaPipe에서는 RGB 형식을 사용하므로 영상형식을 변환해 준다 

 

20 Line : MediaPipe의 hands 모듈을 이용해서 손동작을 인식한다. 이 한줄로서 손동작 인식 AI모델이 작동되고 결과 값이 result로 저장된다. 

 

22 Line :  MediaPipe용 RGB 형식으로 변환했던 것을 OpenCV 영상저리를위해 다시 BGR형식으로 되돌린다. 

 

24~25 : result값이 정상인 경우에만 후속 작업 처리한다. 

 

26~27 : result로 반환된 landmark 데이터를 사용한다. 

 

인식된 손가락 모양은 다음과 같은 index값으로 가지는 배열로 제공된다.

즉, 업지손가락 끝은 landmark[4]에, 검지 손가락 끝은 landmark[8]에 좌표값이 반환되는데, 좌표값은 image상의 x,y위치값을 0.0~1.0 사이의 값으로 표시한다. 즉 image 좌측 최상단은 x=0.0 y=0.0  우측최하단은 x=1.0, y=1.0이 된다. 따라서int(hand_landmarks.landmark[4].x * 100)은 엄지손가락 끝의 x좌표를 100분율로 표시한 것이 된다. 

 

28 Line : 두 손가락 끝의 x좌표값 차이의 절대값을 구해 두 손가락 끝이 벌어진 정도를 계산한다. 

 

34 ~ 35 Line : MediaPipe에 내장된 유틸리티 기능을 이용해서 구해진 손가락 모양을 서로 연결한 그림을 그려준다.

 

위와 같이 손가락 모양을 인식하고 좌표값을 구해낼 수 있고 이를 이용하여 다양한 기능을 개발할 수 있다. 예를 들어 샘플프로그램에서 처럼 두 손가락 끝이 벌어진 정도값을 구해 스피커 볼륨을 조정하는 기기를 개발할 수 있고 가위바위보 게임을 개발할 수도 있다.  또는 연속되는 손동작 변화를 저장해서 animation용 데이터로 활용할 수 도 있을 것이다. 

+ Recent posts