OpenVINO ํ•ด์ปคํ†ค: Raspberry Pi์—์„œ ์Œ์„ฑ๊ณผ ๊ฐ์ • ์ธ์‹

30์›” 1์ผ๋ถ€ํ„ฐ XNUMX์›” XNUMX์ผ๊นŒ์ง€ ๋‹ˆ์ฆˆ๋‹ˆ๋…ธ๋ธŒ๊ณ ๋กœ๋“œ์—์„œ ๊ฐœ์ตœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. OpenVINO ํ•ด์ปคํ†ค. ์ฐธ๊ฐ€์ž๋“ค์€ Intel OpenVINO ํˆดํ‚ท์„ ์‚ฌ์šฉํ•˜์—ฌ ์ œํ’ˆ ์†”๋ฃจ์…˜์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ์ƒ์„ฑํ•˜๋ผ๋Š” ์š”์ฒญ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. ์ฃผ์ตœ์ธก์€ ์ž‘์—…์„ ์„ ํƒํ•  ๋•Œ ์ฐธ๊ณ ํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€๋žต์ ์ธ ์ฃผ์ œ ๋ชฉ๋ก์„ ์ œ์•ˆํ–ˆ์ง€๋งŒ ์ตœ์ข… ๊ฒฐ์ •์€ ํŒ€์˜ ๋ชซ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ œํ’ˆ์— ํฌํ•จ๋˜์ง€ ์•Š์€ ๋ชจ๋ธ์˜ ์‚ฌ์šฉ์„ ์žฅ๋ คํ–ˆ์Šต๋‹ˆ๋‹ค.

OpenVINO ํ•ด์ปคํ†ค: Raspberry Pi์—์„œ ์Œ์„ฑ๊ณผ ๊ฐ์ • ์ธ์‹

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ œํ’ˆ์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ๋งŒ๋“ค์—ˆ๊ณ  ๊ฒฐ๊ตญ XNUMX์œ„๋ฅผ ์ฐจ์ง€ํ–ˆ๋Š”์ง€์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฒˆ ํ•ด์ปคํ†ค์—๋Š” 10๊ฐœ ์ด์ƒ์˜ ํŒ€์ด ์ฐธ๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค ์ค‘ ์ผ๋ถ€๊ฐ€ ๋‹ค๋ฅธ ์ง€์—ญ์—์„œ ์™”๋‹ค๋Š” ๊ฒƒ์€ ์ข‹์€ ์ผ์ž…๋‹ˆ๋‹ค. ํ•ด์ปคํ†ค ์žฅ์†Œ๋Š” ๋‹ˆ์ฆˆ๋‹ˆ๋…ธ๋ธŒ๊ณ ๋กœ๋“œ์˜ ๊ณ ๋Œ€ ์‚ฌ์ง„์ด ๋‚ด๋ถ€์— ๊ฑธ๋ ค ์žˆ๋Š” "Kremlinsky on Pochain" ๋‹จ์ง€์˜€์Šต๋‹ˆ๋‹ค! (ํ˜„์žฌ Intel์˜ ์ค‘์•™ ์‚ฌ๋ฌด์‹ค์€ Nizhny Novgorod์— ์žˆ์Œ์„ ์ƒ๊ธฐ์‹œ์ผœ๋“œ๋ฆฝ๋‹ˆ๋‹ค.) ์ฐธ๊ฐ€์ž๋“ค์—๊ฒŒ๋Š” 26์‹œ๊ฐ„ ๋™์•ˆ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ๋งˆ์ง€๋ง‰์—๋Š” ์†”๋ฃจ์…˜์„ ๋ฐœํ‘œํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ณ„๋„์˜ ์žฅ์ ์€ ๊ณ„ํš๋œ ๋ชจ๋“  ๊ฒƒ์ด ์‹ค์ œ๋กœ ๊ตฌํ˜„๋˜์—ˆ์œผ๋ฉฐ ํ”„๋ ˆ์  ํ…Œ์ด์…˜์— ์•„์ด๋””์–ด๊ฐ€ ๋‚จ์•„ ์žˆ์ง€ ์•Š์€์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ๋ชจ ์„ธ์…˜์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ƒํ’ˆ, ๊ฐ„์‹, ์Œ์‹ ๋“ฑ ๋ชจ๋“  ๊ฒƒ์ด ๊ฑฐ๊ธฐ์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค!

๋˜ํ•œ Intel์€ ์„ ํƒ์ ์œผ๋กœ ์นด๋ฉ”๋ผ, Raspberry PI, Neural Compute Stick 2๋ฅผ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค.

์ž‘์—… ์„ ํƒ

์ž์œ  ํ˜•์‹ ํ•ด์ปคํ†ค์„ ์ค€๋น„ํ•  ๋•Œ ๊ฐ€์žฅ ์–ด๋ ค์šด ๋ถ€๋ถ„ ์ค‘ ํ•˜๋‚˜๋Š” ๋„์ „ ๊ณผ์ œ๋ฅผ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋ฐœํ‘œ์—์„œ ์ด๊ฒƒ์ด ๋งค์šฐ ํ™˜์˜๋ฐ›๋Š”๋‹ค๊ณ  ๋งํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์•„์ง ์ œํ’ˆ์— ์—†๋Š” ๊ฒƒ์„ ์ƒ๊ฐํ•ด๋‚ด๊ธฐ๋กœ ์ฆ‰์‹œ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ถ„์„ํ•˜๊ณ  ๋ชจ๋ธ, ํ˜„์žฌ ๋ฆด๋ฆฌ์Šค์˜ ์ œํ’ˆ์— ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๋‚ด์šฉ์„ ๋ณด๋ฉด ๋Œ€๋ถ€๋ถ„์ด ๋‹ค์–‘ํ•œ ์ปดํ“จํ„ฐ ๋น„์ „ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค๋Š” ๊ฒฐ๋ก ์— ๋„๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ OpenVINO๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†๋Š” ์ปดํ“จํ„ฐ ๋น„์ „ ๋ถ„์•ผ์˜ ๋ฌธ์ œ๋ฅผ ์ œ๊ธฐํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์–ด๋ ต๊ณ , ์„ค์‚ฌ ๊ทธ๊ฒƒ์ด ๋ฐœ๋ช…๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ์‚ฌ์ „ ํ›ˆ๋ จ๋œ ๋ชจ๋ธ์„ ๊ณต๊ฐœ ๋„๋ฉ”์ธ์—์„œ ์ฐพ๊ธฐ๊ฐ€ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์Œ์„ฑ ์ฒ˜๋ฆฌ ๋ฐ ๋ถ„์„์ด๋ผ๋Š” ๋‹ค๋ฅธ ๋ฐฉํ–ฅ์„ ํƒ๊ตฌํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ง์—์„œ ๊ฐ์ •์„ ์ธ์‹ํ•˜๋Š” ํฅ๋ฏธ๋กœ์šด ์ž‘์—…์„ ๊ณ ๋ คํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. OpenVINO์—๋Š” ์ด๋ฏธ ์–ผ๊ตด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ๋žŒ์˜ ๊ฐ์ •์„ ๊ฒฐ์ •ํ•˜๋Š” ๋ชจ๋ธ์ด ์žˆ์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์ด๋ก ์ ์œผ๋กœ๋Š” ์†Œ๋ฆฌ์™€ ์ด๋ฏธ์ง€ ๋ชจ๋‘์— ์ž‘๋™ํ•˜๋Š” ๊ฒฐํ•ฉ๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ์ •ํ™•๋„๊ฐ€ ๋†’์•„์ง‘๋‹ˆ๋‹ค.
  • ์นด๋ฉ”๋ผ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์‹œ์•ผ๊ฐ์ด ์ข๊ธฐ ๋•Œ๋ฌธ์— ๋„“์€ ์˜์—ญ์„ ์ปค๋ฒ„ํ•˜๋ ค๋ฉด ๋‘ ๋Œ€ ์ด์ƒ์˜ ์นด๋ฉ”๋ผ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์†Œ๋ฆฌ์—๋Š” ์ด๋Ÿฌํ•œ ์ œํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.

์•„์ด๋””์–ด๋ฅผ ๋ฐœ์ „์‹œํ‚ค์ž. ์†Œ๋งค ๋ถ€๋ฌธ์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ๊ธฐ์ดˆ๋กœ ์‚ผ์ž. ๋งค์žฅ ๊ฒฐ์ œ ์‹œ ๊ณ ๊ฐ ๋งŒ์กฑ๋„๋ฅผ ์ธก์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณ ๊ฐ ์ค‘ ํ•œ ๋ช…์ด ์„œ๋น„์Šค์— ๋งŒ์กฑํ•˜์ง€ ๋ชปํ•˜๊ณ  ๋ชฉ์†Œ๋ฆฌ๋ฅผ ๋†’์ด๊ธฐ ์‹œ์ž‘ํ•˜๋ฉด ์ฆ‰์‹œ ๊ด€๋ฆฌ์ž์—๊ฒŒ ๋„์›€์„ ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ๊ฒฝ์šฐ ์‚ฌ๋žŒ์˜ ์Œ์„ฑ ์ธ์‹์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋งค์žฅ ์ง์›๊ณผ ๊ณ ๊ฐ์„ ๊ตฌ๋ณ„ํ•˜๊ณ  ๊ฐ ๊ฐœ์ธ์— ๋Œ€ํ•œ ๋ถ„์„์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธ€์Ž„์š”, ๋งค์žฅ ์ง์›์˜ ํ–‰๋™์„ ์ง์ ‘ ๋ถ„์„ํ•˜๊ณ  ํŒ€์˜ ๋ถ„์œ„๊ธฐ๋ฅผ ํ‰๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ข‹์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค!

์šฐ๋ฆฌ๋Š” ์†”๋ฃจ์…˜์— ๋Œ€ํ•œ ์š”๊ตฌ ์‚ฌํ•ญ์„ ๊ณต์‹ํ™”ํ•ฉ๋‹ˆ๋‹ค.

  • ๋Œ€์ƒ ์žฅ์น˜์˜ ์ž‘์€ ํฌ๊ธฐ
  • ์‹ค์‹œ๊ฐ„ ์šด์˜
  • ์ €๋ ดํ•œ ๊ฐ€๊ฒฉ
  • ์‰ฌ์šด ํ™•์žฅ์„ฑ

๊ฒฐ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” Raspberry Pi 3 c๋ฅผ ๋Œ€์ƒ ์žฅ์น˜๋กœ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ธํ…” NCS 2.

์—ฌ๊ธฐ์—์„œ NCS์˜ ์ค‘์š”ํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋ฅผ ์–ธ๊ธ‰ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ‘œ์ค€ CNN ์•„ํ‚คํ…์ฒ˜์—์„œ ๊ฐ€์žฅ ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ์‚ฌ์šฉ์ž ์ •์˜ ๋ ˆ์ด์–ด๊ฐ€ ์žˆ๋Š” ๋ชจ๋ธ์„ ์‹คํ–‰ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋‚ฎ์€ ์ˆ˜์ค€์˜ ์ตœ์ ํ™”๋ฅผ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค.

ํ•ด์•ผ ํ•  ์ž‘์€ ์ผ์ด ํ•˜๋‚˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ดํฌ๋ฅผ ๊ตฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜ USB ๋งˆ์ดํฌ๋ผ๋ฉด ๊ดœ์ฐฎ์ง€๋งŒ RPI์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๋ณด๊ธฐ์— ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์„œ๋„ ํ•ด๊ฒฐ์ฑ…์€ ๋ฌธ์ž ๊ทธ๋Œ€๋กœ "๊ฐ€๊นŒ์šด ๊ณณ์— ์žˆ์Šต๋‹ˆ๋‹ค." ์Œ์„ฑ์„ ๋…น์Œํ•˜๊ธฐ ์œ„ํ•ด ํ‚คํŠธ์— ํฌํ•จ๋œ Voice Bonnet ๋ณด๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. Google AIY ์Œ์„ฑ ํ‚คํŠธ, ์œ ์„  ์Šคํ…Œ๋ ˆ์˜ค ๋งˆ์ดํฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์—์„œ Raspbian์„ ๋‹ค์šด๋กœ๋“œํ•˜์„ธ์š”. AIY ํ”„๋กœ์ ํŠธ ์ €์žฅ์†Œ ํ”Œ๋ž˜์‹œ ๋“œ๋ผ์ด๋ธŒ์— ์—…๋กœ๋“œํ•˜๊ณ  ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์ดํฌ๊ฐ€ ์ž‘๋™ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. 5์ดˆ ๊ธธ์ด์˜ ์˜ค๋””์˜ค๋ฅผ ๋…น์Œํ•˜๊ณ  ํŒŒ์ผ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

arecord -d 5 -r 16000 test.wav

๋งˆ์ดํฌ๊ฐ€ ๋งค์šฐ ๋ฏผ๊ฐํ•˜๊ณ  ์†Œ์Œ์„ ์ž˜ ํฌ์ฐฉํ•œ๋‹ค๋Š” ์ ์„ ์ฆ‰์‹œ ์ฃผ๋ชฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด alsamixer๋กœ ์ด๋™ํ•˜์—ฌ ์บก์ฒ˜ ์žฅ์น˜๋ฅผ ์„ ํƒํ•˜๊ณ  ์ž…๋ ฅ ์‹ ํ˜ธ ๋ ˆ๋ฒจ์„ 50-60%๋กœ ์ค„์ด์„ธ์š”.

OpenVINO ํ•ด์ปคํ†ค: Raspberry Pi์—์„œ ์Œ์„ฑ๊ณผ ๊ฐ์ • ์ธ์‹
ํŒŒ์ผ๋กœ ๋ณธ์ฒด๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์ด ๋งž๊ณ  ๋šœ๊ป‘์œผ๋กœ ๋‹ซ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ‘œ์‹œ๊ธฐ ๋ฒ„ํŠผ ์ถ”๊ฐ€

AIY Voice Kit๋ฅผ ๋ถ„ํ•ดํ•˜๋ฉด์„œ ์†Œํ”„ํŠธ์›จ์–ด๋กœ ๋ฐฑ๋ผ์ดํŠธ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋Š” RGB ๋ฒ„ํŠผ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ–ˆ์Šต๋‹ˆ๋‹ค. "Google AIY Led"๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ๋ฌธ์„œ๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. https://aiyprojects.readthedocs.io/en/latest/aiy.leds.html
์ธ์‹๋œ ๊ฐ์ •์„ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด ์ด ๋ฒ„ํŠผ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์–ด๋–จ๊นŒ์š”? ํด๋ž˜์Šค๋Š” 7๊ฐœ๋ฟ์ด๊ณ  ๋ฒ„ํŠผ์—๋Š” 8๊ฐ€์ง€ ์ƒ‰์ƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฑ ๋งž์Šต๋‹ˆ๋‹ค!

GPIO๋ฅผ ํ†ตํ•ด ๋ฒ„ํŠผ์„ Voice Bonnet์— ์—ฐ๊ฒฐํ•˜๊ณ  ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค(AIY ํ”„๋กœ์ ํŠธ์˜ ๋ฐฐํฌ ํ‚คํŠธ์— ์ด๋ฏธ ์„ค์น˜๋˜์–ด ์žˆ์Œ).

from aiy.leds import Leds, Color
from aiy.leds import RgbLeds

๊ฐ ๊ฐ์ •์ด RGB Tuple ํ˜•ํƒœ์˜ ํ•ด๋‹น ์ƒ‰์ƒ๊ณผ aiy.leds.Leds ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋ฅผ ๊ฐ–๋Š” ์‚ฌ์ „์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ƒ‰์ƒ์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

led_dict = {'neutral': (255, 255, 255), 'happy': (0, 255, 0), 'sad': (0, 255, 255), 'angry': (255, 0, 0), 'fearful': (0, 0, 0), 'disgusted':  (255, 0, 255), 'surprised':  (255, 255, 0)} 
leds = Leds()

๊ทธ๋ฆฌ๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ ๊ฐ์ •์— ๋Œ€ํ•œ ๊ฐ๊ฐ์˜ ์ƒˆ๋กœ์šด ์˜ˆ์ธก ํ›„์— ๊ทธ์— ๋”ฐ๋ผ (ํ‚ค๋ณ„๋กœ) ๋ฒ„ํŠผ์˜ ์ƒ‰์ƒ์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

leds.update(Leds.rgb_on(led_dict.get(classes[prediction])))

OpenVINO ํ•ด์ปคํ†ค: Raspberry Pi์—์„œ ์Œ์„ฑ๊ณผ ๊ฐ์ • ์ธ์‹
๋ฒ„ํŠผ, ๋ถˆํƒœ์›Œ๋ผ!

์Œ์„ฑ ์ž‘์—…

pyaudio๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋งˆ์ดํฌ์—์„œ ์ŠคํŠธ๋ฆผ์„ ์บก์ฒ˜ํ•˜๊ณ  webrtcvad๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†Œ์Œ์„ ํ•„ํ„ฐ๋งํ•˜๊ณ  ์Œ์„ฑ์„ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์Œ์„ฑ ๋ฐœ์ทŒ๋ฅผ ๋น„๋™๊ธฐ์‹์œผ๋กœ ์ถ”๊ฐ€ ๋ฐ ์ œ๊ฑฐํ•  ๋Œ€๊ธฐ์—ด์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

webrtcvad์—๋Š” ์ œ๊ณต๋œ ์กฐ๊ฐ์˜ ํฌ๊ธฐ์— ์ œํ•œ์ด ์žˆ์œผ๋ฏ€๋กœ(10/20/30ms์™€ ๊ฐ™์•„์•ผ ํ•˜๋ฉฐ) ๊ฐ์ • ์ธ์‹ ๋ชจ๋ธ์˜ ํ›ˆ๋ จ(๋‚˜์ค‘์— ๋ฐฐ์šฐ๊ฒ ์ง€๋งŒ)์€ 48kHz ๋ฐ์ดํ„ฐ์„ธํŠธ์—์„œ ์ˆ˜ํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 48000ร—20ms/1000ร—1(๋ชจ๋…ธ)=960๋ฐ”์ดํŠธ ํฌ๊ธฐ์˜ ์ฒญํฌ๋ฅผ ์บก์ฒ˜ํ•ฉ๋‹ˆ๋‹ค. Webrtcvad๋Š” ๊ฐ ์ฒญํฌ์— ๋Œ€ํ•ด True/False๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ์ด๋Š” ์ฒญํฌ์— ํˆฌํ‘œ๊ฐ€ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ๋…ผ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ํˆฌํ‘œ๊ฐ€ ์žˆ๋Š” ์ฒญํฌ๋ฅผ ๋ชฉ๋ก์— ์ถ”๊ฐ€ํ•˜๊ณ , ํˆฌํ‘œ๊ฐ€ ์—†์œผ๋ฉด ๋นˆ ์ฒญํฌ์˜ ์นด์šดํ„ฐ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ต๋‹ˆ๋‹ค.
  • ๋นˆ ์ฒญํฌ์˜ ์นด์šดํ„ฐ๊ฐ€ 30(600ms)๋ณด๋‹ค ํฌ๋ฉด ๋ˆ„์ ๋œ ์ฒญํฌ ๋ชฉ๋ก์˜ ํฌ๊ธฐ๋ฅผ ํ™•์ธํ•˜๊ณ , 250๋ณด๋‹ค ํฌ๋ฉด ํ์— ์ถ”๊ฐ€ํ•˜๋ฉฐ, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๊ธธ์ด๋ฅผ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ก์˜ ์–‘์€ ํ™”์ž๋ฅผ ์‹๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋ธ์— ์ œ๊ณตํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ๋นˆ ์ฒญํฌ์˜ ์นด์šดํ„ฐ๊ฐ€ ์—ฌ์ „ํžˆ < 30์ด๊ณ  ๋ˆ„์  ์ฒญํฌ ๋ชฉ๋ก์˜ ํฌ๊ธฐ๊ฐ€ 300์„ ์ดˆ๊ณผํ•˜๋Š” ๊ฒฝ์šฐ ๋ณด๋‹ค ์ •ํ™•ํ•œ ์˜ˆ์ธก์„ ์œ„ํ•ด ์กฐ๊ฐ์„ ๋Œ€๊ธฐ์—ด์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. (๊ฐ์ •์€ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€ํ•˜๋Š” ๊ฒฝํ–ฅ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—)

 def to_queue(frames):
    d = np.frombuffer(b''.join(frames), dtype=np.int16)
    return d

framesQueue = queue.Queue()
def framesThreadBody():
    CHUNK = 960
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 48000

    p = pyaudio.PyAudio()
    vad = webrtcvad.Vad()
    vad.set_mode(2)
    stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)
    false_counter = 0
    audio_frame = []
    while process:
        data = stream.read(CHUNK)
        if not vad.is_speech(data, RATE):
            false_counter += 1
            if false_counter >= 30:
                if len(audio_frame) > 250:              
                    framesQueue.put(to_queue(audio_frame,timestamp_start))
                    audio_frame = []
                    false_counter = 0

        if vad.is_speech(data, RATE):
            false_counter = 0
            audio_frame.append(data)
            if len(audio_frame) > 300:                
                    framesQueue.put(to_queue(audio_frame,timestamp_start))
                    audio_frame = []

์ด์ œ ๊ณต๊ฐœ ๋„๋ฉ”์ธ์—์„œ ์‚ฌ์ „ ํ›ˆ๋ จ๋œ ๋ชจ๋ธ์„ ์ฐพ๊ณ , github, Google๋กœ ์ด๋™ํ•ด์•ผ ํ•  ๋•Œ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‚ฌ์šฉ๋˜๋Š” ์•„ํ‚คํ…์ฒ˜์—๋Š” ์ œํ•œ์ด ์žˆ๋‹ค๋Š” ์ ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. ์ž…๋ ฅ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ๋ชจ๋ธ์„ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์ถ”๊ฐ€๋กœ OpenVINO์˜ ๋‚ด๋ถ€ ํ˜•์‹์ธ IR(Intermediate Representation)๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Š” ๋‹ค์†Œ ์–ด๋ ค์šด ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” github์—์„œ ์•ฝ 5~7๊ฐ€์ง€์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์†”๋ฃจ์…˜์„ ์‹œ๋„ํ–ˆ๊ณ , ๊ฐ์ • ์ธ์‹ ๋ชจ๋ธ์ด ์ฆ‰์‹œ ์ž‘๋™ํ–ˆ๋‹ค๋ฉด ์Œ์„ฑ ์ธ์‹์˜ ๊ฒฝ์šฐ ๋” ์˜ค๋ž˜ ๊ธฐ๋‹ค๋ ค์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ๋” ๋ณต์žกํ•œ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๋‹ค์Œ ์‚ฌํ•ญ์— ์ค‘์ ์„ ๋‘ก๋‹ˆ๋‹ค.

  • ๋ชฉ์†Œ๋ฆฌ๋กœ ๋Š๋ผ๋Š” ๊ฐ์ • - https://github.com/alexmuhr/Voice_Emotion
    ์ด๋Š” ๋‹ค์Œ ์›๋ฆฌ์— ๋”ฐ๋ผ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋””์˜ค๋Š” ํŠน์ • ํฌ๊ธฐ์˜ ๋ถ€๋ถ„์œผ๋กœ ์ž˜๋ ค์ง€๋ฉฐ, ๊ฐ ๋ถ€๋ถ„์— ๋Œ€ํ•ด ์šฐ๋ฆฌ๊ฐ€ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. MFCC ๊ทธ๋Ÿฐ ๋‹ค์Œ CNN์— ์ž…๋ ฅ์œผ๋กœ ์ œ์ถœํ•ฉ๋‹ˆ๋‹ค.
  • ์Œ์„ฑ ์ธ์‹ - https://github.com/linhdvu14/vggvox-speaker-identification
    ์—ฌ๊ธฐ์„œ๋Š” MFCC ๋Œ€์‹  ์ŠคํŽ™ํŠธ๋กœ๊ทธ๋žจ์„ ์‚ฌ์šฉํ•˜๊ณ  FFT ํ›„ ์‹ ํ˜ธ๋ฅผ CNN์— ๊ณต๊ธ‰ํ•˜๊ณ  ์ถœ๋ ฅ์—์„œ โ€‹โ€‹์Œ์„ฑ์˜ ๋ฒกํ„ฐ ํ‘œํ˜„์„ ์–ป์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ ์ด๋ก ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ๋ชจ๋ธ ๋ณ€ํ™˜์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. OpenVINO์—๋Š” ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๊ท€ํ•˜์˜ ์ œํ’ˆ์— ์‚ฌ์šฉ ๋ฐ ํฌํ•จ๋  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋ธ์ธ Open Model Zoo
  • Model Optimzer ๋•๋ถ„์— ๋‹ค์–‘ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ ํ˜•์‹(Tensorflow, ONNX ๋“ฑ)์˜ ๋ชจ๋ธ์„ ์ค‘๊ฐ„ ํ‘œํ˜„ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ถ”๋ก  ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋ฉด Intel ํ”„๋กœ์„ธ์„œ, Myriad ์นฉ ๋ฐ Neural Compute Stick ๊ฐ€์†๊ธฐ์—์„œ IR ํ˜•์‹์œผ๋กœ ๋ชจ๋ธ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • OpenCV์˜ ๊ฐ€์žฅ ํšจ์œจ์ ์ธ ๋ฒ„์ „(์ถ”๋ก  ์—”์ง„ ์ง€์› ํฌํ•จ)
    IR ํ˜•์‹์˜ ๊ฐ ๋ชจ๋ธ์€ .xml ๋ฐ .bin์ด๋ผ๋Š” ๋‘ ํŒŒ์ผ๋กœ ์„ค๋ช…๋ฉ๋‹ˆ๋‹ค.
    ๋ชจ๋ธ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด Model Optimizer๋ฅผ ํ†ตํ•ด IR ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.

    python /opt/intel/openvino/deployment_tools/model_optimizer/mo_tf.py --input_model speaker.hdf5.pb --data_type=FP16 --input_shape [1,512,1000,1]

    --data_type ๋ชจ๋ธ์ด ์ž‘๋™ํ•  ๋ฐ์ดํ„ฐ ํ˜•์‹์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. FP32, FP16, INT8์ด ์ง€์›๋ฉ๋‹ˆ๋‹ค. ์ตœ์ ์˜ ๋ฐ์ดํ„ฐ ์œ ํ˜•์„ ์„ ํƒํ•˜๋ฉด ์„ฑ๋Šฅ์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    --input_shape ์ž…๋ ฅ ๋ฐ์ดํ„ฐ์˜ ์ฐจ์›์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ธฐ๋Šฅ์€ C++ API์— ์žˆ๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ ์šฐ๋ฆฌ๋Š” ๊ทธ๋ ‡๊ฒŒ๊นŒ์ง€ ์ž์„ธํžˆ ์•Œ์•„๋ณด์ง€ ์•Š๊ณ  ๋‹จ์ˆœํžˆ ๋ชจ๋ธ ์ค‘ ํ•˜๋‚˜์— ๋Œ€ํ•ด ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
    ๋‹ค์Œ์œผ๋กœ ์ด๋ฏธ ๋ณ€ํ™˜๋œ IR ํ˜•์‹์˜ ๋ชจ๋ธ์„ DNN ๋ชจ๋“ˆ์„ ํ†ตํ•ด OpenCV์— ๋กœ๋“œํ•˜๊ณ  ์ „๋‹ฌํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

    import cv2 as cv
    emotionsNet = cv.dnn.readNet('emotions_model.bin',
                              'emotions_model.xml')
    emotionsNet.setPreferableTarget(cv.dnn.DNN_TARGET_MYRIAD)

    ์ด ๊ฒฝ์šฐ ๋งˆ์ง€๋ง‰ ์ค„์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ณ„์‚ฐ์„ Neural Compute Stick์œผ๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ธฐ๋ณธ ๊ณ„์‚ฐ์€ ํ”„๋กœ์„ธ์„œ์—์„œ ์ˆ˜ํ–‰๋˜์ง€๋งŒ Raspberry Pi์˜ ๊ฒฝ์šฐ ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์Šคํ‹ฑ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

    ๋‹ค์Œ์œผ๋กœ ๋…ผ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜ค๋””์˜ค๋ฅผ ํŠน์ • ํฌ๊ธฐ(0.4์ดˆ)์˜ ์ฐฝ์œผ๋กœ ๋‚˜๋ˆ„๊ณ  ์ด๋Ÿฌํ•œ ๊ฐ ์ฐฝ์„ MFCC๋กœ ๋ณ€ํ™˜ํ•œ ๋‹ค์Œ ๊ทธ๋ฆฌ๋“œ์— ๊ณต๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

    emotionsNet.setInput(MFCC_from_window)
    result = emotionsNet.forward()

    ๋‹ค์Œ์œผ๋กœ ๋ชจ๋“  ์ฐฝ์— ๋Œ€ํ•ด ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ํด๋ž˜์Šค๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ ํ•ด๊ฒฐ์ฑ…์ด์ง€๋งŒ ํ•ด์ปคํ†ค์˜ ๊ฒฝ์šฐ ์‹œ๊ฐ„์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋„ˆ๋ฌด ๋‚œํ•ดํ•œ ๊ฒƒ์„ ์ƒ๊ฐํ•ด๋‚ผ ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์•„์ง ํ•ด์•ผ ํ•  ์ผ์ด ๋งŽ์œผ๋‹ˆ ๋‹ค์Œ์œผ๋กœ ๋„˜์–ด๊ฐ€์„œ ์Œ์„ฑ ์ธ์‹์„ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ ๋…น์Œ๋œ ์Œ์„ฑ์˜ ์ŠคํŽ™ํŠธ๋กœ๊ทธ๋žจ์„ ์ €์žฅํ•  ์ผ์ข…์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์‹œ๊ฐ„์ด ๊ฑฐ์˜ ๋‚จ์ง€ ์•Š์•˜์œผ๋ฏ€๋กœ ์ตœ์„ ์„ ๋‹คํ•ด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

    ์ฆ‰, ์Œ์„ฑ ๋ฐœ์ทŒ๋ฅผ ๋…น์Œํ•˜๊ธฐ ์œ„ํ•œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค(์œ„์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•˜๋ฉฐ ํ‚ค๋ณด๋“œ์—์„œ ์ค‘๋‹จ๋˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์Œ์„ฑ์„ ํŒŒ์ผ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค).

    ํ•ด๋ณด์ž:

    python3 voice_db/record_voice.py test.wav

    ์—ฌ๋Ÿฌ ์‚ฌ๋žŒ์˜ ๋ชฉ์†Œ๋ฆฌ๋ฅผ ๋…น์Œํ•ฉ๋‹ˆ๋‹ค. (์ €ํฌ ๊ฒฝ์šฐ์—๋Š” ํŒ€์› XNUMX๋ช…)
    ๋‹ค์Œ์œผ๋กœ, ๋…น์Œ๋œ ๊ฐ ์Œ์„ฑ์— ๋Œ€ํ•ด ๋น ๋ฅธ ํ‘ธ๋ฆฌ์— ๋ณ€ํ™˜์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ŠคํŽ™ํŠธ๋กœ๊ทธ๋žจ์„ ์–ป์€ ๋‹ค์Œ ์ด๋ฅผ numpy ๋ฐฐ์—ด(.npy)๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

    for file in glob.glob("voice_db/*.wav"):
            spec = get_fft_spectrum(file)
            np.save(file[:-4] + '.npy', spec)

    ์ž์„ธํ•œ ๋‚ด์šฉ์€ ํŒŒ์ผ์— create_base.py
    ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ฉ”์ธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋งจ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ด๋Ÿฌํ•œ ์ŠคํŽ™ํŠธ๋กœ๊ทธ๋žจ์—์„œ ์ž„๋ฒ ๋”ฉ์„ ์–ป๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

    for file in glob.glob("voice_db/*.npy"):
        spec = np.load(file)
        spec = spec.astype('float32')
        spec_reshaped = spec.reshape(1, 1, spec.shape[0], spec.shape[1])
        srNet.setInput(spec_reshaped)
        pred = srNet.forward()
        emb = np.squeeze(pred)

    ์†Œ๋ฆฌ๊ฐ€ ๋‚˜๋Š” ์„ธ๊ทธ๋จผํŠธ์—์„œ ์ž„๋ฒ ๋”ฉ์„ ๋ฐ›์€ ํ›„, ๊ตฌ์ ˆ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ชจ๋“  ์Œ์„ฑ๊นŒ์ง€์˜ ์ฝ”์‚ฌ์ธ ๊ฑฐ๋ฆฌ๋ฅผ ์ทจํ•˜์—ฌ(๋” ์ž‘์„์ˆ˜๋ก ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Œ) ๊ทธ๊ฒƒ์ด ๋ˆ„๊ตฌ์— ์†ํ•˜๋Š”์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ๋ชจ์—์„œ๋Š” ์ž„๊ณ„๊ฐ’์„ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. 0.3์œผ๋กœ):

            dist_list = cdist(emb, enroll_embs, metric="cosine")
            distances = pd.DataFrame(dist_list, columns = df.speaker)

    ๊ฒฐ๊ตญ ์ถ”๋ก  ์†๋„๊ฐ€ ๋นจ๋ผ์„œ ๋ชจ๋ธ์„ 1~2๊ฐœ ๋” ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค๋Š” ์ ์„ ์ง€์ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. (์ƒ˜ํ”Œ 7์ดˆ์˜ ๊ฒฝ์šฐ ์ถ”๋ก ์— 2.5๊ฐ€ ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค.) ์šฐ๋ฆฌ๋Š” ๋” ์ด์ƒ ์ƒˆ๋กœ์šด ๋ชจ๋ธ์„ ์ถ”๊ฐ€ํ•  ์‹œ๊ฐ„์ด ์—†์—ˆ๊ณ  ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ”„๋กœํ† ํƒ€์ž…์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ์ง‘์ค‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

    ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

    ์ค‘์š”ํ•œ ์ ์€ ์ง‘์—์„œ ๋ผ์šฐํ„ฐ๋ฅผ ๊ฐ€์ ธ๊ฐ€ ๋กœ์ปฌ ๋„คํŠธ์›Œํฌ๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์žฅ์น˜์™€ ๋…ธํŠธ๋ถ์„ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

    ๋ฐฑ์—”๋“œ๋Š” websocket ๊ธฐ์ˆ (http over tcp ํ”„๋กœํ† ์ฝœ)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ํ”„๋ŸฐํŠธ์™€ Raspberry Pi ๊ฐ„์˜ ์—”๋“œํˆฌ์—”๋“œ ๋ฉ”์‹œ์ง€ ์ฑ„๋„์ž…๋‹ˆ๋‹ค.

    ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” ๋ผ์ฆˆ๋ฒ ๋ฆฌ๋กœ๋ถ€ํ„ฐ ๊ฐ€๊ณต๋œ ์ •๋ณด๋ฅผ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฆ‰, json์œผ๋กœ ํฌ์žฅ๋œ ์˜ˆ์ธก์ž๋Š” ์—ฌ์ • ์ค‘๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜์–ด ํ•ด๋‹น ๊ธฐ๊ฐ„ ๋™์•ˆ ์‚ฌ์šฉ์ž์˜ ๊ฐ์ •์  ๋ฐฐ๊ฒฝ์— ๋Œ€ํ•œ ํ†ต๊ณ„๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด ํŒจํ‚ท์€ ๊ตฌ๋…์„ ์‚ฌ์šฉํ•˜๊ณ  websocket ๋์ ์—์„œ ํŒจํ‚ท์„ ์ˆ˜์‹ ํ•˜๋Š” ํ”„๋ŸฐํŠธ์—”๋“œ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค. ์ „์ฒด ๋ฐฑ์—”๋“œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ golang ์–ธ์–ด๋กœ ๊ตฌ์ถ•๋˜์—ˆ์œผ๋ฉฐ, goroutine์ด ์ž˜ ์ฒ˜๋ฆฌํ•˜๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์— ๋งค์šฐ ์ ํ•ฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ ํƒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
    ์—”๋“œํฌ์ธํŠธ์— ์•ก์„ธ์Šคํ•˜๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ๋“ฑ๋ก๋˜๊ณ  ๊ตฌ์กฐ์— ์ž…๋ ฅ๋œ ๋‹ค์Œ ํ•ด๋‹น ๋ฉ”์‹œ์ง€๊ฐ€ ์ˆ˜์‹ ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์™€ ๋ฉ”์‹œ์ง€๋Š” ๋ชจ๋‘ ๊ณตํ†ต ํ—ˆ๋ธŒ์— ์ž…๋ ฅ๋˜๋ฉฐ, ์—ฌ๊ธฐ์—์„œ ๋ฉ”์‹œ์ง€๋Š” ์ด๋ฏธ ์ถ”๊ฐ€๋กœ(๊ตฌ๋…ํ•œ ํ”„๋ŸฐํŠธ๋กœ) ์ „์†ก๋˜๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ ์—ฐ๊ฒฐ(๋ผ์ฆˆ๋ฒ ๋ฆฌ ๋˜๋Š” ํ”„๋ŸฐํŠธ)์„ ๋‹ซ์œผ๋ฉด ๊ตฌ๋…์ด ์ทจ์†Œ๋˜๊ณ ์—์„œ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ํ—ˆ๋ธŒ.

    OpenVINO ํ•ด์ปคํ†ค: Raspberry Pi์—์„œ ์Œ์„ฑ๊ณผ ๊ฐ์ • ์ธ์‹
    ์šฐ๋ฆฌ๋Š” ๋’ค์—์„œ ์—ฐ๊ฒฐ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค

    ํ”„๋ก ํŠธ์—”๋“œ๋Š” ๊ฐœ๋ฐœ ํ”„๋กœ์„ธ์Šค์˜ ์†๋„๋ฅผ ๋†’์ด๊ณ  ๋‹จ์ˆœํ™”ํ•˜๊ธฐ ์œ„ํ•ด React ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JavaScript๋กœ ์ž‘์„ฑ๋œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ž…๋‹ˆ๋‹ค. ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ชฉ์ ์€ ๋ฐฑ์—”๋“œ ์ธก๊ณผ Raspberry Pi์—์„œ ์ง์ ‘ ์‹คํ–‰๋˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์–ป์€ ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๊ฐํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํŽ˜์ด์ง€์—๋Š” React-Router๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„น์…˜ ๋ผ์šฐํŒ…์ด ๊ตฌํ˜„๋˜์–ด ์žˆ์ง€๋งŒ ๊ด€์‹ฌ ์žˆ๋Š” ์ฃผ์š” ํŽ˜์ด์ง€๋Š” WebSocket ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„์—์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ง€์†์ ์ธ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆผ์„ ์ˆ˜์‹ ํ•˜๋Š” ๋ฉ”์ธ ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค. ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋Š” ์Œ์„ฑ์„ ๊ฐ์ง€ํ•˜๊ณ  ๋“ฑ๋ก๋œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ํŠน์ •์ธ์˜ ๊ฒƒ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ํŒ๋‹จํ•œ ํ›„ ํ™•๋ฅ  ๋ชฉ๋ก์„ ํด๋ผ์ด์–ธํŠธ์— ๋ณด๋ƒ…๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” ์ตœ์‹  ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•˜๊ณ , ๋งˆ์ดํฌ์— ๋Œ€๊ณ  ๋งํ–ˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๊ฐ€์žฅ ๋†’์€ ์‚ฌ๋žŒ์˜ ์•„๋ฐ”ํƒ€์™€ ๊ทธ๊ฐ€ ๋‹จ์–ด๋ฅผ ๋ฐœ์Œํ•  ๋•Œ์˜ ๊ฐ์ •์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

    OpenVINO ํ•ด์ปคํ†ค: Raspberry Pi์—์„œ ์Œ์„ฑ๊ณผ ๊ฐ์ • ์ธ์‹
    ์—…๋ฐ์ดํŠธ๋œ ์˜ˆ์ธก์ด ํฌํ•จ๋œ ํ™ˆํŽ˜์ด์ง€

    ๊ฒฐ๋ก 

    ๊ณ„ํš๋Œ€๋กœ ๋ชจ๋“  ๊ฒƒ์„ ์™„๋ฃŒํ•˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅํ–ˆ๊ณ  ์‹œ๊ฐ„๋„ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ฃผ๋œ ํฌ๋ง์€ ๋ชจ๋“  ๊ฒƒ์ด ์ž‘๋™ํ•˜๋Š” ๋ฐ๋ชจ์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋ ˆ์  ํ…Œ์ด์…˜์—์„œ ๊ทธ๋“ค์€ ๋ชจ๋“  ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€, ์–ด๋–ค ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜๋Š”์ง€, ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ๋ฐ๋ชจ ๋ถ€๋ถ„์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์ „๋ฌธ๊ฐ€๋“ค์€ ๋ฌด์ž‘์œ„ ์ˆœ์„œ๋กœ ๋ฐฉ์„ ๋Œ์•„๋‹ค๋‹ˆ๋ฉฐ ๊ฐ ํŒ€์— ์ ‘๊ทผํ•˜์—ฌ ์ž‘๋™ ์ค‘์ธ ํ”„๋กœํ† ํƒ€์ž…์„ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋“ค์€ ์šฐ๋ฆฌ์—๊ฒŒ๋„ ์งˆ๋ฌธ์„ ํ–ˆ๊ณ , ๋ชจ๋‘๊ฐ€ ์ž์‹ ์˜ ์—ญํ• ์— ๋‹ตํ–ˆ์œผ๋ฉฐ, ๋…ธํŠธ๋ถ์— ์›น์„ ๋‚จ๊ฒจ๋‘์—ˆ๊ณ  ๋ชจ๋“  ๊ฒƒ์ด ์‹ค์ œ๋กœ ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

    ์šฐ๋ฆฌ ์†”๋ฃจ์…˜์˜ ์ด ๋น„์šฉ์€ 150๋‹ฌ๋Ÿฌ์˜€์Šต๋‹ˆ๋‹ค.

    • ๋ผ์ฆˆ๋ฒ ๋ฆฌ ํŒŒ์ด 3 ~ $35
    • Google AIY Voice Bonnet (์žฌ๋ฐœ์–ธ ๋น„์šฉ ๋ถ€๋‹ด ๊ฐ€๋Šฅ) ~ 15$
    • ์ธํ…” NCS 2 ~ 100$

    ๊ฐœ์„  ๋ฐฉ๋ฒ•:

    • ํด๋ผ์ด์–ธํŠธ์—์„œ ๋“ฑ๋ก ์‚ฌ์šฉ - ๋ฌด์ž‘์œ„๋กœ ์ƒ์„ฑ๋œ ํ…์ŠคํŠธ๋ฅผ ์ฝ๋„๋ก ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.
    • ๋ชจ๋ธ์„ ๋ช‡ ๊ฐœ ๋” ์ถ”๊ฐ€ํ•˜์„ธ์š”. ์Œ์„ฑ์œผ๋กœ ์„ฑ๋ณ„๊ณผ ๋‚˜์ด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ๋™์‹œ์— ๋“ค๋ฆฌ๋Š” ์Œ์„ฑ ๋ถ„๋ฆฌ(๋ถ„ํ• )

    ์ €์žฅ์†Œ: https://github.com/vladimirwest/OpenEMO

    OpenVINO ํ•ด์ปคํ†ค: Raspberry Pi์—์„œ ์Œ์„ฑ๊ณผ ๊ฐ์ • ์ธ์‹
    ํ”ผ๊ณคํ•˜์ง€๋งŒ ํ–‰๋ณตํ•ด์š” ์šฐ๋ฆฌ

    ๋์œผ๋กœ ์ฃผ์ตœ์ธก๊ณผ ์ฐธ๊ฐ€์ž๋ถ„๋“ค๊ป˜ ๊ฐ์‚ฌ ์ธ์‚ฌ๋ฅผ ์ „ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํŒ€์˜ ํ”„๋กœ์ ํŠธ ์ค‘์—์„œ ์šฐ๋ฆฌ๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ๋ฌด๋ฃŒ ์ฃผ์ฐจ ๊ณต๊ฐ„์„ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ์†”๋ฃจ์…˜์„ ์ข‹์•„ํ–ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์—๊ฒŒ๋Š” ์ œํ’ˆ๊ณผ ๊ฐœ๋ฐœ์— ๋ชฐ์ž…ํ•˜๋Š” ์ •๋ง ๋ฉ‹์ง„ ๊ฒฝํ—˜์ด์—ˆ์Šต๋‹ˆ๋‹ค. AI ์ฃผ์ œ๋ฅผ ํฌํ•จํ•ด ์ง€์—ญ์—์„œ ์ ์  ๋” ํฅ๋ฏธ๋กœ์šด ํ–‰์‚ฌ๊ฐ€ ์—ด๋ฆฌ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€