Electron을 이용한 Annotation tool 개발기

목차

  1. 배경
  2. Electron 사용 배경
  3. 개발화면 구성 및 기능
  4. 시행착오
  5. 개발 후기

1. 배경


라인웍스에서는 의료 데이터를 활용한 다양한 머신러닝 프로젝트를 진행하고 있습니다. 머신러닝에는 사용하는 접근 방법에 따라 다양한 방법론들이 있지만, 이번 글에서 다루는 내용은 지도 학습(supervised learning)을 이용한 진단보조시스템(Clinical Decision Supporting System 이하 CDSS) 개발을 주로 설명하고 있습니다.

의료 데이터를 활용한 CDSS를 개발하는 경우에는 생각보다 많은 걸림돌이 있습니다. 그중 대표적인 것은 양질의 데이터를 확보하는 것입니다. 일반적으로 많이 알려지고 많은 팀들이 시도하는 문제들은 충분히 양질의 데이터셋이 공개(Kaggle, Amazon AWS 등등)되어있는 경우가 많습니다만, 그렇지 않은 문제들은 직접 데이터셋을 준비해야된다는 어려움이 있습니다. 더불어 지도학습 접근으로 문제를 해결하려면 양질의 라벨링(Labeling, Annotation)을 함으로써 양질의 데이터를 확보 하는 것이 필요합니다.

라인웍스 Tech Group 에서는 현재 안저 이미지를 기반으로한 연구를 진행하고 있으며, 같은 안구에서 시행된 이종의 검사 이미지간의 좌표 정보를 동기화 시키기 위한 목적으로 의료 전문가들이 좀 더 직관적으로 라벨링을 할 수 있는 Standalone 데스크탑 애플리케이션을 개발하였습니다. 본 포스트는 이 과정을 정리한 개발기입니다.


2. Electron이란?

  • Electron은 HTML, CSS, JavaScript 를 사용해서 크로스 플랫폼 데스크탑 애플리케이션을 만들 수 있는 오픈소스 프레임워크 입니다. Chromium과 Node.js를 하나의 런타임으로 통합하여, Windows, Linux, MacOS 용으로 패키징 할 수 있습니다. HTML, CSS, JavaScript 와 같이 기존에 Web 개발자가 친숙한 기술을 활용할 수 있어서 학습곡선이 높지 않다는 장점이 있고, 하나의 코드베이스로 다양한 운영체제(Windows, Linux, MacOS)를 지원할 수 있는 편의성이 크나큰 장점으로 작용하였습니다.
  • Electron은 요즘 다양한 스타트업에서 도입되어 사용되고 있으며, 이름만 들어도 아는 어플리케이션들이 Electron을 이용하여 개발되었습니다.

(출처 – https://electronjs.org/apps)

  • Electron Application Architecture은 다음과 같습니다.

  • Main Process

package.json의 메인 스크립트를 실행하는 프로세스를 메인 프로세스라고 하며, 메인 프로세스에서 실행되는 스크립트는 웹페이지들을 GUI(메뉴, 프레임 등)로 표시합니다.

  • Render Process

Chromium기반으로 각각의 웹페이지의 View를 담당하는 것을 렌더 프로세스라 합니다. 그리고 메인 프로세스와 렌더 프로세스 사이에 데스크탑 애플리케이션의 개발을 지원하는 API를 통신 할 수 있게 해주는 IPC와 remote module이 존재 합니다.

  • React

React는 웹개발에서 Virtual DOM을 통하여 화면을 렌더링해주기 때문에, MVC 패턴 중 V인 View를 담당하는 기능에 특화되어 있습니다. React와 Electron을 결합하면, View를 빠르게 렌더링 할 수 있고, React의 선언적인 문법으로 깔끔한 코드를 작성할 수 있는 장점이 있습니다.


3. 개발화면 구성 및 기능

Electron으로 처음 개발을 해보는 것이기 때문에, 가장 기본적인 라벨링 기능으로 MVP를 구성하여 두가지 화면을 기획하고 구현하였습니다.

1) 파일 로드 화면

  • FP Image(FP – Fundus Photo) 파일들과 TM Image(TM – Thickness Map) 파일들을 라벨링 하기위해서, Image 폴더를 지정해주고, Find paired images버튼을 클릭하면 같은 날짜에 촬영한 이미지들끼리 각각 짝지어 줍니다.

2) 라벨링 화면

FP Image와 TM Image가 짝지어진 상태에서 각각 이미지들을 확대, 축소 할 수 있고, 상하좌우로 오프셋을 준 만큼 이미지들이 이동 할 수 있습니다. 이러한 기능을 통해서 Image Overlap화면에서 이미지들의 Opacity를 조절하여 두 이미지를 반투명하게 만들어서 FP Image와 TM Image가 일치하는지 확인 할 수 있습니다. TM Image는 픽셀에서의 높이값을 알려주는 이미지인데, 저희는 FP Image로 픽셀에서의 높이값을 알고 싶기 때문에 FP Image와  TM Image가 같은 위치를 나타내도록 이미지를 일치시켰습니다. 이미지가 일치 되어있으면 save버튼을 통해서 이미지데이터들을 라벨링해서 별도의 csv파일로 저장하게 됩니다.


4. 시행착오

처음 사용한 것임에도 불구하고 다양한 Boilerplate가 공개되어 있어 개발을 시작하는 데에는 큰 어려움은 없었습니다. 저희가 사용한 https://github.com/electron-react-boilerplate/electron-react-boilerplate은 마치 create-react-app과 같이 일반적인 개발 세팅이 갖춰져 있어 React를 다룬 경험만 있으면 쉽게 개발을 시작할 수 있습니다.

웬만한 기능들은 어렵지 않게 개발할 수 있었으나, Electron 특성상, 그리고 데스크탑 애플리케이션 특성상 자체 API 와 관련해서 몇가지 시행착오를 겪었습니다. 본 장에서는 그런 경험을 공유하고자 합니다.

  1. Window resizing 문제

a) 웹 페이지와는 달리 데스크탑 애플리케이션에서는 화면 레이아웃이 고정되어있는 경우가 많습니다. 하지만 Electron은 Chromium기반으로 되어있다보니 화면 사이즈 변경이 기본적으로 가능합니다. 이럴 경우, 화면 사이즈를 고정하는 방법으로 다음과 같이 해결할 수 있습니다.

b) resizing 코드 예시

 
import BrowserWindow from 'react-electron-browser-window';
...
export default class Home extends Component {
  ...
  render() {
    return (
       <div className={styles.container} data-tid='container'>
         <BrowserWindow resizable={false} />
         <h2>Specify paths for folders for annotation</h2>
         ...
       </div>      
    )  
  }
} 

Electron API를 이용해서 BrowserWindow 객체의 resizable option을 false로 설정해주었습니다.

2. 이미지 조정 문제

a) 입력 영상(A)를 타겟 영상(B)로 매칭 시키기 위해 A영상을 다양하게 조정할 수 있는 기능을 구현했습니다. 기본적으로 확대/축소(Zoom), 수직 오프셋, 수평 오프셋을 조정하도록 했는데, 이는 다음과 같이 transform의 property인 scale과 translate 으로 해결할 수 있었습니다.

b) 확대, 축소 코드 예시


import React from 'react'
...
const ZoomImage = ({
  zoomRatio,
  ...
}) => {
  const image = {
    ...,
    transform: `scale(${zoomRatio})` ...
  }
}

CSS zoom property는 모든 브라우저에서 동작하지 않기 때문에,  translate의 scale property를 이용하였습니다.

c) 수직, 수평 조절 코드 예시


import React from 'react'
...
const ZoomImage = ({
  horizontalOffset,
  verticalOffset,
  ...
}) => {
  const image = {
    ...,
    transform: `translate(${horizontalOffSet}px, ${verticalOffSet}px)` ...
  }
}

background-position을 이용했을 때, zoom 상태에서 수직 오프셋이 동작하면 수평 오프셋이 동작이 안되거나 반대의 경우가 있었기 때문에 translate속성을 이용하였습니다.


5. 개발 후기

이번에 Annotation 프로젝트를 하면서 처음 사용해보는 프레임워크라 막연한 두려움이 앞서 있었습니다. 하지만 다양한 Boilerplate와 익숙한 웹개발 언어로 데스크탑 애플리케이을 개발 할 수 있다는 장점 덕분에, 개발 할 때 처음 접하는 프레임워크 치고는 개발속도가 빨랐습니다. 개발하면서 Electron의 API를 많이 활용하지 못한 것과 코드에서 각 컴포넌트마다 props를 많이 사용한 것이 아쉬웠고, Redux의 대한 필요성을 느끼게 한 프로젝트 였습니다. 다음엔 Redux를 활용해서 더 좋은 코드와 Electron으로 만든 유명한 앱을 만들어 보고 싶습니다.

읽어주셔서 감사합니다

No comments yet.

Leave a comment

Your email address will not be published.