<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>폴크(FOLC)</title>
    <link>https://folcjin.tistory.com/</link>
    <description>새로운 삶의 시작!

Clear Coding &amp;amp; Clean Coding</description>
    <language>ko</language>
    <pubDate>Sun, 21 Jun 2026 07:03:06 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>folcjin</managingEditor>
    <image>
      <title>폴크(FOLC)</title>
      <url>https://tistory1.daumcdn.net/tistory/4786354/attach/29c249fa91404fe9a5cae09e4ed3b757</url>
      <link>https://folcjin.tistory.com</link>
    </image>
    <item>
      <title>알고리즘 - Edge 추출 방법 ( Optimally Oriented Flux )</title>
      <link>https://folcjin.tistory.com/376</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;OOF는 국소적인 미분 연산의 한계를 넘어, 영역 기반의 에너지 흐름을 분석함으로써 복잡하고 밀집된 구조물에서 가장 신뢰할 수 있는 선 추출이 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목적: 이미지에서 가늘고 길게 이어진 구조를 검출&lt;br /&gt;적용 분야: 혈관, 신경 섬유, 기관지, 섬유 패턴 분석 등&lt;br /&gt;핵심 아이디어:&lt;br /&gt;- 픽셀 주변의 Hessian 행렬(2차 미분) 분석 + 인접 구조물의 간섭 활용&lt;br /&gt;- 고유값 패턴으로 선형성 판단의 약점을 보완하고자 개발됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;br /&gt;&lt;span&gt;- 인접 구조 간섭에 강함&lt;br /&gt;&lt;/span&gt;- 방향 정보 추출 가능&lt;br /&gt;- scale 추정이 가능&lt;br /&gt;- 분석적 계산 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한계&lt;br /&gt;&lt;span&gt;- 반지름 범위 설정이 중요&lt;br /&gt;&lt;/span&gt;- 노이즈에 완전히 자유롭지 못함&lt;br /&gt;- 분기점과 고곡률 구조는 후처리가 필요함.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스 코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;//&amp;nbsp;C++14&amp;nbsp;/&amp;nbsp;OpenCV&amp;nbsp;4.x &lt;br /&gt;#include&amp;nbsp;&amp;lt;opencv2/opencv.hpp&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;algorithm&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;vector&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;cmath&amp;gt; &lt;br /&gt;&lt;br /&gt;#include&amp;nbsp;&amp;lt;opencv2/opencv.hpp&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;iostream&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;complex&amp;gt; &lt;br /&gt;&lt;br /&gt;using&amp;nbsp;namespace&amp;nbsp;cv; &lt;br /&gt;using&amp;nbsp;namespace&amp;nbsp;std; &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;OOF&amp;nbsp;필터&amp;nbsp;함수 &lt;br /&gt;void&amp;nbsp;applyOOF(const&amp;nbsp;Mat&amp;amp;&amp;nbsp;src,&amp;nbsp;Mat&amp;amp;&amp;nbsp;response,&amp;nbsp;float&amp;nbsp;radius)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;gray; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(src.channels()&amp;nbsp;==&amp;nbsp;3)&amp;nbsp;cvtColor(src,&amp;nbsp;gray,&amp;nbsp;COLOR_BGR2GRAY); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&amp;nbsp;gray&amp;nbsp;=&amp;nbsp;src.clone(); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;1.&amp;nbsp;입력을&amp;nbsp;float&amp;nbsp;형으로&amp;nbsp;변환&amp;nbsp;및&amp;nbsp;FFT를&amp;nbsp;위한&amp;nbsp;패딩 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;floatSrc; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gray.convertTo(floatSrc,&amp;nbsp;CV_32F,&amp;nbsp;1.0&amp;nbsp;/&amp;nbsp;255.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;m&amp;nbsp;=&amp;nbsp;getOptimalDFTSize(floatSrc.rows); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;n&amp;nbsp;=&amp;nbsp;getOptimalDFTSize(floatSrc.cols); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;padded; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;copyMakeBorder(floatSrc,&amp;nbsp;padded,&amp;nbsp;0,&amp;nbsp;m&amp;nbsp;-&amp;nbsp;floatSrc.rows,&amp;nbsp;0,&amp;nbsp;n&amp;nbsp;-&amp;nbsp;floatSrc.cols,&amp;nbsp;BORDER_CONSTANT,&amp;nbsp;Scalar::all(0)); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;2.&amp;nbsp;FFT&amp;nbsp;수행 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;planes[]&amp;nbsp;=&amp;nbsp;{Mat_&amp;lt;float&amp;gt;(padded),&amp;nbsp;Mat::zeros(padded.size(),&amp;nbsp;CV_32F)}; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;complexI; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;merge(planes,&amp;nbsp;2,&amp;nbsp;complexI); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dft(complexI,&amp;nbsp;complexI); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;3.&amp;nbsp;주파수&amp;nbsp;도메인에서&amp;nbsp;OOF&amp;nbsp;필터(Bessel&amp;nbsp;기반)&amp;nbsp;생성&amp;nbsp;및&amp;nbsp;적용 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;OOF&amp;nbsp;커널:&amp;nbsp;1/r&amp;nbsp;*&amp;nbsp;(sin(r*w)&amp;nbsp;/&amp;nbsp;w&amp;nbsp;-&amp;nbsp;cos(r*w))&amp;nbsp;형태의&amp;nbsp;근사치&amp;nbsp;사용 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;m;&amp;nbsp;i++)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;j&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;j&amp;nbsp;&amp;lt;&amp;nbsp;n;&amp;nbsp;j++)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float&amp;nbsp;u&amp;nbsp;=&amp;nbsp;(i&amp;nbsp;&amp;gt;&amp;nbsp;m&amp;nbsp;/&amp;nbsp;2)&amp;nbsp;?&amp;nbsp;(float)i&amp;nbsp;-&amp;nbsp;m&amp;nbsp;:&amp;nbsp;(float)i; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float&amp;nbsp;v&amp;nbsp;=&amp;nbsp;(j&amp;nbsp;&amp;gt;&amp;nbsp;n&amp;nbsp;/&amp;nbsp;2)&amp;nbsp;?&amp;nbsp;(float)j&amp;nbsp;-&amp;nbsp;n&amp;nbsp;:&amp;nbsp;(float)j; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float&amp;nbsp;w&amp;nbsp;=&amp;nbsp;sqrt(u&amp;nbsp;*&amp;nbsp;u&amp;nbsp;+&amp;nbsp;v&amp;nbsp;*&amp;nbsp;v); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(w&amp;nbsp;&amp;gt;&amp;nbsp;0)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;주파수&amp;nbsp;영역에서의&amp;nbsp;OOF&amp;nbsp;가중치&amp;nbsp;계산 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float&amp;nbsp;filterValue&amp;nbsp;=&amp;nbsp;(sin(radius&amp;nbsp;*&amp;nbsp;w)&amp;nbsp;/&amp;nbsp;(radius&amp;nbsp;*&amp;nbsp;w)&amp;nbsp;-&amp;nbsp;cos(radius&amp;nbsp;*&amp;nbsp;w))&amp;nbsp;/&amp;nbsp;(w&amp;nbsp;*&amp;nbsp;w); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;complexI.at&amp;lt;Vec2f&amp;gt;(i,&amp;nbsp;j)[0]&amp;nbsp;*=&amp;nbsp;filterValue; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;complexI.at&amp;lt;Vec2f&amp;gt;(i,&amp;nbsp;j)[1]&amp;nbsp;*=&amp;nbsp;filterValue; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;4.&amp;nbsp;역&amp;nbsp;FFT&amp;nbsp;(Inverse&amp;nbsp;DFT) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;idft(complexI,&amp;nbsp;complexI); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;split(complexI,&amp;nbsp;planes); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;5.&amp;nbsp;결과&amp;nbsp;후처리&amp;nbsp;(고유값&amp;nbsp;분석&amp;nbsp;대용으로&amp;nbsp;크기&amp;nbsp;계산) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;magnitude(planes[0],&amp;nbsp;planes[1],&amp;nbsp;response); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;response&amp;nbsp;=&amp;nbsp;response(Rect(0,&amp;nbsp;0,&amp;nbsp;gray.cols,&amp;nbsp;gray.rows)); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;normalize(response,&amp;nbsp;response,&amp;nbsp;0,&amp;nbsp;255,&amp;nbsp;NORM_MINMAX,&amp;nbsp;CV_8U); &lt;br /&gt;}&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;opencv2/opencv.hpp&amp;gt; &lt;br /&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat&amp;nbsp;gray&amp;nbsp;=&amp;nbsp;cv::imread(&quot;input.png&quot;,&amp;nbsp;cv::IMREAD_GRAYSCALE); &lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat oofResult;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; applyOOF(gray, oofResult, 5.f); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;보기&amp;nbsp;좋게&amp;nbsp;0~255로&amp;nbsp;변환해&amp;nbsp;저장 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat vis; oofResult.convertTo(vis, CV_8U, 255.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::imwrite(&quot; oofResult.png&quot;, vis); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;/p&gt;</description>
      <category>머신 비전/머신 비전 알고리즘 테크닉 CPP</category>
      <category>FFT</category>
      <category>flux</category>
      <category>idft</category>
      <category>normalize</category>
      <category>OOF</category>
      <category>Optimally</category>
      <category>oriented</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/376</guid>
      <comments>https://folcjin.tistory.com/376#entry376comment</comments>
      <pubDate>Mon, 20 Apr 2026 08:56:57 +0900</pubDate>
    </item>
    <item>
      <title>알고리즘 - Edge 추출 방법 ( Frangi-Vesselness )</title>
      <link>https://folcjin.tistory.com/375</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이미지(또는 볼륨)에서 선형/관 구조(line-/tube-like structure)를 강조하는 필터로, 핵심은 각 픽셀에서 Hessian 행렬(2차 미분)의 고유값을 보고 한 축으로는 휘도 변화가 강하고(굵직함) 직교 축으로는 변화가 약한(가늘게 길게) 패턴을 높은 점수를 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목적: 이미지에서 길쭉한 선형 패턴 검출&lt;br /&gt;적용 분야: 혈관 영상 분석, 스크래치/크랙 검출, 섬유 패턴 분석 등&lt;br /&gt;핵심 아이디어:&lt;br /&gt;- 픽셀 주변의 Hessian 행렬(2차 미분) 분석&lt;br /&gt;- 고유값 패턴으로 선형성 판단&lt;br /&gt;- 다양한 **스케일(&amp;sigma;)**에서 선 구조 탐색&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;- 선형 구조에 특화, 노이즈 강인&lt;br /&gt;&lt;/span&gt;- 다양한 굵기 대응 가능 (멀티스케일)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한계&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;- 교차/분기부 반응 약함&lt;br /&gt;&lt;/span&gt;- 극성 혼합 시 두 번 계산 필요&lt;br /&gt;- &amp;sigma; 범위와 파라미터에 따라 성능 차이 큼&lt;br /&gt;&lt;br /&gt;예시&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;- 혈관 네트워크 추출&lt;br /&gt;&lt;/span&gt;- 금속 표면 스크래치 검출&lt;br /&gt;- 섬유/패턴 분석&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스 코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;//&amp;nbsp;C++14&amp;nbsp;/&amp;nbsp;OpenCV&amp;nbsp;4.x &lt;br /&gt;#include&amp;nbsp;&amp;lt;opencv2/opencv.hpp&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;algorithm&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;vector&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;cmath&amp;gt; &lt;br /&gt;&lt;br /&gt;cv::Mat&amp;nbsp;FrangiVesselnessMultiScaleOCV(const&amp;nbsp;cv::Mat&amp;amp;&amp;nbsp;src8or32f, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;amp;&amp;nbsp;sigmas, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool&amp;nbsp;bright_on_dark&amp;nbsp;=&amp;nbsp;false,&amp;nbsp;//&amp;nbsp;밝은&amp;nbsp;선&amp;nbsp;찾기(true)&amp;nbsp;/&amp;nbsp;어두운&amp;nbsp;선(false,&amp;nbsp;기본) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;beta&amp;nbsp;=&amp;nbsp;0.5, &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;c&amp;nbsp;=&amp;nbsp;15.0) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CV_Assert(!sigmas.empty()); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CV_Assert(src8or32f.channels()&amp;nbsp;==&amp;nbsp;1); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat&amp;nbsp;f; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(src8or32f.type()&amp;nbsp;==&amp;nbsp;CV_32F)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;f&amp;nbsp;=&amp;nbsp;src8or32f.clone(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;src8or32f.convertTo(f,&amp;nbsp;CV_32F,&amp;nbsp;1.0&amp;nbsp;/&amp;nbsp;255.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat&amp;nbsp;V&amp;nbsp;=&amp;nbsp;cv::Mat::zeros(f.size(),&amp;nbsp;CV_32F); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;double&amp;nbsp;beta2&amp;nbsp;=&amp;nbsp;2.0&amp;nbsp;*&amp;nbsp;beta&amp;nbsp;*&amp;nbsp;beta; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;double&amp;nbsp;c2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;=&amp;nbsp;2.0&amp;nbsp;*&amp;nbsp;c&amp;nbsp;*&amp;nbsp;c; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(double&amp;nbsp;sigma&amp;nbsp;:&amp;nbsp;sigmas)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(sigma&amp;nbsp;&amp;lt;=&amp;nbsp;0)&amp;nbsp;continue; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;1)&amp;nbsp;가우시안으로&amp;nbsp;스무딩(스케일-스페이스) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat&amp;nbsp;g; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::GaussianBlur(f,&amp;nbsp;g,&amp;nbsp;cv::Size(),&amp;nbsp;sigma,&amp;nbsp;sigma,&amp;nbsp;cv::BORDER_REFLECT101); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;2)&amp;nbsp;Hessian&amp;nbsp;근사:&amp;nbsp;2차/혼합&amp;nbsp;미분&amp;nbsp;(스무딩된&amp;nbsp;영상에&amp;nbsp;Sobel&amp;nbsp;적용) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat&amp;nbsp;Ixx,&amp;nbsp;Iyy,&amp;nbsp;Ixy; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;d2/dx2,&amp;nbsp;d2/dy2,&amp;nbsp;d2/dxdy &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Sobel(g,&amp;nbsp;Ixx,&amp;nbsp;CV_32F,&amp;nbsp;2,&amp;nbsp;0,&amp;nbsp;3,&amp;nbsp;1,&amp;nbsp;0,&amp;nbsp;cv::BORDER_REFLECT101); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Sobel(g,&amp;nbsp;Iyy,&amp;nbsp;CV_32F,&amp;nbsp;0,&amp;nbsp;2,&amp;nbsp;3,&amp;nbsp;1,&amp;nbsp;0,&amp;nbsp;cv::BORDER_REFLECT101); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Sobel(g,&amp;nbsp;Ixy,&amp;nbsp;CV_32F,&amp;nbsp;1,&amp;nbsp;1,&amp;nbsp;3,&amp;nbsp;1,&amp;nbsp;0,&amp;nbsp;cv::BORDER_REFLECT101); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;3)&amp;nbsp;스케일&amp;nbsp;정규화&amp;nbsp;(sigma^2) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float&amp;nbsp;s2&amp;nbsp;=&amp;nbsp;static_cast&amp;lt;float&amp;gt;(sigma&amp;nbsp;*&amp;nbsp;sigma); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Ixx&amp;nbsp;*=&amp;nbsp;s2;&amp;nbsp;Iyy&amp;nbsp;*=&amp;nbsp;s2;&amp;nbsp;Ixy&amp;nbsp;*=&amp;nbsp;s2; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;4)&amp;nbsp;Frangi&amp;nbsp;vesselness&amp;nbsp;(단일&amp;nbsp;스케일)&amp;nbsp;+&amp;nbsp;5)&amp;nbsp;멀티스케일&amp;nbsp;max-projection &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;int&amp;nbsp;rows&amp;nbsp;=&amp;nbsp;f.rows,&amp;nbsp;cols&amp;nbsp;=&amp;nbsp;f.cols; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;y&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;y&amp;nbsp;&amp;lt;&amp;nbsp;rows;&amp;nbsp;++y)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;float*&amp;nbsp;ax&amp;nbsp;=&amp;nbsp;Ixx.ptr&amp;lt;float&amp;gt;(y); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;float*&amp;nbsp;bx&amp;nbsp;=&amp;nbsp;Ixy.ptr&amp;lt;float&amp;gt;(y); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;float*&amp;nbsp;dx&amp;nbsp;=&amp;nbsp;Iyy.ptr&amp;lt;float&amp;gt;(y); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;float*&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vx&amp;nbsp;=&amp;nbsp;V&amp;nbsp;&amp;nbsp;.ptr&amp;lt;float&amp;gt;(y); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;x&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;x&amp;nbsp;&amp;lt;&amp;nbsp;cols;&amp;nbsp;++x)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;a&amp;nbsp;=&amp;nbsp;ax[x],&amp;nbsp;b&amp;nbsp;=&amp;nbsp;bx[x],&amp;nbsp;d&amp;nbsp;=&amp;nbsp;dx[x]; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;eigenvalues&amp;nbsp;of&amp;nbsp;[[a,b],[b,d]]&amp;nbsp;with&amp;nbsp;|&amp;lambda;1|&amp;nbsp;&amp;le;&amp;nbsp;|&amp;lambda;2| &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;tr&amp;nbsp;=&amp;nbsp;a&amp;nbsp;+&amp;nbsp;d; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;det&amp;nbsp;=&amp;nbsp;a&amp;nbsp;*&amp;nbsp;d&amp;nbsp;-&amp;nbsp;b&amp;nbsp;*&amp;nbsp;b; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;disc2&amp;nbsp;=&amp;nbsp;0.25&amp;nbsp;*&amp;nbsp;tr&amp;nbsp;*&amp;nbsp;tr&amp;nbsp;-&amp;nbsp;det; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;disc&amp;nbsp;=&amp;nbsp;std::sqrt(disc2&amp;nbsp;&amp;gt;&amp;nbsp;0.0&amp;nbsp;?&amp;nbsp;disc2&amp;nbsp;:&amp;nbsp;0.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;l1&amp;nbsp;=&amp;nbsp;0.5&amp;nbsp;*&amp;nbsp;tr&amp;nbsp;-&amp;nbsp;disc; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;l2&amp;nbsp;=&amp;nbsp;0.5&amp;nbsp;*&amp;nbsp;tr&amp;nbsp;+&amp;nbsp;disc; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;polarity&amp;nbsp;(밝은&amp;nbsp;선/어두운&amp;nbsp;선) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(bright_on_dark)&amp;nbsp;{&amp;nbsp;if&amp;nbsp;(l2&amp;nbsp;&amp;lt;&amp;nbsp;0.0)&amp;nbsp;continue;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&amp;nbsp;if&amp;nbsp;(l2&amp;nbsp;&amp;gt;&amp;nbsp;0.0)&amp;nbsp;continue;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;Rb&amp;nbsp;=&amp;nbsp;(l2&amp;nbsp;==&amp;nbsp;0.0)&amp;nbsp;?&amp;nbsp;0.0&amp;nbsp;:&amp;nbsp;std::abs(l1)&amp;nbsp;/&amp;nbsp;std::abs(l2);&amp;nbsp;//&amp;nbsp;blob&amp;nbsp;대비&amp;nbsp;선형성 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;S2&amp;nbsp;=&amp;nbsp;l1*l1&amp;nbsp;+&amp;nbsp;l2*l2;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;‖H‖_F^2 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;v&amp;nbsp;&amp;nbsp;=&amp;nbsp;std::exp(-(Rb*Rb)/beta2)&amp;nbsp;*&amp;nbsp;(1.0&amp;nbsp;-&amp;nbsp;std::exp(-S2/c2)); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(v&amp;nbsp;&amp;gt;&amp;nbsp;vx[x])&amp;nbsp;vx[x]&amp;nbsp;=&amp;nbsp;static_cast&amp;lt;float&amp;gt;(v);&amp;nbsp;//&amp;nbsp;max&amp;nbsp;over&amp;nbsp;scales &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;6)&amp;nbsp;(선택)&amp;nbsp;0~1&amp;nbsp;클램프 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::threshold(V,&amp;nbsp;V,&amp;nbsp;1.0,&amp;nbsp;1.0,&amp;nbsp;cv::THRESH_TRUNC); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::threshold(V,&amp;nbsp;V,&amp;nbsp;0.0,&amp;nbsp;0.0,&amp;nbsp;cv::THRESH_TOZERO); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;V; &lt;br /&gt;} &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;opencv2/opencv.hpp&amp;gt; &lt;br /&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat&amp;nbsp;gray&amp;nbsp;=&amp;nbsp;cv::imread(&quot;input.png&quot;,&amp;nbsp;cv::IMREAD_GRAYSCALE); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;sigmas&amp;nbsp;=&amp;nbsp;{1.0,&amp;nbsp;2.0,&amp;nbsp;3.0,&amp;nbsp;4.0}; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;어두운&amp;nbsp;선(스크래치)&amp;nbsp;강조:&amp;nbsp;bright_on_dark=false &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat&amp;nbsp;vessel&amp;nbsp;=&amp;nbsp;FrangiVesselnessMultiScaleOCV(gray,&amp;nbsp;sigmas,&amp;nbsp;/*bright_on_dark=*/false,&amp;nbsp;0.5,&amp;nbsp;15.0); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;보기&amp;nbsp;좋게&amp;nbsp;0~255로&amp;nbsp;변환해&amp;nbsp;저장 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::Mat&amp;nbsp;vis;&amp;nbsp;vessel.convertTo(vis,&amp;nbsp;CV_8U,&amp;nbsp;255.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cv::imwrite(&quot;vessel.png&quot;,&amp;nbsp;vis); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;/p&gt;</description>
      <category>congruency</category>
      <category>DFT</category>
      <category>FFT</category>
      <category>gabor filter</category>
      <category>light</category>
      <category>mean</category>
      <category>normalize</category>
      <category>PC</category>
      <category>phase</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/375</guid>
      <comments>https://folcjin.tistory.com/375#entry375comment</comments>
      <pubDate>Wed, 13 Aug 2025 13:11:18 +0900</pubDate>
    </item>
    <item>
      <title>알고리즘 - Edge 추출 방법 ( Phase Congruency )</title>
      <link>https://folcjin.tistory.com/374</link>
      <description>&lt;p data-end=&quot;226&quot; data-start=&quot;34&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;영상에서 에지(edge)나 코너(corner) 같은 **특징(feature)**을 밝기(intensity) 값에 의존하지 않고 검출하는 방법입니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이는 인간 시각 시스템(HVS, Human Visual System)이 위상(phase) 정보를 통해 형태와 구조를 인식&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;226&quot; data-start=&quot;34&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;픽셀의 절대 밝기 변화가 아니라 위상이 일치하는 정도를 측정합니다. &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;즉, 조명 변화나 콘트라스트 변화에 강건하며, 동일한 구조를 다양한 밝기 조건에서도 안정적으로 검출&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;226&quot; data-start=&quot;34&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;226&quot; data-start=&quot;34&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2. 기본 원리&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이미지를 주파수 영역(특히 다중 스케일 및 다중 방향)으로 변환했을 때, &lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;각 주파수 성분은 **진폭(amplitude)**과 위상(phase) 정보&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;646&quot; data-start=&quot;537&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;589&quot; data-start=&quot;537&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;에지나 코너 부근에서는 여러 주파수 성분의 위상이 같은 위치에서 최대값&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;919&quot; data-start=&quot;910&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;919&quot; data-start=&quot;910&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;3. 장점&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1. 조명 변화 불변성 &amp;mdash; 밝기나 명암 대비가 달라도 특징 위치가 동일하게 검출됨.&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2. 스케일/방향 분석 가능 &amp;mdash; 멀티스케일, 멀티방향 필터 사용으로 정밀한 특징 분석 가능.&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;3. 정규화 필요 없음 &amp;mdash; 이미지 명암값의 전처리(normalization)가 불필요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;919&quot; data-start=&quot;910&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1098&quot; data-start=&quot;1086&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;4. 구현 방식&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1181&quot; data-start=&quot;1099&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;가장 널리 쓰이는 구현은 Log-Gabor 필터를 다중 스케일&amp;middot;다중 방향으로 적용한 뒤,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;각 위치에서 위상 일치도를 계산하는 방법입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1189&quot; data-start=&quot;1183&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;구현 절차:&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1329&quot; data-start=&quot;1190&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1221&quot; data-start=&quot;1190&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이미지 &amp;rarr; Log-Gabor 필터 뱅크 변환&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1244&quot; data-start=&quot;1222&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;각 스케일&amp;middot;방향별 진폭과 위상 계산&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1268&quot; data-start=&quot;1245&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;모든 스케일&amp;middot;방향에서 위상 평균 계산&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1299&quot; data-start=&quot;1269&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;위상 일치도(phase congruency) 산출&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1329&quot; data-start=&quot;1300&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;결과를 특징 맵(feature map)으로 변환&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스 코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;opencv2/opencv.hpp&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;iostream&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;vector&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;cmath&amp;gt; &lt;br /&gt;&lt;br /&gt;using&amp;nbsp;namespace&amp;nbsp;cv; &lt;br /&gt;using&amp;nbsp;namespace&amp;nbsp;std; &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;간단한&amp;nbsp;Log-Gabor&amp;nbsp;필터&amp;nbsp;생성&amp;nbsp;(주파수&amp;nbsp;영역) &lt;br /&gt;Mat&amp;nbsp;createLogGaborKernel(Size&amp;nbsp;size,&amp;nbsp;double&amp;nbsp;wavelength,&amp;nbsp;double&amp;nbsp;sigmaOnf,&amp;nbsp;double&amp;nbsp;theta)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;kernel(size,&amp;nbsp;CV_32FC2,&amp;nbsp;Scalar(0,&amp;nbsp;0)); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Point&amp;nbsp;center(size.width&amp;nbsp;/&amp;nbsp;2,&amp;nbsp;size.height&amp;nbsp;/&amp;nbsp;2); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;thetaRad&amp;nbsp;=&amp;nbsp;theta&amp;nbsp;*&amp;nbsp;CV_PI&amp;nbsp;/&amp;nbsp;180.0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;cosTheta&amp;nbsp;=&amp;nbsp;cos(thetaRad); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;sinTheta&amp;nbsp;=&amp;nbsp;sin(thetaRad); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;y&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;y&amp;nbsp;&amp;lt;&amp;nbsp;size.height;&amp;nbsp;y++)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;x&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;x&amp;nbsp;&amp;lt;&amp;nbsp;size.width;&amp;nbsp;x++)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;u&amp;nbsp;=&amp;nbsp;(x&amp;nbsp;-&amp;nbsp;center.x)&amp;nbsp;/&amp;nbsp;(double)size.width; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;v&amp;nbsp;=&amp;nbsp;(y&amp;nbsp;-&amp;nbsp;center.y)&amp;nbsp;/&amp;nbsp;(double)size.height; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;회전&amp;nbsp;좌표계로&amp;nbsp;변환 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;uRot&amp;nbsp;=&amp;nbsp;u&amp;nbsp;*&amp;nbsp;cosTheta&amp;nbsp;+&amp;nbsp;v&amp;nbsp;*&amp;nbsp;sinTheta; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;vRot&amp;nbsp;=&amp;nbsp;-u&amp;nbsp;*&amp;nbsp;sinTheta&amp;nbsp;+&amp;nbsp;v&amp;nbsp;*&amp;nbsp;cosTheta; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;radius&amp;nbsp;=&amp;nbsp;sqrt(uRot&amp;nbsp;*&amp;nbsp;uRot&amp;nbsp;+&amp;nbsp;vRot&amp;nbsp;*&amp;nbsp;vRot); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(radius&amp;nbsp;==&amp;nbsp;0)&amp;nbsp;continue; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Log-Gabor&amp;nbsp;필터&amp;nbsp;방정식 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;logGabor&amp;nbsp;=&amp;nbsp;exp((-(log(radius&amp;nbsp;/&amp;nbsp;(1.0&amp;nbsp;/&amp;nbsp;wavelength))&amp;nbsp;*&amp;nbsp;log(radius&amp;nbsp;/&amp;nbsp;(1.0&amp;nbsp;/&amp;nbsp;wavelength))))&amp;nbsp;/ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(2&amp;nbsp;*&amp;nbsp;log(sigmaOnf)&amp;nbsp;*&amp;nbsp;log(sigmaOnf))); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;kernel.at&amp;lt;Vec2f&amp;gt;(y,&amp;nbsp;x)[0]&amp;nbsp;=&amp;nbsp;logGabor;&amp;nbsp;//&amp;nbsp;실수부 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;kernel.at&amp;lt;Vec2f&amp;gt;(y,&amp;nbsp;x)[1]&amp;nbsp;=&amp;nbsp;0.0f;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;허수부 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;kernel; &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;입력&amp;nbsp;이미지 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;imgGray&amp;nbsp;=&amp;nbsp;imread(&quot;test.png&quot;,&amp;nbsp;IMREAD_GRAYSCALE); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(imgGray.empty())&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cerr&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;이미지를&amp;nbsp;불러올&amp;nbsp;수&amp;nbsp;없습니다.&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;endl; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;-1; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;imgGray.convertTo(imgGray,&amp;nbsp;CV_32F,&amp;nbsp;1.0&amp;nbsp;/&amp;nbsp;255.0); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;FFT&amp;nbsp;준비 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;padded; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;m&amp;nbsp;=&amp;nbsp;getOptimalDFTSize(imgGray.rows); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;n&amp;nbsp;=&amp;nbsp;getOptimalDFTSize(imgGray.cols); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;copyMakeBorder(imgGray,&amp;nbsp;padded,&amp;nbsp;0,&amp;nbsp;m&amp;nbsp;-&amp;nbsp;imgGray.rows,&amp;nbsp;0,&amp;nbsp;n&amp;nbsp;-&amp;nbsp;imgGray.cols,&amp;nbsp;BORDER_CONSTANT,&amp;nbsp;Scalar::all(0)); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;planes[]&amp;nbsp;=&amp;nbsp;{padded.clone(),&amp;nbsp;Mat::zeros(padded.size(),&amp;nbsp;CV_32F)}; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;complexImg; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;merge(planes,&amp;nbsp;2,&amp;nbsp;complexImg); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;dft(complexImg,&amp;nbsp;complexImg); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;다중&amp;nbsp;스케일&amp;nbsp;&amp;amp;&amp;nbsp;방향&amp;nbsp;설정 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vector&amp;lt;double&amp;gt;&amp;nbsp;wavelengths&amp;nbsp;=&amp;nbsp;{3.0,&amp;nbsp;5.0,&amp;nbsp;8.0};&amp;nbsp;//&amp;nbsp;스케일 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vector&amp;lt;double&amp;gt;&amp;nbsp;orientations&amp;nbsp;=&amp;nbsp;{0,&amp;nbsp;45,&amp;nbsp;90,&amp;nbsp;135};&amp;nbsp;//&amp;nbsp;방향 &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;sumAmp&amp;nbsp;=&amp;nbsp;Mat::zeros(padded.size(),&amp;nbsp;CV_32F); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;sumPC&amp;nbsp;&amp;nbsp;=&amp;nbsp;Mat::zeros(padded.size(),&amp;nbsp;CV_32F); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(double&amp;nbsp;wl&amp;nbsp;:&amp;nbsp;wavelengths)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(double&amp;nbsp;angle&amp;nbsp;:&amp;nbsp;orientations)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Log-Gabor&amp;nbsp;필터&amp;nbsp;생성 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;logGabor&amp;nbsp;=&amp;nbsp;createLogGaborKernel(padded.size(),&amp;nbsp;wl,&amp;nbsp;0.55,&amp;nbsp;angle); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;주파수&amp;nbsp;영역에서&amp;nbsp;곱셈 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;filtered; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;mulSpectrums(complexImg,&amp;nbsp;logGabor,&amp;nbsp;filtered,&amp;nbsp;0); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;역&amp;nbsp;FFT &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;invDFT; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;idft(filtered,&amp;nbsp;invDFT,&amp;nbsp;DFT_SCALE&amp;nbsp;|&amp;nbsp;DFT_REAL_OUTPUT); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;진폭과&amp;nbsp;위상&amp;nbsp;계산 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;magImg,&amp;nbsp;phaseImg; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;magnitude(invDFT,&amp;nbsp;Mat::zeros(invDFT.size(),&amp;nbsp;CV_32F),&amp;nbsp;magImg); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;phase(invDFT,&amp;nbsp;Mat::zeros(invDFT.size(),&amp;nbsp;CV_32F),&amp;nbsp;phaseImg); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;위상&amp;nbsp;평균(단순&amp;nbsp;예시) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sumAmp&amp;nbsp;+=&amp;nbsp;magImg; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sumPC&amp;nbsp;+=&amp;nbsp;magImg.mul(cos(phaseImg&amp;nbsp;-&amp;nbsp;mean(phaseImg)[0])); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Phase&amp;nbsp;Congruency&amp;nbsp;계산 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Mat&amp;nbsp;PC&amp;nbsp;=&amp;nbsp;sumPC&amp;nbsp;/&amp;nbsp;(sumAmp&amp;nbsp;+&amp;nbsp;1e-9); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;시각화 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;normalize(PC,&amp;nbsp;PC,&amp;nbsp;0,&amp;nbsp;1,&amp;nbsp;NORM_MINMAX); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;imshow(&quot;Phase&amp;nbsp;Congruency&quot;,&amp;nbsp;PC); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;waitKey(0); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;/p&gt;</description>
      <category>congruency</category>
      <category>DFT</category>
      <category>FFT</category>
      <category>gabor filter</category>
      <category>light</category>
      <category>mean</category>
      <category>normalize</category>
      <category>PC</category>
      <category>phase</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/374</guid>
      <comments>https://folcjin.tistory.com/374#entry374comment</comments>
      <pubDate>Fri, 8 Aug 2025 23:59:06 +0900</pubDate>
    </item>
    <item>
      <title>치수 계산하기 - smooth filtering 8</title>
      <link>https://folcjin.tistory.com/373</link>
      <description>&lt;p data-end=&quot;150&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;Wavelet Denoising은 신호의 주파수와 시간 정보를 동시에 고려하여 노이즈를 제거하는 고급 기법&lt;/p&gt;
&lt;p data-end=&quot;150&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;- 특히 경계(에지)를 보존하면서 노이즈를 억제하는 데 효과적이며, 의료 신호, 이미지, 음향 신호, 과학 데이터 등에 널리 사용됩니다.&lt;/p&gt;
&lt;p data-end=&quot;231&quot; data-start=&quot;197&quot; data-ke-size=&quot;size16&quot;&gt;Wavelet Denoising은 다음 세 단계로 수행됩니다:&lt;br /&gt;1 단계 : Wavelet Transform: 입력 신호를 다중 해상도(다양한 주파수)로 분해.&lt;br /&gt;2 단계 : Thresholding: 노이즈가 주로 포함된 세부 계수(detail coefficients)에 임계값을 적용해 제거.&lt;br /&gt;3 단계 : Inverse Transform: 노이즈가 제거된 계수를 기반으로 신호를 복원.&lt;/p&gt;
&lt;p data-end=&quot;759&quot; data-start=&quot;734&quot; data-ke-size=&quot;size16&quot;&gt;1D Soft Thresholding:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;308&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F4KzI/btsOVraQenE/2PUEDp8kJId4zWKgkSlEHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F4KzI/btsOVraQenE/2PUEDp8kJId4zWKgkSlEHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F4KzI/btsOVraQenE/2PUEDp8kJId4zWKgkSlEHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF4KzI%2FbtsOVraQenE%2F2PUEDp8kJId4zWKgkSlEHK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;308&quot; height=&quot;63&quot; data-origin-width=&quot;308&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;iostream&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;vector&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;cmath&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;algorithm&amp;gt; &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;Soft&amp;nbsp;thresholding &lt;br /&gt;double&amp;nbsp;softThreshold(double&amp;nbsp;val,&amp;nbsp;double&amp;nbsp;lambda)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(std::abs(val)&amp;nbsp;&amp;lt;=&amp;nbsp;lambda)&amp;nbsp;return&amp;nbsp;0.0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;(val&amp;nbsp;&amp;gt;&amp;nbsp;0)&amp;nbsp;?&amp;nbsp;(val&amp;nbsp;-&amp;nbsp;lambda)&amp;nbsp;:&amp;nbsp;(val&amp;nbsp;+&amp;nbsp;lambda); &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;1-Level&amp;nbsp;Haar&amp;nbsp;Wavelet&amp;nbsp;Decomposition&amp;nbsp;+&amp;nbsp;Denoising&amp;nbsp;+&amp;nbsp;Reconstruction &lt;br /&gt;std::vector&amp;lt;double&amp;gt;&amp;nbsp;waveletDenoise(const&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;amp;&amp;nbsp;signal,&amp;nbsp;double&amp;nbsp;lambda)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;N&amp;nbsp;=&amp;nbsp;signal.size(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;half&amp;nbsp;=&amp;nbsp;N&amp;nbsp;/&amp;nbsp;2; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;approx(half),&amp;nbsp;detail(half); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Haar&amp;nbsp;Transform&amp;nbsp;(decomposition) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;half;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;approx[i]&amp;nbsp;=&amp;nbsp;(signal[2&amp;nbsp;*&amp;nbsp;i]&amp;nbsp;+&amp;nbsp;signal[2&amp;nbsp;*&amp;nbsp;i&amp;nbsp;+&amp;nbsp;1])&amp;nbsp;/&amp;nbsp;std::sqrt(2.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail[i]&amp;nbsp;=&amp;nbsp;(signal[2&amp;nbsp;*&amp;nbsp;i]&amp;nbsp;-&amp;nbsp;signal[2&amp;nbsp;*&amp;nbsp;i&amp;nbsp;+&amp;nbsp;1])&amp;nbsp;/&amp;nbsp;std::sqrt(2.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Thresholding&amp;nbsp;(soft) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;half;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;detail[i]&amp;nbsp;=&amp;nbsp;softThreshold(detail[i],&amp;nbsp;lambda); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Inverse&amp;nbsp;Haar&amp;nbsp;Transform&amp;nbsp;(reconstruction) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;denoised(N); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;half;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;denoised[2&amp;nbsp;*&amp;nbsp;i]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;=&amp;nbsp;(approx[i]&amp;nbsp;+&amp;nbsp;detail[i])&amp;nbsp;/&amp;nbsp;std::sqrt(2.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;denoised[2&amp;nbsp;*&amp;nbsp;i&amp;nbsp;+&amp;nbsp;1]&amp;nbsp;=&amp;nbsp;(approx[i]&amp;nbsp;-&amp;nbsp;detail[i])&amp;nbsp;/&amp;nbsp;std::sqrt(2.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;denoised; &lt;br /&gt;} &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;signal&amp;nbsp;=&amp;nbsp;{1.2,&amp;nbsp;0.9,&amp;nbsp;1.1,&amp;nbsp;1.0,&amp;nbsp;10.0,&amp;nbsp;10.2,&amp;nbsp;9.9,&amp;nbsp;10.1};&amp;nbsp;//&amp;nbsp;신호&amp;nbsp;+&amp;nbsp;잡음 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;lambda&amp;nbsp;=&amp;nbsp;0.5; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;denoised&amp;nbsp;=&amp;nbsp;waveletDenoise(signal,&amp;nbsp;lambda); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;Original&amp;nbsp;vs&amp;nbsp;Denoised:\n&quot;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(size_t&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;signal.size();&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;x[&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;]&amp;nbsp;=&amp;nbsp;&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;signal[i] &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;\t=&amp;gt;\t&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;denoised[i]&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;std::endl; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;/p&gt;</description>
      <category>decomposition</category>
      <category>denoise</category>
      <category>edge</category>
      <category>Filtering</category>
      <category>Haar</category>
      <category>subpixel</category>
      <category>Threshold</category>
      <category>Wavelet</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/373</guid>
      <comments>https://folcjin.tistory.com/373#entry373comment</comments>
      <pubDate>Sat, 28 Jun 2025 10:39:32 +0900</pubDate>
    </item>
    <item>
      <title>치수 계산하기 - smooth filtering 7</title>
      <link>https://folcjin.tistory.com/372</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Elliptic 필터(= Cauer filter)는 가장 급격한 주파수 전이 특성을 가지는 IIR 필터입니다. 동일한 필터 스펙(통과대역, 저지대역, ripple, 차단 감쇠)을 만족시키는 필터 중 **가장 낮은 차수(order)**로 구현 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 실시간 DSP, 고정밀 신호 처리, 자원 제약 환경 등에 매우 유리합니다.&lt;/p&gt;
&lt;p data-end=&quot;223&quot; data-start=&quot;197&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;223&quot; data-start=&quot;197&quot; data-ke-size=&quot;size16&quot;&gt;Elliptic Filter란?&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;371&quot; data-start=&quot;234&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;266&quot; data-start=&quot;234&quot;&gt;통과대역과 저지대역 모두에 ripple이 존재.&lt;/li&gt;
&lt;li data-end=&quot;322&quot; data-start=&quot;267&quot;&gt;**Elliptic 함수 (Jacobian elliptic function)**을 이용해 설계.&lt;/li&gt;
&lt;li data-end=&quot;371&quot; data-start=&quot;323&quot;&gt;Butterworth, Chebyshev보다 더 적은 차수로 동일 성능 구현 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;386&quot; data-start=&quot;373&quot; data-ke-size=&quot;size16&quot;&gt;설계 파라미터&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;요소설명
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;631&quot; data-start=&quot;387&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;631&quot; data-start=&quot;415&quot;&gt;
&lt;tr data-end=&quot;454&quot; data-start=&quot;415&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;428&quot; data-start=&quot;415&quot;&gt;Order (차수)&lt;/td&gt;
&lt;td data-end=&quot;454&quot; data-start=&quot;428&quot; data-col-size=&quot;sm&quot;&gt;필터의 sharpness 및 정확도 결정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;511&quot; data-start=&quot;455&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;485&quot; data-start=&quot;455&quot;&gt;Passband ripple (&lt;span&gt;&lt;span&gt;rpr_p&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;td data-end=&quot;511&quot; data-start=&quot;485&quot; data-col-size=&quot;sm&quot;&gt;통과대역에서 허용되는 최대 리플 (dB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;574&quot; data-start=&quot;512&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;547&quot; data-start=&quot;512&quot;&gt;Stopband attenuation (&lt;span&gt;&lt;span&gt;rsr_s&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;r&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;s&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;)&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;574&quot; data-start=&quot;547&quot;&gt;저지대역에서 요구되는 최소 감쇠량 (dB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;600&quot; data-start=&quot;575&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;589&quot; data-start=&quot;575&quot;&gt;Cutoff freq&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;600&quot; data-start=&quot;589&quot;&gt;컷오프 주파수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;631&quot; data-start=&quot;601&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;617&quot; data-start=&quot;601&quot;&gt;Sampling rate&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;631&quot; data-start=&quot;617&quot;&gt;디지털 필터이므로 필수&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;656&quot; data-start=&quot;638&quot; data-ke-size=&quot;size16&quot;&gt;주파수 응답 형태&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;186&quot; data-origin-height=&quot;57&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIfTm6/btsOUCjhprg/FQd7dAMkHwVj1GpoMPvJx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIfTm6/btsOUCjhprg/FQd7dAMkHwVj1GpoMPvJx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIfTm6/btsOUCjhprg/FQd7dAMkHwVj1GpoMPvJx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIfTm6%2FbtsOUCjhprg%2FFQd7dAMkHwVj1GpoMPvJx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;186&quot; height=&quot;57&quot; data-origin-width=&quot;186&quot; data-origin-height=&quot;57&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;827&quot; data-start=&quot;721&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;777&quot; data-start=&quot;721&quot;&gt;&lt;span&gt;&lt;span&gt;Rn &lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: nth-order elliptic rational function (특수함수)&lt;/li&gt;
&lt;li data-end=&quot;807&quot; data-start=&quot;778&quot;&gt;통과대역/저지대역 모두에서 잔류 리플 존재&lt;/li&gt;
&lt;li data-end=&quot;827&quot; data-start=&quot;808&quot;&gt;가장 빠른 roll-off 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;vector&amp;gt; &lt;br /&gt;&lt;br /&gt;class&amp;nbsp;EllipticIIR&amp;nbsp;{ &lt;br /&gt;public: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EllipticIIR(const&amp;nbsp;double*&amp;nbsp;b,&amp;nbsp;const&amp;nbsp;double*&amp;nbsp;a,&amp;nbsp;int&amp;nbsp;order) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;b(b),&amp;nbsp;a(a),&amp;nbsp;order(order)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w.assign(order,&amp;nbsp;0.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;process(double&amp;nbsp;x)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;y&amp;nbsp;=&amp;nbsp;b[0]&amp;nbsp;*&amp;nbsp;x&amp;nbsp;+&amp;nbsp;w[0]; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;1;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;order;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w[i&amp;nbsp;-&amp;nbsp;1]&amp;nbsp;=&amp;nbsp;b[i]&amp;nbsp;*&amp;nbsp;x&amp;nbsp;+&amp;nbsp;w[i]&amp;nbsp;-&amp;nbsp;a[i]&amp;nbsp;*&amp;nbsp;y; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w[order&amp;nbsp;-&amp;nbsp;1]&amp;nbsp;=&amp;nbsp;-a[order]&amp;nbsp;*&amp;nbsp;y; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;y; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;private: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;double*&amp;nbsp;b; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;double*&amp;nbsp;a; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;order; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;w; &lt;br /&gt;}; &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;iostream&amp;gt; &lt;br /&gt;&lt;br /&gt;const double b_ellip[5] = { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0.01967436,&amp;nbsp;-0.01713698,&amp;nbsp;0.0332899,&amp;nbsp;-0.01713698,&amp;nbsp;0.01967436 &lt;br /&gt;}; &lt;br /&gt;const&amp;nbsp;double&amp;nbsp;a_ellip[5]&amp;nbsp;=&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.0,&amp;nbsp;-3.03300954,&amp;nbsp;3.81179517,&amp;nbsp;-2.29109673,&amp;nbsp;0.55535694 &lt;br /&gt;}; &lt;br /&gt;&lt;br /&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EllipticIIR&amp;nbsp;filter(b_ellip,&amp;nbsp;a_ellip,&amp;nbsp;5);&amp;nbsp;//&amp;nbsp;4차&amp;nbsp;&amp;rarr;&amp;nbsp;계수&amp;nbsp;5개 &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;50;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;input&amp;nbsp;=&amp;nbsp;(i&amp;nbsp;%&amp;nbsp;2&amp;nbsp;==&amp;nbsp;0)&amp;nbsp;?&amp;nbsp;1.0&amp;nbsp;:&amp;nbsp;-1.0;&amp;nbsp;&amp;nbsp;//&amp;nbsp;고주파&amp;nbsp;성분&amp;nbsp;포함&amp;nbsp;신호 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;output&amp;nbsp;=&amp;nbsp;filter.process(input); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;input:&amp;nbsp;&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;input&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;\toutput:&amp;nbsp;&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;output&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;std::endl; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;/p&gt;</description>
      <category>cauer</category>
      <category>DSP</category>
      <category>edge</category>
      <category>elliptic</category>
      <category>Filtering</category>
      <category>IIR</category>
      <category>Jacobian</category>
      <category>Order</category>
      <category>subpixel</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/372</guid>
      <comments>https://folcjin.tistory.com/372#entry372comment</comments>
      <pubDate>Sat, 28 Jun 2025 10:34:47 +0900</pubDate>
    </item>
    <item>
      <title>치수 계산하기 - smooth filtering 6</title>
      <link>https://folcjin.tistory.com/371</link>
      <description>&lt;p data-end=&quot;200&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;Chebyshev 필터는 클래식 IIR 필터 설계법 중 하나로, 주어진 사양(통과대역 ripple, 차단대역 감쇠, 전이대역 너비)을 만족시키면서 빠른 롤오프(roll-off)를 제공하는 고성능 필터&lt;/p&gt;
&lt;p data-end=&quot;200&quot; data-start=&quot;0&quot; data-ke-size=&quot;size16&quot;&gt;- 특히 Butterworth 필터보다 짧은 전이대역을 갖지만, **통과대역 또는 저지대역에 ripple(잔류진동)**을 허용합니다.&lt;/p&gt;
&lt;p data-end=&quot;227&quot; data-start=&quot;207&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;227&quot; data-start=&quot;207&quot; data-ke-size=&quot;size16&quot;&gt;Chebyshev 필터&lt;/p&gt;
&lt;p data-end=&quot;256&quot; data-start=&quot;229&quot; data-ke-size=&quot;size16&quot;&gt;- Chebyshev Type I (1형)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;316&quot; data-start=&quot;257&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;291&quot; data-start=&quot;257&quot;&gt;통과대역에 ripple, 저지대역은 단조롭게 감쇠.&lt;/li&gt;
&lt;li data-end=&quot;316&quot; data-start=&quot;292&quot;&gt;롤오프가 Butterworth보다 빠름.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;346&quot; data-start=&quot;318&quot; data-ke-size=&quot;size16&quot;&gt;- Chebyshev Type II (2형)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;406&quot; data-start=&quot;347&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;377&quot; data-start=&quot;347&quot;&gt;저지대역에 ripple, 통과대역은 평탄함.&lt;/li&gt;
&lt;li data-end=&quot;406&quot; data-start=&quot;378&quot;&gt;Type I보다 덜 사용됨 (주로 특수 목적).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;434&quot; data-start=&quot;413&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;434&quot; data-start=&quot;413&quot; data-ke-size=&quot;size16&quot;&gt;주파수 응답 (Type I)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;206&quot; data-origin-height=&quot;64&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPljHV/btsOVfgJLyS/qpVRigeGkkyVryXO5oIUrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPljHV/btsOVfgJLyS/qpVRigeGkkyVryXO5oIUrK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPljHV/btsOVfgJLyS/qpVRigeGkkyVryXO5oIUrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPljHV%2FbtsOVfgJLyS%2FqpVRigeGkkyVryXO5oIUrK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;206&quot; height=&quot;64&quot; data-origin-width=&quot;206&quot; data-origin-height=&quot;64&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;556&quot; data-start=&quot;527&quot;&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;n&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​ &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: n차 Chebyshev 다항식&lt;/li&gt;
&lt;li data-end=&quot;582&quot; data-start=&quot;557&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;omega;c &lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;: 컷오프 주파수&lt;/li&gt;
&lt;li data-end=&quot;636&quot; data-start=&quot;583&quot;&gt;&lt;span&gt;&lt;span&gt;ϵ &lt;/span&gt;&lt;/span&gt;: ripple 크기 제어 (0일 때 Butterworth와 동일)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;vector&amp;gt; &lt;br /&gt;&lt;br /&gt;class&amp;nbsp;ChebyshevIIR&amp;nbsp;{ &lt;br /&gt;public: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChebyshevIIR(const&amp;nbsp;double*&amp;nbsp;b,&amp;nbsp;const&amp;nbsp;double*&amp;nbsp;a,&amp;nbsp;int&amp;nbsp;order) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;:&amp;nbsp;b(b),&amp;nbsp;a(a),&amp;nbsp;order(order)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w.assign(order,&amp;nbsp;0.0); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;process(double&amp;nbsp;x)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;y&amp;nbsp;=&amp;nbsp;b[0]&amp;nbsp;*&amp;nbsp;x&amp;nbsp;+&amp;nbsp;w[0]; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;1;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;order;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w[i&amp;nbsp;-&amp;nbsp;1]&amp;nbsp;=&amp;nbsp;b[i]&amp;nbsp;*&amp;nbsp;x&amp;nbsp;+&amp;nbsp;w[i]&amp;nbsp;-&amp;nbsp;a[i]&amp;nbsp;*&amp;nbsp;y; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;w[order&amp;nbsp;-&amp;nbsp;1]&amp;nbsp;=&amp;nbsp;-a[order]&amp;nbsp;*&amp;nbsp;y; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;y; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;private: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;double*&amp;nbsp;b; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;const&amp;nbsp;double*&amp;nbsp;a; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;order; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;w; &lt;br /&gt;}; &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;iostream&amp;gt; &lt;br /&gt;&lt;br /&gt;// (4차 필터) &lt;br /&gt;const&amp;nbsp;double&amp;nbsp;b_cheby[5]&amp;nbsp;=&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0.00183555,&amp;nbsp;0.0073422,&amp;nbsp;0.0110133,&amp;nbsp;0.0073422,&amp;nbsp;0.00183555 &lt;br /&gt;}; &lt;br /&gt;const&amp;nbsp;double&amp;nbsp;a_cheby[5]&amp;nbsp;=&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.0,&amp;nbsp;-3.05433968,&amp;nbsp;3.82899923,&amp;nbsp;-2.29245173,&amp;nbsp;0.55074452 &lt;br /&gt;}; &lt;br /&gt;&lt;br /&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ChebyshevIIR&amp;nbsp;filter(b_cheby,&amp;nbsp;a_cheby,&amp;nbsp;5);&amp;nbsp;//&amp;nbsp;4차&amp;nbsp;&amp;rarr;&amp;nbsp;계수&amp;nbsp;5개 &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;50;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;input&amp;nbsp;=&amp;nbsp;(i&amp;nbsp;%&amp;nbsp;2&amp;nbsp;==&amp;nbsp;0)&amp;nbsp;?&amp;nbsp;1.0&amp;nbsp;:&amp;nbsp;-1.0;&amp;nbsp;&amp;nbsp;//&amp;nbsp;고주파&amp;nbsp;성분&amp;nbsp;포함된&amp;nbsp;신호 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;output&amp;nbsp;=&amp;nbsp;filter.process(input); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;input:&amp;nbsp;&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;input&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;\toutput:&amp;nbsp;&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;output&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;std::endl; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>butterworth</category>
      <category>chebyshev</category>
      <category>edge</category>
      <category>Filtering</category>
      <category>IIR</category>
      <category>ripple</category>
      <category>subpixel</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/371</guid>
      <comments>https://folcjin.tistory.com/371#entry371comment</comments>
      <pubDate>Sat, 28 Jun 2025 10:32:03 +0900</pubDate>
    </item>
    <item>
      <title>치수 계산하기 - smooth filtering 5</title>
      <link>https://folcjin.tistory.com/370</link>
      <description>&lt;p data-end=&quot;240&quot; data-start=&quot;213&quot; data-ke-size=&quot;size16&quot;&gt;Butterworth Filter&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;321&quot; data-start=&quot;251&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;293&quot; data-start=&quot;251&quot;&gt;매끄럽고 평탄한 주파수 응답 (통과대역에서 ripple이 없음).&lt;/li&gt;
&lt;li data-end=&quot;321&quot; data-start=&quot;294&quot;&gt;필터 차수가 증가할수록 롤오프가 더 급격해짐.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;331&quot; data-start=&quot;323&quot; data-ke-size=&quot;size16&quot;&gt;특징&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;373&quot; data-start=&quot;332&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;350&quot; data-start=&quot;332&quot;&gt;응답이 가장 &quot;부드러운&quot; 필터&lt;/li&gt;
&lt;li data-end=&quot;373&quot; data-start=&quot;351&quot;&gt;급격한 에지 응답은 부족하지만 안정적&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;397&quot; data-start=&quot;375&quot; data-ke-size=&quot;size16&quot;&gt;주파수 응답 (저역통과 기준)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;178&quot; data-origin-height=&quot;66&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vOsDm/btsOVkiG7vW/Ig6aCYSx8P82jWv4qs6Kc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vOsDm/btsOVkiG7vW/Ig6aCYSx8P82jWv4qs6Kc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vOsDm/btsOVkiG7vW/Ig6aCYSx8P82jWv4qs6Kc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvOsDm%2FbtsOVkiG7vW%2FIg6aCYSx8P82jWv4qs6Kc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;178&quot; height=&quot;66&quot; data-origin-width=&quot;178&quot; data-origin-height=&quot;66&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;예제&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;#include&amp;nbsp;&amp;lt;iostream&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;cmath&amp;gt; &lt;br /&gt;&lt;br /&gt;class&amp;nbsp;ButterworthLPF&amp;nbsp;{ &lt;br /&gt;public: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ButterworthLPF(double&amp;nbsp;sampleRate,&amp;nbsp;double&amp;nbsp;cutoffFreq)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;fr&amp;nbsp;=&amp;nbsp;cutoffFreq&amp;nbsp;/&amp;nbsp;sampleRate; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;ita&amp;nbsp;=&amp;nbsp;1.0&amp;nbsp;/&amp;nbsp;std::tan(M_PI&amp;nbsp;*&amp;nbsp;fr); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;q&amp;nbsp;=&amp;nbsp;std::sqrt(2.0);&amp;nbsp;&amp;nbsp;//&amp;nbsp;Q&amp;nbsp;factor&amp;nbsp;for&amp;nbsp;2nd-order&amp;nbsp;Butterworth &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a0&amp;nbsp;=&amp;nbsp;1.0&amp;nbsp;/&amp;nbsp;(1.0&amp;nbsp;+&amp;nbsp;q&amp;nbsp;*&amp;nbsp;ita&amp;nbsp;+&amp;nbsp;ita&amp;nbsp;*&amp;nbsp;ita); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a1&amp;nbsp;=&amp;nbsp;2&amp;nbsp;*&amp;nbsp;a0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a2&amp;nbsp;=&amp;nbsp;a0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b1&amp;nbsp;=&amp;nbsp;2.0&amp;nbsp;*&amp;nbsp;(ita&amp;nbsp;*&amp;nbsp;ita&amp;nbsp;-&amp;nbsp;1.0)&amp;nbsp;*&amp;nbsp;a0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b2&amp;nbsp;=&amp;nbsp;(1.0&amp;nbsp;-&amp;nbsp;q&amp;nbsp;*&amp;nbsp;ita&amp;nbsp;+&amp;nbsp;ita&amp;nbsp;*&amp;nbsp;ita)&amp;nbsp;*&amp;nbsp;a0; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x1&amp;nbsp;=&amp;nbsp;x2&amp;nbsp;=&amp;nbsp;y1&amp;nbsp;=&amp;nbsp;y2&amp;nbsp;=&amp;nbsp;0.0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;process(double&amp;nbsp;x0)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;y0&amp;nbsp;=&amp;nbsp;a0&amp;nbsp;*&amp;nbsp;x0&amp;nbsp;+&amp;nbsp;a1&amp;nbsp;*&amp;nbsp;x1&amp;nbsp;+&amp;nbsp;a2&amp;nbsp;*&amp;nbsp;x2 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;b1&amp;nbsp;*&amp;nbsp;y1&amp;nbsp;-&amp;nbsp;b2&amp;nbsp;*&amp;nbsp;y2; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;시프트 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x2&amp;nbsp;=&amp;nbsp;x1; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x1&amp;nbsp;=&amp;nbsp;x0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;y2&amp;nbsp;=&amp;nbsp;y1; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;y1&amp;nbsp;=&amp;nbsp;y0; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;y0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;private: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;a0,&amp;nbsp;a1,&amp;nbsp;a2,&amp;nbsp;b1,&amp;nbsp;b2; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;x1,&amp;nbsp;x2,&amp;nbsp;y1,&amp;nbsp;y2; &lt;br /&gt;}; &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ButterworthLPF&amp;nbsp;lpf(1000.0,&amp;nbsp;100.0);&amp;nbsp;&amp;nbsp;//&amp;nbsp;fs=1000Hz,&amp;nbsp;cutoff=100Hz &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;20;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;input&amp;nbsp;=&amp;nbsp;(i&amp;nbsp;%&amp;nbsp;2&amp;nbsp;==&amp;nbsp;0)&amp;nbsp;?&amp;nbsp;1.0&amp;nbsp;:&amp;nbsp;-1.0;&amp;nbsp;&amp;nbsp;//&amp;nbsp;대역&amp;nbsp;외&amp;nbsp;고주파&amp;nbsp;입력 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;output&amp;nbsp;=&amp;nbsp;lpf.process(input); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;Input:&amp;nbsp;&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;input&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;\tFiltered:&amp;nbsp;&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;output&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;std::endl; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>butterworth</category>
      <category>cut off</category>
      <category>detection</category>
      <category>edge</category>
      <category>Filtering</category>
      <category>LPF</category>
      <category>rate</category>
      <category>sample</category>
      <category>subpixel</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/370</guid>
      <comments>https://folcjin.tistory.com/370#entry370comment</comments>
      <pubDate>Sat, 28 Jun 2025 10:27:51 +0900</pubDate>
    </item>
    <item>
      <title>치수 계산하기 - smooth filtering 4</title>
      <link>https://folcjin.tistory.com/369</link>
      <description>&lt;p data-end=&quot;215&quot; data-start=&quot;180&quot; data-ke-size=&quot;size16&quot;&gt;Band-pass Filter (대역통과 필터)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;310&quot; data-start=&quot;226&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;272&quot; data-start=&quot;226&quot;&gt;특정 주파수 범위만 통과시키고, 그 이외의 저주파와 고주파는 차단합니다.&lt;/li&gt;
&lt;li data-end=&quot;310&quot; data-start=&quot;273&quot;&gt;예: 5&lt;s&gt;15Hz만 통과 &amp;rarr; 0&lt;/s&gt;5Hz, 15Hz~ 이상은 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;320&quot; data-start=&quot;312&quot; data-ke-size=&quot;size16&quot;&gt;용도&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;380&quot; data-start=&quot;321&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;354&quot; data-start=&quot;321&quot;&gt;특정 이벤트나 센서가 생성하는 주파수만 추출하고 싶을 때&lt;/li&gt;
&lt;li data-end=&quot;380&quot; data-start=&quot;355&quot;&gt;잡음이 저역 또는 고역에 집중되어 있을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;418&quot; data-start=&quot;387&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;418&quot; data-start=&quot;387&quot; data-ke-size=&quot;size16&quot;&gt;Notch Filter (대역저지 필터)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;503&quot; data-start=&quot;429&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;466&quot; data-start=&quot;429&quot;&gt;특정 좁은 주파수 대역만 제거하고 나머지는 통과시킵니다.&lt;/li&gt;
&lt;li data-end=&quot;503&quot; data-start=&quot;467&quot;&gt;예: 60Hz 전력 노이즈 제거 (Line frequency)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;513&quot; data-start=&quot;505&quot; data-ke-size=&quot;size16&quot;&gt;용도&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;583&quot; data-start=&quot;514&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;550&quot; data-start=&quot;514&quot;&gt;주기적이고 명확한 간섭 신호(기계 진동, 전력 간섭 등) 제거&lt;/li&gt;
&lt;li data-end=&quot;583&quot; data-start=&quot;551&quot;&gt;신호 구조를 최대한 유지하면서 잡음만 제거하고자 할 때&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;iostream&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;vector&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;cmath&amp;gt; &lt;br /&gt;&lt;br /&gt;const&amp;nbsp;double&amp;nbsp;PI&amp;nbsp;=&amp;nbsp;3.14159265358979323846; &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;간단한&amp;nbsp;IIR&amp;nbsp;2차&amp;nbsp;Band-pass&amp;nbsp;필터&amp;nbsp;클래스 &lt;br /&gt;class&amp;nbsp;BandPassFilter&amp;nbsp;{ &lt;br /&gt;public: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BandPassFilter(double&amp;nbsp;sampleRate,&amp;nbsp;double&amp;nbsp;lowCut,&amp;nbsp;double&amp;nbsp;highCut)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;nyq&amp;nbsp;=&amp;nbsp;0.5&amp;nbsp;*&amp;nbsp;sampleRate; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;low&amp;nbsp;=&amp;nbsp;lowCut&amp;nbsp;/&amp;nbsp;nyq; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;high&amp;nbsp;=&amp;nbsp;highCut&amp;nbsp;/&amp;nbsp;nyq; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Butterworth&amp;nbsp;2차&amp;nbsp;설계&amp;nbsp;(biquad&amp;nbsp;형태) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;theta&amp;nbsp;=&amp;nbsp;PI&amp;nbsp;*&amp;nbsp;(high&amp;nbsp;-&amp;nbsp;low); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;d&amp;nbsp;=&amp;nbsp;1.0&amp;nbsp;/&amp;nbsp;std::tan(theta); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;beta&amp;nbsp;=&amp;nbsp;0.5&amp;nbsp;*&amp;nbsp;((1.0&amp;nbsp;-&amp;nbsp;d)&amp;nbsp;/&amp;nbsp;(1.0&amp;nbsp;+&amp;nbsp;d)); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a0&amp;nbsp;=&amp;nbsp;0.5&amp;nbsp;*&amp;nbsp;(1.0&amp;nbsp;-&amp;nbsp;beta); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a1&amp;nbsp;=&amp;nbsp;0.0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;a2&amp;nbsp;=&amp;nbsp;-a0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b1&amp;nbsp;=&amp;nbsp;-2.0&amp;nbsp;*&amp;nbsp;beta; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;b2&amp;nbsp;=&amp;nbsp;(1.0&amp;nbsp;-&amp;nbsp;beta); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x1&amp;nbsp;=&amp;nbsp;x2&amp;nbsp;=&amp;nbsp;y1&amp;nbsp;=&amp;nbsp;y2&amp;nbsp;=&amp;nbsp;0.0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;process(double&amp;nbsp;input)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;output&amp;nbsp;=&amp;nbsp;a0&amp;nbsp;*&amp;nbsp;input&amp;nbsp;+&amp;nbsp;a1&amp;nbsp;*&amp;nbsp;x1&amp;nbsp;+&amp;nbsp;a2&amp;nbsp;*&amp;nbsp;x2 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;-&amp;nbsp;b1&amp;nbsp;*&amp;nbsp;y1&amp;nbsp;-&amp;nbsp;b2&amp;nbsp;*&amp;nbsp;y2; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x2&amp;nbsp;=&amp;nbsp;x1; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;x1&amp;nbsp;=&amp;nbsp;input; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;y2&amp;nbsp;=&amp;nbsp;y1; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;y1&amp;nbsp;=&amp;nbsp;output; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;output; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;private: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;a0,&amp;nbsp;a1,&amp;nbsp;a2,&amp;nbsp;b1,&amp;nbsp;b2; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;x1,&amp;nbsp;x2,&amp;nbsp;y1,&amp;nbsp;y2; &lt;br /&gt;}; &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;예제&amp;nbsp;신호&amp;nbsp;(노이즈&amp;nbsp;+&amp;nbsp;10Hz&amp;nbsp;사인파) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;fs&amp;nbsp;=&amp;nbsp;100.0;&amp;nbsp;&amp;nbsp;//&amp;nbsp;샘플링&amp;nbsp;주파수 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;f_target&amp;nbsp;=&amp;nbsp;10.0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;duration&amp;nbsp;=&amp;nbsp;2.0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;N&amp;nbsp;=&amp;nbsp;static_cast&amp;lt;int&amp;gt;(fs&amp;nbsp;*&amp;nbsp;duration); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;signal(N); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;N;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;t&amp;nbsp;=&amp;nbsp;i&amp;nbsp;/&amp;nbsp;fs; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;signal[i]&amp;nbsp;=&amp;nbsp;sin(2&amp;nbsp;*&amp;nbsp;PI&amp;nbsp;*&amp;nbsp;f_target&amp;nbsp;*&amp;nbsp;t)&amp;nbsp;+&amp;nbsp;0.5&amp;nbsp;*&amp;nbsp;sin(2&amp;nbsp;*&amp;nbsp;PI&amp;nbsp;*&amp;nbsp;60.0&amp;nbsp;*&amp;nbsp;t);&amp;nbsp;//&amp;nbsp;60Hz&amp;nbsp;노이즈&amp;nbsp;포함 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;8~12Hz&amp;nbsp;Band-pass&amp;nbsp;필터 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BandPassFilter&amp;nbsp;bpf(fs,&amp;nbsp;8.0,&amp;nbsp;12.0); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;필터링 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;filtered(N); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;N;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;filtered[i]&amp;nbsp;=&amp;nbsp;bpf.process(signal[i]); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;결과&amp;nbsp;출력&amp;nbsp;(일부만) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;20;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;raw:&amp;nbsp;&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;signal[i]&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;\tfiltered:&amp;nbsp;&quot;&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;filtered[i]&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;\n&quot;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;/p&gt;</description>
      <category>accumulate</category>
      <category>edge</category>
      <category>Filtering</category>
      <category>mean</category>
      <category>MSE</category>
      <category>Spike</category>
      <category>subpixel</category>
      <category>variation</category>
      <category>wiener</category>
      <category>window</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/369</guid>
      <comments>https://folcjin.tistory.com/369#entry369comment</comments>
      <pubDate>Sat, 28 Jun 2025 10:25:58 +0900</pubDate>
    </item>
    <item>
      <title>치수 계산하기 - smooth filtering 3</title>
      <link>https://folcjin.tistory.com/368</link>
      <description>&lt;p data-end=&quot;194&quot; data-start=&quot;169&quot; data-ke-size=&quot;size16&quot;&gt;Wiener Filter&lt;br /&gt;- 노이즈를 억제하면서 신호를 왜곡 없이 보존하는 것이 목표.&lt;br /&gt;- 선형 필터 중 평균 제곱 오차(Mean Square Error, MSE)를 최소화함.&lt;/p&gt;
&lt;p data-end=&quot;306&quot; data-start=&quot;295&quot; data-ke-size=&quot;size16&quot;&gt;동작 방식&lt;br /&gt;- 입력 &lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;x&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (신호 + 잡음)&lt;br /&gt;- 출력 &lt;span&gt;&lt;span&gt;y[n]&lt;/span&gt;&lt;/span&gt;는 다음 조건을 만족하도록 설계:&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;238&quot; data-origin-height=&quot;29&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uqAaj/btsOWsl8IEv/IqAFvDKKwCzlYCrZXdP5fK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uqAaj/btsOWsl8IEv/IqAFvDKKwCzlYCrZXdP5fK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uqAaj/btsOWsl8IEv/IqAFvDKKwCzlYCrZXdP5fK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuqAaj%2FbtsOWsl8IEv%2FIqAFvDKKwCzlYCrZXdP5fK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;238&quot; height=&quot;29&quot; data-origin-width=&quot;238&quot; data-origin-height=&quot;29&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;306&quot; data-start=&quot;295&quot; data-ke-size=&quot;size16&quot;&gt;- 주파수 영역에서의 형태 (1D 버전):&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;181&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xvORV/btsOWIvu95H/5pT8QuxgeezGIkOlMKisXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xvORV/btsOWIvu95H/5pT8QuxgeezGIkOlMKisXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xvORV/btsOWIvu95H/5pT8QuxgeezGIkOlMKisXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxvORV%2FbtsOWIvu95H%2F5pT8QuxgeezGIkOlMKisXK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;181&quot; height=&quot;53&quot; data-origin-width=&quot;181&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;591&quot; data-start=&quot;539&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;563&quot; data-start=&quot;539&quot;&gt;&lt;span&gt;&lt;span&gt;S(f) &lt;/span&gt;&lt;/span&gt;: 신호 파워 스펙트럼&lt;/li&gt;
&lt;li data-end=&quot;591&quot; data-start=&quot;566&quot;&gt;&lt;span&gt;&lt;span&gt;N(f) &lt;/span&gt;&lt;/span&gt;: 노이즈 파워 스펙트럼&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 1D Wiener Filter 구현 로직&lt;/p&gt;
&lt;p data-end=&quot;654&quot; data-start=&quot;635&quot; data-ke-size=&quot;size16&quot;&gt;핵심 공식 (시간영역 근사)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;212&quot; data-origin-height=&quot;50&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pqzC3/btsOXfzNyBq/v89kRpc6Wk3yfuFoaKbY81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pqzC3/btsOXfzNyBq/v89kRpc6Wk3yfuFoaKbY81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pqzC3/btsOXfzNyBq/v89kRpc6Wk3yfuFoaKbY81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpqzC3%2FbtsOXfzNyBq%2Fv89kRpc6Wk3yfuFoaKbY81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;212&quot; height=&quot;50&quot; data-origin-width=&quot;212&quot; data-origin-height=&quot;50&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;826&quot; data-start=&quot;735&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;757&quot; data-start=&quot;735&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;mu; &lt;/span&gt;&lt;/span&gt;: 로컬 윈도우 평균&lt;/li&gt;
&lt;li data-end=&quot;784&quot; data-start=&quot;758&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;sigma;2 &lt;/span&gt;&lt;/span&gt;: 로컬 신호 분산&lt;/li&gt;
&lt;li data-end=&quot;826&quot; data-start=&quot;785&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nu;2 &lt;/span&gt;&lt;/span&gt;: 노이즈 추정 분산 (전역 평균 또는 사전 정보)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;iostream&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;vector&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;numeric&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;cmath&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;algorithm&amp;gt; &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;평균&amp;nbsp;계산&amp;nbsp;함수 &lt;br /&gt;double&amp;nbsp;mean(const&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;amp;&amp;nbsp;data)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;std::accumulate(data.begin(),&amp;nbsp;data.end(),&amp;nbsp;0.0)&amp;nbsp;/&amp;nbsp;data.size(); &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;분산&amp;nbsp;계산&amp;nbsp;함수 &lt;br /&gt;double&amp;nbsp;variance(const&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;amp;&amp;nbsp;data,&amp;nbsp;double&amp;nbsp;data_mean)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;var&amp;nbsp;=&amp;nbsp;0.0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(auto&amp;nbsp;v&amp;nbsp;:&amp;nbsp;data)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;var&amp;nbsp;+=&amp;nbsp;(v&amp;nbsp;-&amp;nbsp;data_mean)&amp;nbsp;*&amp;nbsp;(v&amp;nbsp;-&amp;nbsp;data_mean); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;var&amp;nbsp;/&amp;nbsp;data.size(); &lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;1D&amp;nbsp;Wiener&amp;nbsp;Filter &lt;br /&gt;std::vector&amp;lt;double&amp;gt;&amp;nbsp;wienerFilter(const&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;amp;&amp;nbsp;signal,&amp;nbsp;int&amp;nbsp;windowSize,&amp;nbsp;double&amp;nbsp;noiseVariance&amp;nbsp;=&amp;nbsp;-1.0)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;N&amp;nbsp;=&amp;nbsp;signal.size(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;half&amp;nbsp;=&amp;nbsp;windowSize&amp;nbsp;/&amp;nbsp;2; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;output(N); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;전체&amp;nbsp;평균&amp;nbsp;기반으로&amp;nbsp;노이즈&amp;nbsp;분산&amp;nbsp;추정&amp;nbsp;(옵션) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(noiseVariance&amp;nbsp;&amp;lt;&amp;nbsp;0)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;global_mean&amp;nbsp;=&amp;nbsp;mean(signal); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;noiseVariance&amp;nbsp;=&amp;nbsp;variance(signal,&amp;nbsp;global_mean)&amp;nbsp;*&amp;nbsp;0.1;&amp;nbsp;&amp;nbsp;//&amp;nbsp;약한&amp;nbsp;노이즈&amp;nbsp;가정 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;N;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;window; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;j&amp;nbsp;=&amp;nbsp;-half;&amp;nbsp;j&amp;nbsp;&amp;lt;=&amp;nbsp;half;&amp;nbsp;++j)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;idx&amp;nbsp;=&amp;nbsp;std::clamp(i&amp;nbsp;+&amp;nbsp;j,&amp;nbsp;0,&amp;nbsp;N&amp;nbsp;-&amp;nbsp;1); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.push_back(signal[idx]); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;local_mean&amp;nbsp;=&amp;nbsp;mean(window); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;local_var&amp;nbsp;=&amp;nbsp;variance(window,&amp;nbsp;local_mean); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;gain&amp;nbsp;=&amp;nbsp;(local_var&amp;nbsp;&amp;gt;&amp;nbsp;0.0)&amp;nbsp;?&amp;nbsp;std::max(0.0,&amp;nbsp;(local_var&amp;nbsp;-&amp;nbsp;noiseVariance)&amp;nbsp;/&amp;nbsp;local_var)&amp;nbsp;:&amp;nbsp;0.0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output[i]&amp;nbsp;=&amp;nbsp;local_mean&amp;nbsp;+&amp;nbsp;gain&amp;nbsp;*&amp;nbsp;(signal[i]&amp;nbsp;-&amp;nbsp;local_mean); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;output; &lt;br /&gt;} &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;input&amp;nbsp;=&amp;nbsp;{10,&amp;nbsp;12,&amp;nbsp;11,&amp;nbsp;80,&amp;nbsp;12,&amp;nbsp;11,&amp;nbsp;10};&amp;nbsp;&amp;nbsp;//&amp;nbsp;스파이크&amp;nbsp;포함된&amp;nbsp;노이즈&amp;nbsp;신호 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;windowSize&amp;nbsp;=&amp;nbsp;3; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;filtered&amp;nbsp;=&amp;nbsp;wienerFilter(input,&amp;nbsp;windowSize); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;Wiener&amp;nbsp;Filter&amp;nbsp;Output:\n&quot;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(double&amp;nbsp;v&amp;nbsp;:&amp;nbsp;filtered)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;v&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;&amp;nbsp;&quot;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;std::endl; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;/p&gt;</description>
      <category>accumulate</category>
      <category>edge</category>
      <category>Filtering</category>
      <category>mean</category>
      <category>MSE</category>
      <category>Spike</category>
      <category>subpixel</category>
      <category>variation</category>
      <category>wiener</category>
      <category>window</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/368</guid>
      <comments>https://folcjin.tistory.com/368#entry368comment</comments>
      <pubDate>Sat, 28 Jun 2025 10:19:11 +0900</pubDate>
    </item>
    <item>
      <title>치수 계산하기 - smooth filtering 2</title>
      <link>https://folcjin.tistory.com/367</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;윈도우 내 값들을 오름차순 정렬.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 순위(rank) 또는 백분위(percentile)에 해당하는 값을 반환.&lt;br /&gt;- Percentile filter: 0~100 중 하나의 백분위값 (e.g., 20%)&lt;br /&gt;- Rank filter: 윈도우 내 인덱스로 직접 지정 (e.g., 3번째 작은 값)&lt;/p&gt;
&lt;p data-end=&quot;507&quot; data-start=&quot;445&quot; data-ke-size=&quot;size16&quot;&gt;입력: [8, 3, 4, 2, 10], 커널 size = 5&lt;br /&gt;정렬: [2, 3, 4, 8, 10]&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;604&quot; data-start=&quot;508&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;540&quot; data-start=&quot;508&quot;&gt;20% percentile &amp;rarr; 1번째 값 &amp;rarr; 3&lt;/li&gt;
&lt;li data-end=&quot;571&quot; data-start=&quot;541&quot;&gt;50% percentile &amp;rarr; 중앙값 &amp;rarr; 4&lt;/li&gt;
&lt;li data-end=&quot;604&quot; data-start=&quot;572&quot;&gt;80% percentile &amp;rarr; 4번째 값 &amp;rarr; 8&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Median보다 더 다양한 filtering 특성이 가능&lt;br /&gt;특정 방향성 있는 노이즈 억제 가능 (e.g. 아래쪽 스파이크 제거)&lt;/p&gt;
&lt;p data-end=&quot;495&quot; data-start=&quot;487&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;495&quot; data-start=&quot;487&quot; data-ke-size=&quot;size16&quot;&gt;예제&lt;/p&gt;
&lt;p data-end=&quot;495&quot; data-start=&quot;487&quot; data-ke-size=&quot;size16&quot;&gt;#include&amp;nbsp;&amp;lt;iostream&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;vector&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;algorithm&amp;gt; &lt;br /&gt;#include&amp;nbsp;&amp;lt;cmath&amp;gt; &lt;br /&gt;&lt;br /&gt;//&amp;nbsp;percentile&amp;nbsp;필터&amp;nbsp;함수 &lt;br /&gt;std::vector&amp;lt;double&amp;gt;&amp;nbsp;percentileFilter(const&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;amp;&amp;nbsp;signal,&amp;nbsp;int&amp;nbsp;windowSize,&amp;nbsp;double&amp;nbsp;percentile)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;half&amp;nbsp;=&amp;nbsp;windowSize&amp;nbsp;/&amp;nbsp;2; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;N&amp;nbsp;=&amp;nbsp;signal.size(); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;output(N); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;i&amp;nbsp;=&amp;nbsp;0;&amp;nbsp;i&amp;nbsp;&amp;lt;&amp;nbsp;N;&amp;nbsp;++i)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;window; &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;윈도우&amp;nbsp;추출 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(int&amp;nbsp;j&amp;nbsp;=&amp;nbsp;-half;&amp;nbsp;j&amp;nbsp;&amp;lt;=&amp;nbsp;half;&amp;nbsp;++j)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;idx&amp;nbsp;=&amp;nbsp;i&amp;nbsp;+&amp;nbsp;j; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(idx&amp;nbsp;&amp;lt;&amp;nbsp;0)&amp;nbsp;idx&amp;nbsp;=&amp;nbsp;0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(idx&amp;nbsp;&amp;gt;=&amp;nbsp;N)&amp;nbsp;idx&amp;nbsp;=&amp;nbsp;N&amp;nbsp;-&amp;nbsp;1; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;window.push_back(signal[idx]); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;정렬 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::sort(window.begin(),&amp;nbsp;window.end()); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;Percentile&amp;nbsp;인덱스&amp;nbsp;계산&amp;nbsp;(0~100&amp;nbsp;&amp;rarr;&amp;nbsp;0~windowSize-1) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;rank&amp;nbsp;=&amp;nbsp;std::floor((percentile&amp;nbsp;/&amp;nbsp;100.0)&amp;nbsp;*&amp;nbsp;(windowSize&amp;nbsp;-&amp;nbsp;1)); &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output[i]&amp;nbsp;=&amp;nbsp;window[rank]; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;output; &lt;br /&gt;}&lt;/p&gt;
&lt;p data-end=&quot;495&quot; data-start=&quot;487&quot; data-ke-size=&quot;size16&quot;&gt;int&amp;nbsp;main()&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;input&amp;nbsp;=&amp;nbsp;{8,&amp;nbsp;3,&amp;nbsp;4,&amp;nbsp;2,&amp;nbsp;10,&amp;nbsp;7,&amp;nbsp;6}; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;windowSize&amp;nbsp;=&amp;nbsp;5; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;double&amp;nbsp;percentile&amp;nbsp;=&amp;nbsp;20.0;&amp;nbsp;&amp;nbsp;//&amp;nbsp;하위&amp;nbsp;20%&amp;nbsp;값 &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::vector&amp;lt;double&amp;gt;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;percentileFilter(input,&amp;nbsp;windowSize,&amp;nbsp;percentile); &lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;Filtered&amp;nbsp;output:&amp;nbsp;&quot;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for&amp;nbsp;(double&amp;nbsp;val&amp;nbsp;:&amp;nbsp;result)&amp;nbsp;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;val&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;&quot;&amp;nbsp;&quot;; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;std::cout&amp;nbsp;&amp;lt;&amp;lt;&amp;nbsp;std::endl; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;0; &lt;br /&gt;} &lt;/p&gt;</description>
      <category>coefficient</category>
      <category>edge</category>
      <category>Filtering</category>
      <category>Order</category>
      <category>percentile</category>
      <category>rank</category>
      <category>Smooth</category>
      <category>subpixel</category>
      <category>window</category>
      <author>folcjin</author>
      <guid isPermaLink="true">https://folcjin.tistory.com/367</guid>
      <comments>https://folcjin.tistory.com/367#entry367comment</comments>
      <pubDate>Sat, 28 Jun 2025 10:12:53 +0900</pubDate>
    </item>
  </channel>
</rss>