2018/08/23

[Python] 컬러 영상의 채널 분리하기

컬러영상의 각 채널데이터를 분리할 일이 있었는데 C++로 만들어 보려다 Python 예제를 찾아 만들어보았는데 아주 간단한 코드로 원하는 결과를 얻을 수 있었다.
Python의 생산성은 정말 대단한 것 같다. Python을 좀더 공부해야겠다.
import cv2
import numpy as np
img = cv2.imread("ColorImage.png")
b,g,r = cv2.split(img)
cv2.imwrite('Image_R.png', r)
cv2.imwrite('Image_G.png', g)
cv2.imwrite('Image_B.png', b)

2018/08/21

Build OpenCV 3.4.2 with VTK 8.1.1

오래전에 OpenCV의 viz 모듈에 관심이 있어 VTK를 OpenCV 와 VTK를 빌드한 적이 있었다.
Build OpenCV 3.1 with VTK 7.0 in Visual Studio 2015

그때당시 VTK의 Renderer 설정과 world 모듈 생성에 문제가 있어서 복잡하게 했던 기억이 있다.

먼저 VTK 를 CMake를 이용하여 정적라이브러리로 빌드한다.
이전과는 다르게 Renderer 설정을 변경할 필요가 없었다. 기본 제공하는 OpenGL2로 진행을 한다.
OpenCV와 정적으로 연결되도록 BUILD_SHARED_LIBS 옵션을 해제하였다.

Srouce: E:/DevWork/VTK/VTK-8.1.1
Build:  E:/DevWork/VTK/VTK-8.1.1_VS2013_x86Static
 
Configuration options
  BUILD_EXAMPLES                   uncheck
  BUILD_SHARED_LIBS                uncheck
  BUILD_TESTING                    uncheck
  CMAKE_INSTALL_PREFIX             BuildPath/install

VTK 빌드를 완료하였다면 OpenCV를 빌드 할 차례이다.
OpenCV는 VTK 빌드 경로와 viz와 world 모듈을 빌드하도록 하였고 CXX11, OpenGL과 OpenMP를 사용하도록 설정하였다. 빠른 테스트를 위해 BUILD_TESTS 옵션을 선택하였다.

Source: E:/DevWork/OpenCV/VTK/opencv-3.4.2
Build:  E:/DevWork/OpenCV/VTK/opencv-3.4.2_VC2013_x86
 
Configuration options
  BUILD_DOCS            uncheck
  BUILD_EXAMPLES        uncheck
  BUILD_TESTS           check
  VTK_DIR               E:/DevWork/VTK/VTK-8.1.1_VS2013_x86Static
  WITH_OPENGL           check
  WITH_OPENMP           check
  
  BUILD_opencv_viz      check
  BUILD_opencv_world    check

이전에는 viz 모듈이 world모듈로 포함이되지 않아서 world 별도로 빌드하고 viz 빌드시 라이브러리 참조를 opencv_core에서 opencv_world 로 변경하였는데 이번에는 viz 모듈이 world모듈로 포함이 되었다.
따라서 빌드후 world 모듈인 opencv_world342.dll 파일만 있으면 된다.

완료후 실제 테스트를 하려면 시간이 소요될 것 같아서 OpenCV를 빌드할 때 BUILD_TESTS 옵션을 선택하여 테스트 파일이 만들어지도록 하였다.

빌드를 마친후 bin\Release 폴더의 opencv_test_viz.exe를 실행해 보았다.

문제없이 실행되는 것으로 보아 viz 모듈이 world에 제대로 포함된 것 같다.

Build Poco 1.9.0 with OpenSSL and MySQL

오랜만에 Poco 라이브러리 1.9 버전을 빌드해 보았다.
얼마전부터 계속 시도해 보았지만 OpenSSL을 포함하는데 문제가 있어서 계속 실패를 하다가 인터넷을 통해 도움을 얻어 드디어 성공하였다.
일단 Poco 라이브러리의 추가 포함 라이브러리는 목적에따라 OpenSSL과 MySQL을 추가할 수 있다.
언제든 사용할 수 있는 라이브러리라서 빌드할 때 이들을 추가해 놓으면 편할 것 같아서 항상 이를 포함하여 빌드한다.

우선 빌드에 필요한 것들은 다음과 같다.
Poco Library 1.9
https://github.com/pocoproject/poco
poco-poco-1.9.0-release.zip
OpenSSL
https://github.com/pocoproject/openssl
openssl-develop.zip
MySQL
https://dev.mysql.com/downloads/mysql/5.7.html#downloads
mysql-5.7.23-win32.zip
mysql-5.7.23-winx64.zip

OpenSSL 빌드하기
https://github.com/pocoproject/openssl 에서 받은 소스를 빌드한다.
이미 Vsiual Studio 2013 버전으로 빌드가 되어있는 dll과 라이브러리가 소스에 포함되어있어 이를 이용하는 경우 빌드를 할 필요가 없다.
혹시 OpenSSL 버전을 변경하고자 하는경우 다시 빌드를 해야한다.
2018년 08월 17일 현재 올려져있는 버전은 1.1.0g 버전이다.
새롭게 빌드를 하고자 하는경우 소스를 압축해제하고 해제한 폴더에서 다음 명령을 수행하면 된다.
build.ps1을 실행하면 된다.
build.ps1 명령을 아래와 같은 형식이고,
build.ps1 [-openssl_release 1.0.0 | 1.1.0]
          [-vs_version 150 | 140 | 120 | 110 | 100 | 90]
          [-config     release | debug | both]
          [-platform   Win32 | x64] # TODO WinCE/WCE
          [-library    shared | static | both]
       
실행 예제는 다음과 같다.       
powershell -ExecutionPolicy RemoteSigned -File build.ps1 -openssl_release 1.1.0h -vs_version 120 -config both -platform x64 -library both

빌드를 하면 소스 경로에 VC_(버전번호) 의 폴더가 만들어지고 그 안에 결과 파일들이 생성된다.

Poco 추가 라이브러리 구성하기
먼저 Poco 라이브러리 소스 파일(poco-poco-1.9.0-release.zip)을 압축해제한다.
그리고 OpenSSL을 빌드를 하지 않은경우 openssl-develop.zip 파일의 build 폴더를 Poco 소스의 openssl 폴더에 복사한다.
OpenSSL을 빌드하였다면 결과 폴더(VC_(버전번호))를 openssl 폴더에 복사하고 이름을 build로 변경한다.

Poco 소스 폴더에 mysql 폴더를 생성하고 mysql-5.7.23-win32.zip 파일의 include 와 lib 폴더를 압축해제하고 lib 폴더는 lib32로 변경한다.
그리고 mysql-5.7.23-winx64.zip 파일의 lib 폴더를 mysql 폴더에 압축해제하고 lib64로 변경한다.
그러면 최종적으로 추가 생성된 폴더는 아래와 같은 구성된다.
poco-poco-1.9.0-release
openssl
build
include
openssl
win32
bin
lib
win64
bin
lib
mysql
include
lib32
lib64

빌드를 하기전에 buildwin.cmd 파일에서 위에서 구성한 mysql 폴더를 사용하도록 변경을 해 주어야한다.
PLATFORM 파라메터를 인식한 후에 아래 코드를 추가(62line)한다.
rem MySQL
set MYSQL_DIR=%POCO_BASE%\mysql
set MYSQL_INCLUDE=%MYSQL_DIR%\include
if "%PLATFORM%"=="Win32" (set MYSQL_LIB=%MYSQL_DIR%\lib32)
if "%PLATFORM%"=="x64" (set MYSQL_LIB=%MYSQL_DIR%\lib64)
set INCLUDE=%INCLUDE%;%MYSQL_INCLUDE%
set LIB=%LIB%;%MYSQL_LIB%

echo MySQL Path: %MYSQL_DIR%
echo Include: %INCLUDE%
echo Lib: %LIB%
pause

echo 명령과 pause 명령은 mysql 관련 설정이 제대로 되었는지 확인하기 위해 넣은 코드이다.

이제 Visual Studio 버전에 맞는 빌드 명령을 호출하면 된다.
buildwin.cmd 명령 형식은 다음과 같다.
Usage:
------
buildwin VS_VERSION [ACTION] [LINKMODE] [CONFIGURATION] [PLATFORM] [SAMPLES] [TESTS] [TOOL]
VS_VERSION:    "90|100|110|120|140|150"
ACTION:        "build|rebuild|clean"
LINKMODE:      "static_mt|static_md|shared|all"
CONFIGURATION: "release|debug|both"
PLATFORM:      "Win32|x64|WinCE|WEC2013"
SAMPLES:       "samples|nosamples"
TESTS:         "tests|notests"
TOOL:          "devenv|vcexpress|wdexpress|msbuild"

아래 명령은 Visual Studio 2013 버전으로 빌드하기 위해 실행한 명령이다.
buildwin.cmd 120 build all both x64 samples tests msbuild

빠르게 빌드만 하려면 SAMPLES과 TESTS에 대하여 nosamples 와 notests로 설정하여 빌드한다.

2018/01/18

Hello Electron!!

Electron을 이용한 App을 만들기 위해서는 위해서는 Electron홈페이지(https://electronjs.org/)에서 배포하고 있는 electron을 다운(https://github.com/electron/electron/releases)받아 설치하여 만드는 방법이 있다. 이 패키지에는 nodejs와 Chromium 그리고 V8 엔진이 포함되어 있다.
또 다른 방법은 nodejs를 설치하고 electron 모듈을 설치하는 방법이 있다. App를 만든 후 배포를 고려한다면 nodejs 의 모듈 형태의 electron을 설치하는 것이 좋아 보였다. 그래서 Nodejs를 이용한 개발 환경 구축을 해 보았다.

Nodejs 설치하기
먼저 nodejs 홈페이지(https://nodejs.org/en/download/)를 통해 nodejs를 다운 받는다.
nodejs 홈페이지에서는 각 플랫폼에 대해서 Installer 형태와 Binary 형태의 파일을 다운 받을 수 있다. 개인적으로 자동 설치를 선호하지 않아 수동설치를 위한 Binary 형태의 zip 파일(https://nodejs.org/dist/v8.9.4/node-v8.9.4-win-x64.zip)을 다운받았다.
다운 받은 파일을 특정 폴더(D:\Dev\node-x64)에 압축을 풀고 시스템의 전역 설정에서 Path을 추가하여 어느 경로에서건 nodejs를 실행할 수 있도록 설정하였다.
D:\Dev\node-x64>node -v
v8.9.4

electron 모듈 설치하기
electron 을 모든 프로젝트에서 사용할 수 있도록 "npm install -g electron" 명령을 이용하여 electron을 전역 설치하였다. 이전에는 electron-prebuilt 였는데 electron으로 변경이 되었다.
D:\Dev\node-x64>npm install -g electron
D:\Dev\node-x64\electron -> D:\Dev\node-x64\node_modules\electron\cli.js

> electron@1.7.10 postinstall D:\Dev\node-x64\node_modules\electron
> node install.js

+ electron@1.7.10
added 152 packages in 14.212s

D:\Dev\node-x64>npm list electron
D:\Dev\node-x64
`-- electron@1.7.10

D:\Dev\node-x64>

Git 설치하기
Git는 electron 개발과 직접적으로 관련은 없지만 quick start 프로젝트를 받기위해 설치 하였다. quick start 프로젝트 없이 electron 홈페이지의 tutorial을 보고 따라해 볼 경우 Git를 설치할 필요는 없다.
Git 홈페이지(https://git-scm.com/)에서 설치파일을 다운로드받아 설치하면 된다.

Quick start 프로젝트 실행 해보기
git 명령을 이용하여 electron quick start 프로젝트를 다운받는다.
D:\DevWork\Projects\Electron\Study>git clone https://github.com/electron/electron-quick-start
Cloning into 'electron-quick-start'...
remote: Counting objects: 267, done.
Receiving objects: 66% (177/267) remote: Total 267 (delta 0), reused 0 (delta 0), pack-reused 267
Receiving objects: 100% (267/267), 44.07 KiB | 0 bytes/s, done.
Resolving deltas: 100% (123/123), done.

D:\DevWork\Projects\Electron\Study>cd electron-quick-start
D:\DevWork\Projects\Electron\Study\electron-quick-start>dir
 Volume in drive D is Work
 Volume Serial Number is C0A2-CA63

 Directory of D:\DevWork\Projects\Electron\Study\electron-quick-start

2018-01-14 23:15 <dir> .
2018-01-14 23:15 <dir> ..
2018-01-14 23:15 14 .gitignore
2018-01-14 23:15 603 index.html
2018-01-14 23:15 6,585 LICENSE.md
2018-01-14 23:15 1,985 main.js
2018-01-14 23:15 456 package.json
2018-01-14 23:15 2,373 README.md
2018-01-14 23:15 174 renderer.js
  7 File(s) 12,190 bytes
  2 Dir(s) 77,275,750,400 bytes free

D:\DevWork\Projects\Electron\Study\electron-quick-start>electron .

이번에는 수동으로 프로젝트를 만들어 보았다.
electron의 tutorial 페이지(https://electronjs.org/docs/tutorial/quick-start)를 참조하였다.
프로젝트는 기본적으로 3개의 파일들(package.json, main.js, index.html)로 구성된다.

package.json
{
  "name" : "your-app",
  "version" : "0.1.0",
  "main" : "main.js"
}

main.js
const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win

function createWindow () {
  // Create the browser window.
  win = new BrowserWindow({width: 800, height: 600})

  // and load the index.html of the app.
  win.loadURL(url.format({
  pathname: path.join(__dirname, 'index.html'),
  protocol: 'file:',
  slashes: true
  }))

  // Open the DevTools.
  win.webContents.openDevTools()

  // Emitted when the window is closed.
  win.on('closed', () => {
  // Dereference the window object, usually you would store windows
  // in an array if your app supports multi windows, this is the time
  // when you should delete the corresponding element.
  win = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
  app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
  createWindow()
  }
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

index.html

<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <title>Hello Electron!</title>
  </head>
  <body>
  <h1>Hello World!</h1>
  We are using node <script>document.write(process.versions.node)</script>,
  Chrome <script>document.write(process.versions.chrome)</script>,
  and Electron <script>document.write(process.versions.electron)</script>.
  </body>
</html>