<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>하리우라</title>
    <link>https://hariura.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 1 Jun 2026 23:00:33 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>하리우라</managingEditor>
    <item>
      <title>두 카메라 스테레오 캘리브레이션 (ChArUco 기반)</title>
      <link>https://hariura.tistory.com/11</link>
      <description>&lt;div style=&quot;color: #cccccc; text-align: start;&quot;&gt;
&lt;div style=&quot;color: #000000;&quot; data-testid=&quot;assistant-message&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; font-size: 1.62em; letter-spacing: -1px;&quot;&gt;왜 캘리브레이션이 필요한가&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #cccccc; text-align: start;&quot;&gt;
&lt;div style=&quot;color: #000000;&quot; data-testid=&quot;assistant-message&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라는 3D 세계를 2D 이미지로 투영하는 장치입니다. 이 과정에서 두 가지 문제가 생깁니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;렌즈 왜곡&lt;/b&gt;: 실제 직선이 이미지에서 휘어 보임 (배럴/핀쿠션 왜곡)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;투영 관계의 불확실성&lt;/b&gt;: 픽셀 좌표와 실제 3D 좌표 사이의 수치 관계를 모름&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캘리브레이션은 이 두 가지를 수치로 정확히 구하는 과정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 카메라를 함께 쓸 때는 추가로 **두 카메라 사이의 상대 위치&amp;middot;자세(외부 파라미터)**도 구해야 합니다. 이것이 있어야 두 이미지를 픽셀 단위로 정렬할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;캘리브레이션으로 얻는 결과물&lt;/h2&gt;
결과물의미
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;cameraMatrix&lt;span&gt;&amp;nbsp;&lt;/span&gt;(K)&lt;/td&gt;
&lt;td&gt;초점거리(fx, fy), 주점(cx, cy) &amp;mdash; 내부 파라미터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;distCoeffs&lt;/td&gt;
&lt;td&gt;렌즈 왜곡 계수 (k1, k2, p1, p2, ...)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;R,&lt;span&gt;&amp;nbsp;&lt;/span&gt;T&lt;/td&gt;
&lt;td&gt;카메라1 &amp;rarr; 카메라2 회전&amp;middot;평행이동 &amp;mdash; 스테레오 외부 파라미터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E,&lt;span&gt;&amp;nbsp;&lt;/span&gt;F&lt;/td&gt;
&lt;td&gt;Essential/Fundamental Matrix &amp;mdash; 두 카메라 간 기하학적 제약&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 ChArUco 보드인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 체커보드 대신 ArUco 마커가 박힌 체커보드를 사용합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;체커보드의 단점&lt;/b&gt;: 코너가 일부만 보이면 어느 코너인지 ID를 알 수 없음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ChArUco의 장점&lt;/b&gt;: 각 코너 근처에 고유 ID 마커가 있어서, 보드가 부분적으로 잘려도 어느 코너인지 식별 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 환경에서 보드를 다양한 각도로 기울이거나 이미지 가장자리에 걸칠 때 훨씬 안정적으로 동작합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;전체 파이프라인&lt;/h2&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. ChArUco 보드 제작 및 정의
        &amp;darr;
2. 이미지 수집 (카메라1, 카메라2 동기화 쌍)
        &amp;darr;
3. 각 이미지에서 ChArUco 코너 검출
        &amp;darr;
4. 단일 카메라 내부 파라미터 캘리브레이션 (카메라1, 카메라2 각각 독립적으로)
        &amp;darr;
5. 스테레오 캘리브레이션 (외부 파라미터 R, T 산출)
        &amp;darr;
6. 이미지 정렬 (스테레오 렉티피케이션 또는 호모그래피)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 1. 보드 제작과 코드 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보드를 인쇄한 뒤 &lt;b&gt;실제 정사각형 한 변의 길이를 자로 직접 측정&lt;/b&gt;합니다. 이 수치가 코드와 일치하지 않으면 스케일이 틀려집니다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ARUCO_DICT = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)

board = cv2.aruco.CharucoBoard_create(
    squaresX=5,
    squaresY=5,
    squareLength=0.12,   # 실제 측정값 (미터 단위)
    markerLength=0.09,   # ArUco 마커 크기 (squareLength보다 작아야 함)
    dictionary=ARUCO_DICT
)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단위는 미터든 센티미터든 무관하지만 프로젝트 전체에서 &lt;b&gt;일관성&lt;/b&gt;이 있어야 합니다. T(평행이동 벡터)의 단위가 여기서 결정됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 2. 이미지 수집 시 주의사항&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;장수&lt;/b&gt;: 최소 15~20쌍 이상 권장&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다양성&lt;/b&gt;: 다양한 각도, 거리, 화면 내 위치에서 촬영해야 왜곡 계수 추정이 안정적입니다. 한 자세로만 찍으면 특정 방향 왜곡 추정이 부정확해집니다&lt;/li&gt;
&lt;li&gt;&lt;b&gt;동기화&lt;/b&gt;: 두 카메라의 쌍은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;같은 시점에 찍혀야&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;합니다. 타임스탬프 차이가 크면 스테레오 외부 파라미터가 틀어집니다&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프레임 샘플링&lt;/b&gt;: 연속 촬영 영상에서 추출할 경우 인접 프레임은 거의 동일하므로 일정 간격(예: 10프레임마다 1장)으로 샘플링하는 것이 효율적입니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 3. ChArUco 코너 검출&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검출은 두 단계로 이루어집니다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def detect_charuco(image, board, dictionary):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if image.ndim == 3 else image

    # ① ArUco 마커 검출 (어느 코너인지 ID 파악)
    params = cv2.aruco.DetectorParameters_create()
    corners, ids, rejected = cv2.aruco.detectMarkers(gray, dictionary, parameters=params)

    if ids is None or len(ids) == 0:
        return False, None, None

    # ② ChArUco 코너 보간 (마커 사이 교차점을 서브픽셀 정밀도로 계산)
    retval, charuco_corners, charuco_ids = cv2.aruco.interpolateCornersCharuco(
        markerCorners=corners,
        markerIds=ids,
        image=gray,
        board=board
    )

    if charuco_corners is None or len(charuco_ids) == 0:
        return False, None, None

    return True, charuco_corners, charuco_ids
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ArUco 마커로 &quot;어느 코너인지&quot;를 파악하고, 실제 정밀 좌표는 체스판 코너(교차점)에서 얻습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 4. 단일 카메라 내부 파라미터 캘리브레이션&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 카메라를 &lt;b&gt;독립적으로&lt;/b&gt; 각각 캘리브레이션합니다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ret, cameraMatrix, distCoeffs, rvecs, tvecs = cv2.aruco.calibrateCameraCharuco(
    charucoCorners=all_corners,  # 각 이미지의 코너 좌표 리스트
    charucoIds=all_ids,          # 각 이미지의 코너 ID 리스트
    board=board,
    imageSize=image_size,
    cameraMatrix=None,
    distCoeffs=None,
)
print(&quot;RMS reprojection error:&quot;, ret)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ret은 &lt;b&gt;RMS 재투영 오차(reprojection error)&lt;/b&gt; 입니다. &quot;3D 점을 추정된 파라미터로 다시 2D에 투영했을 때 실제 검출 위치와 얼마나 차이나는가&quot;를 픽셀 단위로 나타냅니다.&lt;/p&gt;
RMS 범위상태
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.5px 이하&lt;/td&gt;
&lt;td&gt;양호&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.5 ~ 1.0px&lt;/td&gt;
&lt;td&gt;보통 (데이터 다양성 부족 가능성)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.0px 이상&lt;/td&gt;
&lt;td&gt;데이터 품질 재검토 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 5. 스테레오 캘리브레이션&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 카메라가 &lt;b&gt;같은 보드의 같은 코너를 동시에 본&lt;/b&gt; 이미지 쌍을 사용합니다. 각 쌍에서 공통으로 보이는 코너 ID를 기준으로 2D 좌표 대응을 만듭니다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;# 공통 코너 ID 추출
common_ids, idx1, idx2 = np.intersect1d(ids_cam1, ids_cam2, return_indices=True)

# 공통 코너의 3D 보드 좌표 및 각 카메라의 2D 좌표
obj_pts     = board.chessboardCorners[common_ids]  # (N, 3)
img_pts_cam1 = corners_cam1[idx1]
img_pts_cam2 = corners_cam2[idx2]
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수집한 모든 쌍을 묶어 스테레오 캘리브레이션을 실행합니다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;retval, _, _, _, _, R, T, E, F = cv2.stereoCalibrate(
    objectPoints=objp_list,
    imagePoints1=pts_cam1_list,
    imagePoints2=pts_cam2_list,
    cameraMatrix1=cam1_mtx,
    distCoeffs1=cam1_dist,
    cameraMatrix2=cam2_mtx,
    distCoeffs2=cam2_dist,
    imageSize=image_size,
    flags=cv2.CALIB_FIX_INTRINSIC,
    criteria=(cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS, 100, 1e-5)
)
print(&quot;Stereo RMS:&quot;, retval)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CALIB_FIX_INTRINSIC이 핵심입니다.&lt;/b&gt; Step 4에서 구한 내부 파라미터를 고정하고 R과 T만 최적화합니다. 이것이 표준적인 2단계 접근법입니다. 모든 파라미터를 동시에 최적화하면 자유도가 너무 높아져 오히려 불안정해집니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 6. 결과 활용 &amp;mdash; 두 가지 방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 A: 스테레오 렉티피케이션&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 카메라 이미지를 에피폴라 라인이 수평이 되도록 변환합니다. 스테레오 깊이 추정이나 정밀 정렬에 적합합니다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;smali&quot;&gt;&lt;code&gt;R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(
    cam1_mtx, cam1_dist,
    cam2_mtx, cam2_dist,
    image_size, R, T,
    flags=cv2.CALIB_ZERO_DISPARITY
)

map1, map2 = cv2.initUndistortRectifyMap(
    cam1_mtx, cam1_dist, R1, P1, image_size, cv2.CV_32FC1
)
cam1_rectified = cv2.remap(img_cam1, map1, map2, cv2.INTER_LINEAR)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렉티피케이션 맵(map1, map2)은 한 번만 계산해 저장해두면, 이후 매 프레임마다 cv2.remap만 호출하면 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 B: 호모그래피로 카메라2 &amp;rarr; 카메라1 정렬&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;R, T, 두 카메라의 내부 파라미터를 알고 있으면 &lt;b&gt;씬이 특정 깊이의 평면에 있다는 가정 하에&lt;/b&gt; 투영 변환 행렬(호모그래피 H)을 수식으로 직접 유도할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유도된 H를 사용하면 렉티피케이션 없이도 한 카메라의 이미지를 다른 카메라에 맞게 변환할 수 있습니다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;warped = cv2.warpPerspective(img_cam2, H, image_size)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: 이 방법은 씬이 단일 평면이라는 가정에 의존합니다. 깊이 변화가 큰 환경에서는 오정렬이 생기므로, 그런 경우에는 방법 A(렉티피케이션)를 권장합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결과 저장 및 재사용&lt;/h2&gt;
&lt;div&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 저장
np.savez(&quot;calib_cam1.npz&quot;, cameraMatrix=cam1_mtx, distCoeffs=cam1_dist)
np.savez(&quot;calib_cam2.npz&quot;, cameraMatrix=cam2_mtx, distCoeffs=cam2_dist)
np.savez(&quot;stereo_calib.npz&quot;, R=R, T=T, E=E, F=F)

# 불러오기
data = np.load(&quot;stereo_calib.npz&quot;)
R, T = data[&quot;R&quot;], data[&quot;T&quot;]
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렉티피케이션 맵도 같은 방식으로 저장해두면 실시간 처리 시 재사용할 수 있습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;품질 점검 체크리스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;수집 단계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;보드의&lt;span&gt;&amp;nbsp;&lt;/span&gt;squareLength를 실제로 측정했는가&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두 카메라 쌍의 타임스탬프 차이가 충분히 작은가&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;다양한 각도/거리/위치에서 15장 이상 촬영했는가&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캘리브레이션 단계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;단일 카메라 RMS &amp;lt; 0.5px&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;스테레오 RMS &amp;lt; 1.0px&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;언디스토션 이미지에서 직선이 실제로 직선으로 보이는가&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정렬 결과 확인&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;렉티피케이션 후 에피폴라 라인이 수평으로 정렬되는가&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두 카메라 이미지의 특징점 위치가 일치하는가&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캘리브레이션에서 가장 중요한 것은 코드가 아니라 &lt;b&gt;좋은 데이터를 수집하는 것&lt;/b&gt;입니다. 아무리 정확한 알고리즘도 한 자세로만 찍은 이미지로는 왜곡 계수를 제대로 추정하지 못합니다. 다양한 자세로 충분히 수집하고, RMS 오차로 품질을 확인하는 습관을 들이는 것이 핵심입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>CV</category>
      <author>하리우라</author>
      <guid isPermaLink="true">https://hariura.tistory.com/11</guid>
      <comments>https://hariura.tistory.com/11#entry11comment</comments>
      <pubDate>Thu, 2 Apr 2026 15:27:34 +0900</pubDate>
    </item>
    <item>
      <title>GPT CLI (Codex) 설치</title>
      <link>https://hariura.tistory.com/9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;  도커 컨테이너 안에서 GPT CLI (Codex) 설치 및 사용법&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 설치&lt;/h2&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;# 전역 설치
npm install -g @openai/codex
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치가 완료되면 codex 명령어를 사용할 수 있다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 첫 실행 (자동 인증)&lt;/h2&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;codex
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음 실행하면 &lt;b&gt;자동으로 로그인/인증 프롬프트&lt;/b&gt;가 뜬다.&lt;/li&gt;
&lt;li&gt;브라우저 인증 또는 토큰 입력 방식으로 진행된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 기본 사용&lt;/h2&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;codex
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CLI 환경에서 바로 GPT 기반 코드 생성/수정 가능&lt;/li&gt;
&lt;li&gt;자연어로 명령 입력하면 코드 생성 및 수정 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;&amp;gt; create a python script that reads wav files and prints duration
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 재인증 (로그인 문제 발생 시)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가끔 인증이 꼬일 수 있는데, 이럴 때는 아래처럼 초기화하면 된다.&lt;/p&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# 인증 정보 삭제
rm ~/.codex/auth.json

# 다시 실행 (재로그인)
codex
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 CLI 내부에서:&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;/logout
/login
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 업데이트 (선택)&lt;/h2&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;npm update -g @openai/codex
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;✅ 정리&lt;/h2&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;npm install -g @openai/codex

codex  # 최초 실행 &amp;rarr; 인증

(문제 발생 시)
rm ~/.codex/auth.json
codex

# 또는
/logout
/login
&lt;/code&gt;&lt;/pre&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;팀으로 쓰던 클로드코드가 만료되서 임시로 쓰는 Codex&lt;/p&gt;</description>
      <category>코딩에이전트</category>
      <author>하리우라</author>
      <guid isPermaLink="true">https://hariura.tistory.com/9</guid>
      <comments>https://hariura.tistory.com/9#entry9comment</comments>
      <pubDate>Tue, 31 Mar 2026 17:49:22 +0900</pubDate>
    </item>
    <item>
      <title>PTQ와 QDQ</title>
      <link>https://hariura.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;#&amp;nbsp;TFLite&amp;nbsp;INT8&amp;nbsp;양자화:&amp;nbsp;우리가&amp;nbsp;사용한&amp;nbsp;PTQ와&amp;nbsp;QDQ의&amp;nbsp;차이 &lt;br /&gt;&lt;br /&gt;PyTorch&amp;nbsp;모델을&amp;nbsp;Edge&amp;nbsp;TPU용&amp;nbsp;INT8&amp;nbsp;TFLite로&amp;nbsp;변환하면서,&amp;nbsp;양자화&amp;nbsp;방식에&amp;nbsp;대해&amp;nbsp;정리한다. &lt;br /&gt;우리가&amp;nbsp;사용한&amp;nbsp;방식은&amp;nbsp;**TFLite&amp;nbsp;Native&amp;nbsp;PTQ**이며,&amp;nbsp;흔히&amp;nbsp;말하는&amp;nbsp;**QDQ&amp;nbsp;방식과는&amp;nbsp;다르다**. &lt;br /&gt;&lt;br /&gt;--- &lt;br /&gt;&lt;br /&gt;##&amp;nbsp;우리가&amp;nbsp;한&amp;nbsp;것 &lt;br /&gt;&lt;br /&gt;``` &lt;br /&gt;FP32&amp;nbsp;ONNX&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;▼&amp;nbsp;&amp;nbsp;onnx2tf &lt;br /&gt;FP32&amp;nbsp;SavedModel &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;▼&amp;nbsp;&amp;nbsp;TFLiteConverter&amp;nbsp;+&amp;nbsp;calibration&amp;nbsp;데이터 &lt;br /&gt;Full&amp;nbsp;INT8&amp;nbsp;TFLite &lt;br /&gt;``` &lt;br /&gt;&lt;br /&gt;핵심은,&amp;nbsp;**ONNX&amp;nbsp;그래프에는&amp;nbsp;양자화&amp;nbsp;관련&amp;nbsp;노드가&amp;nbsp;전혀&amp;nbsp;없다**는&amp;nbsp;것이다. &lt;br /&gt;ONNX는&amp;nbsp;순수&amp;nbsp;FP32&amp;nbsp;그래프로서&amp;nbsp;모델&amp;nbsp;구조를&amp;nbsp;전달하는&amp;nbsp;역할만&amp;nbsp;하고, &lt;br /&gt;양자화는&amp;nbsp;마지막&amp;nbsp;단계에서&amp;nbsp;`TFLiteConverter`가&amp;nbsp;전부&amp;nbsp;처리한다. &lt;br /&gt;&lt;br /&gt;```python &lt;br /&gt;converter&amp;nbsp;=&amp;nbsp;tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) &lt;br /&gt;converter.optimizations&amp;nbsp;=&amp;nbsp;[tf.lite.Optimize.DEFAULT] &lt;br /&gt;converter.representative_dataset&amp;nbsp;=&amp;nbsp;representative_dataset &lt;br /&gt;converter.target_spec.supported_ops&amp;nbsp;=&amp;nbsp;[tf.lite.OpsSet.TFLITE_BUILTINS_INT8] &lt;br /&gt;converter.inference_input_type&amp;nbsp;=&amp;nbsp;tf.int8 &lt;br /&gt;converter.inference_output_type&amp;nbsp;=&amp;nbsp;tf.int8 &lt;br /&gt;tflite_model&amp;nbsp;=&amp;nbsp;converter.convert() &lt;br /&gt;``` &lt;br /&gt;&lt;br /&gt;`representative_dataset`으로&amp;nbsp;calibration&amp;nbsp;데이터(학습&amp;nbsp;데이터&amp;nbsp;200개)를&amp;nbsp;넘기면, &lt;br /&gt;TFLiteConverter가&amp;nbsp;이&amp;nbsp;데이터를&amp;nbsp;FP32&amp;nbsp;그래프에&amp;nbsp;통과시키면서&amp;nbsp;각&amp;nbsp;레이어의 &lt;br /&gt;activation&amp;nbsp;범위(min/max)를&amp;nbsp;수집한다.&amp;nbsp;이&amp;nbsp;통계를&amp;nbsp;기반으로&amp;nbsp;레이어별 &lt;br /&gt;scale과&amp;nbsp;zero\_point를&amp;nbsp;계산하고,&amp;nbsp;최종적으로&amp;nbsp;INT8&amp;nbsp;TFLite를&amp;nbsp;생성한다. &lt;br /&gt;&lt;br /&gt;결과&amp;nbsp;TFLite&amp;nbsp;파일&amp;nbsp;안에는&amp;nbsp;Q/DQ&amp;nbsp;노드&amp;nbsp;같은&amp;nbsp;것이&amp;nbsp;없다. &lt;br /&gt;각&amp;nbsp;텐서의&amp;nbsp;양자화&amp;nbsp;파라미터는&amp;nbsp;**텐서&amp;nbsp;메타데이터**에&amp;nbsp;저장되고, &lt;br /&gt;연산&amp;nbsp;자체가&amp;nbsp;INT8로&amp;nbsp;실행된다. &lt;br /&gt;&lt;br /&gt;--- &lt;br /&gt;&lt;br /&gt;##&amp;nbsp;QDQ&amp;nbsp;방식은&amp;nbsp;어떻게&amp;nbsp;다른가 &lt;br /&gt;&lt;br /&gt;QDQ(Quantize-DeQuantize)는&amp;nbsp;**그래프&amp;nbsp;안에&amp;nbsp;양자화&amp;nbsp;노드를&amp;nbsp;명시적으로&amp;nbsp;삽입**하는&amp;nbsp;방식이다. &lt;br /&gt;`onnxruntime.quantization.quantize_static()`이&amp;nbsp;대표적인&amp;nbsp;도구다. &lt;br /&gt;&lt;br /&gt;``` &lt;br /&gt;[FP32&amp;nbsp;Weight]&amp;nbsp;&amp;rarr;&amp;nbsp;QuantizeLinear&amp;nbsp;&amp;rarr;&amp;nbsp;DequantizeLinear&amp;nbsp;&amp;rarr;&amp;nbsp;Conv2D&amp;nbsp;&amp;rarr;&amp;nbsp;Q&amp;nbsp;&amp;rarr;&amp;nbsp;DQ&amp;nbsp;&amp;rarr;&amp;nbsp;ReLU&amp;nbsp;&amp;rarr;&amp;nbsp;Q&amp;nbsp;&amp;rarr;&amp;nbsp;DQ&amp;nbsp;&amp;rarr;&amp;nbsp;... &lt;br /&gt;``` &lt;br /&gt;&lt;br /&gt;calibration&amp;nbsp;과정은&amp;nbsp;비슷하다.&amp;nbsp;데이터를&amp;nbsp;흘려서&amp;nbsp;activation&amp;nbsp;범위를&amp;nbsp;수집하고 &lt;br /&gt;scale/zero\_point를&amp;nbsp;계산한다.&amp;nbsp;다만&amp;nbsp;그&amp;nbsp;결과를&amp;nbsp;**그래프&amp;nbsp;노드로&amp;nbsp;삽입**한다는&amp;nbsp;점이&amp;nbsp;다르다. &lt;br /&gt;&lt;br /&gt;QDQ&amp;nbsp;그래프는&amp;nbsp;여전히&amp;nbsp;FP32로&amp;nbsp;실행된다.&amp;nbsp;Q&amp;rarr;DQ&amp;nbsp;쌍이&amp;nbsp;실제&amp;nbsp;양자화&amp;nbsp;효과를&amp;nbsp;시뮬레이션할&amp;nbsp;뿐이다. &lt;br /&gt;이&amp;nbsp;그래프를&amp;nbsp;TFLite나&amp;nbsp;TensorRT&amp;nbsp;같은&amp;nbsp;런타임에&amp;nbsp;넘기면,&amp;nbsp;런타임이&amp;nbsp;Q/DQ&amp;nbsp;노드를&amp;nbsp;읽어서 &lt;br /&gt;해당&amp;nbsp;레이어를&amp;nbsp;INT8로&amp;nbsp;실행할지&amp;nbsp;결정한다. &lt;br /&gt;&lt;br /&gt;--- &lt;br /&gt;&lt;br /&gt;##&amp;nbsp;비교 &lt;br /&gt;&lt;br /&gt;|&amp;nbsp;|&amp;nbsp;QDQ&amp;nbsp;|&amp;nbsp;TFLite&amp;nbsp;Native&amp;nbsp;PTQ&amp;nbsp;(우리&amp;nbsp;방식)&amp;nbsp;| &lt;br /&gt;|---|---|---| &lt;br /&gt;|&amp;nbsp;양자화&amp;nbsp;정보&amp;nbsp;위치&amp;nbsp;|&amp;nbsp;ONNX&amp;nbsp;그래프&amp;nbsp;안&amp;nbsp;(Q/DQ&amp;nbsp;노드)&amp;nbsp;|&amp;nbsp;TFLite&amp;nbsp;텐서&amp;nbsp;메타데이터&amp;nbsp;| &lt;br /&gt;|&amp;nbsp;양자화&amp;nbsp;시점&amp;nbsp;|&amp;nbsp;ONNX&amp;nbsp;단계에서&amp;nbsp;|&amp;nbsp;TFLiteConverter&amp;nbsp;단계에서&amp;nbsp;| &lt;br /&gt;|&amp;nbsp;calibration&amp;nbsp;실행&amp;nbsp;|&amp;nbsp;onnxruntime&amp;nbsp;|&amp;nbsp;TensorFlow&amp;nbsp;| &lt;br /&gt;|&amp;nbsp;ONNX&amp;nbsp;그래프&amp;nbsp;상태&amp;nbsp;|&amp;nbsp;Q/DQ&amp;nbsp;노드&amp;nbsp;포함&amp;nbsp;|&amp;nbsp;순수&amp;nbsp;FP32&amp;nbsp;| &lt;br /&gt;|&amp;nbsp;실행&amp;nbsp;방식&amp;nbsp;|&amp;nbsp;FP32&amp;nbsp;+&amp;nbsp;양자화&amp;nbsp;시뮬레이션&amp;nbsp;|&amp;nbsp;진짜&amp;nbsp;INT8&amp;nbsp;연산&amp;nbsp;| &lt;br /&gt;|&amp;nbsp;양자화&amp;nbsp;결정&amp;nbsp;주체&amp;nbsp;|&amp;nbsp;변환&amp;nbsp;도구&amp;nbsp;(onnxruntime)&amp;nbsp;|&amp;nbsp;런타임&amp;nbsp;(TFLiteConverter)&amp;nbsp;| &lt;br /&gt;&lt;br /&gt;--- &lt;br /&gt;&lt;br /&gt;##&amp;nbsp;왜&amp;nbsp;PTQ를&amp;nbsp;선택했는가 &lt;br /&gt;&lt;br /&gt;1.&amp;nbsp;**타겟이&amp;nbsp;TFLite이다.**&amp;nbsp;TFLiteConverter가&amp;nbsp;직접&amp;nbsp;양자화하면&amp;nbsp;Edge&amp;nbsp;TPU가&amp;nbsp;지원하는 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;op&amp;nbsp;set에&amp;nbsp;정확히&amp;nbsp;맞는&amp;nbsp;INT8&amp;nbsp;모델이&amp;nbsp;나온다.&amp;nbsp;QDQ를&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;있다. &lt;br /&gt;&lt;br /&gt;2.&amp;nbsp;**ONNX는&amp;nbsp;전달&amp;nbsp;역할만&amp;nbsp;하면&amp;nbsp;된다.**&amp;nbsp;우리&amp;nbsp;파이프라인에서&amp;nbsp;ONNX는 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;PyTorch&amp;nbsp;&amp;rarr;&amp;nbsp;TensorFlow&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;&lt;br /&gt;3.&amp;nbsp;**디버깅이&amp;nbsp;단순하다.**&amp;nbsp;문제가&amp;nbsp;생겼을&amp;nbsp;때&amp;nbsp;&quot;ONNX&amp;nbsp;그래프가&amp;nbsp;맞는가&quot;와 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;양자화가&amp;nbsp;맞는가&quot;를&amp;nbsp;분리해서&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있다.&amp;nbsp;QDQ&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;어렵다. &lt;br /&gt;&lt;br /&gt;--- &lt;br /&gt;&lt;br /&gt;##&amp;nbsp;QDQ를&amp;nbsp;써야&amp;nbsp;하는&amp;nbsp;경우는 &lt;br /&gt;&lt;br /&gt;-&amp;nbsp;**NVIDIA&amp;nbsp;TensorRT**가&amp;nbsp;타겟일&amp;nbsp;때.&amp;nbsp;TensorRT는&amp;nbsp;QDQ&amp;nbsp;ONNX를&amp;nbsp;네이티브로&amp;nbsp;지원하고, &lt;br /&gt;&amp;nbsp;&amp;nbsp;Q/DQ&amp;nbsp;노드를&amp;nbsp;보고&amp;nbsp;어떤&amp;nbsp;레이어를&amp;nbsp;INT8로&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;FP16으로, &lt;br /&gt;&amp;nbsp;&amp;nbsp;나머지는&amp;nbsp;INT8로&amp;nbsp;하는&amp;nbsp;mixed-precision이&amp;nbsp;필요하면&amp;nbsp;QDQ가&amp;nbsp;적합하다. &lt;br /&gt;-&amp;nbsp;**QAT(Quantization-Aware&amp;nbsp;Training)**를&amp;nbsp;했을&amp;nbsp;때.&amp;nbsp;QAT는&amp;nbsp;학습&amp;nbsp;중에 &lt;br /&gt;&amp;nbsp;&amp;nbsp;Q/DQ&amp;nbsp;노드를&amp;nbsp;삽입해서&amp;nbsp;양자화&amp;nbsp;효과를&amp;nbsp;시뮬레이션하는데,&amp;nbsp;그&amp;nbsp;결과&amp;nbsp;자체가 &lt;br /&gt;&amp;nbsp;&amp;nbsp;QDQ&amp;nbsp;그래프다. &lt;br /&gt;&lt;br /&gt;우리처럼&amp;nbsp;**PyTorch&amp;nbsp;&amp;rarr;&amp;nbsp;TFLite&amp;nbsp;(Edge&amp;nbsp;TPU)**&amp;nbsp;경로에서는, &lt;br /&gt;ONNX를&amp;nbsp;FP32로&amp;nbsp;깨끗하게&amp;nbsp;유지하고&amp;nbsp;TFLiteConverter에게&amp;nbsp;양자화를&amp;nbsp;맡기는&amp;nbsp;것이 &lt;br /&gt;가장&amp;nbsp;단순하고&amp;nbsp;안정적인&amp;nbsp;선택이었다. &lt;/p&gt;</description>
      <category>경량화</category>
      <author>하리우라</author>
      <guid isPermaLink="true">https://hariura.tistory.com/8</guid>
      <comments>https://hariura.tistory.com/8#entry8comment</comments>
      <pubDate>Tue, 3 Mar 2026 16:11:23 +0900</pubDate>
    </item>
    <item>
      <title>핸즈온 LLM</title>
      <link>https://hariura.tistory.com/6</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;본인은 비전 AI를 공부했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM이라는 명칭이 있기 전에 자연어를 공부했기에 최신 LLM 내용을 공부하기 위해 이 블로그를 통해 글을 작성하고자 한다&lt;/p&gt;</description>
      <category>LLM</category>
      <author>하리우라</author>
      <guid isPermaLink="true">https://hariura.tistory.com/6</guid>
      <comments>https://hariura.tistory.com/6#entry6comment</comments>
      <pubDate>Thu, 27 Nov 2025 17:44:50 +0900</pubDate>
    </item>
    <item>
      <title>Claude code 설치 방법</title>
      <link>https://hariura.tistory.com/5</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  도커 컨테이너 안에서 nvm + Node.js 설치 순서&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. nvm 설치&lt;/h3&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# 컨테이너 안에서 실행
apt-get update &amp;amp;&amp;amp; apt-get install -y curl

# nvm 설치
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# nvm 로드 (bash 환경)
export NVM_DIR=&quot;$HOME/.nvm&quot;
[ -s &quot;$NVM_DIR/nvm.sh&quot; ] &amp;amp;&amp;amp; \. &quot;$NVM_DIR/nvm.sh&quot;
[ -s &quot;$NVM_DIR/bash_completion&quot; ] &amp;amp;&amp;amp; \. &quot;$NVM_DIR/bash_completion&quot;

# 설치 확인
nvm --version
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Node.js 설치&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# Node.js LTS 설치 (예: 18 버전)
nvm install 18
nvm use 18
nvm alias default 18

# 확인
node -v
npm -v
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. npm 최신화&lt;/h3&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;npm install -g npm
npm -v
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ 정리&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;apt-get update &amp;amp;&amp;amp; apt-get install -y curl&lt;/li&gt;
&lt;li&gt;nvm 설치 &amp;rarr; .nvm 경로 export &amp;rarr; nvm --version 확인&lt;/li&gt;
&lt;li&gt;nvm install 18 &amp;rarr; node -v, npm -v 확인&lt;/li&gt;
&lt;li&gt;npm install -g npm 최신화&lt;/li&gt;
&lt;li&gt;npm install &amp;amp;&amp;amp; npm run start&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. Claude code 설치&amp;nbsp;&lt;/h3&gt;
&lt;pre id=&quot;code_1758617397307&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install -g @anthropic-ai/claude-code&lt;/code&gt;&lt;/pre&gt;</description>
      <category>코딩에이전트</category>
      <author>하리우라</author>
      <guid isPermaLink="true">https://hariura.tistory.com/5</guid>
      <comments>https://hariura.tistory.com/5#entry5comment</comments>
      <pubDate>Tue, 23 Sep 2025 17:50:07 +0900</pubDate>
    </item>
    <item>
      <title>복소 스펙트럼, 스펙트럼 그래프, 스펙트로그램 완벽 정리</title>
      <link>https://hariura.tistory.com/4</link>
      <description>&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오디오 신호 처리에서 자주 헷갈리는 용어들을 한 번에 정리했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 복소 스펙트럼(Complex Spectrum)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정의&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FFT(STFT)를 돌리면 각 주파수 빈 k마다 나오는 &lt;b&gt;복소수 값&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;inform7&quot;&gt;&lt;code&gt;X[k] = Re{X[k]} + j&amp;middot;Im{X[k]}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;실수부(Real)&lt;/b&gt;: Re{X[k]}&lt;/li&gt;
&lt;li&gt;&lt;b&gt;허수부(Imag)&lt;/b&gt;: Im{X[k]}&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;복소 스펙트럼이 담고 있는 정보&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;크기(Magnitude)&lt;/b&gt;: |X[k]| = &amp;radic;(Re{X[k]}&amp;sup2; + Im{X[k]}&amp;sup2;)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;위상(Phase)&lt;/b&gt;: &amp;ang;X[k] = arctan(Im{X[k]}/Re{X[k]})&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  STFT 결과 전체를 '복소 스펙트럼'이라고 부르며, &lt;b&gt;크기와 위상 정보를 모두&lt;/b&gt; 담고 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. (진폭) 스펙트럼 그래프(Magnitude Spectrum Plot)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정의&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복소 스펙트럼에서 &lt;b&gt;크기(|X[k]|)만&lt;/b&gt; 뽑아서 시각화한 것&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;만드는 과정&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;크기 정보만 추출: |X[k]|&lt;/li&gt;
&lt;li&gt;dB 단위로 변환: 20&amp;middot;log₁₀(|X[k]|)&lt;/li&gt;
&lt;li&gt;그래프로 표현:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;X축&lt;/b&gt;: 주파수 (로그 스케일)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Y축&lt;/b&gt;: 진폭(dB)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;피크 위치&lt;/b&gt;: 해당 주파수에 에너지가 많다 &amp;rarr; 악기의 기본음&amp;middot;고조파&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로그 주파수 축&lt;/b&gt;: 저역부터 고역까지 고르게 보이도록&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &quot;스펙트럼 그래프&quot;는 복소 스펙트럼의 &lt;b&gt;크기 정보만&lt;/b&gt; 골라서 사람이 보기 편하게 시각화한 것&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 복소 스펙트럼 vs 스펙트럼 그래프 한눈에 비교&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구분 복소 스펙트럼 스펙트럼 그래프&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;값의 형태&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;복소수 (Real + j&amp;middot;Imag)&lt;/td&gt;
&lt;td&gt;실수 (크기 또는 dB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;표현 정보&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;크기 + 위상&lt;/td&gt;
&lt;td&gt;크기만 (보통 dB 스케일)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;축 설정&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;빈(bin) 인덱스 or 주파수(선형)&lt;/td&gt;
&lt;td&gt;주파수(로그/선형)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;용도&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;신호 합성&amp;middot;재구성&amp;lt;br&amp;gt;(위상 정보 필요)&lt;/td&gt;
&lt;td&gt;주파수 성분 분석&amp;middot;특징 추출&amp;lt;br&amp;gt;(크기 정보만으로 충분)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 정리&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&quot;복소 스펙트럼&quot;&lt;/b&gt; = 이론&amp;middot;연산 결과 그 자체(크기+위상)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&quot;스펙트럼 그래프&quot;&lt;/b&gt; = 크기만 골라서 dB로 변환해 시각화한 것&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 스펙트럼 vs 스펙트로그램&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 개념&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;스펙트럼(한 프레임)&lt;/b&gt;: 한 순간에서 FFT 수행한 결과
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;크기: |X[k]|&lt;/li&gt;
&lt;li&gt;위상: &amp;ang;X[k]&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스펙트로그램(시간-주파수 행렬)&lt;/b&gt;: 여러 프레임의 스펙트럼을 시간축으로 쌓은 2D 행렬
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;n: 프레임 인덱스(시간)&lt;/li&gt;
&lt;li&gt;k: 주파수 빈&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;S[n,k] = |X[n,k]|&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&quot;크기 값을 쌓는다&quot;의 의미&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;❌ 히스토그램처럼 값을 누적(sum)하는 것이 &lt;b&gt;아님&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;⭕ 각 프레임의 스펙트럼 벡터를 &lt;b&gt;시간 차원으로 배열&lt;/b&gt;하는 것
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;멜 스펙트로그램: |X[n,k]| 사용&lt;/li&gt;
&lt;li&gt;파워 스펙트로그램: |X[n,k]|&amp;sup2; 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 스펙트로그램의 위상 정보&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일반 스펙트로그램(이미지)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;위상 정보가 들어가지 않습니다&lt;/b&gt; ❌&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이유: 시각화&amp;middot;머신러닝 입력용으로는 크기(또는 로그 크기)만 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;복소 스펙트로그램&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;STFT 결과물 자체에는 위상이 남아있음 ⭕&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역변환(ifft)&lt;/b&gt; 등 재구성 작업 시 위상 정보 필수&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부가 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;위상 스펙트로그램&lt;/b&gt;: &amp;ang;X[n,k]만 시각화 (잘 안 씀)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;복소 스펙트로그램&lt;/b&gt;: 크기+위상 모두 저장, 신호 재합성용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  최종 요약&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;복소 스펙트럼&lt;/b&gt;: FFT 결과 그 자체 (크기+위상)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스펙트럼 그래프&lt;/b&gt;: 크기만 뽑아서 dB로 시각화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스펙트로그램&lt;/b&gt;: 시간축으로 쌓은 크기 스펙트럼&lt;/li&gt;
&lt;li&gt;&lt;b&gt;일반 스펙트로그램 이미지에는 위상 정보 없음&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  기억하기: 스펙트로그램은 &quot;시간축으로 쌓은 크기 스펙트럼&quot;이고, 위상 정보는 일반 스펙트로그램 이미지에 포함되지 않는다!&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>오디오</category>
      <author>하리우라</author>
      <guid isPermaLink="true">https://hariura.tistory.com/4</guid>
      <comments>https://hariura.tistory.com/4#entry4comment</comments>
      <pubDate>Thu, 7 Aug 2025 16:31:53 +0900</pubDate>
    </item>
    <item>
      <title>주파수 해상도와 빈(bin)</title>
      <link>https://hariura.tistory.com/3</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;주파수 해상도와 빈(bin) 개념을 좀 더 쉬운 말로 풀어서 설명해 볼게요.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 빈(bin)이란 무엇인가?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;STFT를 하면 시간 축마다 &lt;b&gt;연속적인 소리 신호&lt;/b&gt;를 잘라서 FFT(푸리에 변환)를 적용해 &lt;b&gt;주파수 성분의 세기&lt;/b&gt;를 계산합니다.&lt;/li&gt;
&lt;li&gt;이때 FFT가 반환하는 값 하나하나를 우리는 &amp;ldquo;빈(bin)&amp;rdquo;이라고 부릅니다.&lt;/li&gt;
&lt;li&gt;각 빈은 &amp;ldquo;이 구간 주파수 대역(Hz) 안에 얼마나 에너지가 모여 있는가&amp;rdquo;를 나타내는 &lt;b&gt;막대(bar)&lt;/b&gt; 하나라고 생각하면 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;예: bin[0] &amp;rarr; 0&amp;ndash;31.25Hz
    bin[1] &amp;rarr; 31.25&amp;ndash;62.5Hz
    &amp;hellip;
    bin[512] &amp;rarr; 15968.75&amp;ndash;16000Hz&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 빈 개수 (bins) 계산&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우리가 n_fft = 1024로 설정했다면,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복소수 FFT 결과로는 1024개의 값이 나오지만,&lt;/li&gt;
&lt;li&gt;실수(real) 신호를 대칭성 때문에 절반만(＋0~＋Nyquist) 쓴다면,&lt;/li&gt;
&lt;li&gt;**1024/2 + 1 = 513**개의 빈(bin)이 생깁니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결론:&lt;/b&gt; STFT 한 프레임마다 513개의 주파수 &amp;ldquo;막대&amp;rdquo;가 생겨요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 주파수 해상도(frequency resolution)란?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;**&amp;ldquo;하나의 bin이 나타내는 주파수 폭&amp;rdquo;**입니다.&lt;/li&gt;
&lt;li&gt;계산식은 매우 간단해요:&amp;Delta;f=샘플링 레이트(sr)n_fft \Delta f = \frac{\text{샘플링 레이트}(sr)}{n\_fft}예를 들어&amp;Delta;f=32000 Hz1024&amp;asymp;31.25 Hz \Delta f = \frac{32000\text{ Hz}}{1024} \approx 31.25\text{ Hz}&lt;/li&gt;
&lt;li&gt;즉, &lt;b&gt;각 bin은 약 31.25 Hz&lt;/b&gt; 폭을 담당합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;bin 0 &amp;rarr; 0~31.25 Hz
bin 1 &amp;rarr; 31.25~62.5 Hz
bin 2 &amp;rarr; 62.5~93.75 Hz
&amp;hellip;&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 왜 이것이 중요할까?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;시간 해상도 vs. 주파수 해상도&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;n_fft를 크게 하면 &amp;rarr; &amp;Delta;f가 작아져(더 촘촘히, 예: 10 Hz/bin) &amp;rarr; 주파수 해상도 &amp;uarr;&lt;/li&gt;
&lt;li&gt;하지만 n_fft가 커지면 &amp;rarr; 윈도우 길이(시간 길이)도 길어져 &amp;rarr; 시간 해상도 &amp;darr;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;빈 개수&lt;/b&gt; (=513) 만큼 그래프의 세로(주파수) 축이 촘촘해져서,
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;음성에서 낮은 주파수 대역(목소리의 포먼트)과 높은 대역(해머링, 잡음)을&lt;/li&gt;
&lt;li&gt;구분해서 볼 수 있게 해 줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;빈(bin)&lt;/b&gt;: FFT 결과의 각 주파수 구간 하나하나(막대)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;빈 개수&lt;/b&gt;: n_fft/2+1 &amp;rarr; 1024/2+1 = &lt;b&gt;513개&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주파수 해상도 &amp;Delta;f&lt;/b&gt;: sr / n_fft &amp;rarr; 32000/1024 &amp;asymp; &lt;b&gt;31.25 Hz/bin&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;빈[k]는&amp;nbsp;주파수&amp;nbsp;구간&amp;nbsp;[k&amp;nbsp;*&amp;nbsp;&amp;Delta;f,&amp;nbsp;(k&amp;nbsp;+&amp;nbsp;1)&amp;nbsp;*&amp;nbsp;&amp;Delta;f]를&amp;nbsp;의미합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;빈&amp;rdquo;과 &amp;ldquo;해상도&amp;rdquo; 개념을 이해하면,&lt;br /&gt;STFT나 멜 스펙트로그램이&lt;br /&gt;왜 특정 대역에서 에너지가 높거나 낮은지를&lt;br /&gt;해석하는 데 큰 도움이 돼요.&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>오디오</category>
      <author>하리우라</author>
      <guid isPermaLink="true">https://hariura.tistory.com/3</guid>
      <comments>https://hariura.tistory.com/3#entry3comment</comments>
      <pubDate>Fri, 18 Jul 2025 16:07:03 +0900</pubDate>
    </item>
    <item>
      <title>오디오 데이터 증강 : SpecAugment</title>
      <link>https://hariura.tistory.com/2</link>
      <description>&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;100&quot; data-start=&quot;0&quot;&gt;본 글에서는 SpecAugment 데이터 증강 기법의 세 가지 주요 단계인 Time Warping, Frequency Masking, Time Masking을 소개했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;811&quot; data-origin-height=&quot;607&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKkzHh/btsPnwn3hzs/A8g6BmB66ivg2BC5Dg4J61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKkzHh/btsPnwn3hzs/A8g6BmB66ivg2BC5Dg4J61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKkzHh/btsPnwn3hzs/A8g6BmB66ivg2BC5Dg4J61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKkzHh%2FbtsPnwn3hzs%2FA8g6BmB66ivg2BC5Dg4J61%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;486&quot; height=&quot;364&quot; data-origin-width=&quot;811&quot; data-origin-height=&quot;607&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;366&quot; data-start=&quot;101&quot;&gt;&lt;b&gt;Time Warping&lt;/b&gt;은 TensorFlow의 sparse_image_warp 함수를 활용하여 log-mel-spectrogram을 왜곡하는 방법입니다. 가로축을 시간축(&amp;tau;), 세로축을 주파수축(&amp;nu;)으로 간주하고, 중앙 수평선 상의 임의 지점 x&amp;isin;[W, &amp;tau;&amp;minus;W]를 선택하여 좌우로 w만큼 이동시켰습니다. 여기서 w는 [0, W] 균등분포에서 샘플링하였고, 이미지 경계의 네 모서리와 양쪽 세로 중간점 총 6개의 앵커 포인트를 고정하여 안정적인 왜곡을 수행했습니다.&lt;/li&gt;
&lt;li data-end=&quot;545&quot; data-start=&quot;367&quot;&gt;&lt;b&gt;Frequency Masking&lt;/b&gt;은 mel 주파수 채널 &amp;nu; 중 연속된 f개의 채널 [f₀, f₀+f)를 0으로 마스킹하는 방법입니다. f는 [0, F] 균등분포에서, 시작 위치 f₀는 [0, &amp;nu;&amp;minus;f) 범위에서 랜덤하게 선택했습니다. 이를 통해 모델이 특정 주파수 대역 결손에도 견고하게 학습될 수 있도록 했습니다.&lt;/li&gt;
&lt;li data-end=&quot;732&quot; data-start=&quot;546&quot;&gt;&lt;b&gt;Time Masking&lt;/b&gt;은 &amp;tau;개의 시간 단계 중 연속된 t개의 구간 [t₀, t₀+t)를 0으로 마스킹하는 방법입니다. t는 [0, T] 균등분포에서, 시작 위치 t₀는 [0, &amp;tau;&amp;minus;t) 범위에서 랜덤하게 선정했습니다. 추가로 마스킹 폭이 전체 시간의 p배를 초과하지 않도록 상한을 설정하여 과도한 시간 정보 손실을 방지했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yhh7Q/btsPpWAbVWw/36dr71k51fRyM5LVfmZw80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yhh7Q/btsPpWAbVWw/36dr71k51fRyM5LVfmZw80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yhh7Q/btsPpWAbVWw/36dr71k51fRyM5LVfmZw80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyhh7Q%2FbtsPpWAbVWw%2F36dr71k51fRyM5LVfmZw80%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;341&quot; height=&quot;156&quot; data-origin-width=&quot;465&quot; data-origin-height=&quot;213&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-is-last-node=&quot;&quot; data-end=&quot;859&quot; data-start=&quot;733&quot;&gt;T: time step, F : 멜 스펙트로그램의 채널(멜 필터뱅크 채널) 개수 기준 분포 파라메터&lt;/li&gt;
&lt;li data-is-last-node=&quot;&quot; data-end=&quot;859&quot; data-start=&quot;733&quot;&gt;위 세 가지 증강 기법을 결합함으로써 음성 인식 모델이 다양한 시간-주파수 왜곡 및 결측 상황에도 강인하게 일반화될 수 있도록 했습니다. SpecAugment는 여러 연구에서 인식 성능 향상에 기여한다고 보고되었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>오디오</category>
      <author>하리우라</author>
      <guid isPermaLink="true">https://hariura.tistory.com/2</guid>
      <comments>https://hariura.tistory.com/2#entry2comment</comments>
      <pubDate>Thu, 17 Jul 2025 15:15:53 +0900</pubDate>
    </item>
  </channel>
</rss>