이 블로그는 애드센스 수익으로 운영되고 있습니다.
광고차단앱을 해제해주시면 블로그 운영에 큰 도움이 됩니다.
Please disable Adblock?
본문 바로가기
정보, 기술/개발 모음

전자잉크 디스플레이용 흑백적(RBW) 이미지 만들기 | 라즈베리파이 활용

by 킨쨩 2021. 8. 22.
반응형

전자잉크 디스플레이용 흑백적(RBW) 이미지 만들기 | 라즈베리파이 활용

 이번 게시글에서는, 전자잉크 디스플레이를 활용해서 이미지를 표현하기 위한 처리에 대해서 알아보도록 하겠다. 사실 흑백인 경우에는 색

반전에 디더링 정도만 신경 쓰면 된다. 나는 아무 생각 없이 흑백적 전자 종이를 구매한 관계로, 단순한 흑백이 아닌 흑백적 이미지로 만들고 색상별로 분류해줄 필요가 생기게 되었다. 먼저 인터넷 상에서 영어로 검색을 했는데, 몇 가지 결과가 나오긴 하는데, 좀 나사가 풀렸거나 퀄리티가 낫거나, 도중에 포토샵으로 전처리를 해줘야 제대로 나오는 등등의 문제가 있었다. 그렇기에 그냥 내가 아예 새롭게 다시 만들면서 적게 된 포스팅이다. 이미지의 변환에 대해서 공부하고 싶은 사람들이나 전자종이를 사용할 사람들은 참고하도록 하자.


목차

1. 포토샵을 이용한 전처리

2. ImageMagick을 사용한 전처리 + 최종본까지
3. 코드 설명
부연 설명: 디더링(dithering)


포토샵을 이용한 전처리

 먼저 다양한 색의 정보를 가지고 있는 사진들을 전처리를 통해서 흑,백,적의 3가지 요소들만 가지도록 바꾸어 주어야 한다. 그렇지 않으면 빨갛게 나오지 않아야 하는 부분도 빨갛게 나오거나, 이미지의 형태를 알아볼 수 없게 되기 때문이다. 일단 가장 쉬운 방법은 포토샵을 이용하는 방법이다.


https://www.waveshare.com/wiki/E-Paper_Floyd-Steinberg

 

E-Paper Floyd-Steinberg - Waveshare Wiki

 

www.waveshare.com

1. 위의 사이트에서 컬러 테이블을 다운받는다.

 덤으로 원래의 간단한 설명이 적혀있으니 참고할 사람은 참고하자.

2. 이미지의 사이즈를 사용하려는 전자잉크 디스플레이의 픽셀 수에 맞춰준다.

내가 구매한 제품의 경우 296 * 152의 사이즈를 가지고 있었기 때문에, 해당 사이즈에 맞게 이미지의 크기를 조절했다. 이미지 - 이미지 사이즈의 메뉴를 골라서 줄여주면 된다.

3. 파일, 내보내기, 웹용(레거시)을 눌러준다.

4. 다운로드한 파일 속에서 알맞은 컬러 테이블을 선택해준다.

5. 디더링의 정도를 내가 원하는 정도로 설정한다.

 디더링이란, 쉽게 말하면 요구된 색상이 불가능할 때, 다른 색상을 섞거나, 밀도 등등의 잡음 신호를 추가해서 원래의 이미지와 최대한 비슷하게 만들어주려고 하는 것이다. 그림의 경우, 기본적으로 포토샵의 디더링 설정인 88%를 그대로 놓아도 큰 문제는 없다. 하지만 원하는 스타일(어느 정도까지 선명하게 보일지)이 있다면 그에 맞춰서 조절해주도록 하자.

6. 이후 이미지 분리는 아래의 코드를 참고한다.

아래의 ImageMagick을 사용한 전처리의 2번부터 따라 한다. 다만, split_image.py의 코드의 앞부분(ImageMagick을 사용한 부분)을 날려버려 주도록 하자.


 나의 경우, 빨간색을 잘 표현할 수 있는 캐릭터에 대해서 생각하다가, 마키 쨩을 골라서 이미지를 만들어보았다. 다음과 같은 이미지가 완성되었다. 멀리서 보거나 작게 보면 원본 이미지와 상당히 비슷해 보이는 것이, 점묘화와 비슷한 느낌을 준다.

실제로 만들어본 이미지


ImageMagick을 사용한 전처리 + 최종본까지

 ImgaeMagick 이라는 라이브러리를 활용해서 위와 동일한 결과물을 만들어 내는 것이 가능하다. 특히 리눅스나 파이썬, 프로그래밍 등등에 익숙한 사람이라면 디더링과 적백흑 처리를 한 번에 아주 쉽게 처리해줄 수 있다. 개인적으로 가장 추천하는 방법이니 잘 활용해보도록 하자.


1. ImageMagick을 설치해준다.

 아래의 사이트에서 다운로드할 수 있다. pip 등의 명령어로도 설치가 가능하지만, 라즈베리파이의 경우 다양한 오류가 발생하기 때문에, Linux Binary Release라고 써진 부분을 참고로 설치해보도록 하자.

https://imagemagick.org/script/download.php

 

ImageMagick

Create, Edit, Compose, or Convert Digital Images

imagemagick.org

https://imagemagick.org/script/install-source.php

 *맥의 경우에는 Brew를 활용하면 쉽게 설치할 수 있다. 라즈베리파이에 넣어주기 전에 코딩이 잘 되는지 테스트할 때에 아주 편하니 참고하도록 하자.

 *라즈베리파이 1 B+의 경우 설치에 거의 5시간이 걸렸던 것 같다. 4 B의 경우에는 10~30분 정도가 소요된다. 참을성을 가지자.

 

2. openCV를 설치해준다.

https://www.piwheels.org/project/opencv-python/

 

piwheels - opencv-python

opencv-python Wrapper package for OpenCV python bindings.

www.piwheels.org

정식 홈페이지를 참고로 설치해준다. 터미널에 아래와 같이 넣어주면 보통 된다.

pip install numpy --upgrade
pip3 install --upgrade numpy

다만, 경우에 따라서 아래와 같은 오류가 발생할 수 있다.

 

RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd

 

 해당 오류의 경우, numpy의 버전이 맞지 않아 발생하는 것이다. 아래의 명령어를 터미널에 입력해서 numpy를 삭제하고 다시 최신 버전을 설치해주면 해결된다.

sudo apt update
sudo apt remove python3-numpy
sudo apt install libatlas3-base
sudo pip3 install numpy

*참고 맥에 설치하기

아래의 두 명령어를 입력하고 기다려 주면 가능하다. 물론 brew를 미리 깔아 두어야 하는 점은 주의하자.

brew install opencv
pip install opencv-python

3. 미리 파일을 준비해준다.

 적절히 저작권이 없는 이미지든, 개인적인 목적으로 쓸 이미지든 간에 준비한다. 주의할 점은, 자기 자신의 전자 잉크 디스플레이와 같은 비율, 사이즈로 크롭해두어야한다는 점이다.

4. 아래의 프로그래밍 코드를 바탕으로 경로를 적절히 설정한다.

 나의 깃허브 코드를 다룬 받는다. 아래의 페이지에서 split_image.py를 열고 복붙을 하든, clone을 하든 뭘 하든 상관은 없다. 

https://github.com/KDS-study/RBW4eink

 

GitHub - KDS-study/RBW4eink: This repository includes code to convert an image to a 3-color-image(Red,White,Black) in order to d

This repository includes code to convert an image to a 3-color-image(Red,White,Black) in order to display it on an E-ink display - GitHub - KDS-study/RBW4eink: This repository includes code to conv...

github.com

 그리고 다운로드한 파일을 내가 원하는 위치에 이동시켜주고, 'picdir'의 경로를 적절히 설정해주도록 한다.

  • png가 아닌 파일을 이용하고 싶을 경우에는, 적절히 바꾸어주도록 하자.
  • 내가 직접 디더링의 기본 값을 사진/이미지에 적절하게 설정해두었으니(포토샵 88%와 유사하다) 그림이나 사진은 그대로 쓰면 된다.
  • 글의 경우, 주석처리되어있는 부분을 바꿔 넣어주자

5. python3로 실행한다.

 터미널 상에서 python3로 실행한다. 맥의 경우 관리자 권한이 없어도 실행되지만, 라즈베리파이의 경우, sudo 관리자 권한을 줄 필요가 있다.

python3 split_image.py
실제 실행결과

 이번에는 저작권 무료 이미지를 다운로드하여 크롭 한 뒤 작성해 보았다. 실제 나의 결과는 다음과 같다. 

원본, 흑백적 변환, 흑/적 분리 이미지들

 

실제 표시된 이미지


코드 설명

 일단 전체 코드의 경우 아래와 같다. 자세하게 한번 파고들어 보자.

import os
import cv2 
import numpy as np

#R+B+G =White
#R^c + B^c +G^c =Black
#R^c + B + G = Red
#invert it!

def ConvertRBW(filename):
    print('create palette')
    #os.system('magick xc:red xc:black xc:white  +append palette.png')
    os.system('magick xc:"rgb(0,0,0)" xc:"rgb(255,0,0)" xc:"rgb(255,255,255)" +append palette.png')
    
    #you need to change code to your path!!!!
    picdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'pic')
    #print(picdir)
    print('setfile name as ' + filename)
    path = os.path.join(picdir, str(filename)+'.png')
    #print(path)
    print('remap file') 
    
    #picture, photo etc
    os.system('magick ' + os.path.join(picdir, str(filename)+'.png') +'  -dither FloydSteinberg -define dither:diffusion-amount=66% -remap palette.png ' + os.path.join(picdir, str(filename)) +'R.png')
    #text
    #os.system('magick ' + os.path.join(picdir, str(filename)+'.png') +'  +dither -remap palette.png ' + os.path.join(picdir, str(filename)) +'R.png')

    nfilename = filename + 'R'
    npath = os.path.join(picdir, str(nfilename)+'.png')

    img = cv2.imread(npath,1)

    print('split into rbw')
    imagem = cv2.bitwise_not(img)
    b,g,r = cv2.split(img)
    be,ge,re = cv2.split(imagem)

    Black = r 
    Red = re + b + g

    img_number = 0

    for color in [Black,Red]:
        print('save'+str(img_number)+'.bmp')
        cv2.imwrite(os.path.join(picdir,str(nfilename)+str(img_number)+".bmp"),color)
        img_number+=1
    return nfilename

if __name__ == '__main__':
    filename = input('please input file name:')
    ConvertRBW(filename)

임포트 + 어떤 원리로 적백흑을 분리하는지에 대한 간결한 기술

 일반적인 디스플레이는 하얀색이 모든 색의 혼합, 최대치를 나타낸다. 내가 이용하고 있는 전자 종이의 경우, 입력 데이터 상에서의 하얀 부분이 아닌 검은 부분이 해당 색(검정, 빨강)이 들어가도 설정되어 있었다. 그렇기 때문에, 라이브러리 자체를 수정하거나 색을 반전시켜서 넣어줄 필요성 있다. 그런 내용을 간단히 적어둔 것이다.

import os
import cv2 
import numpy as np

#R+B+G =White
#R^c + B^c +G^c =Black
#R^c + B + G = Red
#invert it!

전처리 + 색 분리 함수

def ConvertRBW(filename):
    print('create palette')
    #os.system('magick xc:red xc:black xc:white  +append palette.png')
    os.system('magick xc:"rgb(0,0,0)" xc:"rgb(255,0,0)" xc:"rgb(255,255,255)" +append palette.png')
    
    #you need to change code to your path!!!!
    picdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'pic')
    #print(picdir)
    print('setfile name as ' + filename)
    path = os.path.join(picdir, str(filename)+'.png')
    #print(path)
    print('remap file') 
    
    #picture, photo etc
    os.system('magick ' + os.path.join(picdir, str(filename)+'.png') +'  -dither FloydSteinberg -define dither:diffusion-amount=66% -remap palette.png ' + os.path.join(picdir, str(filename)) +'R.png')
    #text
    #os.system('magick ' + os.path.join(picdir, str(filename)+'.png') +'  +dither -remap palette.png ' + os.path.join(picdir, str(filename)) +'R.png')

    nfilename = filename + 'R'
    npath = os.path.join(picdir, str(nfilename)+'.png')

    img = cv2.imread(npath,1)

    print('split into rbw')
    imagem = cv2.bitwise_not(img)
    b,g,r = cv2.split(img)
    be,ge,re = cv2.split(imagem)

    Black = r 
    Red = re + b + g

    img_number = 0

    for color in [Black,Red]:
        print('save'+str(img_number)+'.bmp')
        cv2.imwrite(os.path.join(picdir,str(nfilename)+str(img_number)+".bmp"),color)
        img_number+=1
    return nfilename

 먼저 magick 명령어를 사용해서 RBW의 색 팔레트를 만들어 준다. 사실 만들어주지 않고 바로 하는 방법도 있었지만, 좀 더 직관적이고 알기 쉽도록 일부러 이용했다. 그리고 팔레트의 색 부분만 바꿔주면 바로 다른 색상에 대응하는 것도 가능하다.

 이후 경로 설정 부분에서 자기 자신의 경로를 반영해주도록 하자. 

def ConvertRBW(filename):
    print('create palette')
    #os.system('magick xc:red xc:black xc:white  +append palette.png')
    os.system('magick xc:"rgb(0,0,0)" xc:"rgb(255,0,0)" xc:"rgb(255,255,255)" +append palette.png')
    
    #you need to change code to your path!!!!
    picdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'pic')
    #print(picdir)
    print('setfile name as ' + filename)
    path = os.path.join(picdir, str(filename)+'.png')
    #print(path)

 이후 magick 명령어를 통해서 색을 remap 해주면서 포토샵의 컬러 테이블과 같은 결과물을 만들어준다. 이미지가 메인인지, 글이 메인인지 잘 파악해서 디더링의 옵션을 넣어주도록 하자. 기본값은 포토샵 88%와 비슷하게 나오게 설정해두었지만, 글자의 경우 깨지는 경향이 있으니 주의하자. 이후 새로운 이름으로 저장해준다.

	
    print('remap file') 
    #picture, photo etc
    os.system('magick ' + os.path.join(picdir, str(filename)+'.png') +'  -dither FloydSteinberg -define dither:diffusion-amount=66% -remap palette.png ' + os.path.join(picdir, str(filename)) +'R.png')
    #text
    #os.system('magick ' + os.path.join(picdir, str(filename)+'.png') +'  +dither -remap palette.png ' + os.path.join(picdir, str(filename)) +'R.png')
    
    nfilename = filename + 'R'
    npath = os.path.join(picdir, str(nfilename)+'.png')

 마지막으로, RGB의 관계를 통해서 빨강과 블랙으로 색을 분리해낸다. 또, 색이 거꾸로 표시되는 점을 생각해서 아래와 같이 넣게 되었다. 조금 직관적이지 않기에 간단히 설명을 하자면,

  • 빨강(검은색으로 나와야 함) = 빨강 제외, 파랑 포함, 녹색 포함
  • 검정(검은색으로 나와야함) = 빨강 포함

 파랑과 녹색은 단순히 하얀색 배경을 보조하기 위한 값을 가지고 있는, 의미 없는 레이어이기에 위와 같은 결과가 나오게 되었다. 만약 검정, 노랑, 하양의 세 가지 색상이었다면, 위의 팔레트를 수정해준 뒤, 

  • 노랑(검은색으로 나와야 함) = 빨강 제외, 녹색 제외, 파랑 포함
  • 검정(검은색으로 나와야함) = 빨강 포함, 녹색 포함

과 같은 방식으로 지정해주면 될 것이다. (설명이 어렵다면 미안하다 ㅠ) 이후에는 해당 색깔별로 이름을 지정해서 저장해준다.

    img = cv2.imread(npath,1)

    print('split into rbw')
    imagem = cv2.bitwise_not(img)
    b,g,r = cv2.split(img)
    be,ge,re = cv2.split(imagem)

    Black = r 
    Red = re + b + g

    img_number = 0

    for color in [Black,Red]:
        print('save'+str(img_number)+'.bmp')
        cv2.imwrite(os.path.join(picdir,str(nfilename)+str(img_number)+".bmp"),color)
        img_number+=1
    return nfilename

파일 이름 입력 요구

 기본적으로 나는 출력 함수에서 위의 함수를 임포트 하게 만들어두었다. 하지만 단독 실행에도 대비해서 아래의 코드를 넣어두었다. 간단히 말하면, 해당 함수가 실행되면 나오는 것으로, 파일의 이름을 입력하면 처리가 이루어지도록 만들어 두었다.

if __name__ == '__main__':
    filename = input('please input file name:')
    ConvertRBW(filename)


부연 설명: 디더링(dithering)

 위에서 아주 간단하게 디더링의 개념에 대해서 말하긴 했지만, 아무래도 처음 접하는 사람들의 경우 이해하기 어려울 수 있다. 당장 나도 왜 포토샵에서 전처리를 하면 잘 나오고, ImageMagick으로 하면 제대로 안 나오는 지를 몰라서 포기할 뻔했었기 때문이다. 그러니 실제 모습을 간단히 보여주려고 한다.

 

예시로 쓸 애니 케릭터
(좌) 디더링 0% (우) 디더링 100%

 디더링이 없을 경우, 모든 색을 빨간색 100%, 흰색 100%, 검은색 100%로 나눠서 콘트라스트가 아주 크게 올라가는 느낌이다. 반면 디더링을 최대한 넣을 경우, 원래 파일에 있던 모든 색을 최대한 살리기 위해서 자잘한 부분에까지 지저분하게 점이 들어가는 느낌이다. 이렇게 이해해주면 된다. 

 

 참고로 디더링은 조금 지저분하게 들어갔더라도 멀리서 보거나 작게 보면 꽤 괜찮게 보이기도 한다. 그러니 자기가 사용하는 전자잉크 종이의 사이즈 등등을 생각해서 적절하게 설정하도록 하자.

 

 *포토샵의 디더링 알고리즘은 FloydSteinberg으로 추정된다. 확실하지는 않지만.


맺음말

 이번 게시글에서는 전자 종이에 표시하기 위한 이미지의 전처리와 색 분리에 대해서 알아보았다. RBW의 이미지를 만드는 법을 아무리 찾아봐도 제대로 나오지 않았기에 직접 코딩도 하고 자료들도 수 없이 많이 찾아가면서 작성한 게시글이다. 특히, 인터넷 상에서는 이미지에서 가장 많은 색을 분류하는 방식을 통해서 나타내는 방법이 있었는데, 디더링을 거친 이미지를 제대로 표시하지 못하는 불편함이 있어서 직접 해결해보게 되었다. 아무튼, 전자종이로 이것저것 도전하는 사람들에게 도움이 되기를 바라며 이만 글을 마친다.

밑에 공감 버튼 한 번씩 클릭 부탁드립니다! 
내용에 관한 질문이나 의견이 있다면 댓글로 남겨주세요.

인스타: @kkingchangg

크라우드픽: @Gehdtlr2547

 

일본 유학 KIN쨩 작가 - 크라우드픽의 사진, 이미지, 일러스트, 캘리그라피

저작권 걱정 없는 상업용 이미지 서비스 크라우드픽에서 일본 유학 KIN쨩 작가의 이미지를 무료로 사용해보세요

www.crowdpic.net

Copyright 2021 KIN All rights reserved. 
KIN

반응형

댓글