๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ–ฑ๏ธ ๊ธฐ์ˆ  ๊ฒ€ํ† 

[React] SEG NIfTI, ์™œ ๋ฒ„๋ ธ๋‚˜ ๋ณ‘๋ชฉ์˜ ํ•ด๋ถ€์™€ BBox ์ „ํ™˜ ๋ฐฐ๊ฒฝ

SEG NIfTI์˜ ๋ฌธ์ œ์™€ BBox JSON ์ „ํ™˜ ๋ฐฐ๊ฒฝ
1ํŽธ / 3ํŽธ

SEG NIfTI, ์™œ ๋ฒ„๋ ธ๋‚˜
๋ณ‘๋ชฉ์˜ ํ•ด๋ถ€์™€ BBox ์ „ํ™˜ ๋ฐฐ๊ฒฝ

BE์—์„œ Seg NIfTI๋ฅผ ๋ฐ›์•„ VTK๋กœ ์˜ค๋ฒ„๋ ˆ์ดํ•˜๋˜ ๋ฐฉ์‹์ด ์™œ ๋ฌธ์ œ์˜€๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  BBox JSON์ด๋ผ๋Š” ์„ ํƒ์ด ์–ด๋–ป๊ฒŒ ๊ทธ ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ํ•œ๋ฒˆ์— ํ•ด๊ฒฐํ–ˆ๋Š”์ง€ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

NIfTI Seg ๋ณ‘๋ชฉ Web Worker BBox JSON ์•„ํ‚คํ…์ฒ˜ ์ „ํ™˜ ๋ฐ์ดํ„ฐ ํ๋ฆ„

๐Ÿ—‚ ์‹œ๋ฆฌ์ฆˆ: SEG NIfTI์—์„œ BBox JSON์œผ๋กœ

1
SEG NIfTI์˜ ๋ฌธ์ œ์™€ BBox JSON ์ „ํ™˜ ๋ฐฐ๊ฒฝ โ† ํ˜„์žฌ
2
BBox JSON API ์„ค๊ณ„์™€ Canvas ์˜ค๋ฒ„๋ ˆ์ด ๊ตฌํ˜„
3
VTK ์ขŒํ‘œ๊ณ„์—์„œ 3๊ฐœ ๋ทฐ ๋™์‹œ์— BBox ๊ทธ๋ฆฌ๊ธฐ
01 ยท Background

๋ฌด์—‡์ด ๋ฌธ์ œ์˜€๋‚˜

VTK.js ๊ธฐ๋ฐ˜ ์˜๋ฃŒ ์˜์ƒ ๋ทฐ์–ด์—์„œ ์„ธ๊ทธ๋ฉ˜ํ…Œ์ด์…˜ ์˜ค๋ฒ„๋ ˆ์ด๋Š” ์˜ค๋žซ๋™์•ˆ "SEG NIfTI๋ฅผ ๋ฐ›์•„์„œ VTK ImageSlice๋กœ ๋ Œ๋”๋ง"ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ๋™์ž‘ ์ž์ฒด๋Š” ๋ฌธ์ œ์—†์—ˆ์ง€๋งŒ, ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ์ธก๋ฉด์—์„œ ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ๋ฐ˜๋ณต์ ์œผ๋กœ ๋ณด๊ณ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜๋‚˜๋Š” ๋กœ๋”ฉ ์‹œ๊ฐ„์ด์—ˆ๊ณ , ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์ €์‚ฌ์–‘ ๊ธฐ๊ธฐ์—์„œ์˜ ๋ฉ”๋ชจ๋ฆฌ ์••๋ฐ•์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋‘ ๋ฌธ์ œ ๋ชจ๋‘ ์›์ธ์„ ํŒŒ๊ณ ๋“ค๋ฉด ๊ฐ™์€ ๊ณณ์„ ๊ฐ€๋ฆฌํ‚ค๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค โ€” SEG NIfTI ํŒŒ์ผ ์ž์ฒด.

+10s
SEG ๋กœ๋”ฉ ์ถ”๊ฐ€ ๋Œ€๊ธฐ
ร—2
๋ฉ”๋ชจ๋ฆฌ ์ถ”๊ฐ€ ์ ์œ 
์ˆ˜ KB
BBox JSON ์‘๋‹ต ํฌ๊ธฐ
0 MB
SEG ๊ด€๋ จ ๋ฉ”๋ชจ๋ฆฌ (์ „ํ™˜ ํ›„)
02 ยท Before โ€” ๊ธฐ์กด ํŒŒ์ดํ”„๋ผ์ธ

๊ธฐ์กด ๋ฐฉ์‹์ด ๋А๋ ธ๋˜ ์ด์œ 

๊ธฐ์กด SEG ๋ Œ๋”๋ง ํŒŒ์ดํ”„๋ผ์ธ์€ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์ˆœ์„œ๋Œ€๋กœ ๊ฑฐ์ณ์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋‹จ๊ณ„๊ฐ€ ์™„๋ฃŒ๋˜์–ด์•ผ ๋‹ค์Œ ๋‹จ๊ณ„๊ฐ€ ์‹œ์ž‘๋˜๋Š” ์ˆœ์ฐจ์  ๋ธ”๋กœํ‚น ๊ตฌ์กฐ์˜€์Šต๋‹ˆ๋‹ค.

1
fetchAxialSegVolume() โ€” ๋„คํŠธ์›Œํฌ
BE์—์„œ SEG NIfTI(.nii.gz)๋ฅผ ArrayBuffer๋กœ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๋‹ค. ์••์ถ• ์ƒํƒœ์—์„œ๋„ ์ˆ˜์‹ญ MB ์ด์ƒ. ๋„คํŠธ์›Œํฌ ์ƒํƒœ์— ๋”ฐ๋ผ ์ˆ˜ ์ดˆ~์ˆ˜์‹ญ ์ดˆ ์†Œ์š”๋ฉ๋‹ˆ๋‹ค. Base ๋ณผ๋ฅจ๊ณผ ๋ณ‘๋ ฌ fetch๋Š” ๋˜์ง€๋งŒ, ์ด ๋‹จ๊ณ„๊ฐ€ ๋๋‚˜์•ผ ๋‹ค์Œ์œผ๋กœ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
2
parseNifti() โ€” gzip ์••์ถ• ํ•ด์ œ
nifti-reader-js์˜ decompress()๋กœ gzip์„ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค. JavaScript ์‹ฑ๊ธ€์Šค๋ ˆ๋“œ์—์„œ ์‹คํ–‰๋˜๋ฏ€๋กœ, ํ•ด์ œ๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ธ”๋กœํ‚น๋ฉ๋‹ˆ๋‹ค. ํ•ด์ œ ํ›„ ๋ณผ๋ฅจ์ด ์ˆ˜๋ฐฑ MB๋กœ ํŒฝ์ฐฝํ•ฉ๋‹ˆ๋‹ค.
3
Web Worker โ€” ๋ฆฌ์ƒ˜ํ”Œ๋ง + RGBA ๋ณ€ํ™˜
SEG ์Šค์นผ๋ผ๋ฅผ ๋ผ๋ฒจ๋ณ„ ์ƒ‰์ƒ RGBA ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ž‘์—…์„ Web Worker์—์„œ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. Base ๋ณผ๋ฅจ๊ณผ ํ•ด์ƒ๋„๊ฐ€ ๋‹ค๋ฅผ ๊ฒฝ์šฐ ๋ฆฌ์ƒ˜ํ”Œ๋ง์ด ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. Float32Array โ†’ Uint8Array RGBA ๋ณ€ํ™˜์œผ๋กœ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋‹ค์‹œ 4๋ฐฐ๋กœ ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
4
createSegVtkImageData() + GPU ์—…๋กœ๋“œ
4์ฑ„๋„ RGBA VTK ImageData๋ฅผ ์ƒ์„ฑํ•˜๊ณ  GPU ํ…์Šค์ฒ˜์— ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. CPU์—๋Š” RGBA ๋ฐฐ์—ด์ด, GPU์—๋Š” ํ…์Šค์ฒ˜๊ฐ€ ๋™์‹œ์— ์˜ฌ๋ผ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ 2์ค‘์œผ๋กœ ์ ์œ ๋ฉ๋‹ˆ๋‹ค.
๊ธฐ์กด SEG ํŒŒ์ดํ”„๋ผ์ธ โ€” ์ง๋ ฌ ๋ธ”๋กœํ‚น ๊ตฌ์กฐ โ‘  fetch SEG nifti ~5~20์ดˆ (๋„คํŠธ์›Œํฌ) โ‘ก gzip ํ•ด์ œ ๋ฉ”์ธ์Šค๋ ˆ๋“œ ๋ธ”๋กœํ‚น โ‘ข Worker RGBA ๋ณ€ํ™˜ ๋ฆฌ์ƒ˜ํ”Œ + ๋ฉ”๋ชจ๋ฆฌ 4๋ฐฐโ†‘ โ‘ฃ VTK ImageData + GPU CPU + GPU ์ด์ค‘ ์ ์œ  SEG ํ‘œ์‹œ ์ด +10~30์ดˆ Base ๋ณผ๋ฅจ ํ‘œ์‹œ ์ดํ›„ SEG๊นŒ์ง€ ์ถ”๊ฐ€๋กœ 10~30์ดˆ ๋Œ€๊ธฐ โ€” ์‚ฌ์šฉ์ž๋Š” ์„ธ๊ทธ ์—†๋Š” ํ™”๋ฉด์„ ๋ด…๋‹ˆ๋‹ค

๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์  ๊ตฌ์กฐ

๊ฐ ๋‹จ๊ณ„๋ฅผ ๊ฑฐ์น ์ˆ˜๋ก ๊ฐ™์€ SEG ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฌ๋Ÿฌ ํ˜•ํƒœ๋กœ ๋ฉ”๋ชจ๋ฆฌ์— ์Œ“์ž…๋‹ˆ๋‹ค.

โ‘  ์••์ถ• ArrayBuffer
~30 MB
โ‘ก ํ•ด์ œ ํ›„ ์Šค์นผ๋ผ
~300 MB
โ‘ข RGBA (ร—4)
~600 MB
โ‘ฃ GPU ํ…์Šค์ฒ˜ ์ถ”๊ฐ€
~1.2 GB+

* 512ร—512ร—300 SEG ๋ณผ๋ฅจ, Float32 โ†’ RGBA ๋ณ€ํ™˜ ๊ธฐ์ค€ ์ถ”์ •

๐Ÿšจ ๋‚ด์žฅ GPU ํ™˜๊ฒฝ๊ณผ 16GB RAM ๋…ธํŠธ๋ถ ํ…Œ์ŠคํŠธ์—์„œ SEG ๋กœ๋”ฉ ์ค‘ ๋ธŒ๋ผ์šฐ์ € ํƒญ ํฌ๋ž˜์‹œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. Base(1.2GB) + SEG RGBA(1.2GB) + GPU ํ…์Šค์ฒ˜๊ฐ€ ๋™์‹œ์— ์˜ฌ๋ผ๊ฐ€๋ฉด์„œ ํƒญ ๋ฉ”๋ชจ๋ฆฌ ํ•œ๋„๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.
03 ยท Root Cause

๊ทผ๋ณธ ์›์ธ โ€” ํฌ๋งท ์„ ํƒ์˜ ๋ถˆ์ผ์น˜

๋ฌธ์ œ๋ฅผ ํ•œ ์ค„๋กœ ์š”์•ฝํ•˜๋ฉด ์ด๋ ‡์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก "์šฐ๋ฆฌ๊ฐ€ ํ™”๋ฉด์— ๊ทธ๋ ค์•ผ ํ•˜๋Š” ์ •๋ณด"์™€ "์šฐ๋ฆฌ๊ฐ€ ์‹ค์ œ๋กœ ๋ฐ›๊ณ  ์žˆ๋˜ ๋ฐ์ดํ„ฐ" ์‚ฌ์ด์˜ ๊ฐ„๊ทน์ด ๋„ˆ๋ฌด ์ปธ์Šต๋‹ˆ๋‹ค.

ํ™”๋ฉด์— ๊ทธ๋ ค์•ผ ํ•˜๋Š” ๊ฒƒ์€ ๋‹จ์ˆœํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์Šฌ๋ผ์ด์Šค์—์„œ ์–ด๋А ํ”ฝ์…€ ์ขŒํ‘œ์—, ์–ด๋–ค ์ƒ‰์˜ ๋ฐ•์Šค(๋˜๋Š” ์œค๊ณฝ์„ )๋ฅผ ๊ทธ๋ฆด ๊ฒƒ์ธ๊ฐ€์ž…๋‹ˆ๋‹ค. ์ด ์ •๋ณด๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ํฌ๊ธฐ๋Š” ๊ฒจ์šฐ ์ˆ˜ KB์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ NIfTI SEG๋Š” ๊ทธ ์ˆ˜ KB์งœ๋ฆฌ ์ •๋ณด๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์ˆ˜๋ฐฑ MB์˜ 3D ๋ณต์…€ ๋ณผ๋ฅจ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๋ณต์…€์€ 0(๋ฐฐ๊ฒฝ)์ด๊ณ , ์‹ค์ œ ๋ ˆ์ด๋ธ”์ด ์žˆ๋Š” ๋ณต์…€์€ ์ „์ฒด์˜ 1~5%์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

์‹ค์ œ ํ•„์š”ํ•œ ์ •๋ณด ์Šฌ๋ผ์ด์Šค 150๋ฒˆ: ์ขŒํ‘œ (120, 80)~(200, 160), ๋นจ๊ฐ„์ƒ‰ ์Šฌ๋ผ์ด์Šค 151๋ฒˆ: ์ขŒํ‘œ (118, 82)~(198, 162), ๋นจ๊ฐ„์ƒ‰ ์Šฌ๋ผ์ด์Šค 152๋ฒˆ: ์ขŒํ‘œ (116, 84)~(196, 164), ๋นจ๊ฐ„์ƒ‰ โ†’ JSON ๋ช‡ ์ค„ = ์ˆ˜ KB ํŒŒ์‹ฑ: ์ˆ˜ ms, ๋ฉ”๋ชจ๋ฆฌ: ๋ฌด์‹œ ๊ฐ€๋Šฅ Worker ๋ถˆํ•„์š”, VTK ๋ถˆํ•„์š” ๊ธฐ์กด์— ์ „๋‹ฌ๋ฐ›๋˜ ๋ฐ์ดํ„ฐ 512 ร— 512 ร— 300 = 78,643,200 ๋ณต์…€ ๊ทธ ์ค‘ ๋ ˆ์ด๋ธ” ์žˆ๋Š” ๋ณต์…€: ~1,000,000๊ฐœ ๋‚˜๋จธ์ง€ 77,643,200๊ฐœ: ์ „๋ถ€ 0 (๋ฐฐ๊ฒฝ) โ†’ NIfTI gzip = ~30 MB ์••์ถ• / ~300 MB ํ•ด์ œ ํŒŒ์‹ฑ: ์ˆ˜~์ˆ˜์‹ญ ์ดˆ, ๋ฉ”๋ชจ๋ฆฌ: ์ˆ˜๋ฐฑ MB~1GB+ Worker ํ•„์š”, VTK ImageData ํ•„์š” โ‰  ๋ถˆ์ผ์น˜
04 ยท The Decision

ํ•ด๊ฒฐ์ฑ… โ€” BBox JSON์œผ๋กœ์˜ ์ „ํ™˜

๊ฒ€ํ† ๋œ ๋Œ€์•ˆ์€ ์„ธ ๊ฐ€์ง€์˜€์Šต๋‹ˆ๋‹ค.

๋Œ€์•ˆ์ ‘๊ทผ ๋ฐฉ์‹๋ฉ”๋ชจ๋ฆฌ๊ตฌํ˜„ ๋ณต์žก๋„์ฑ„ํƒ
Sparse Zarr SEG SEG NIfTI โ†’ Zarr ๋ณ€ํ™˜, ์ฒญํฌ ๋‹จ์œ„ fetch ๊ฐœ์„ ๋จ ๋†’์Œ (์ปค์Šคํ…€ ๋กœ๋”) ๋ฏธ์ฑ„ํƒ
์„œ๋ฒ„์‚ฌ์ด๋“œ ์Šฌ๋ผ์ด์Šค ๋ Œ๋”๋ง BE์—์„œ PNG๋กœ ๋ Œ๋”๋ง, ์Šฌ๋ผ์ด์Šค๋งˆ๋‹ค ์š”์ฒญ ์ตœ์†Œ ์ค‘๊ฐ„ ๋ฏธ์ฑ„ํƒ
BBox/Contour JSON BE์—์„œ ์ขŒํ‘œ ๊ณ„์‚ฐ, FE Canvas์—์„œ ๊ทธ๋ฆฌ๊ธฐ ์ตœ์†Œ (~0) ๋‚ฎ์Œ โœ“ ์ฑ„ํƒ

BBox JSON ๋ฐฉ์‹์ด ์ฑ„ํƒ๋œ ํ•ต์‹ฌ ์ด์œ ๋Š” ์„ธ ๊ฐ€์ง€ ๋ฌธ์ œ๋ฅผ ๋™์‹œ์— ํ•ด๊ฒฐํ•˜๋ฉด์„œ ๊ตฌํ˜„ ๋ณต์žก๋„๋Š” ์˜คํžˆ๋ ค ์ค„์–ด๋“ค์—ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๐Ÿ“ฆ

๋ฉ”๋ชจ๋ฆฌ ๋ฌธ์ œ ํ•ด๊ฒฐ

SEG ๊ด€๋ จ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์‚ฌ์‹ค์ƒ 0์ด ๋ฉ๋‹ˆ๋‹ค. JSON ์‘๋‹ต ์ž์ฒด๊ฐ€ ์ˆ˜ KB์ด๊ณ , Canvas 2D๋กœ ๊ทธ๋ฆฌ๋ฏ€๋กœ GPU ํ…์Šค์ฒ˜ ์—…๋กœ๋“œ๋„ ์—†์Šต๋‹ˆ๋‹ค.

โšก

๋กœ๋”ฉ ์‹œ๊ฐ„ ํ•ด๊ฒฐ

์ˆ˜์‹ญ MB gzip ๋‹ค์šด๋กœ๋“œ โ†’ ์ˆ˜ KB JSON. gzip ํ•ด์ œ, Worker, VTK ImageData ์ƒ์„ฑ ๋‹จ๊ณ„๊ฐ€ ๋ชจ๋‘ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค. Base ๋ณผ๋ฅจ๊ณผ ๋ณ‘๋ ฌ๋กœ ์ฆ‰์‹œ ์™„๋ฃŒ๋ฉ๋‹ˆ๋‹ค.

๐Ÿงน

์ฝ”๋“œ ๋‹จ์ˆœํ™”

fetchAxialSegVolume, Web Worker ํŒŒ์ดํ”„๋ผ์ธ, createSegVtkImageData, createSegPlanarSlices ๋“ฑ ์ˆ˜๋ฐฑ ์ค„์˜ ๋ณต์žกํ•œ ์ฝ”๋“œ๊ฐ€ ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

๐Ÿ“

3๋ทฐ ์ง€์› ๊ฐ€๋Šฅ

BBox ์ขŒํ‘œ์—์„œ 3D ๋ฐ”์šด๋”ฉ ๋ฐ•์Šค๋ฅผ ์žฌ๊ตฌ์„ฑํ•˜๋ฉด Axial๋ฟ ์•„๋‹ˆ๋ผ Sagittal, Coronal ๋ทฐ์—์„œ๋„ ํˆฌ์˜ ๋ฐ•์Šค๋ฅผ ๊ทธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (3ํŽธ์—์„œ ์ƒ์„ธ ์„ค๋ช…)

05 ยท After โ€” ์ƒˆ ํŒŒ์ดํ”„๋ผ์ธ

๋ณ€๊ฒฝ ํ›„ ํŒŒ์ดํ”„๋ผ์ธ

Before
fetchAxialSegVolume()
  โ†’ NIfTI ArrayBuffer (~30MB)
  โ†’ parseNifti() gzip ํ•ด์ œ
  โ†’ Web Worker ๋ฆฌ์ƒ˜ํ”Œ + RGBA
  โ†’ createSegVtkImageData()
  โ†’ createSegPlanarSlices()
  โ†’ VTK GPU ํ…์Šค์ฒ˜ ์—…๋กœ๋“œ
  โ†’ renderWindow.render()

์ด ์‹œ๊ฐ„: +10~30์ดˆ (Base ์ดํ›„)
๋ฉ”๋ชจ๋ฆฌ: +600MB~1.2GB
After
fetchAxialBBox()
  โ†’ JSON (~์ˆ˜ KB)
  โ†’ response.json() ํŒŒ์‹ฑ
  โ†’ bboxAnnotations state ์ €์žฅ
  โ†’ Canvas 2D drawBBoxOverlay()

์ด ์‹œ๊ฐ„: Base์™€ ๋™์‹œ ์™„๋ฃŒ
๋ฉ”๋ชจ๋ฆฌ: ~0 (JSON ์™ธ ์ถ”๊ฐ€ ์—†์Œ)
์ƒˆ ํŒŒ์ดํ”„๋ผ์ธ โ€” Base์™€ BBox๋ฅผ ๋ณ‘๋ ฌ fetch, ๋‘ ๋ ˆ์ด์–ด ๋…๋ฆฝ ๋ Œ๋”๋ง Base fetch nifti (~์ˆ˜์‹ญ MB) parseNifti + VTK VTK ๋ Œ๋”๋ง BBox fetch JSON (~์ˆ˜ KB) JSON ํŒŒ์‹ฑ Canvas ์˜ค๋ฒ„๋ ˆ์ด โ† Base: VTK, BBox: Canvas ๋ถ„๋ฆฌ ๋ Œ๋”๋ง โ†’ โœ“ ์™„์ „ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ BBox๋Š” Base fetch ์ค‘ ์ด๋ฏธ ์™„๋ฃŒ Worker ์—†์Œ / GPU ์ถ”๊ฐ€ ์—…๋กœ๋“œ ์—†์Œ SEG ๊ด€๋ จ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์‹ค์ƒ 0
06 ยท Code Removed

์ œ๊ฑฐ๋œ ๊ฒƒ๋“ค โ€” ์‚ฌ๋ผ์ง„ ๋ณต์žก์„ฑ

์ด๋ฒˆ ์ „ํ™˜์—์„œ ์‚ญ์ œ๋œ ์ฝ”๋“œ์™€ ์˜์กด์„ฑ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ๊ฒƒ๋ณด๋‹ค ์ œ๊ฑฐ๋œ ๊ฒƒ์ด ํ›จ์”ฌ ๋งŽ์Šต๋‹ˆ๋‹ค.

๊ตฌ๋ถ„์ œ๊ฑฐ๋œ ํ•ญ๋ชฉ์ด์œ 
API ํ•จ์ˆ˜fetchAxialSegVolume(), fetchSegVolume()BBox JSON์œผ๋กœ ๋Œ€์ฒด
์œ ํ‹ธ๋ฆฌํ‹ฐcreateSegVtkImageData(), createSegPlanarSlices(), createSegCrossSlices()VTK SEG ํŒŒ์ดํ”„๋ผ์ธ ์ „์ฒด ์ œ๊ฑฐ
Web WorkerSegProcessRequest, SegProcessResponse, resample ๋กœ์งJSON์€ ํŒŒ์‹ฑ๋งŒ์œผ๋กœ ๋๋‚จ
importvtkDataArray, SegProcessRequest, fetchSegVolume ๋“ฑ ๋‹ค์ˆ˜๋ฏธ์‚ฌ์šฉ
์ƒํƒœsegImageData, segDims, segOriginalScalars (MapperRegistry)๋” ์ด์ƒ VTK SEG ์ƒํƒœ ๋ถˆํ•„์š”
MapperRegistrysetSegMappers(), applySegColorMap(), segOriginalScalarsSEG VTK ๋ Œ๋”๋ง ์ œ๊ฑฐ
๐Ÿงน ๋ณต์žกํ•œ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๊ณ  ์ œ๊ฑฐํ•จ์œผ๋กœ์จ ์„ฑ๋Šฅ์ด ๊ฐœ์„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ์ ˆ๊ฐ, ๋กœ๋”ฉ ์†๋„ ํ–ฅ์ƒ, ํƒญ ํฌ๋ž˜์‹œ ๋ฐฉ์ง€ โ€” ์„ธ ๊ฐ€์ง€ ๋ชจ๋‘ ์ฝ”๋“œ ์‚ญ์ œ์—์„œ ๋น„๋กฏ๋ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ข‹์€ ์ตœ์ ํ™”๋Š” ์‹คํ–‰ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
07 ยท Summary

1ํŽธ ์š”์•ฝ

ํ•ญ๋ชฉBeforeAfter
SEG ๋ฐ์ดํ„ฐ ํ˜•์‹NIfTI gzip (~30MB+)JSON (~์ˆ˜ KB)
SEG ๋กœ๋”ฉ ์‹œ๊ฐ„Base ์ดํ›„ +10~30์ดˆBase์™€ ๋™์‹œ ์™„๋ฃŒ
SEG ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ+600MB~1.2GB~0 MB
Web Worker๋ฆฌ์ƒ˜ํ”Œ + RGBA ๋ณ€ํ™˜๋ถˆํ•„์š”
GPU ํ…์Šค์ฒ˜SEG RGBA ํ…์Šค์ฒ˜ ์ถ”๊ฐ€์ถ”๊ฐ€ ์—†์Œ
๋ Œ๋”๋ง ๋ฐฉ์‹VTK ImageSliceCanvas 2D
3๋ทฐ ์ง€์›Axial๋งŒ (Seg overlay)Axial + Sagittal + Coronal
๐Ÿ“Œ 2ํŽธ ์˜ˆ๊ณ : BBox JSON API๊ฐ€ ์–ด๋–ป๊ฒŒ ์„ค๊ณ„๋˜์—ˆ๋Š”์ง€, FE์—์„œ ์–ด๋–ป๊ฒŒ Canvas์— ์ง์ ‘ ๊ทธ๋ฆฌ๋Š”์ง€, AxialGridViewer์™€ BBoxOverlay ์ปดํฌ๋„ŒํŠธ์˜ ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

NIfTI Viewer ํ”„๋กœ์ ํŠธ ยท SEG โ†’ BBox ์ „ํ™˜ ์‹œ๋ฆฌ์ฆˆ 1ํŽธ ยท 2026