<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Errors make me stronger</title>
        <link>https://velog.io/</link>
        <description>기술(technology)을 기술(discription)하자.</description>
        <lastBuildDate>Mon, 15 Jul 2024 04:10:29 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Errors make me stronger</title>
            <url>https://images.velog.io/images/lumi_hunter/profile/010fcf73-a92e-47e0-8210-a6b6d1bf7747/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Errors make me stronger. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/lumi_hunter" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[알고리즘 2: 조합 & 순열]]></title>
            <link>https://velog.io/@lumi_hunter/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-2-%EC%A1%B0%ED%95%A9-%EC%88%9C%EC%97%B4</link>
            <guid>https://velog.io/@lumi_hunter/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-2-%EC%A1%B0%ED%95%A9-%EC%88%9C%EC%97%B4</guid>
            <pubDate>Mon, 15 Jul 2024 04:10:29 GMT</pubDate>
            <description><![CDATA[<h2 id="조합combination">조합(Combination)</h2>
<blockquote>
<p>조합은 n개의 index 중 0<del>n, 1</del>n, 2~n ... 순으로 append 하며, 고른 요소의 수(level)가 r에 도달하면 return하는 방식</p>
</blockquote>
<pre><code>example: 5C3

[1,]                                                               
    [1,2,]
        [1,2,3], [1,2,4], [1,2,5] 
    [1,3,]
        [1,3,4], [1,3,5]
    [1,4,]
        [1,4,5]
[2,]
    [2,3,]
        [2,3,4], [2,3,5]
    [2,4,]
        [2,4,5]
[3,]
    [3,4,]
        [3,4,5]
</code></pre><p>-&gt; <strong>index의 시작점을 1씩 늘리는 재귀적 구조</strong>로 구현 가능. </p>
<pre><code># lst의 요소를 nCr
N = 5
R = 3
choose = []
lst = [1,2,3,4,5]

def combination(index, level):
    global N, R, choose, lst
    if level == R:
        print(choose)
        return
    for i in range(index, N):
        choose.append(lst[i])
        combination(i+1, level+1)
        choose.pop()

combination(0,0)</code></pre><h2 id="순열permutation">순열(Permutation)</h2>
<blockquote>
<p>순열의 경우 <code>순서가 있다</code>는 특성에 의해, index를 매번 0~n 순으로 append 하며 고른 요소의 수(level)가 r에 도달하면 return. 단, <code>중복을 피하기</code> 위한 check 리스트가 필요하다.</p>
</blockquote>
<pre><code>example: 5P3

[1,]                                                               
    [1,2,]
        [1,2,3], [1,2,4], [1,2,5] 
    [1,3,]
        [1,3,2], [1,3,4], [1,3,5]
    [1,4,]
        [1,4,2], [1,4,3], [1,4,5]
    [1,5,]
        [1,5,2], [1,5,3], [1,5,4]
[2,]
    [2,1,]
        [2,1,3], [2,1,4], [2,1,5]
    [2,3,]
        [2,3,1], [2,3,4], [2,3,5]
    [2,4,]
        [2,4,1], [2,4,3], [2,4,5]
    [2,5,]
        [2,5,1], [2,5,3], [2,5,4]
[3,]
    [3,1,]
        [3,1,2], [3,1,4], [3,1,5]
    [3,2,]
        [3,2,1], [3,2,4], [3,2,5]
    [3,4,]
        [3,4,1], [3,4,2], [3,4,5]
    [3,5,]
        [3,5,1], [3,5,2], [3,5,4]
[4,]
    [4,1,]
        [4,1,2], [4,1,3], [4,1,5]
    [4,2,]
        [4,2,1], [4,2,3], [4,2,5]
    [4,3,]
        [4,3,1], [4,3,2], [4,3,5]
    [4,5,]
        [4,5,1], [4,5,2], [4,5,3]
[5,]
    [5,1,]
        [5,1,2], [5,1,3], [5,1,4]
    [5,2,]
        [5,2,1], [5,2,3], [5,2,4]
    [5,3,]
        [5,3,1], [5,3,2], [5,3,4]
    [5,4,]
        [5,4,1], [5,4,2], [5,4,3]
</code></pre><pre><code># lst의 요소를 nPr
N = 5
R = 3
choose = []
check = [False] * N
lst = [1,2,3,4,5]

def permutation(level):    # 매 요소에서 0~N까지 
    global N, R, choose, lst
    if level == R:
        print(choose)
        return
    for i in range(N):
        if check[i] == True:    # 중복된 요소라면 append 하지 않음
            continue
        choose.append(lst[i])
        check[i] = True        # 중복 표기
        permutation(level+1)
        check[i] = False    # 중복 해제
        choose.pop()

permutation(0)</code></pre><h2 id="중복조합-중복순열">중복조합, 중복순열</h2>
<p>중복순열(nπr)의 경우 permutation 구현에서 중복요소 check만 빠지면 된다!</p>
<pre><code># lst의 요소를 nπr
N = 5
R = 3
choose = []
lst = [1,2,3,4,5]

def product(level):
    global N, R, choose, lst
    if level == R:
        print(choose)
        return
    for i in range(N):
        choose.append(lst[i])
        product(level+1)
        choose.pop()

permutation(0)</code></pre><p>중복조합 nHr = n+r-1Cr = n+r-1Cn-1 로 변경해서 푼다!
(고등수학 수준의 중복조합 설명: <a href="https://blog.naver.com/baboedition/220933436576">https://blog.naver.com/baboedition/220933436576</a>)</p>
<h4 id="로또"><a href="https://www.acmicpc.net/problem/6603">로또</a></h4>
<p>-&gt; r = 6인 전형적인 조합문제</p>
<pre><code>def comb(index, level):
    global choose, lst, k
    if level == 6:
        print(&#39; &#39;.join(choose))
        return
    for i in range(index, k):
        choose.append(lst[i])
        comb(i+1, level+1)
        choose.pop()

while True:
    case = input().split()
    if len(case) == 1:
        break
    k = int(case[0])
    choose = []
    lst = case[1:]
    comb(0,0)
    print()</code></pre><h4 id="암호-만들기"><a href="https://www.acmicpc.net/problem/1759">암호 만들기</a></h4>
<p>-&gt; <strong>조건이 주어진 조합 또는 순열의 문제는 조건부를 따로 함수로 구현해두는 것이 좋다.</strong>
-&gt; 조합 또는 순열을 만드는 알고리즘은 n개의 요소를 index 순으로 삽입하기 때문에, 문제에 &#39;사전 순으로 출력&#39; 등의 조건이 붙은 경우 반드시 <strong>처음부터 n개의 입력 요소를 정렬하고 시작하는 것이 좋다.</strong></p>
<pre><code>L, C = tuple(map(int,input().split()))
chars = sorted(input().split())
mo_chars = [&#39;a&#39;, &#39;e&#39;, &#39;i&#39;, &#39;o&#39;, &#39;u&#39;]
choose = []

def is_possible(choose:list):
    mo = 0
    for char in choose:
        if char in mo_chars:
            mo += 1
    ja = len(choose) - mo
    return (mo &gt;= 1 and ja &gt;= 2)

def com(index, level):
    global L, C, chars, choose
    if level == L:
        if is_possible(choose):
            print(&#39;&#39;.join(choose))
        else:
            pass
    for i in range(index, C):
        choose.append(chars[i])
        com(i+1, level+1)
        choose.pop()

com(0,0)</code></pre><p>(+) 틀린 풀이: 가능한 조합을 모두 만들어놓은 다음, 조건에 맞지 않는 조합을 삭제하는 방식
-&gt; <strong>list를 순회하면서 요소를 제거하면, 순회 도중 list의 indexing이 변경되면서 버그가 발생</strong>하므로 오답이 됨! 이러한 논리로 문제를 풀려면 조건에 맞는 것을 다른 list에 하나씩 추가하는 식으로 진행되어야 함.
-&gt; 문자열 각각을 오름차순으로, 문자열들끼리도 오름차순(사전순)으로 정렬하기 위해 <code>sorted()</code>를 두번 사용하는 것 보다는 초기 input부터 정렬시키는 것이 훨씬 효율적.</p>
<pre><code>from itertools import combinations

L, C = input().split()
chars = list(input().split())

mo = [&#39;a&#39;, &#39;e&#39;, &#39;i&#39;, &#39;o&#39;, &#39;u&#39;]

candidates = list(combinations(chars, int(L)))
for can in candidates:
    mo_num, ja_num = 0, 0
    for i in can:
        if i in mo:
            mo_num += 1
        else:
            ja_num += 1
    if mo_num &lt; 1 or ja_num &lt; 2:
        candidates.remove(can)    # candidates의 요소를 직접 삭제하면서 indexing에 문제가 발생함.
sol = []       
for ans in candidates:
    ans_str = &#39;&#39;
    for i in sorted(ans):
        ans_str += i
    sol.append(ans_str)

for i in sorted(sol):    # sorted를 두번 중복으로 사용 -&gt; 비효율
    print(i)</code></pre><p>-&gt; 수정된 풀이</p>
<pre><code>from itertools import combinations

L, C = map(int, input().split())
chars = input().split()

mo = {&#39;a&#39;, &#39;e&#39;, &#39;i&#39;, &#39;o&#39;, &#39;u&#39;}

candidates = list(combinations(sorted(chars), L))    # 초기값 chars를 처음부터 정렬
valid_candidates = []

for can in candidates:
    mo_num, ja_num = 0, 0
    for i in can:
        if i in mo:
            mo_num += 1
        else:
            ja_num += 1
    if mo_num &gt;= 1 and ja_num &gt;= 2:
        valid_candidates.append(&#39;&#39;.join(can))    
        # candidates의 요소를 삭제하는 것이 아니라 조건에 맞는 요소를 valid_candidates에 보관

for ans in valid_candidates:
    print(ans)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[알고리즘 1: 재귀함수]]></title>
            <link>https://velog.io/@lumi_hunter/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-1-%EC%9E%AC%EA%B7%80%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@lumi_hunter/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-1-%EC%9E%AC%EA%B7%80%ED%95%A8%EC%88%98</guid>
            <pubDate>Mon, 08 Jul 2024 12:07:28 GMT</pubDate>
            <description><![CDATA[<pre><code>def sum_func(n):
    # Base Case: 종료 부분
    if n = 1:
        return 1

    # Recursive Case: 자기 자신을 호출하는 부분
    return sum_func(n-1) + n</code></pre><p>Base Case와 Recursive Case가 함께 있지 않으면 재귀함수가 아니다. </p>
<p>단, 재귀함수는 함수 호출을 반복하면서 &#39;이미 구한 값을 또 구하면서&#39; 시간 복잡도가 증가할 수 있다.
그러므로 한번 구한 값은 저장해 불필요한 중복 계산을 피하는 것이 좋다. -&gt; <code>메모이제이션</code></p>
<blockquote>
<p>핵심: f(n)과 f(n-1)의 관계를 찾아 나타낼 수 있느냐!</p>
</blockquote>
<p>위의 sum_func(n) 함수는 f(n) = f(n-1) + n의 관계</p>
<h4 id="피보나치-함수"><a href="https://www.acmicpc.net/problem/10870">피보나치 함수</a></h4>
<p>-&gt; 가장 대표적인 재귀문제 &#39;피보나치 함수&#39;는 f(n) = f(n-1) + f(n-2)의 관계.</p>
<pre><code>n = int(input())

fibo_list = [-1] * (n + 2)    # list 공간은 미리 확보해두어야 함. (2개의 초기값이 있으므로 n+2개 공간 확보)
fibo_list[0] = 0
fibo_list[1] = 1    # 메모이제이션을 위해 각 결과를 list에 저장

def fibo(n):

    global fibo_list

    if fibo_list[n] != -1:
        return fibo_list[n]    # 이미 답을 한 번 구했다면 저장한 답을 return

    fibo_list[n] = fibo(n-1) + fibo(n-2)     # 구한 답은 list에 저장한 다음 return
    return fibo_list[n]

print(fibo(n))</code></pre><h4 id="칸토어-집합"><a href="https://www.acmicpc.net/problem/4779">칸토어 집합</a></h4>
<p>-&gt; 이 문제는 [문자열] f(n) = f(n-1) + &#39; &#39; * (3 ** (n-1)) + f(n-1)의 관계.</p>
<pre><code>def sol(n):
    if n == 0:
        return(&#39;-&#39;)
    return(sol(n-1) + &#39; &#39; * pow(3,(n-1)) + sol(n-1))

while True:
    try:
        N = int(input())
        print(sol(N))
    except:
        break</code></pre><p>(+) 다른 풀이</p>
<pre><code>ans = [&#39; &#39; for i in range(13)]    # 문제의 최대만큼 공간 확보
ans[0] = &#39;-&#39;

# 미리 만들어놓기 -&gt; ans[12]까지!
for i in range(12):
    ans[i+1] = ans[i] + (&#39; &#39; * (3 ** i)) + ans[i]

while True:
    try:
        N = int(input())
        print(ans[N])
    except:
        break</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[객체 인식 이론 정리(계속 추가)]]></title>
            <link>https://velog.io/@lumi_hunter/%EA%B0%9D%EC%B2%B4-%EC%9D%B8%EC%8B%9D-%EC%9D%B4%EB%A1%A0-%EC%A0%95%EB%A6%AC%EA%B3%84%EC%86%8D-%EC%B6%94%EA%B0%80</link>
            <guid>https://velog.io/@lumi_hunter/%EA%B0%9D%EC%B2%B4-%EC%9D%B8%EC%8B%9D-%EC%9D%B4%EB%A1%A0-%EC%A0%95%EB%A6%AC%EA%B3%84%EC%86%8D-%EC%B6%94%EA%B0%80</guid>
            <pubDate>Thu, 13 Jun 2024 00:50:12 GMT</pubDate>
            <description><![CDATA[<h2 id="지역-제안-기반region-proposal-based">지역 제안 기반(Region Proposal based)</h2>
<p>-&gt; Two-Stage Detectors</p>
<h2 id="회귀분류-기반regressionclassification-based">회귀/분류 기반(Regression/Classification based)</h2>
<p>-&gt; One-Stage Detectors</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[헷갈리는 용어 정리(계속 수정)]]></title>
            <link>https://velog.io/@lumi_hunter/%ED%97%B7%EA%B0%88%EB%A6%AC%EB%8A%94-%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC%EA%B3%84%EC%86%8D-%EC%88%98%EC%A0%95</link>
            <guid>https://velog.io/@lumi_hunter/%ED%97%B7%EA%B0%88%EB%A6%AC%EB%8A%94-%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC%EA%B3%84%EC%86%8D-%EC%88%98%EC%A0%95</guid>
            <pubDate>Sun, 02 Jun 2024 03:56:53 GMT</pubDate>
            <description><![CDATA[<h3 id="라우팅">라우팅</h3>
<p>: 클라이언트로부터의 HTTP 요청을 적절한 함수나 메소드로 연결하여 처리하는 프로세스</p>
<ul>
<li>라우트는 HTTP 요청 메서드(GET, POST, PUT, PATCH, DELETE)의 요청을 수락하고, 선택적으로 인수를 받을 수 있도록 정의된다.</li>
</ul>
<h4 id="waswab-application-server">WAS(Wab Application Server)</h4>
<p>: 클라이언트/서버 환경에서 트랜잭션 처리 및 관리와 애플리케이션 실행 환경을 제공하는 미들웨어 소프트 웨어 서버.</p>
<ul>
<li>웹 서버, 애플리케이션, 데이터베이스의 3계층 웹 컴퓨팅 환경으로 구축됨.</li>
<li>① 애플리케이션 실행 환경과 데이터베이스 접속 기능을 제공하고, ② 트랜잭션을 관리하며, ③ 업무를 처리하는 비즈니스 로직을 수행하고, ④ 다른 기종 시스템 간의 애플리케이션 연동 등을 수행한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Flask vs FastAPI]]></title>
            <link>https://velog.io/@lumi_hunter/FastAPI-%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95</link>
            <guid>https://velog.io/@lumi_hunter/FastAPI-%EC%A3%BC%EC%9A%94-%ED%8A%B9%EC%A7%95</guid>
            <pubDate>Wed, 15 May 2024 11:57:37 GMT</pubDate>
            <description><![CDATA[<ul>
<li>둘 모두 마이크로 프레임워크다: MSA(Micro Service Architecture) 기반.<ul>
<li>웹 서비스 개발 
1세대 정적 웹 페이지(HTML/CSS)
2세대 동적 웹 페이지(CGI/데이터베이스 활용) -&gt; PHP, JSP, ASP
3세대 MVC 프레임워크(Model, View, Controller)
: 모델-DB, 뷰-화면, 컨트롤러-기능 처리 세 가지 부분으로 코드를 나눔 -&gt; Spring, Django, NestJS
4세대 API 중심 서비스(MSA)
: 한 화면에도 여러 기능이 동시에 소화되므로, 각각의 다양한 기능을 주소로 접근해서 하나의 웹 페이지로 전달해주는 형태로, 안정성과 분산처리에 용이함 -&gt; FastAPI</li>
</ul>
</li>
<li>Flask가 동기 처리 기반인 반면 FastAPI는 비동기 처리 기반이다: 첫번째 요청이 다 끝나기 전에 두번째 요청을 시행하는 방식. (CPU가 &#39;노는 시간&#39;을 최소화 한다) -&gt; DB 쿼리, 서버 간 통신 등 I/O 작업이 많은 애플리케이션에서 유리</li>
<li>FastAPI는 API 작성 시 자동으로 문서 생성(Feat. Swagger)을 하고, Pydantic 데이터 유효성 검사를 내장하고 있어 편리함. -&gt; Flask에서는 써드파티 필요</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[AI 허브 데이터 YOLO format으로 변환 과정]]></title>
            <link>https://velog.io/@lumi_hunter/AI-%ED%97%88%EB%B8%8C-%EB%8D%B0%EC%9D%B4%ED%84%B0-YOLO-format%EC%9C%BC%EB%A1%9C-%EB%B3%80%ED%99%98-%EA%B3%BC%EC%A0%95</link>
            <guid>https://velog.io/@lumi_hunter/AI-%ED%97%88%EB%B8%8C-%EB%8D%B0%EC%9D%B4%ED%84%B0-YOLO-format%EC%9C%BC%EB%A1%9C-%EB%B3%80%ED%99%98-%EA%B3%BC%EC%A0%95</guid>
            <pubDate>Fri, 10 May 2024 07:20:21 GMT</pubDate>
            <description><![CDATA[<p>예시로 사용한 AI 허브 데이터: <a href="https://www.aihub.or.kr/aihubdata/data/view.do?currMenu=115&amp;topMenu=100&amp;aihubDataSe=data&amp;dataSetSn=140">생활 폐기물 이미지</a></p>
<h4 id="original-json-file예시">Original Json File(예시)</h4>
<p>15_X001_C011_1006_0.json</p>
<pre><code>{
  &quot;FILE NAME&quot;: &quot;15_X001_C011_1006_0.jpg&quot;,
  &quot;COLLECTION METHOD&quot;: &quot;제작자료&quot;,
  &quot;FORM&quot;: &quot;이미지&quot;,
  &quot;DATE&quot;: &quot;2020-10-06 14:40:02&quot;,
  &quot;GPS&quot;: &quot;37.5212093997222/126.715606899722&quot;,
  &quot;ID CODE&quot;: &quot;C011&quot;,
  &quot;RESOLUTION&quot;: &quot;1920*1440&quot;,
  &quot;focus distance&quot;: &quot;4.32mm&quot;,
  &quot;exposure time&quot;: &quot;1/278sec&quot;,
  &quot;Aperture values&quot;: &quot;2.52&quot;,
  &quot;Sensitivity iso&quot;: &quot;50&quot;,
  &quot;exposure method&quot;: &quot;normal program&quot;,
  &quot;MAKE&quot;: &quot;samsung&quot;,
  &quot;Camera Model Name&quot;: &quot;SM-G977N&quot;,
  &quot;Software&quot;: &quot;G977NKSU4CTG1&quot;,
  &quot;File Size&quot;: &quot;589983&quot;,
  &quot;DAY/NIGHT&quot;: &quot;주간&quot;,
  &quot;PLACE&quot;: &quot;실외&quot;,
  &quot;PROJECT SORTING&quot;: &quot;생활폐기물&quot;,
  &quot;BoundingCount&quot;: &quot;1&quot;,
  &quot;Bounding&quot;: [
    {
      &quot;CLASS&quot;: &quot;비닐류&quot;,
      &quot;DETAILS&quot;: &quot;과자봉지&quot;,
      &quot;DAMAGE&quot;: &quot;일부훼손&quot;,
      &quot;TRANSPARENCY&quot;: &quot;불투명&quot;,
      &quot;Color&quot;: &quot;176/137/113&quot;,
      &quot;Shape&quot;: &quot;평면형&quot;,
      &quot;Texture&quot;: &quot;부드러움&quot;,
      &quot;Object Size&quot;: &quot;소&quot;,
      &quot;Direction&quot;: &quot;원거리&quot;,
      &quot;Drawing&quot;: &quot;BOX&quot;,
      &quot;x1&quot;: &quot;540&quot;,
      &quot;y1&quot;: &quot;765&quot;,
      &quot;x2&quot;: &quot;827&quot;,
      &quot;y2&quot;: &quot;930&quot;
    }
  ]
}</code></pre><blockquote>
<ol>
<li>이 중 class와 bbox만을 필요로 하는 YOLO format에서는 사실상 나머지 정보는 필요가 없고, &quot;Bounding&quot; 안의 <strong>&quot;CLASS&quot;(혹은 &quot;DETAILS&quot;), &quot;x1&quot;, &quot;x2&quot;, &quot;y1&quot;, &quot;y2&quot;</strong>가 필요할 뿐이다. class 중에서도 자신의 필요에 맞는 class만 남기고 삭제하는 작업이 필요하다.</li>
<li>YOLO format의 bbox가 nomalize된 값인 것을 고려하면 &quot;RESOLUTION&quot;(사진의 width와 height) 정보도 필요하나, 이는 이미지를 직접 불러와 읽어들이도록 한다. </li>
<li>&quot;Drawing&quot;이 &quot;BOX&quot;가 아니라 &quot;POLYGON&quot;인 것은 제외한다. 이 경우 bbox annotation을 제공하지 않은 것과 같으므로... 어쩔 수 없이 직접 bbox를 라벨링 할 수 밖에 없다.</li>
</ol>
</blockquote>
<h3 id="1-labels와-images-각각-원하는-디렉토리에-옮기기">1. labels와 images 각각 원하는 디렉토리에 옮기기</h3>
<pre><code>import os
import shutil

orig_label_dir = &#39;path/to/생활 폐기물 이미지/Validation/[V라벨링]라벨링데이터&#39;
label_dir = &#39;path/to/labels&#39;

for curDir, dirs, files in os.walk(orig_label_dir):
    for f in files:
            shutil.move(os.path.join(curDir, f), os.path.join(label_dir, f))

orig_image_dir = &#39;path/to/생활 폐기물 이미지/Validation&#39;
image_dir = &#39;path/to/images&#39;

for curDir, dirs, files in os.walk(orig_image_dir):
    for f in files:
        shutil.move(os.path.join(curDir, f), os.path.join(image_dir, f))</code></pre><ul>
<li><code>os.walk()</code>의 출력<ul>
<li>curDir: 파일이 존재하는 모든 디렉토리 경로(str, 파일명은 미포함)</li>
<li>dirs: 모든 디렉토리 명(list)</li>
<li>files: 모든 디렉토리별로 존재하는 모든 파일명(list)</li>
</ul>
</li>
</ul>
<h3 id="2-필요한-class들-정의하기">2. 필요한 class들 정의하기</h3>
<p>-&gt; image는 AI hub에서 부분적으로는 골라서 받을 수 있지만, label은 내 task에 필요하지 않은 것들도 한번에 받도록 되어 있으므로, 맞는 image가 없는 label data는 먼저 삭제한다.</p>
<pre><code>filenames = os.listdir(image_dir)
names = [name[:-4] for name in filenames]    # &#39;파일명.jpg&#39;에서 &#39;파일명&#39;만 남김

for curDir, dirs, files in os.walk(label_dir):
    for f in files:
        if f[:-5] not in names:    # &#39;파일명.Json&#39;에서 &#39;파일명&#39;으로 판단하고 없으면 삭제
            os.remove(os.path.join(curDir, f))</code></pre><p> -&gt; 남은 label들이 어떤 클래스를 갖고 있는지 먼저 추리고 파악한다.</p>
<pre><code>import json
labels = []
for file in names:
    json_path = os.path.join(label_dir, file+&#39;.Json&#39;)

    # json 파일 내용에 한글이 포함되어 있으므로 encoding 추가
    with open(json_path, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f:    
        json_data = json.load(f)
    for obj in json_data[&#39;Bounding&#39;]:
        labels.append(obj[&#39;DETAILS&#39;])
label_set = set(labels)    # &quot;DETAILS&quot;를 모두 저장한 다음 set 자료형으로 중복 제거
print(label_set)</code></pre><p>-&gt;  task 정의에 따라 label_set들을 class를 0부터 시작하는 정수 번호로 지정해주는 함수를 정의한다.</p>
<pre><code>def class_choose(cls):
    bottle = [&#39;기타술병&#39;, &#39;맥주병&#39;, &#39;물병&#39;, &#39;박카스병&#39;, &#39;소주병&#39;, &#39;음료수병&#39;, &#39;페트병&#39;]
    can = [&#39;맥주캔&#39;, &#39;음료수캔&#39;, &#39;통조림캔&#39;, &#39;커피캔&#39;, &#39;참기름캔&#39;, &#39;스팸류&#39;]
    if cls in bottle:
        return 0
    elif cls in can:
        return 1
    else:
        return 2</code></pre><h3 id="3-yolo-format-annotation-txt-파일-만들기">3. YOLO format annotation txt 파일 만들기</h3>
<pre><code>import json
import cv2
for file in names:
    json_path = os.path.join(label_dir, file+&#39;.Json&#39;)
    img_path = os.path.join(image_dir, file+&#39;.jpg&#39;)
    image = cv2.imread(img_path)
    h,w,_ = image.shape    # 이미지 처리에서는 이미지 shape를 height, width, channal 순으로 정의한다.
    with open(json_path, &#39;r&#39;, encoding=&#39;utf-8&#39;) as f:
        json_data = json.load(f)
    objs = []
    for obj in json_data[&#39;Bounding&#39;]:
        if obj[&#39;Drawing&#39;] != &#39;BOX&#39;:    # bbox가 아닌 polygon 등 다른 방식의 annotation 제외
            break
        cls = obj[&#39;DETAILS&#39;]
        cls_num = class_choose(cls)
        x1 = int(obj[&#39;x1&#39;])
        x2 = int(obj[&#39;x2&#39;])
        y1 = int(obj[&#39;y1&#39;])
        y2 = int(obj[&#39;y2&#39;])
        center_x = (x1 + x2) / (2*w)
        center_y = (y1 + y2) / (2*h)
        width = (x2 - x1) / w
        height = (y2 - y1) / h    # YOLO format의 normalized bbox
        objs.append(f&#39;{cls_num} {center_x} {center_y} {width} {height}\n&#39;)
    with open(&#39;path/to/yolo/labels/{file}.txt&#39;, &#39;w&#39;) as f:
        f.writelines(objs)</code></pre><p>이후 적절히 annotation file과 image file의 경로를 맞추고, 라벨링 상태를 확인한 다음 YOLO를 훈련시키면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Python 예외처리]]></title>
            <link>https://velog.io/@lumi_hunter/Python-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC</link>
            <guid>https://velog.io/@lumi_hunter/Python-%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC</guid>
            <pubDate>Wed, 08 May 2024 09:17:53 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.inflearn.com/course/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%85%EB%AC%B8-%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%98%A4%EB%A6%AC%EC%A7%80%EB%84%90/dashboard">Inflearn &lt;프로그래밍 시작하기: 파이썬 입문 강의&gt; 내용임을 밝힙니다.</a></p>
<p>에러를 예외처리하는 것큼이나 코드 실행 프로세스에서 예상과 다르게 돌아가는 예외를 처리하는 방법도 필요하므로, <code>raise</code> 키워드로 예외를 발생시키기도 한다.</p>
<blockquote>
<p>에러가 발생해 프로그램이 멈추지 않게 하기 위해,</p>
</blockquote>
<ol>
<li>예외는 반드시 처리되어야 하고, </li>
<li>그에 대한 로그가 남아야 하며,</li>
<li>예상하지 못한 프로세스에 관해 예외를 발생시키기도 한다.</li>
<li>Python에서는 예외가 없는 것을 가정하고 프로그램을 작성 후, 런타임에서 예외가 발생 시 예외 처리하는 것을 권장한다.</li>
</ol>
<h4 id="에러의-예시">에러의 예시</h4>
<ul>
<li>SyntaxError: 문법적 오류</li>
<li>TypeError: 자료형에 맞지 않는 연산을 수행하려고 할 경우<pre><code>x = [1,2]
y = (1,2)
print(x + y)    # TypeError: can only concatenate list (not &quot;tuple&quot;) to list</code></pre></li>
<li>NameError: 참조할 변수가 선언되어 있지 않은 경우</li>
<li>IndexError: 인덱스 범위를 벗어난 호출을 시도할 경우<pre><code>x = [50, 70, 90]
print(x.pop())
print(x.pop())
print(x.pop())
print(x.pop())    # IndexError: pop from empty list</code></pre></li>
<li>KeyError: 존재하지 않는 키를 호출할 경우<pre><code>dic = {&#39;name&#39;: &#39;Lee&#39;, &#39;Age&#39;: 41, &#39;City&#39;: &#39;Busan&#39;}
print(dic[&#39;hobby&#39;])    # KeyError: &#39;hobby&#39;
print(dic.get(&#39;hobby&#39;))    # dictionary에서 get을 쓰는 것이 권장됨-&gt;KeyError 대신 &#39;None&#39;을 출력하므로.</code></pre></li>
<li>ValueError: 존재하지 않는 값을 호출할 경우<pre><code>x = [10, 50, 90]
x.remove(200)    # ValueError: list.remove(x): x not in list</code></pre></li>
<li>AttributeError: 모듈, 클래스에 있는 속성을 잘못 사용할 경우<pre><code>import time
print(time.time2())    # AttributeError: module &#39;time&#39; has no attribute &#39;time2&#39;. Did you mean: &#39;time&#39;?</code></pre><h3 id="예외처리-기본-문법">예외처리 기본 문법</h3>
<blockquote>
</blockquote>
try : 에러가 발생 할 가능성이 있는 코드 실행
  except 에러명1: 여러개 가능
  except 에러명2:
else : try 블록의 에러가 없을 경우 실행
finally : 항상 실행</li>
</ul>
<h3 id="예외처리-패턴-4가지">예외처리 패턴 4가지</h3>
<ol>
<li>발생할 에러를 예측해서 명시하는 경우(권장)<pre><code>name = [&#39;Kim&#39;, &#39;Lee&#39;, &#39;Park&#39;]
</code></pre></li>
</ol>
<p>try:
    z = &#39;Kim&#39; # &#39;Cho&#39;
    x = name.index(z)
    print(&#39;{} Found it! {} in name&#39;.format(z, x + 1))
except ValueError:
    print(&#39;Not found it! - Occurred ValueError!&#39;)
else:
    print(&#39;Ok! else.&#39;)</p>
<pre><code>2. 에러를 명시하지 않고 예외처리하는 경우</code></pre><p>name = [&#39;Kim&#39;, &#39;Lee&#39;, &#39;Park&#39;]</p>
<p>try:
    z = &#39;Cho&#39; # &#39;Cho&#39;
    x = name.index(z)
    print(&#39;{} Found it! {} in name&#39;.format(z, x + 1))
except:
    print(&#39;Not found it! - Occurred ValueError!&#39;)
else:
    print(&#39;Ok! else.&#39;)</p>
<pre><code>3. 모든 에러를 Exception 객체로 묶어 표기하는 경우</code></pre><p>name = [&#39;Kim&#39;, &#39;Lee&#39;, &#39;Park&#39;]</p>
<p>try:
    z = &#39;Cho&#39; # &#39;Cho&#39;
    x = name.index(z)
    print(&#39;{} Found it! {} in name&#39;.format(z, x + 1))
except Exception as e:
    print(e)    # 어떤 에러 발생했는지 로그 남기기
    print(&#39;Not found it! - Occurred ValueError!&#39;)
else:
    print(&#39;Ok! else.&#39;)
finally:
    print(&#39;Ok! finally&#39;)</p>
<pre><code>4. 에러-예외처리 직접 발생 시키는 경우</code></pre><p>try:
    a = &#39;Park&#39;
    if a == &#39;Park&#39;:
        print(&#39;OK! Pass!&#39;)
    else:    # 프로그램 목적상 &#39;Park&#39;이 아니면 문제가 발생한다면 에러로 처리할 수 있다
        raise ValueError
except ValueError:
    print(&#39;Occurred! Exception!&#39;)
else:
    print(&#39;Ok! else!&#39;)</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Python 가상환경 만들기(VS Code)]]></title>
            <link>https://velog.io/@lumi_hunter/Python-%EA%B0%80%EC%83%81%ED%99%98%EA%B2%BD-%EB%A7%8C%EB%93%A4%EA%B8%B0VS-Code</link>
            <guid>https://velog.io/@lumi_hunter/Python-%EA%B0%80%EC%83%81%ED%99%98%EA%B2%BD-%EB%A7%8C%EB%93%A4%EA%B8%B0VS-Code</guid>
            <pubDate>Wed, 08 May 2024 01:50:47 GMT</pubDate>
            <description><![CDATA[<p><a href="https://www.inflearn.com/course/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%A4%91%EA%B8%89-%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%98%A4%EB%A6%AC%EC%A7%80%EB%84%90/dashboard">Inflearn &lt;우리를 위한 프로그래밍: 파이썬 중급&gt; 강의 내용임을 밝힙니다.</a></p>
<ul>
<li><p>python-ex 라는 이름의 가상환경 만들기: 가상환경을 만들 폴더로 이동해 다음 명령어 실행</p>
<pre><code>$ python -m venv python-ex</code></pre></li>
<li><p>python-ex 가상환경 실행</p>
<pre><code>$ cd python-ex/Scripts
$ activate</code></pre></li>
<li><p>VS Code에서 python-ex 사용: commend palette(<code>ctrl+shift+p</code>) 에서 &#39;python interpreter&#39; 검색 후 선택, 또는 python-ex이 설치된 폴더에서 Scripts&gt;python.exe 실행</p>
</li>
<li><p>python-ex  가상환경에서 패키지 설치: 가상환경을 실행한 다음 pip</p>
</li>
<li><blockquote>
<p>&#39;Fatal error in launcher: Unable to create process using~&#39; 오류가 생긴다면 <code>python -m pip install --upgrade --force-reinstall pip</code>으로 현재 가상환경에서 pip 강제 재설치</p>
</blockquote>
</li>
</ul>
<ul>
<li>python-ex 가상환경 종료<pre><code>$ deactivate</code></pre></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[컴파일언어, 인터프리터언어, 스크립트언어 개념 비교]]></title>
            <link>https://velog.io/@lumi_hunter/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%96%B8%EC%96%B4-%EB%B9%84%EA%B5%90</link>
            <guid>https://velog.io/@lumi_hunter/%EC%BB%B4%ED%8C%8C%EC%9D%BC%EC%9D%B8%ED%84%B0%ED%94%84%EB%A6%AC%ED%84%B0%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%96%B8%EC%96%B4-%EB%B9%84%EA%B5%90</guid>
            <pubDate>Sun, 11 Jun 2023 12:06:23 GMT</pubDate>
            <description><![CDATA[<p>컴파일 언어: 반드시 <strong>기계어로 컴파일 되어야만</strong> 실행시킬 수 있는 언어</p>
<ul>
<li>소스 코드 파일을 실행파일, 라이브러리 등의 Object 파일로 바꾸는 작업을 <strong>컴파일</strong>이라고 한다. 코드에 문법적인 오류가 있으면(컴파일되지 않으면) 실행되지 않는다.
cf. 소스 코드 파일을 컴퓨터에서 실행할 수 있는 독립 소프트웨어 산출물로 변환하는 과정을 <strong>빌드</strong>라고 하며, 빌드 단계에 컴파일이 포함된다.
ex. Java의 경우 class 파일이 생성된다.</li>
<li>컴파일 단계와 실행 단계가 분리되어 있으며, 컴파일은 단 한번 실행되고 실행은 컴파일 된 것을 실행만 하면 되므로 실행 속도가 빠르다.</li>
</ul>
<p>인터프리터 언어: 컴파일러를 거쳐 기계어로 변환되지 않고 바로 실행되는 언어</p>
<ul>
<li>인터프리터가 <strong>한 줄씩 해석해서 바로 실행</strong>된다. 문법적인 오류가 있어도 실행은 시작된다.</li>
<li>실행파일을 별도로 생성하지 않기 때문에 실행 시마다 인터프리트 과정이 반복 수행되어 실행 속도가 느리다.</li>
</ul>
<table>
<thead>
<tr>
<th>구분</th>
<th>컴파일 언어</th>
<th>인터프리터 언어</th>
</tr>
</thead>
<tbody><tr>
<td>번역</td>
<td>컴파일러가 전체 번역</td>
<td>인터프리터가 한 줄씩 번역 (바이트 코드로 변환)</td>
</tr>
<tr>
<td>속도</td>
<td>번역 속도🔽실행 속도🔼</td>
<td>번역 속도🔼실행 속도🔽</td>
</tr>
<tr>
<td>프로그램 저장</td>
<td>Disk</td>
<td>ROM</td>
</tr>
<tr>
<td>메모리 할당</td>
<td>⭕(목적 프로그램 생성)</td>
<td>❌(즉시 실행)</td>
</tr>
<tr>
<td>예시</td>
<td>C, C++, C#, Java</td>
<td>Python, JavaScript, Ruby</td>
</tr>
</tbody></table>
<blockquote>
<p><strong>스크립트 언어는 응용프로그램을 제어하는 언어, 즉 언어의 사용처가 어플리케이션, SW인 언어를 말하는 것</strong>이다. 언어의 기계적 해석 방식의 차이로 컴파일 언어와 인터프리터 언어를 구분하는 것과는 다른 개념.
ex. JavaScript는 웹 브라우저 위에서 웹 브라우저를 제어하는 언어이므로 스크립트 언어이자, 인터프리터가 한 줄씩 번역해 실행하는 인터프리터 언어이다.</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>