Jekyll2023-01-30T00:51:30+09:00https://tyami.github.io/feed.xmltyami’s study blogData science, Machine learning, Deep learningTaeyang Yang윈도우즈에서 Jekyll blog 로컬 서버 자동 시작 파일 만들기2020-11-17T00:00:00+09:002020-11-17T00:00:00+09:00https://tyami.github.io/blog/jekyll-local-server-start-batch<blockquote>
<p>이번 포스팅에서는 <strong>Jekyll blog를 local server에서 구동하는 방법</strong>을 정리해보고자 합니다.</p>
</blockquote>
<p>2020.11.17 기준 본 블로그는 Jekyll <a href="https://github.com/mmistakes/minimal-mistakes">minimal mistake</a>을 바탕으로 만들어졌습니다.</p>
<p>블로그 관리 및 포스팅 시, 매번 git commit해서 수정된 걸 보다가 쓸데없이 Github commit수 만 뻥튀기되고, 이건 좀 아닌 것 같아서 로컬 서버를 구동해서 수정사항을 보기로 했습니다.</p>
<h1 id="requirements">Requirements</h1>
<p>Jekyll blog 로컬 서버 구동에는 아래 두 가지가 필요합니다. 자세한 내용은 Procedure에서 설명해두었습니다.</p>
<ul>
<li>Jekyll blog folder</li>
<li>Ruby</li>
<li>Gemfile</li>
</ul>
<h1 id="procedure">Procedure</h1>
<h2 id="1-install-ruby">1. Install Ruby</h2>
<p>Ruby는 Python과 같은 프로그래밍 언어입니다. Jekyll은 Ruby를 기반으로 동작합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/Blog/2020-11-17-jekyll-local-server-start-batch/ruby-install.PNG" alt="ruby-install.PNG" /></p>
<p><a href="https://rubyinstaller.org/downloads/">Ruby website</a>에서 Ruby를 다운로드받아 설치합니다.</p>
<p>설치과정은 생략합니다.</p>
<p><strong>📌 NOTE</strong></p>
<ul>
<li>설치 마지막에 <code class="language-plaintext highlighter-rouge">Run 'ridk install' ...</code>를 체크해줍니다. cmd 창이 나타나면서 무슨 글자가 뜨는데, <code class="language-plaintext highlighter-rouge">1</code>을 치고 엔터를 눌러줍니다. 그러면 자동으로 뭔가를 설치합니다.</li>
</ul>
<h2 id="2-prepare-gemfile">2. Prepare Gemfile</h2>
<p>Ruby 언어에서는 플러그인들을 <code class="language-plaintext highlighter-rouge">gem</code> 이라고 합니다.</p>
<p>Jekyll server를 구동하기 위해서 필요한 플러그인을 모아둔 파일을 <code class="language-plaintext highlighter-rouge">Gemfile</code>이라고 합니다. Python의 <code class="language-plaintext highlighter-rouge">requirements.txt</code> 같은 역할이라고 보면 될 것 같습니다.</p>
<p>Jekyll blog의 theme에 따라 필요한 플러그인이 다르기 때문에, Gemfile을 다르게 쓰며, 일반적으로 Jekyll blog의 root 폴더에 포함되어 있습니다.</p>
<p><strong>Gemfile 예시</strong>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">source</span> <span class="s2">"https://rubygems.org"</span>
<span class="n">gem</span> <span class="s2">"github-pages"</span><span class="p">,</span> <span class="ss">group: :jekyll_plugins</span>
<span class="n">gem</span> <span class="s2">"tzinfo-data"</span>
<span class="n">gem</span> <span class="s2">"wdm"</span><span class="p">,</span> <span class="s2">"~> 0.1.0"</span> <span class="k">if</span> <span class="no">Gem</span><span class="p">.</span><span class="nf">win_platform?</span>
<span class="c1"># If you have any plugins, put them here!</span>
<span class="n">group</span> <span class="ss">:jekyll_plugins</span> <span class="k">do</span>
<span class="n">gem</span> <span class="s2">"jekyll-paginate"</span>
<span class="n">gem</span> <span class="s2">"jekyll-sitemap"</span>
<span class="n">gem</span> <span class="s2">"jekyll-gist"</span>
<span class="n">gem</span> <span class="s2">"jekyll-feed"</span>
<span class="n">gem</span> <span class="s2">"jemoji"</span>
<span class="n">gem</span> <span class="s2">"jekyll-algolia"</span>
<span class="n">gem</span> <span class="s1">'jekyll-include-cache'</span>
<span class="n">gem</span> <span class="s1">'github-pages'</span>
<span class="k">end</span>
</code></pre></div></div>
<p>Jekyll server 구동 시, 특정 버전 이상의 <code class="language-plaintext highlighter-rouge">gem</code>을 설치하도록 요구할 수도 있습니다. <code class="language-plaintext highlighter-rouge">gem 'gem name', "~> version"</code> 처럼 쓰면 됩니다. Error message를 잘 읽어보세요.</p>
<h2 id="3-local-server-구동">3. Local server 구동</h2>
<p><img src="https://tyami.github.io/assets/images/post/Blog/2020-11-17-jekyll-local-server-start-batch/2020-11-17-jekyll-local-server-start-batch-2.png" alt="2020-11-17-jekyll-local-server-start-batch-2.png" /></p>
<p>cmd를 실행합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/Blog/2020-11-17-jekyll-local-server-start-batch/2020-11-17-jekyll-local-server-start-batch-3.png" alt="2020-11-17-jekyll-local-server-start-batch-3.png" /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>D:
cd 경로
</code></pre></div></div>
<p>cmd에서 드라이브를 이동할 때는 <code class="language-plaintext highlighter-rouge">cd</code> 커맨드 없이 <code class="language-plaintext highlighter-rouge">D:</code> 와 같이 드라이브만 적습니다. 드라이브를 맞춰준 후 <code class="language-plaintext highlighter-rouge">cd</code> 명령어로 Jekyll blog가 설치된 폴더로 이동해줍니다.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bundle exec jekyll serve
</code></pre></div></div>
<p>Jekyll blog local server를 구동합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/Blog/2020-11-17-jekyll-local-server-start-batch/jekyll-server-start.PNG" alt="jekyll-server-start" /></p>
<p>문제없이 구동이 되었다면 위와 같은 내용이 나타납니다.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bundle install
</code></pre></div></div>
<p>뭐가 없다고 그러면 <code class="language-plaintext highlighter-rouge">Gemfile</code> 파일에 추가해주고, <code class="language-plaintext highlighter-rouge">bundle install</code>로 설치합니다.</p>
<h2 id="4-로컬-서버-접속">4. 로컬 서버 접속</h2>
<p><a href="http://localhost:4000/">localhost:4000</a>로 접속합니다.</p>
<h3 id="로컬-서버-업데이트">로컬 서버 업데이트</h3>
<p><img src="https://tyami.github.io/assets/images/post/Blog/2020-11-17-jekyll-local-server-start-batch/jekyll-server-update.PNG" alt="jekyll-server-update" /></p>
<p>로컬 서버는 파일의 수정이 발생되면 거의 실시간으로 업데이트 됩니다. 다만 몇 초 정도 걸릴 수 있으니 기다려주세요.</p>
<p><strong>📌 NOTE</strong></p>
<ul>
<li>최상단 루트에 있는 <code class="language-plaintext highlighter-rouge">_config.yml</code>의 수정사항은 Local server를 재시작해야 적용됩니다. 그 외에는 바로바로 적용됩니다.</li>
</ul>
<h3 id="로컬-서버-업데이트-에러">로컬 서버 업데이트 에러</h3>
<p><img src="https://tyami.github.io/assets/images/post/Blog/2020-11-17-jekyll-local-server-start-batch/jekyll-server-update-error.PNG" alt="jekyll-server-update-error" /></p>
<p>업데이트 시 문제가 발생하면, cmd에서 에러가 발생한 이유를 확인할 수 있습니다. 복사해서 구글링하면 됩니다 😁</p>
<h2 id="5-local-server-자동-구동-파일-만들기">5. Local server 자동 구동 파일 만들기</h2>
<p>cmd로 경로까지 들어가서 <code class="language-plaintext highlighter-rouge">bundle exec jekyll serve</code> 치는 과정이 너무 귀찮다면, 간단하게 <strong>클릭 한 번 만으로 로컬 서버를 구동시키는 파일</strong>을 만들어봅시다.</p>
<p><img src="https://tyami.github.io/assets/images/post/Blog/2020-11-17-jekyll-local-server-start-batch/2020-11-17-jekyll-local-server-start-batch-5.png" alt="2020-11-17-jekyll-local-server-start-batch-5.png" /></p>
<p>메모장을 열어, cmd에서 적었던 모든 명령어를 적어줍니다.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>D:
cd 경로
bundle exec jekyll serve
</code></pre></div></div>
<p><img src="https://tyami.github.io/assets/images/post/Blog/2020-11-17-jekyll-local-server-start-batch/2020-11-17-jekyll-local-server-start-batch-6.png" alt="2020-11-17-jekyll-local-server-start-batch-6.png" /></p>
<p><code class="language-plaintext highlighter-rouge">파일명.bat</code> 파일로 저장해줍니다. 이후 해당 파일을 실행하면 cmd가 실행되며, Jekyll local server가 구동됩니다.</p>
<p>끝.</p>Taeyang Yangautomatical execution of Jekyll blog local serverPython Jupyter notebook에서 shell command에 반복문 (for loop) 사용하는 법2020-11-16T00:00:00+09:002020-11-16T00:00:00+09:00https://tyami.github.io/python/python-shell-command-for-loop<h2 id="shell-command-in-python">Shell command in Python</h2>
<p><a href="https://tyami.github.io/python/python-shell-command/">지난 포스팅</a>에서 Python에서 shell command를 사용하는 법을 정리했습니다.</p>
<p><code class="language-plaintext highlighter-rouge">!</code>를 이용해 간단히 사용할 수 있었고, <code class="language-plaintext highlighter-rouge">argparse</code> 함수를 이용해 <code class="language-plaintext highlighter-rouge">*.py</code> 파일에 인자를 넣을 수도 있었습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/Python/2020-11-15-python-shell-command/2020-11-15-python-shell-command-2.PNG" alt="2020-11-15-python-shell-command-2" /></p>
<p>이렇게 말이죠.</p>
<h2 id="necessity-of-for-loop">Necessity of for loop</h2>
<p>그런데, 만약 여러 <code class="language-plaintext highlighter-rouge">subject_id</code>를 반복적으로 shell command를 이용해 입력해야 하는 상황이 생긴다면 어떨까요?</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">!</span><span class="n">python</span> <span class="n">argparse_test</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">subject_id</span> <span class="mi">1</span>
<span class="err">!</span><span class="n">python</span> <span class="n">argparse_test</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">subject_id</span> <span class="mi">2</span>
<span class="err">!</span><span class="n">python</span> <span class="n">argparse_test</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">subject_id</span> <span class="mi">3</span>
<span class="err">!</span><span class="n">python</span> <span class="n">argparse_test</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">subject_id</span> <span class="mi">4</span>
<span class="err">!</span><span class="n">python</span> <span class="n">argparse_test</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">subject_id</span> <span class="mi">5</span>
</code></pre></div></div>
<p>이렇게 노가다를 하면 될까요?</p>
<p><img src="https://tyami.github.io/assets/images/post/Python/2020-11-16-python-argparse-for-loop/2020-11-16-python-argparse-for-loop-1.PNG" alt="2020-11-16-python-argparse-for-loop-1" /></p>
<p>이 방법도 되긴 됩니다. 하지만 수백명의 데이터가 있다면, 어떨까요? 효과적인 방법은 <code class="language-plaintext highlighter-rouge">for loop</code>를 쓰는 방법입니다.</p>
<h2 id="problem-of-for-loop">Problem of for loop</h2>
<p>하지만 <code class="language-plaintext highlighter-rouge">!</code> 이후의 명령어는 string 타입으로 argument parser에 전달되고, 이를 parsing해서 변수로 사용합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/Python/2020-11-16-python-argparse-for-loop/2020-11-16-python-argparse-for-loop-2.PNG" alt="2020-11-16-python-argparse-for-loop-2" /></p>
<p>따라서 냅다 for loop의 변수를 값으로 사용하는 것은 옳지 않은 방법입니다.</p>
<h2 id="usage-of-for-loop">Usage of for loop</h2>
<p>그렇다면 올바른 사용법은 어떤 것일까요?</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="n">sub</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="err">!</span><span class="n">python</span> <span class="n">argparse_test</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">subject_id</span> <span class="p">{</span><span class="n">sub</span><span class="p">}</span>
</code></pre></div></div>
<p>간단히 변수에 <code class="language-plaintext highlighter-rouge">{ }</code> 괄호를 씌워주면 됩니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/Python/2020-11-16-python-argparse-for-loop/2020-11-16-python-argparse-for-loop-3.PNG" alt="2020-11-16-python-argparse-for-loop-3" /></p>
<p>네 잘 됩니다.</p>Taeyang Yangpython shell command 명령어와 for loop를 함께 사용하는 법을 정리해봅니다Python Jupyter notebook에서 Shell command (cmd) 사용하기2020-11-15T00:00:00+09:002020-11-15T00:00:00+09:00https://tyami.github.io/python/python-shell-command<h1 id="function">Function</h1>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">print_subject_id</span><span class="p">(</span><span class="n">subject_id</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Subject ID: '</span><span class="p">,</span> <span class="n">subject_id</span> <span class="p">)</span>
</code></pre></div></div>
<p>이 함수는 <code class="language-plaintext highlighter-rouge">subject_id</code>를 입력으로 받아 화면에 출력해주는 간단한 함수입니다. 이 함수를 여러 Python 코드 내에서 사용하려면 일반적으로 <code class="language-plaintext highlighter-rouge">utils.py</code> 파일 안에 작성해준 후 <code class="language-plaintext highlighter-rouge">import utils</code>를 통해 불러와 사용합니다.</p>
<h1 id="shell-command">Shell command</h1>
<p>Shell (실행 > cmd) 에서 Python 코드를 실행하고자 할 때, 함수의 입력 변수들은 명령어 뒤에 쭉 이어서 작성합니다. Github 등 사람들이 작성해둔 코드를 보면, 아래와 같이 <code class="language-plaintext highlighter-rouge">--</code>를 이용해 변수의 값을 넣어주는 것을 많이 보셨을 겁니다.</p>
<p>예를 들어 키 <code class="language-plaintext highlighter-rouge">height</code>와 몸무게 <code class="language-plaintext highlighter-rouge">weight</code>를 받아 BMI 지수를 계산하는 <code class="language-plaintext highlighter-rouge">BMI.py</code>는 아래와 같이 호출합니다.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">!</span><span class="n">python</span> <span class="n">BMI</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">height</span> <span class="mi">185</span> <span class="o">--</span><span class="n">weight</span> <span class="mi">85</span>
</code></pre></div></div>
<p>height, weight와 같이 변수 역할을 하는 것을 <strong>인자 (argument)</strong>라고 부르고, 185, 85와 같이 데이터의 역할을 하는 것을 <strong>값</strong>이라고 부릅니다.</p>
<h1 id="argparse">argparse</h1>
<p>argparse는 Python 내장 라이브러리로, 인자에 대한 값을 정해진 형태에 맞추어 편하게 넣도록 만들어졌습니다.</p>
<h2 id="import">Import</h2>
<p>별도로 설치할 필요 없이 아래 함수로 불러옵니다.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">argparse</span>
</code></pre></div></div>
<h2 id="argparse-basic">argparse basic</h2>
<p>일반적으로 아래와 같이 <code class="language-plaintext highlighter-rouge">*.py</code> 파일을 작성합니다.</p>
<p><code class="language-plaintext highlighter-rouge">argparse_test.py</code>:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">argparse</span>
<span class="c1"># ArgumentParser 생성
</span><span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="p">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s">'argparse 테스트 파일입니다.'</span><span class="p">)</span>
<span class="c1"># Argument 정의
</span><span class="n">parser</span><span class="p">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">'--subject_id'</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'Subject ID를 입력하세요 (int)'</span><span class="p">)</span>
<span class="c1"># Argument parsing
</span><span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="p">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="n">subject_id</span> <span class="o">=</span> <span class="n">args</span><span class="p">.</span><span class="n">subject_id</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Subject ID: '</span><span class="p">,</span> <span class="n">subject_id</span> <span class="p">)</span>
</code></pre></div></div>
<p>위 파일을 한 줄 한 줄 뜯어보면 아래 순서로 구성되어 있습니다. Github 등에 사람들이 올려둔 파일</p>
<ol>
<li><code class="language-plaintext highlighter-rouge">argparse.ArgumentParser</code> 함수를 이용해 argument parser class를 생성해줍니다.</li>
<li><code class="language-plaintext highlighter-rouge">add_argument</code> 함수를 이용해 각 arguement의 이름, 조건 (<code class="language-plaintext highlighter-rouge">requried</code>, <code class="language-plaintext highlighter-rouge">type</code>, <code class="language-plaintext highlighter-rouge">default</code>), 도움말 (<code class="language-plaintext highlighter-rouge">help</code>)을 정의합니다.
3 <code class="language-plaintext highlighter-rouge">parse_args</code> 함수를 이용해 인자들의 값을 불러옵니다 (parsing).</li>
<li>값을 사용해 <code class="language-plaintext highlighter-rouge">*.py</code> 파일 내 코드를 실행합니다.</li>
</ol>
<h2 id="shell-command-in-python">Shell command in Python</h2>
<p>Python (Jupyter notebook)에서 Shell command 실행은 아래와 같이 명령어 앞에 <code class="language-plaintext highlighter-rouge">!</code>를 붙여주면 됩니다.</p>
<h3 id="help">Help</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">!</span><span class="n">python</span> <span class="n">argparse_test</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">h</span>
</code></pre></div></div>
<p><strong>📌 NOTE</strong></p>
<p><img src="https://tyami.github.io/assets/images/post/Python/2020-11-15-python-shell-command/2020-11-15-python-shell-command-1.PNG" alt="2020-11-15-python-shell-command-1" /></p>
<p><code class="language-plaintext highlighter-rouge">-h</code> 인자는 각 <code class="language-plaintext highlighter-rouge">argument</code>에 대한 설명을 보여줍니다.</p>
<h3 id="usage">Usage</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">!</span><span class="n">python</span> <span class="n">argparse_test</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">subject_id</span> <span class="mi">1</span>
</code></pre></div></div>
<p>인자와 키 사이에 공백을 넣어 입력합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/Python/2020-11-15-python-shell-command/2020-11-15-python-shell-command-2.PNG" alt="2020-11-15-python-shell-command-2" /></p>
<h2 id="argparse-application">argparse application</h2>
<p>맨 처음 예시에서 예로 든 BMI 지수를 내뱉는 함수를 작성해봅시다.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">argparse</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="p">.</span><span class="n">ArgumentParser</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s">'argparse 응용 파일입니다.'</span><span class="p">)</span>
<span class="n">parser</span><span class="p">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">'--subject_id'</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">int</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'Subject ID를 입력하세요 (int)'</span><span class="p">)</span>
<span class="n">parser</span><span class="p">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">'--height'</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">float</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'Subject의 height (cm)를 입력하세요 (float)'</span><span class="p">)</span>
<span class="n">parser</span><span class="p">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s">'--weight'</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">float</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'Subject의 weight (kg)를 입력하세요 (float)'</span><span class="p">)</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="p">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="n">subject_id</span> <span class="o">=</span> <span class="n">args</span><span class="p">.</span><span class="n">subject_id</span>
<span class="n">height</span> <span class="o">=</span> <span class="n">args</span><span class="p">.</span><span class="n">height</span>
<span class="n">weight</span> <span class="o">=</span> <span class="n">args</span><span class="p">.</span><span class="n">weight</span>
<span class="k">def</span> <span class="nf">BMI</span><span class="p">(</span><span class="n">height</span><span class="p">,</span> <span class="n">weight</span><span class="p">):</span>
<span class="n">height</span> <span class="o">=</span> <span class="n">height</span> <span class="o">/</span> <span class="mi">100</span> <span class="c1"># cm to m
</span>
<span class="k">return</span> <span class="n">weight</span> <span class="o">/</span> <span class="n">height</span><span class="o">**</span><span class="mi">2</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Subject ID: '</span><span class="p">,</span> <span class="n">subject_id</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Height (cm): '</span><span class="p">,</span> <span class="n">height</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Weight (kg): '</span><span class="p">,</span> <span class="n">weight</span><span class="p">)</span>
<span class="n">bmi</span> <span class="o">=</span> <span class="n">BMI</span><span class="p">(</span><span class="n">height</span><span class="p">,</span> <span class="n">weight</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'BMI: '</span><span class="p">,</span> <span class="n">bmi</span><span class="p">)</span>
<span class="k">if</span> <span class="n">bmi</span> <span class="o"><</span> <span class="mi">20</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'저체중입니다'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">bmi</span> <span class="o"><</span> <span class="mi">24</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'정상 체중입니다'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">bmi</span> <span class="o"><</span> <span class="mi">29</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'과체중입니다'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'비만입니다'</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">!</span><span class="n">python</span> <span class="n">argparse_application_BMI</span><span class="p">.</span><span class="n">py</span> <span class="o">-</span><span class="n">h</span>
</code></pre></div></div>
<p><img src="https://tyami.github.io/assets/images/post/Python/2020-11-15-python-shell-command/2020-11-15-python-shell-command-3.PNG" alt="2020-11-15-python-shell-command-3" /></p>
<p>이 함수는 shell command로 <code class="language-plaintext highlighter-rouge">subject_id</code>, <code class="language-plaintext highlighter-rouge">height</code> 그리고 <code class="language-plaintext highlighter-rouge">weight</code>를 입력으로 받습니다. 이후 parsing된 변수를 이용해 BMI 지수를 계산해서 출력합니다.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">!</span><span class="n">python</span> <span class="n">argparse_application_BMI</span><span class="p">.</span><span class="n">py</span> <span class="o">--</span><span class="n">subject_id</span> <span class="mi">1</span> <span class="o">--</span><span class="n">height</span> <span class="mi">185</span> <span class="o">--</span><span class="n">weight</span> <span class="mi">87</span>
</code></pre></div></div>
<p><img src="https://tyami.github.io/assets/images/post/Python/2020-11-15-python-shell-command/2020-11-15-python-shell-command-4.PNG" alt="2020-11-15-python-shell-command-4" /></p>
<p>잘 되긴 하는데, 좀 열받네요.</p>Taeyang Yang! 명령어와 argparse 함수를 이용해서 Python에서 shell command를 쓰는 법을 정리해봅니다Principal component analysis (주성분분석)2020-11-11T00:00:00+09:002020-11-11T00:00:00+09:00https://tyami.github.io/machine%20learning/PCA<blockquote>
<p>이번 포스팅에서는 <strong>Principal component analysis (주성분분석)</strong>을 정리해보고자 합니다.</p>
</blockquote>
<hr />
<h1 id="pca">PCA</h1>
<p>Principal component analysis (주성분분석)은 데이터의 분산을 가장 잘 설명하는 축으로 데이터를 변환시키는 과정을 말합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/ML/2020-11-11-PCA/2020-11-11-PCA-1.png" alt="2020-11-11-PCA-1.png" /></p>
<p>위 그림에서 기존의 축 \(x_1\) 또는 \(x_2\)로 데이터를 projection 시킬 때보다, 대각선으로 projection시킬 때 데이터가 더 넓게 분포되는 것을 볼 수 있습니다.</p>
<p>주성분분석은 데이터를 가장 넓게 퍼뜨리도록 하는 latent space \(z_k\)를 찾는 과정이라고 볼 수 있습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/ML/2020-11-11-PCA/2020-11-11-PCA-2.png" alt="2020-11-11-PCA-2.png" /></p>
<p><img src="https://tyami.github.io/assets/images/post/ML/2020-11-11-PCA/2020-11-11-PCA-3.png" alt="2020-11-11-PCA-3.png" /></p>
<p><img src="https://tyami.github.io/assets/images/post/ML/2020-11-11-PCA/2020-11-11-PCA-4.png" alt="2020-11-11-PCA-4.png" /></p>
<p><img src="https://tyami.github.io/assets/images/post/ML/2020-11-11-PCA/2020-11-11-PCA-5.png" alt="2020-11-11-PCA-5.png" /></p>
<p><img src="https://tyami.github.io/assets/images/post/ML/2020-11-11-PCA/2020-11-11-PCA-6.png" alt="2020-11-11-PCA-6.png" /></p>
<p><img src="https://tyami.github.io/assets/images/post/ML/2020-11-11-PCA/2020-11-11-PCA-7.png" alt="2020-11-11-PCA-7.png" /></p>
<p><img src="https://tyami.github.io/assets/images/post/ML/2020-11-11-PCA/2020-11-11-PCA-8.png" alt="2020-11-11-PCA-8.png" /></p>Taeyang YangPrincipal component analysis (주성분분석)을 정리해봅니다Segmentation for MEDIA (6) Atlas-based methods and label fusion2020-11-09T00:00:00+09:002020-11-09T00:00:00+09:00https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-6-atlas-based-methods<p>이전 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-5-active-contour-model/">Segmentation for MEDIA (5) Active contour model</a></p>
<blockquote>
<p>이전 포스팅에서는 Shape에 대한 Prior 정보를 바탕으로 최적의 contour를 찾아내는 <strong>Active contour model</strong>을 정리했습니다<br />
이번 포스팅에서는 <strong>Atlas-based segmentation methods와 label fusion 기법</strong>을 정리해보고자 합니다.</p>
</blockquote>
<h2 id="atlas-based-segmentation-method">Atlas-based segmentation method</h2>
<h3 id="atlas">Atlas</h3>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-01.png" alt="2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-01.png" /></p>
<p>일반적으로 Classification에서 Training data라고 불리우는 영상 \(y_i \)와 Label \(z_i\)의 조합을 Atlas라고 말합니다. 즉, Atlas 정보를 바탕으로 Test data \(x\)에 대해 segmentation을 수행합니다.</p>
<h3 id="registration">Registration</h3>
<p>Atlas를 기반으로 하는 알고리즘의 경우 Registration을 이용합니다. Registration은 주어진 틀에 영상을 맞추는 과정입니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-02.png" alt="2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-02.png" /></p>
<p>1번째 Atlas 중 입력 영상 \(y_1\)를 Test 이미지 \(x\)에 registration시키는 함수 \(T\)를 학습(?)합니다. 이 함수 \(T\)는 \(y_i\)의 영상 이미지를 최대한 \(x\)에 가깝게 변환하는 함수입니다.</p>
<p>이제 label 이미지 \(z_i\)를 \(T\) 변환시킵니다. 그러면 새로운 label 이미지 \(T(z_i)\)를 얻을 수 있습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-03.png" alt="2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-03.png" /></p>
<p>2번째 Atlas에 대해서도 위와 같은 과정을 반복합니다. 이 과정을 N개의 Atlas 이미지에 대해 수행합니다.</p>
<h3 id="voting">Voting</h3>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-04.png" alt="2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-04.png" /></p>
<p>그러면 N개의 segmentation result를 얻습니다. 이 결과를 Voting해서 최종 Segmentation 결과를 얻습니다.</p>
<ul>
<li>Voting 개념 참고 포스팅: <a href="https://tyami.github.io/machine%20learning/ensemble-1-basics/#voting의-종류">앙상블 (Ensemble)의 기본 개념</a></li>
</ul>
<h3 id="weighted-voting">Weighted voting</h3>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-05.png" alt="2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-05.png" /></p>
<p>이 때, \(y_i\)와 \(x\) 간 유사도를 계산하여 이를 voting 시 weight로 적용할 수도 있습니다.</p>
<h2 id="drawbacks-of-atlas-basd-method">Drawbacks of atlas-basd method</h2>
<p>Atlas 기반의 알고리즘은 atlas가 많아질 수록 더 좋은 성능을 내지만, 그에 따라 연산량이 증가한다는 단점을 갖습니다.</p>
<p>또한 Registration (T 변환)이 얼마나 잘 되느냐에 따라 Segmentation의 영향을 받습니다.</p>
<p>Non-rigid (?) registration을 사용할 경우 높은 정확도를 보이지만 위에 언급한 바와 같이 연산량이 증가합니다 (=느립니다).</p>
<p>빠른 속도를 위해서는 Registration 시 Rotation, Translation뿐 아니라 Shearing과 Scaling을 사용한 Affine registration을 활용할 수 있지만, 이 경우 정확도가 떨어져서 \(T(z_i)\)를 바로 사용하는게 아니라, 별도의 후처리가를 수행합니다. 이 후처리 과정을 label fusion 이라고 합니다.</p>
<h2 id="label-fusion">Label fusion</h2>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods/2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-06.png" alt="2020-11-09-segmentation-for-medical-image-6-atlas-based-methods-06.png" /></p>
<p>Label fusion은 Patch를 이용합니다.</p>
<p>입력 영상 \(y_i\)의 특정 영역에 대해 작은 Patch 이미지를 추출합니다. 동일한 크기의 Patch를 Test 영상 \(x\)의 모든 부분을 훑게 하면서, 두 패치간 유사도를 계산합니다. 계산된 유사도를 weight 값으로 사용하여, \(T(z_i)\)에 픽셀별로 곱해줍니다. 그러면 위 그림처럼 확률값을 갖는 이미지를 얻을 수 있게 되고, 이를 바탕으로 segmentation을 진행하는 것을 label fusion이라고 합니다.</p>
<h3 id="advantage-of-label-fusion">Advantage of label fusion</h3>
<p>Label fusion 방법은 사람마다 shape이 유사한 장기를 segmentation할 때, 별도의 학습 없이도 높은 성능을 발휘한다고 알려져 있습니다.</p>
<p>또한 연산량을 줄이기 위해, 모든 Atlas에 대해 연산하는 것이 아니라, 유사도가 높은 Atlas 들만 골라 사용하는 방법도 있습니다.</p>
<hr />
<blockquote>
<p>다음 포스팅에서는 <strong>학습 기반의 Segmentation 알고리즘</strong>을 정리해보고자 합니다</p>
</blockquote>
<p>다음 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/ 작성중 /"> 작성중 </a></p>Taeyang YangAtlas-based segmentation methods와 label fusion 기법을 정리해봅니다Segmentation for MEDIA (5) Active contour model2020-11-08T00:00:00+09:002020-11-08T00:00:00+09:00https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-5-active-contour-model<p>이전 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-4-graph-model/">Segmentation for MEDIA (4) Graph model-based segmentation</a></p>
<blockquote>
<p>이전 포스팅에서는 <strong>Graph model-based segmentation</strong>을 정리했습니다<br />
이번 포스팅에서는 <strong>Active contour model</strong>을 정리해보고자 합니다.</p>
</blockquote>
<h2 id="thresholding-region-growing-graph-model">Thresholding, Region growing, Graph model</h2>
<p>앞의 포스팅에서 정리한 Thresholding (+Morphological processing), Region growing, Graph model 등 알고리즘들은 주어진 영상이미지의 pixel 정보 또는 인접 픽셀들의 label 정보를 바탕으로 segmentation을 진행했습니다. 즉, 이 방법들은 <strong>사용자의 Domain knowledge를 활용하지 않는 순수한 영상처리 기법들</strong>입니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-01-comparison.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-01-comparison.png" /></p>
<p>반면 이제부터 정리할 몇가지 segmentation 모델은 <strong>Domain knowledge를 활용</strong>합니다. 즉, Foreground의 형태에 대한 정보를 이미 알고 있는 상황에서 해당 Foreground를 효과적으로 분리해내는 방법을 고안했습니다.</p>
<h1 id="active-contour-model">Active contour model</h1>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-02.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-02.png" /></p>
<p>Active contour model은 foreground의 경계 (contour)를 점차 업데이트 하면서 segmentation을 수행합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-03.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-03.png" /></p>
<p>Active contour model에서는 여러 점 \(v_s=(x_s, y_s)\)의 위치를 점차 업데이트해나가면서 점들의 집합인 contour의 Energy \(E=\int E(v_s)ds\)를 최소화하는 contour를 찾는 것을 목표로 합니다. 즉, 앞서 정리했던 Graph model에서와 같이 Energy function을 최소화하는 문제로 Segmentation을 풉니다.</p>
<h2 id="snake-energy-function">Snake energy function</h2>
<p>이 때 contour의 경계가 업데이트 되는 모습이 마치 뱀과 같이 구불구불하다고 해서 이 Energy function은 Snake energy function \(E_snake\)이라고 불립니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-04.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-04.png" /></p>
<p>Snake energy function은 그 때 그 때 사용자의 목적에 따라 다르게 정의할 수 있습니다.</p>
<p>일반적으로 위와 같이 External energy term 과 Internal energy term으로 나뉘어 정의되며, External/internal energy term 은 세부 energy term 으로 나뉩니다.</p>
<p>Snake energy function을 구성하는 여러 energy term 들을 정리해봅시다.</p>
<h3 id="external-energy-term">External energy term</h3>
<p><strong>External energy function은 영상의 특징을 고려해 정의한 energy function입니다.</strong> 무슨말이냐 하면, Foreground는 “경계에 특정한 값을 갖는다” 또는 “Background와의 경계가 확실하게 나타난다” 같은 특징을 가질 수 있습니다. 이를 활용하여 Snake energy function가 최소화시켜야할 term을 추가할 수 있습니다.</p>
<h4 id="line-energy">Line energy</h4>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-05.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-05.png" /></p>
<p>Line energy term은 <strong>Foreground의 boundary의 line에서 구분되는 값이 있을 것이다</strong>라는 것을 가정하여 energy function을 정의합니다.</p>
<p>예를 들어 Line energy term 을 \(E<em>{line}=I(x)\)로 정의하면, contour가 black line (\(I(x)=0\))을 따라 위치해 있을 때 \(E</em>{line}\)이 가장 작은 값을 나타낼 것입니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-06.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-06.png" /></p>
<p>반면, Line energy term을 \(E<em>{line}=-I(x)\)로 정의하면, 위와 반대로 contour가 white line (\(I(x)=255\))를 따라 위치해 있을 때 \(E</em>{line}\)이 가장 작은 값을 나타낼 것입니다.</p>
<h4 id="edge-energy">Edge energy</h4>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-07.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-07.png" /></p>
<p>또 다른 가정으로 <strong>경계가 뚜렷한 곳에서 Boundary가 생긴다</strong>라는 가정을 띄고 정의한 Energy term을 Edge energy term이라고 합니다.</p>
<p>\[
E_{edge}=-\lvert \nabla I(x,y) \rvert^2
\]</p>
<p>Energy function을 위와 같이 정의하면, \(x\)와 \(y\) 사이의 변화량의 절대값이 클 수록, energy function이 작은 값을 나타냅니다.</p>
<h3 id="internal-energy-term">Internal energy term</h3>
<p>External energy term이 영상에서의 특징을 고려한 것이라면, <strong>Internal energy term은 타겟 ROI의 shape 정보 (Prior)를 바탕으로 정의한 energy term</strong> 입니다.</p>
<p>대표적인 예시로 Elastic energy term과 Bending energy term을 정리해봅시다.</p>
<h4 id="elastic-energy-term">Elastic energy term</h4>
<p>Elastic energy term은 타겟 ROI의 shape이 굴곡이 별로 없다는 것을 알고 있을 때 효과적인 energy term 입니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-08.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-08.png" /></p>
<p>위 식과 같이 각 픽셀값 \(v_s\)을 1차미분한 \(V_s\) 에 가중치를 곱한 값의 합으로 정의합니다.</p>
<p>그러면 Elastic energy function을 최소화하기 위해, 우측 그림처럼 굴곡진 부분이 평평하게 업데이트되는 효과를 얻을 수 있습니다.</p>
<h4 id="bending-energy-term">Bending energy term</h4>
<p>Bending energy term은 타겟 ORI의 shape에 뾰족한 부분이 별로 없다는 것을 알고 있을 때 효과적인 energy term 입니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-09.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-09.png" /></p>
<p>Elastic energy term에서의 1차 미분값 \(V<em>s\)를 다시 한번 더 미분한 2차 미분값 \(V</em>{ss}\)에 가중치를 곱한 값의 합으로 정의합니다.</p>
<p>이번에는 뾰족한 부분이 뭉툭해지도록 업데이트되는 효과를 확인할 수 있습니다.</p>
<h3 id="summary">Summary</h3>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-08-segmentation-for-medical-image-5-active-contour-model/2020-11-08-segmentation-for-medical-image-5-active-contour-model-10.png" alt="2020-11-08-segmentation-for-medical-image-5-active-contour-model-10.png" /></p>
<p>따라서 Snake energy function의 기본적인 전체 모습은 위와 같이 Line energy, Edge energy, Elastic energy, Bending energy term을 모두 합친 형태가 됩니다.</p>
<p>이외에 영상의 특징을 고려해서 추가의 term을 붙인다고도 합니다.</p>
<hr />
<blockquote>
<p>다음 포스팅에서는 <strong>Atlas-based 알고리즘</strong>을 정리해보고자 합니다</p>
</blockquote>
<p>다음 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-6-atlas-based-methods/">Segmentation for MEDIA (6) Atlas-based methods and label fusion</a></p>Taeyang YangShape update 기반의 active contour model을 정리해봅니다Segmentation for MEDIA (4) Graph model-based segmentation2020-11-06T00:00:00+09:002020-11-06T00:00:00+09:00https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-4-graph-model<p>이전 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-3-region-growing/">Segmentation for MEDIA (3) Region growing & Wathershed algorithm</a></p>
<blockquote>
<p>이전 포스팅에서는 <strong>사용자의 도움을 받아 ROI 영역을 분리해내는 Region growing과 Wathershed 알고리즘</strong>을 정리했습니다<br />
이번 포스팅에서는 <strong>Graph model-based segmentation</strong>을 정리해보고자 합니다.</p>
</blockquote>
<hr />
<h2 id="graph-model">Graph model</h2>
<p>Graph model은 foreground와 background를 분리하는 것을 보다 수학적으로 나타낸 모델이라고 할 수 있습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-01.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-01.png" /></p>
<p>주어진 영상 이미지 (좌)의 보라색 부분을 Foreground라고 해봅시다. 이 이미지 자체는 Observation \(z_i\)로, 각 픽셀의 label 값은 \(x_i\)로 나타낼 수 있습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-02-graph-model.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-02-graph-model.png" /></p>
<table>
<tbody>
<tr>
<td>Graph model에서는 주어진 \(Z\) 벡터에 대해 \(P(x_1,x_2,…x_N</td>
<td>z_1,z_2,…z_N)\)을 최대로 하는 \(X\)를 찾는 것을 목표로 합니다.</td>
</tr>
</tbody>
</table>
<p>이를 Posterior probability라고 하는데, 이 확률값을 바로 얻는 것은 쉽지 않습니다. 따라서 수학적으로 식을 변형합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-03-bayes.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-03-bayes.png" /></p>
<p>Posterior probability 수식을 Bayes rule로 풀어보면 아래와 같이 Likelihood \(P(z_1,…z_N \vert x_1,…z_N)P(x_1,…x_N)\)와 Prior probability \(P(x_1,…x_N)\)의 식으로 변형됩니다.</p>
<p>\[
P(x_1,x_2,…x_N \vert z_1,z_2,…z_N)=\frac{P(z_1,…z_N \vert x_1,…z_N)P(x_1,…x_N)}{P(z_1,…z_N)}
\]</p>
<p>여기에 문제를 단순화하기 위해, 두 가지 Assumption을 갖습니다.</p>
<p>첫번째로 각 샘플은 독립적이라는 Naive assumption을 가정합니다. 각 샘플이 독립이라는 말은, 다시 말하면, \(x_i\)를 계산할 때, 다른 픽셀값들을 고려하지 않는다는 말이 됩니다.</p>
<p>Posterior probability는 아래와 같이 표현됩니다.</p>
<p>\[
P(x_1,x_2,…x_N \vert z_1,z_2,…z_N) \propto \prod_i^N P(z_i \vert x_i) \prod_{i,j}P(x_i, x_j)
\]</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-04-markov.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-04-markov.png" /></p>
<p>두번째 Assumption은 Markov Random FIeld입니다. 다른 픽셀값을 고려하지 않되, 주변에 위치한 픽셀의 label \(x_j\)는 고려합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-05-goal.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-05-goal.png" /></p>
<p>Posterior probability 를 최대화시키는 문제는 Negative logarithm을 적용한 Energy를 최소화하는 문제로 생각할 수 있습니다. (<strong>저는 이 부분을 아직 완전히 이해하지 못 했습니다</strong>)</p>
<p>따라서 아래와 같이 식이 변형됩니다.</p>
<p>\begin{aligned}
E(x<em>1,x_2,…x_N \vert z_1,z_2,…z_N) &= log( \prod_i^N P(z_i \vert x_i) \prod</em>{i,j}P(x<em>i, x_j) ) \\<br />
&=\sum_i^N \theta_i(z_i \vert x_i) + \sum</em>{i,j} \theta_{i,j}(x_i,x_j)
\end{aligned}</p>
<p>위 식에서 \(\sum<em>i^N \theta_i(z_i \vert x_i)\)은 Likelihood term으로, \(\sum</em>{i,j} \theta_{i,j}(x_i,x_j)\)은 Prior term으로 생각할 수 있습니다.</p>
<p>위 식을 해석해보면, Assumption 1 (다른 픽셀값을 고려하지 않는다)에 따라 \(z_i\)와 \(x_i\) 사이의 관계만 보되 (Likelihood), Assumption 2 (주변부 픽셀의 label 값은 고려한다)에 따라 \(x_j\)는 고려하는 것으로 볼 수 있습니다 (Prior)</p>
<p>즉, Graph model에서 posterior probability 를 최대화하는 문제는 pixel-wise label \(x_i\) 의 \(2^N\)가지 모든 조합 중 likelihood term과 prior term을 모두 최소화하는 조건을 찾는 문제입니다.</p>
<h3 id="lambda">lambda</h3>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-11-lambda.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-11-lambda.png" /></p>
<p>여기에 Prior term에 얼마나 가중치를 줄 지 나타내는 \(\lambda\)를 붙여 사용합니다.</p>
<p>알고리즘의 \(\lambda\)가 커지면, prior term에 대한 가중치가 높아집니다. 즉, 주변부 픽셀 label의 영향을 더 많이 받게 됩니다.</p>
<h2 id="max-flow-min-cut-algorithm">max-flow min-cut algorithm</h2>
<p><strong>max-flow min-cut 알고리즘은 좀 더 공부가 필요합니다. 대략적인 과정만 참고하세요</strong></p>
<p>Graph model과 관련된 (?) 알고리즘 중 하나로 Max-flow min-cut (Mfmc) 알고리즘이 있습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-06-mfMc-1.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-06-mfMc-1.png" /></p>
<p>Mfmc 알고리즘에서는 Observation (Source)으로부터 Sink까지 가는 path들이 있고, 각 path들에는 capatcity가 존재합니다.</p>
<p>Source로부터 Sink까지 낮은 Capacity를 채워가며 가상의 물이 흐르고, 이 물에 의해 공간이 나뉜다고 생각하면 됩니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-07-mfMc-2.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-07-mfMc-2.png" /></p>
<p>가장 먼저 좌측의 <code class="language-plaintext highlighter-rouge">1</code>, <code class="language-plaintext highlighter-rouge">6</code> path를 따라 Sink로 물이 흐르고, 해당 path들의 capacity는 1만큼 감소합니다. 좌상단의 <code class="language-plaintext highlighter-rouge">1</code> path는 <code class="language-plaintext highlighter-rouge">0</code>으로 바뀌게 되므로, 이 path는 끊기게 됩니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-08-mfMc-3.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-08-mfMc-3.png" /></p>
<p>마찬가지로 이번에는 우측의 <code class="language-plaintext highlighter-rouge">9</code>, <code class="language-plaintext highlighter-rouge">3</code> path를 따라 물이 흐르게 되고, 해당 path는 capacity가 감소합니다. 그 결과, 우 하단의 <code class="language-plaintext highlighter-rouge">3</code> path는 <code class="language-plaintext highlighter-rouge">0</code>이 되어 해당 path도 끊깁니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-09-mfMc-4.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-09-mfMc-4.png" /></p>
<p>같은 방식으로 가운데 위치한 <code class="language-plaintext highlighter-rouge">1</code> path도 끊기게 되면</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-06-segmentation-for-medical-image-4-graph-model/2020-11-06-segmentation-for-medical-image-4-graph-model-10-mfMc-5.png" alt="2020-11-06-segmentation-for-medical-image-4-graph-model-10-mfMc-5.png" /></p>
<p>원래의 Graph는 두 개로 분리가 됩니다. 즉, Foreground/Background로 segmentation 되는 것으로 볼 수 있습니다.</p>
<hr />
<p>Graph model이 익숙하지 않아서 이번 차시 강의의 내용은 전부 이해하지 못했습니다. 추후 시간이 허락하면 좀 더 공부해서 보완하고자 합니다.</p>
<blockquote>
<p>다음 포스팅에서는 <strong>Active contour model</strong>을 정리해보고자 합니다</p>
</blockquote>
<p>다음 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-5-active-contour-model/">Segmentation for MEDIA (5) Active contour model</a></p>Taeyang YangGraph model-based segmentation을 정리해봅니다Segmentation for MEDIA (3) Region growing & Wathershed algorithm2020-11-05T00:00:00+09:002020-11-05T00:00:00+09:00https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-3-region-growing<p>이전 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-2-morphological-processing/">Segmentation for MEDIA (2) Morphological processing</a></p>
<blockquote>
<p>이전 포스팅에서는 Threshold 이후 후처리에 사용되는 <strong>Morphological processing</strong>을 정리했습니다<br />
이번 포스팅에서는 <strong>사용자의 도움을 받아 ROI 영역을 분리해내는 Region growing과 Wathershed 알고리즘</strong>을 정리해보고자 합니다.</p>
</blockquote>
<h2 id="drawback-of-thresholding">Drawback of thresholding</h2>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-14-drawback.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-14-drawback.png" /></p>
<p>먼저 이전에 정리했던 Thresholding, Morphological processing에서 출발합니다. 이 방법들은 ROI와 크기가 비슷한 노이즈들은 제거하지 못한다는 결함이 존재했습니다.</p>
<h2 id="region-growing">Region growing</h2>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-05-segmentation-for-medical-image-3-region-growing/2020-11-05-segmentation-for-medical-image-3-region-growing-1-intro.png" alt="2020-11-05-segmentation-for-medical-image-3-region-growing-1-intro.png" /></p>
<p>Region growing에서는 특정 ROI만 추출할 수 있도록, 사용자의 도움을 받습니다. 즉, 사용자가 특정 영역을 선택하면, 그 영역과 인접한 Foreground만 골라내는 알고리즘입니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-05-segmentation-for-medical-image-3-region-growing/2020-11-05-segmentation-for-medical-image-3-region-growing-2.png" alt="2020-11-05-segmentation-for-medical-image-3-region-growing-2.png" /></p>
<p>사용자가 특정 영역을 선택하면, 해당 영역을 시작으로 주변부를 스캔하면서 반복적으로 intensity를 비교하여 Foregrond 영역을 골라내면, 인접하지 않은 foreground (noise)들은 자동으로 탈락하게 됩니다.</p>
<h3 id="region-growing-in-brain-image">Region growing in brain image</h3>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-05-segmentation-for-medical-image-3-region-growing/2020-11-05-segmentation-for-medical-image-3-region-growing-3.png" alt="2020-11-05-segmentation-for-medical-image-3-region-growing-3.png" /></p>
<p>뇌 이미지에서는 이렇게 된다고 합니다.</p>
<h3 id="region-growing-in-rgb-image">Region growing in RGB image</h3>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-05-segmentation-for-medical-image-3-region-growing/2020-11-05-segmentation-for-medical-image-3-region-growing-4-rgb.png" alt="2020-11-05-segmentation-for-medical-image-3-region-growing-4-rgb.png" /></p>
<p>흑백 이미지뿐 아니라, 컬러 이미지에도 Region growing 알고리즘이 활용됩니다.</p>
<h3 id="drawback-of-region-growing">Drawback of region growing</h3>
<p>사용자의 도움을 받기 때문에, Region growing도 결함을 가집니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-05-segmentation-for-medical-image-3-region-growing/2020-11-05-segmentation-for-medical-image-3-region-growing-5-drawback.png" alt="2020-11-05-segmentation-for-medical-image-3-region-growing-5-drawback.png" /></p>
<p>위와 같은 pathology 데이터의 경우, 모든 셀들을 클릭하기에는 너무 시간과 노동이 많이 든다는 단점이 있습니다.</p>
<h2 id="watershed-algorithm">Watershed algorithm</h2>
<p>Watershed 알고리즘이 이 때 사용될 수 있습니다. Watershed 알고리즘을 간략하게 설명하면 아래와 같습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-05-segmentation-for-medical-image-3-region-growing/2020-11-05-segmentation-for-medical-image-3-region-growing-6-watershed.png" alt="2020-11-05-segmentation-for-medical-image-3-region-growing-6-watershed.png" /></p>
<p>(좌) Watershed 알고리즘은 위와 같이 Intensity 값을 바탕으로 지형을 그립니다. 그러면 여러 개의 웅덩이가 나오게 됩니다. 이제 이 지형에 물을 채운다고 생각할 때, 각 웅덩이의 경계점에 댐을 세우면, 웅덩이끼리 물이 섞이지 않습니다. 결과적으로 지형도의 맨 꼭대기까지 물이 차오르게 되면, 여러 개의 분리된 웅덩이가 형성이 됩니다 (segmentation)</p>
<p>(우) 이 경우 모든 웅덩이를 독립적으로 만들지만, 특정 웅덩이를 marker로 표시하면, marker가 표시된 웅덩이에만 댐을 설치합니다. 즉, marker가 없는 웅덩이들은 근처의 웅덩이로 통합됩니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-05-segmentation-for-medical-image-3-region-growing/2020-11-05-segmentation-for-medical-image-3-region-growing-7-watershed-2D.png" alt="2020-11-05-segmentation-for-medical-image-3-region-growing-7-watershed-2D.png" /></p>
<p>2차원의 이미지의 경우, 위와 같이 지형도를 두 개 만든다고 생각하면 됩니다.</p>
<hr />
<blockquote>
<p>다음 포스팅에서는 <strong>Graph 모델을 이용한 segmentation 방법</strong>을 정리해보고자 합니다</p>
</blockquote>
<p>다음 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-4-graph-model/">Segmentation for MEDIA (4) Graph model-based segmentation</a></p>Taeyang YangRegion growing과 Wathershed algorithm을 정리해봅니다Segmentation for MEDIA (2) Morphological processing2020-11-04T00:00:00+09:002020-11-04T00:00:00+09:00https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-2-morphological-processing<p>이전 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-1-otsu-threshold/">Segmentation for MEDIA (1) Otsu threshold</a></p>
<blockquote>
<p>이전 포스팅에서는 <strong>Segmentation 기법 중 가장 기본적인 기법인 Thresholding 알고리즘</strong>을 정리했습니다<br />
이번 포스팅에서는 Threshold 이후 후처리에 사용되는 <strong>Morphological processing</strong>을 정리해보고자 합니다.</p>
</blockquote>
<h2 id="drawback-of-otsu-thresholding">Drawback of Otsu thresholding</h2>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-10-drawback.png" alt="2020-11-03-segmentation-for-medical-image-10-drawback.png" /></p>
<p>이전 포스팅에서 정리한 것처럼 Otsu threshold를 포함한 Thresholding 방법은 데이터를 두 개의 그룹으로 분리하기 때문에, 깔끔한 Segmentation이 불가능합니다. 따라서 결과 이미지를 보면 위와 같이 여러 종류의 Noise들이 포함되어 있는 것을 확인할 수 있습니다.</p>
<h2 id="morphological-processing">Morphological processing</h2>
<p>Morphological processing은 주변 데이터와의 관계를 이용해 이러한 노이즈를 제거할 수 있는 방법입니다.</p>
<p>Dilation과 Erosion이라는 개념이 등장합니다. 이는 <a href="https://tyami.github.io/medical%20image%20analysis/2020-10-25-MEDIA-5-classification-for-medical-image-3-CNN/">이전의 포스팅</a>에서 정리했던 Convolution과 비슷합니다.</p>
<h3 id="convolution">Convolution</h3>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-10-25-medical-image-classification-3-CNN/2020-10-25-medical-image-classification-3-cnn-2-convolution-2.png" alt="2020-10-25-medical-image-classification-3-cnn-2-convolution-2" /></p>
<p>이전 포스팅에서 정리한 Convolution에서는 필터가 입력 이미지를 훑고 지나가면서, 입력 이미지를 압축하는 효과를 냈습니다.</p>
<h3 id="dilation-and-erosion">Dilation and Erosion</h3>
<h4 id="dilation">Dilation</h4>
<p>Dilation과 Erosion 에서도 필터가 입력 이미지를 훑고 지나갑니다. 다만, 데이터를 압축하는 것이 아니라, 주변 데이터를 인식하고 이에 따라 해당 픽셀의 값을 변화시킵니다.</p>
<p>말보다는 그림이죠. 그림으로 살펴봅시다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-02-filters.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-02-filters.png" /></p>
<p>Dilation/Erosion에 사용되는 필터 Structual element라고 말하며, 위와 같이 1/0으로 이루어져있고 Convolutional filter와 마찬가지로 다양한 모양을 갖습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-03-dilation-1.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-03-dilation-1.png" /></p>
<p>필터가 입력 이미지의 모든 픽셀을 훑고 지나갑니다. 이 때 “1”과 Foreground 가 맞닿는 부분이 생기게 되면, 필터의 중심이 위치한 픽셀 값을 Foreground로 바꾸어줍니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-04-dilation-2.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-04-dilation-2.png" /></p>
<p>즉, 위와 같은 경우 모든 1값이 Foreground와 겹치지 않기 때문에 넘어갑니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-05-dilation-3.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-05-dilation-3.png" /></p>
<p>이 때는 필터의 하단에 위치한 1이 Foreground와 겹치기 때문에, (1,4) 픽셀을 Foreground로 바꿔줍니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-06-dilation-4.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-06-dilation-4.png" /></p>
<p>다음 과정도 마찬가지겠지요.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-07-dilation-5.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-07-dilation-5.png" /></p>
<p>모든 픽셀을 훑게 되면 위와 같이 이전의 이미지 (네이비)보다 확장된 출력 이미지를 얻게 됩니다.</p>
<h4 id="erosion">Erosion</h4>
<p>Dilation은 Foreground를 확장시키는 역할을 수행했습니다. Erosion은 이와 반대로 Foreground를 축소시키는 역할을 수행합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-08-erosion.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-08-erosion.png" /></p>
<p>Dilation과 반대로 필터의 1과 Background가 맞닿는 부분이 있다면, 필터의 중심 픽셀을 Background로 할당합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-09-erosion.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-09-erosion.png" /></p>
<p>결과적으로 Erosion을 거치면 Foreground의 테두리 부분이 축소되는 효과를 얻습니다.</p>
<h3 id="mixture-model-of-dilation-and-erosion">Mixture model of Dilation and Erosion</h3>
<h4 id="opening">Opening</h4>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-10-role-of-erosion.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-10-role-of-erosion.png" /></p>
<p>Erosion은 Foreground를 축소시키기 때문에, 위와 같이 미세한 노이즈를 제거하는 역할을 합니다. 하지만, 타겟 ROI의 크기도 축소시킨다는 단점이 존재합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-11-opening.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-11-opening.png" /></p>
<p>따라서 Erosion 후에, Dilation을 다시 해서 미세한 노이즈는 제거한 뒤, 타겟 ROI의 크기를 다시 키워주는 응용을 할 수 있습니다. 이를 Opening이라고 합니다.</p>
<h4 id="closing">Closing</h4>
<p>Opening이 있다면 Closing도 있겠지요. Closing은 Dilation 후 Erosion을 하는 것이라고 짐작할 수 있습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-12-dilation.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-12-dilation.png" /></p>
<p>Dilation을 하게 되면, Foreground가 확장되기 때문에 타겟 ROI의 안에 잡힌 작은 홀들을 매꿔주는 역할을 합니다. 하지만 타겟 ROI가 커지는 단점이 존재합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-13-closing.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-13-closing.png" /></p>
<p>이 때 다시 Erosion을 해주면 타겟 ROI를 다시 축소시키면서, 가운데 홀을 매꿔주고, 심지어 일부 미세한 노이즈도 제거해주는 효과를 얻을 수 있습니다.</p>
<h2 id="drawback-of-morphological-processing">Drawback of morphological processing</h2>
<p>완벽해보이지만 Morphological processing 만으로는 아직 부족합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-04-segmentation-for-medical-image-2-morphological-processing/2020-11-04-segmentation-for-medical-image-2-morphological-processing-14-drawback.png" alt="2020-11-04-segmentation-for-medical-image-2-morphological-processing-14-drawback.png" /></p>
<p>Thresholding과 Morphological processing을 거쳐 좌측의 이미지를 얻었지만, 여전히 커다란 노이즈들은 존재합니다. 이를 없애줄 필요가 있습니다.</p>
<hr />
<blockquote>
<p>다음 포스팅에서는 사용자의 도움을 받아 ROI영역만을 분리하는 <strong>Region growin과 Wathershed 알고리즘</strong>을 정리해보고자 합니다</p>
</blockquote>
<p>다음 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-3-region-growing/">Segmentation for MEDIA (3) Region growing & Wathershed algorithm</a></p>Taeyang YangThresholding의 후처리 방법인 Morphological processing를 정리해봅니다Segmentation for MEDIA (1) Otsu threshold2020-11-03T00:00:00+09:002020-11-03T00:00:00+09:00https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-1-otsu-threshold<p>이전 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/classification-for-medical-image-7-feature-selection-extraction/">Classification for MEDIA (7) Feature selection and extraction</a></p>
<blockquote>
<p>이전 포스팅들에서 <strong>Classficiation과 관련된 다양한 알고리즘들</strong>을 정리했습니다<br />
이번 포스팅에서는 <strong>Segmentation 기법 중 가장 기본적인 기법인 Thresholding 알고리즘</strong>을 정리해보고자 합니다.</p>
</blockquote>
<h2 id="segmentation">Segmentation</h2>
<p>Segmentation은 이미지 내의 각 영역을 분할하는 것을 말합니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-01-otsu-threshold-intro.png" alt="2020-11-03-segmentation-for-medical-image-01-otsu-threshold-intro.png" /></p>
<p>즉, 위와 같이 뇌나 다른 부위의 MRI 같은 이미지에서, 뇌의 세부 영역들 또는 장기들의 위치를 뽑아내는 것을 말합니다. 이 때 Segmentation에 대해 관심있는 영역을 Region of Interst (ROI)라고 말합니다.</p>
<p>이를 통해 Longitudinal study (시간에 따른 ROI의 크기/비율의 변화)가 가능합니다. 종양을 Segmentation해서 n년 뒤 크기를 예측하는 문제를 풀어볼 수도 있겠네요.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-02-contents.png" alt="2020-11-03-segmentation-for-medical-image-02-contents.png" /></p>
<p>Segmentation 파트에서 다룰 알고리즘들입니다. Classifciation과 마찬가지로 전통적으로 해오던 알고리즘들과 최근 Deep learning을 적용시킨 알고리즘들로 나누어 정리할 예정입니다.</p>
<p>전통적인 알고리즘의 경우, 사용하는 정보에 따라 Intenstiy 기반/Prior 기반/Learning 기반 등으로 점차 발전해나가는 모양을 보여줍니다.</p>
<h2 id="thresholding">Thresholding</h2>
<p>Segmentation의 가장 기본적인 알고리즘으로 Thresholding이 있습니다. 알고리즘이라고 하기도 뭐한게, 그냥 <strong>Intensity 값이 일정 threshold보다 큰 값만 골라낸다</strong>가 핵심입니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-03-manual-threshold.png" alt="2020-11-03-segmentation-for-medical-image-03-manual-threshold.png" /></p>
<p>예를 들어, 좌측 이미지에서 Threshold=200을 기준으로 골라낼 경우 우측 이미지와 같이 나올 수 있습니다.</p>
<p>이 방법은 정말정말정말 간단하지만, 위 예시에서 보듯 Segmentation의 정확도가 그렇게 좋지 않습니다. 또한, Threshold 가 주관적이고 manual 하다는 단점이 존재합니다.</p>
<h2 id="otsu-thresholding">Otsu thresholding</h2>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-04-otsu-threshold.png" alt="2020-11-03-segmentation-for-medical-image-04-otsu-threshold.png" /></p>
<p>Otsu thresohlding은 1979년, Nobuyuki Otsu라는 일본사람이 제안한 Automatic thresholding 방법입니다. Otsu thresholding에서는 위와 같이 데이터를 Intenstity 값에 따라 히스토그램화시킵니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-05-step1.png" alt="2020-11-03-segmentation-for-medical-image-05-step1.png" /></p>
<p>그리고 관심있는 영역인 Foreground와 Background의 Intensity가 다르다고 가정합니다. 따라서 Foreground와 Background는 다른 분포를 띌 것이라고 생각할 수 있습니다. 이제 일정 Threshold 에 따라 Background/Foreground로 히스토그램을 분리합니다.</p>
<p>Threshold의 선택 방법은 후술합니다.</p>
<p>분리된 두 개의 히스토그램에 대해서 데이터의 비율 \(w\), 데이터의 평균 intensity \(\mu\), 그리고 데이터의 분산 \(\sigma\)를 계산합니다</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-06-step2.png" alt="2020-11-03-segmentation-for-medical-image-06-step2.png" /></p>
<p>먼저 Background에 대해서 계산해보면 위와 같습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-07-step3.png" alt="2020-11-03-segmentation-for-medical-image-07-step3.png" /></p>
<p>Foreground에 대해서도 똑같이 계산합니다.</p>
<p>Otsu thresholding에서는 두 히스토그램을 최대한 분리시키는 것을 목표로 합니다. 따라서 히스토그램간 분산 \(\sigma_B\)는 최대화하되, 히스토그램 내 분산 \(\sigma_W\)은 최소화해야합니다. 이를 수식으로 표현하면 아래와 같습니다.</p>
<p>\[
maximize \frac{\sigma_B^2(T)}{\sigma_W^2(T)}
\]</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-08-step4.png" alt="2020-11-03-segmentation-for-medical-image-08-step4.png" /></p>
<p>위 식에 따라 \(\frac{\sigma_B^2(T)}{\sigma_W^2(T)}\)를 계산합니다. 위 예시에서는 0.512가 나왔습니다.</p>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-09-step5.png" alt="2020-11-03-segmentation-for-medical-image-09-step5.png" /></p>
<p>히스토그램의 모든 분계점마다 \(\frac{\sigma_B^2(T)}{\sigma_W^2(T)}\)를 계산해서 최대값을 갖는 지점을 Threshold 로 설정합니다.</p>
<h3 id="drawback-of-otsu-thresholding">Drawback of Otsu thresholding</h3>
<p><img src="https://tyami.github.io/assets/images/post/MEDIA/2020-11-03-segmentation-for-medical-image-1-otsu-threshold/2020-11-03-segmentation-for-medical-image-10-drawback.png" alt="2020-11-03-segmentation-for-medical-image-10-drawback.png" /></p>
<p>Threshold의 두 문제점 중 manual하다는 문제점은 해결했습니다. 하지만, Otsu threshold 역시 데이터를 단지 두 그룹으로만 분리하기 때문에, Otsu threshold만으로는 깔끔한 Segmentation이 불가능합니다. 위와 같이 여러 종류의 Noise들이 포함되어 있는 것을 확인할 수 있습니다.</p>
<hr />
<blockquote>
<p>다음 포스팅에서는 Thresholding 후 Segmentation 결과를 개선하기 위한 방법으로 <strong>Morphological processing</strong>을 정리해보고자 합니다</p>
</blockquote>
<p>다음 포스팅: <a href="https://tyami.github.io/medical%20image%20analysis/segmentation-for-medical-image-2-morphological-processing/">Segmentation for MEDIA (2) Morphological processing</a></p>Taeyang Yang가장 기본적인 Segmentation 기법인 Otsu threshold를 정리해봅니다