์งํ์ ๋ก์ปฌ์ ๋ด์ฅ๋ ์ด๊ฒฝ๋ AI ๋ชจ๋ธ์ ํตํด ๋งค์ผ ์๋ก์ด ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ ,
์ ๊ธฐ๋ฅผ ๊ฑฐ์ ์ฐ์ง ์๋ ์ ์์ํฌ ๋์คํ๋ ์ด์ ์๋์ผ๋ก ํ์ํ๋ ์ค๋งํธ ์ํธ ํ๋ ์ ํ๋ก์ ํธ์
๋๋ค.
์ด ์ ์ฅ์๋ Raspberry Pi ํ๊ฒฝ์์ Stable Diffusion Turbo(OnnxStream ๊ธฐ๋ฐ)๋ฅผ ์ฌ์ฉํด
์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ , ACeP e-ink ๋์คํ๋ ์ด์ ์ถ๋ ฅํ๋ ์ ์ฒด ๋ฐ๋ชจ ํ๋ก์ธ์ค๋ฅผ ํฌํจํฉ๋๋ค.
- โ ์คํ๋ผ์ธ ๋ก์ปฌ AI ์ด๋ฏธ์ง ์์ฑ (Stable Diffusion XL Turbo, Onnx ์์ํ)
- โ e-ink ๊ธฐ๋ฐ ์ปฌ๋ฌ ๋์คํ๋ ์ด ์๋ ํ์
- โ ํ๋กฌํํธ ๋๋ค ์กฐํฉ ์ง์ ๋ฐ ์ฌ์ฉ์ ์ปค์คํฐ๋ง์ด์ง
- โ
cron, shell๊ธฐ๋ฐ ์๋ ์์ฑ/์ถ๋ ฅ ์ค์ผ์ค๋ง ๊ฐ๋ฅ - โ ์ด์ ์ ๋ ฅ ๊ตฌ์ฑ (์ ์ ๋ ฅ SOC + e-ink ์ ์ง ์ ๋ ฅ)
/etc/dphys-swapfile ํ์ผ์ ํธ์งํ๊ณ (sudo vim /etc/dphys-swapfile ๋ฑ์ผ๋ก) CONF_SWAPSIZE ๊ฐ์ 1024๋ก ๋ณ๊ฒฝํ์ธ์.
์ค์ํ์ผ์ ๋น๋ ์ค ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ์ ๋ฐฉ์งํ๊ธฐ ์ํ ๊ฒ์
๋๋ค.
๊ธฐ๋ณธ ์ค์ (256MB)์์๋ OnnxStream ๋ชจ๋ธ์ ๋น๋ํ ๋ ์ค๋จ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ผ๋ฏ๋ก
์ต์ 1024MB ์ด์์ผ๋ก ๋๋ฆฌ๋ ๊ฒ์ด ์์ ์ ์
๋๋ค.
sudo raspi-config
Choose Interfacing Options -> SPI -> Yes Enable SPI interface
sudo reboot๋จผ์ ์๋ ๋ช ๋ น์ผ๋ก ์ด ์ ์ฅ์๋ฅผ ๋ค์ด๋ก๋ํ์ธ์:
sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt install git
git clone https://github.com/mseokq23/jihwa.git๊ทธ๋ฐ ๋ค์ ์ค์น ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ์ธ์:
cd jihwa
chmod +x scripts/install.sh
scripts/install.shscripts/install.sh๋ ํ์ํ ๋ชจ๋ ์์คํ
ํจํค์ง, ํ์ด์ฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐ OnnxStream(Stable Diffusion)์ ์ค์นํ๋ ๋ช
๋ น์ด๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
์ ์ฒด ๋น๋ ๊ณผ์ ์ ์๋นํ ์ค๋ ๊ฑธ๋ฆฝ๋๋ค(6 ์๊ฐ ์์).
cd jihwa # ๋ชจ๋ ๋ช
๋ น์ด๋ jihwa์์๋ง ์คํํด์ผํฉ๋๋ค.python3 src/generate_picture.py image_dir => ์ด๋ฏธ์ง ์์ฑ์ ์ํ ๊ธฐ๋ณธ ๋ช
๋ น์ด์
๋๋ค.
์ด ๋ช ๋ น์ ํ๋กฌํํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๊ณ ์ ์ด๋ฆ์ ๊ฐ์ง ์ ์ด๋ฏธ์ง์ ํ์ํ๊ธฐ ์ฝ๊ฒ 'output.png'๋ผ๋ ์ด๋ฆ์ ๋ณต์ฌ๋ณธ์ ์์ฑํฉ๋๋ค.
์๋๋ python3 src/generate_picture.py์์ ์ฌ์ฉํ ์ ์๋ ๋ช
๋ น์ด ์ต์
(์ปค๋งจ๋๋ผ์ธ ์ธ์)์
๋๋ค.
์์
python3 src/generate_picture.py --[์ ํ์ธ์1] --[์ ํ์ธ์2] --[์ ํ์ธ์3] [ํ์์ธ์]
| ์ธ์ | ์ค๋ช |
|---|---|
| output_dir | ์์ฑ๋ ์ด๋ฏธ์ง๋ฅผ ์ ์ฅํ ๋๋ ํฐ๋ฆฌ (ํ์, ์์น ์ธ์) |
| ์ต์ | ์ค๋ช |
|---|---|
| --prompts | ์ฌ์ฉํ ํ๋กฌํํธ ํ์ผ (๊ธฐ๋ณธ๊ฐ: prompts/flowers.json) |
| --prompt | ์ง์ ํ๋กฌํํธ๋ฅผ ์ ๋ ฅ (์ ๋ ฅ ์ ํ๋กฌํํธ ํ์ผ ๋์ ์ฌ์ฉ) |
| --seed | ์ด๋ฏธ์ง ์์ฑ์ ์ํ ์๋ ๊ฐ (๊ธฐ๋ณธ๊ฐ: 1~10000 ์ค ๋ฌด์์) |
| --steps | ์ถ๋ก ์คํ ์ (๊ธฐ๋ณธ๊ฐ: 3) |
| --width | ์์ฑ ์ด๋ฏธ์ง์ ๋๋น (๊ธฐ๋ณธ๊ฐ: 480) |
| --height | ์์ฑ ์ด๋ฏธ์ง์ ๋์ด (๊ธฐ๋ณธ๊ฐ: 800) |
| --sd | Stable Diffusion ์คํ ํ์ผ ๊ฒฝ๋ก (๊ธฐ๋ณธ๊ฐ: OnnxStream/src/build/sd) |
| --model | ์ฌ์ฉํ Stable Diffusion ๋ชจ๋ธ ๊ฒฝ๋ก (๊ธฐ๋ณธ๊ฐ: models/stable-diffusion-xl-turbo-1.0-anyshape-onnxstream) => ์ฌ์ฉํ ๋ชจ๋ธ์ ๋ณ๊ฒฝํ๊ณ ์ถ์ ๊ฒฝ์ฐ ์ด๊ฑธ๋ก ๋ณ๊ฒฝํ๋ฉด ๋จ. |
|(ํ์ฌ FP32 Aritmetic์ ์ฌ์ฉํ๊ณ ์๊ธฐ์ FP16 aritmetic์ผ๋ก ๋ณ๊ฒฝ๋ ๊ณ ๋ คํด์ผํฉ๋๋ค.)
cd jihwa # ๋ชจ๋ ๋ช
๋ น์ด๋ jihwa์์๋ง ์คํํด์ผํฉ๋๋ค.python3 src/display_picture.py image_dir/output.png => ์ด๋ฏธ์ง ์์ฑ์ ์ํ ๊ธฐ๋ณธ ๋ช
๋ น์ด์
๋๋ค.
| ์ด๋ฏธ์ง ๋ช
์ด output.png์ด ์๋ bunch_of_marigolds_in_cubism_style_seed_6651_steps_3.png ๋๋ output %d์ ๊ฐ์ ์ ์๊ธฐ์ ์ ํ์ธํ๊ณ ํ์
์ผํฉ๋๋ค.
๋ ๋ง์ ์ต์
์ ๋ณด๋ ค๋ฉด -h ๋๋ --help ํ๋๊ทธ ์ฐ์ธ์.
์๋ ์ต์ ๋ค์ src/display_picture.py ๋ฅผ ์คํํ ๋ ์ฌ์ฉํ ์ ์๋ ๊ฒ๋ค์ ๋๋ค.
์ต์ ์กฐํฉ์ ๋ฐ๋ผ
- ์ค์ ๋์คํ๋ ์ด๋ก ์ ์ก
- ์๋ฎฌ๋ ์ด์ (ํ์ผ ์ ์ฅ๋ง)
- ํฌ๋กญ/๋ฆฌ์ฌ์ด์ฆ ๋ฐฉ์
- ํ๋ฉด ๋ฐฉํฅ
- ๋์คํ๋ ์ด ์ข ๋ฅ ๋ฑ์ ๊ฒฐ์ ํ ์ ์์ต๋๋ค. ํ์ํ ์ต์ ์ ์กฐํฉํด์ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
| ์ต์ | ์ค๋ช |
|---|---|
| image | (ํ์) ์ฒ๋ฆฌํ ์ ๋ ฅ ์ด๋ฏธ์ง ํ์ผ ๊ฒฝ๋ก |
| -o, --output | ๊ฒฐ๊ณผ ์ด๋ฏธ์ง๋ฅผ ์ ์ฅํ ๊ฒฝ๋ก (์ ํ) |
| -p, --portrait | ์ธ๋ก ๋ชจ๋๋ก ์ถ๋ ฅ (๊ฐ๋ก/์ธ๋ก ์ ํ) |
| -c, --centre_crop | ์ง๋ฅ์ ํฌ๋กญ ๋์ ์ค์ ํฌ๋กญ ์ฌ์ฉ |
| -r, --resize_only | ํฌ๋กญ ์์ด ๋จ์ ๋ฆฌ์ฌ์ด์ฆ๋ง ์ํ |
| -s, --simulate_display | ์ค์ e-Paper ๋์คํ๋ ์ด ์์ด ์๋ฎฌ๋ ์ด์ ๋ชจ๋(์ถ๋ ฅ X) |
| --width | ๋์คํ๋ ์ด ๋๋น ์ง์ (๊ธฐ๋ณธ๊ฐ: 480) |
| --height | ๋์คํ๋ ์ด ๋์ด ์ง์ (๊ธฐ๋ณธ๊ฐ: 800) |
| --epd | ์ฌ์ฉํ Waveshare EPD ๋ชจ๋ ํ์ ์ง์ (์: epd7in3f) |
| --debug | ๋๋ฒ๊ทธ ๋ก๊น ํ์ฑํ |
# python3 src/display_picture.py [์ด๋ฏธ์งํ์ผ] [์ต์
๋ค]
python3 src/display_picture.py example.jpg --epd epd7in3f
python3 src/display_picture.py example.jpg -p -o output.jpg
python3 src/display_picture.py example.jpg --simulate_display์ด๋ฏธ์ง๋ฅผ ๋ก๋ํด์ Waveshare e-ink ๋์คํ๋ ์ด๋ก ์ถ๋ ฅ : โ ์ต์ ์ --simulate_display๋ฅผ ์ฃผ์ง ์์ผ๋ฉด display_waveshare ํจ์๊ฐ ์คํ๋์ด ์ด๋ฏธ์ง๋ฅผ ์ค์ ๋์คํ๋ ์ด์ ์ถ๋ ฅํฉ๋๋ค.
์๋ฎฌ๋ ์ด์ ๋ชจ๋ (๋์คํ๋ ์ด ์ถ๋ ฅ X): โ -s ๋๋ --simulate_display ์ต์ ์ฌ์ฉ ์ ์ค์ ๋์คํ๋ ์ด ์ฐ๊ฒฐ ์์ด ์ฝ๋ ์คํ(์ด๋ฏธ์ง ์ ์ฅ ๋ฑ๋ง ์ํ).
๋์คํ๋ ์ด ๋ฐฉํฅ ์ ํ(์ธ๋ก/๊ฐ๋ก): โ -p ๋๋ --portrait ์ต์ ์ฌ์ฉ ์ ์ธ๋ก ๋ชจ๋๋ก ์ถ๋ ฅ.
์ง๋ฅ์ ํฌ๋กญ/๋จ์ ์ค์ ํฌ๋กญ/๋ฆฌ์ฌ์ด์ฆ๋ง: โ -c (--centre_crop): ์ค์ ํฌ๋กญ โ -r (--resize_only): ๋ฆฌ์ฌ์ด์ฆ๋ง โ ์ต์ ๋ฏธ์ฌ์ฉ ์ ์ง๋ฅ์ ํฌ๋กญ(ํ์ ๋ ๊ธฐ๋ฐ) => ์ง๋ฅ์ ํฌ๋กญ์ด ํจ์ฌ ์ข์
๋์คํ๋ ์ด ์ข ๋ฅ ์ ํ: โ --epd epd7in3f ํํ๋ก ๋์คํ๋ ์ด ์ข ๋ฅ ์ง์ ๊ฐ๋ฅ.
๊ฐ๋ก๋ก ๋ฐฉํฅ ๋์คํ๋ ์ด์ ์ธ๋ก ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๋ ค๋ฉด generate_picture.py์ ๋๋น์ ๋์ด ๊ฐ์ ๋ฐ๊พธ๊ณ display_picture.py ์คํฌ๋ฆฝํธ์ -p๋ฅผ ํฌํจํ์ธ์.
์๋๋ ์ธ๋ก๊ฐ ์๋ ๊ฐ๋ก ๋ฐฉํฅ์ผ๋ก ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ ํ์ํ๊ธฐ ์ํ ์์ ์คํฌ๋ฆฝํธ์
๋๋ค.
python src/generate_picture.py --width=800 --height=480 image_dir
python src/display_picture.py -c -p image_dir/output.png
์์ ๊ฐ์ด ์
๋ ฅํ๋ฉด ์ธ๋ก๋ฐฉํฅ์ผ๋ก ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ ์ถ๋ ฅํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค.
๋งค์ผ ๊ฐ์ ์๊ฐ์ ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ ์๋์ผ๋ก ํ์ํ๋ ค๋ฉด crontab์ ํ์ฉํ ์ ์์ต๋๋ค.
์๋ cron_auto ์คํฌ๋ฆฝํธ๋ฅผ ์์ฑํ๊ณ chmod +x๋ก ์คํ ๊ฐ๋ฅํ๊ฒ ๋ง๋ ํ,
crontab์ ๋ฑ๋กํ๋ฉด ์์คํ
์ด ์์ ๋ง๋ค ์๋์ผ๋ก ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ ์ถ๋ ฅํฉ๋๋ค.
ํ: ์ฌ๋ฆ์ฒ ๊ณ ์จ ํ๊ฒฝ์์๋ ๋์คํ๋ ์ด๊ฐ ์ผ์์ ์ผ๋ก ๋ณ์๋ ์ ์์ผ๋ฏ๋ก
์ด๋ฏธ์ง ์์ฑ๊ณผ ๋์คํ๋ ์ด ์
๋ฐ์ดํธ ์ฌ์ด์ sleep 30 ๊ฐ์ ์ง์ฐ์ ๋ฃ๋ ๊ฒ๋ ๊ณ ๋ คํด๋ณด์ธ์.
#!/bin/bash
cd "/home/jihwa"
python jihwa/src/generate_picture.py --width 480 --height 800 image_dir
python jihwa/src/display_picture.py -r image_dir/output.png๋น์ฐํ ์ฝ๋๊ฐ ์๋ ์์น๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ๋ณ๊ฒฝํ์ธ์.
๊ทธ๋ฐ ๋ค์ crontab์ ํญ๋ชฉ์ ์ถ๊ฐํ์ต๋๋ค(crontab -e๋ก crontab ํ์ผ ํธ์ง):
0 0 * * * /home/jihwa/bin/cron_auto
์ด ๋ช
๋ น์ ๋งค์ผ ์์ ์ cron_auto๋ฅผ ์คํํฉ๋๋ค.
e-paper ๋์คํ๋ ์ด๋ ์จ๋์ ๋ฏผ๊ฐํ๋ค๋ ์ ์ ์ ์ํ์ธ์. ๋ผ์ฆ๋ฒ ๋ฆฌ ํ์ด ์ ๋ก์ ํ๊ฒฝ์ ๋ฐ๋ผ ์ฅ์๊ฐ ๋จ๊ฑฐ์์ง ์ ์์ผ๋ฉฐ, ์ด๋ก ์ธํด ๋์คํ๋ ์ด์ ๋ณ์์ด ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ ์ด๋ฏธ์ง ์์ฑ ํ ๋์คํ๋ ์ด ์ ๋ฐ์ดํธ๋ฅผ ์ง์ฐ์์ผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
prompts/ ๋๋ ํ ๋ฆฌ์ .json ํ์ผ์ ๋ค์ฐจ์ ๋ฐฐ์ด ํ์์ "ํ๋กฌํํธ ์กฐํฉ ์กฐ๊ฐ๋ค"๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
์๋ฅผ ๋ค์ด [[ "sunset", "dawn" ], [ "over mountains", "by the sea" ]] ์ ๊ฐ์ด ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ,
๊ฐ ๋ฐฐ์ด์์ ํ๋์ฉ ๋ฌด์์๋ก ์ ํ๋์ด "sunset over mountains" ์ ๊ฐ์ ํ๋กฌํํธ๊ฐ ๋ฉ๋๋ค.
--prompt: ์ง์ ๋จ์ผ ํ๋กฌํํธ ๋ฌธ์์ด ์ง์ --prompts prompts/default.json: ํ์ผ ๊ธฐ๋ฐ ๋๋ค ์กฐํฉ ์ฌ์ฉ
์ ์ฅ์(๊ณ ์ ์ด๋ฆ ์ ์ฅ ๊ธฐ๋ฅ์ ์ถ๊ฐํด์ ๊ทธ๋ฆผ 1,2,3,4๋ก ๋์ค๋๋ก ํด์ผํ๊ณ 50๊ฐ ์ด๊ณผ์ ๊ทธ๋ฆผ์ด ์์ ๊ฒฝ์ฐ 51์ 1์ผ๋ก ๋ฎ์ด์ฐ๊ธฐ)(์์ ์ค)
์ด๋ฏธ์ง๋ฅผ ํ๋ฃจ์ ํ ๋ฒ์ฉ ์ ์ฅํด๋ 2๋
๋๊ฒ 1GB ๋ฏธ๋ง์ ๊ณต๊ฐ๋ง ์ฐจ์งํฉ๋๋ค.
ํ์ง๋ง ์ด๋ฏธ์ง๊ฐ ๋งค๋ฒ ์๋ก ์์ฑ๋๋ฏ๋ก ๊ณ ์ ์ด๋ฆ ์ ์ฅ ๊ธฐ๋ฅ์ ๋นํ์ฑํํด๋ ๋ฉ๋๋ค.
# image_dir/uuid.png โ ๋ฎ์ด์ฐ๊ธฐ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝ
fullpath = os.path.join(image_dir, "output.png")๊ฐ๋ฐ์ด ์๋ฃ๋ SD์นด๋๋ฅผ img๋ก ๋ง๋ค์ด์ ๋ค๋ฅธ SD ์นด๋ ๊ทธ๋๋ก ๋ฃ๊ณ ์ ํ๋ฉด ๊ธฐ์กด SD ์นด๋์ ๋น๊ณต๊ฐ๊น์ง imgํ์ผ์ ์ฉ๋์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ ์ค์ ์ฉ๋(24GB)๊ฐ ์๋ 64GB(๊ฐ๋ฐ์ค์ธ SD์นด๋์ ์ต๋์ฉ๋)์ผ๋ก img ํ์ผ์ด ๋ง๋ค์ด์ง ๋๋ฌธ์, ๋ ์ ์ ์ฉ๋์ SD์นด๋์ ์ฎ๊ธฐ๊ธฐ ์ํด์๋ ๋ณต์ ํ imgํ์ผ์ ์ฉ๋์ ์ค์ด๋ ๊ณผ์ ์ด ํ์ํฉ๋๋ค.
์ด๋ฅผ ์ํด Pishrink๋ฅผ ์ฌ์ฉํ์๋ฉด ๋๋ฉฐ, SD์นด๋๋ฅผ imgํ์ผ๋ก ๋ง๋๋ ๊ฒ์ Win32 Disk imager๋ฅผ ์ด์ฉํ๊ณ , ์์ฑ๋ imgํ์ผ(pishrink์ผ๋ก ์ฉ๋์ด ์ถ์๋ ํ์ผ)์ rufus๋ฅผ ํตํด ํฌํ ํฉ๋๋ค.
** SD์นด๋๋ฅผ imgํ์ผ๋ก ๋ง๋๋ ๊ฒ: Win32 Disk imager disk imager ์ค์น ์ฌ์ดํธ **
** ์์ฑ๋ imgํ์ผ(pishrink์ผ๋ก ์ฉ๋์ด ์ถ์๋ ํ์ผ)์ ํฌํ : rufus rufus ์ค์น ์ฌ์ดํธ **
์๋ ๊ธ์ ์ฐธ๊ณ ํ์ธ์.
PiShrink๋ก ๋ผ์ฆ๋ฒ ๋ฆฌํ์ด ์ด๋ฏธ์ง ์ถ์
์ค๊ฐ๋ง๋ค ์๋ก์ด ํ๋กฌํํธ ์์ ์ด๋ ๋ง์ ์ฝ๋๋ฅผ ์ ๋ฐ์ดํธ ํด์ผํ ๋.(ํ์ง๋ง Private ์ํ์ธ ๊ฒฝ์ฐ ์๋จ.)
(ํ๋กฌํํธ ๋ณต์ ์ฉ git)[https://github.com/mseokq23/prompt_create.git]
- ์ ์ฅ์๋ฅผ ํด๋ก ํฉ๋๋ค:
git clone https://github.com/mseokq23/prompt_create.git- ํด๋ก ํ ๋๋ ํ ๋ฆฌ๋ก ์ด๋ํฉ๋๋ค:
cd prompt_create- prompts ํด๋๋ฅผ ์ํ๋ ๊ฒฝ๋ก๋ก ๋ณต์ฌํฉ๋๋ค:
cp -r /home/jion/jihwa/prompt_create/[ํ์ผ๋ช
].json /home/jion/jihwa/prompts์์ฑ๋ ์ด๋ฏธ์ง๋ค์ ์ด๋ฆ์ด ๋๋ฌด ๊ธธ์ด์ ํ ์คํธํ ๋, ๋ฒ๊ฑฐ๋ก์ธ ๊ฒฝ์ฐ ์๋ ๋ช ๋ น์ด๋ก ์ด๋ฆ์ ๋ฐ๊ฟ๋ณด์ธ์.
mv [์์ ์ ํ์ผ๋ช
].json [์์ ํ ํ์ผ๋ช
].json
๊ทธ๋ผ python3 src/display_picture.py -c image_dir/[์์ ํ ํ์ผ๋ช
] ์ด๋ ๊ฒ ์งง๊ฒ ์์ฑํ ์ ์์ต๋๋ค.
