<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jjun-ho.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 14 Sep 2023 05:11:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jjun-ho.log</title>
            <url>https://images.velog.io/images/jjun-ho/profile/9d54c8f9-da4d-4ca5-b31e-8fcf5b06bfb1/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jjun-ho.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jjun-ho" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Object Detection (5) - InternImage(CNN Based)]]></title>
            <link>https://velog.io/@jjun-ho/Object-Detection-5-InternImageCNN-Based</link>
            <guid>https://velog.io/@jjun-ho/Object-Detection-5-InternImageCNN-Based</guid>
            <pubDate>Thu, 14 Sep 2023 05:11:56 GMT</pubDate>
            <description><![CDATA[<h2 id="internimage">InternImage</h2>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/a7b1ea88-a4e4-4485-97fe-6d5cedcd6181/image.png" alt=""></p>
<ul>
<li>Brand-New CNN-based Backbone Network</li>
<li>Characteristics<blockquote>
<p>Dynamic sparse convolutional layer</p>
<blockquote>
</blockquote>
<ul>
<li>Only with 3x3 kernels</li>
<li>Adaptive spatial aggregation</li>
<li>Reduce inductive bias</li>
<li>Low computational cost compared to large convolutional layers</li>
</ul>
<p>Overall Architecture of ViT</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="contributions">Contributions</h3>
<ul>
<li>1st CNN-based backbone with more than 1 billion params.</li>
<li>Add long-rage dependencies and adaptive spatial aggregation with 3x3 DCN</li>
<li>SOTA accuracy in COCO dataset</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/fedd6845-31ed-4105-ae2a-aea2608ed311/image.png" alt=""></p>
<br>

<h3 id="deformable-convolution-v3">Deformable Convolution v3</h3>
<p>Convolution vs MHSA</p>
<ul>
<li>이전 연구에서 CNN과 ViT의 차이점에 대해 다양하게 논의</li>
<li>InterImage의 Core Operator를 결정하기 전에 먼저 Regular Convolution과 MHSA의 차이에 대해 설명</li>
<li>(1) Long-Range Dependencies<blockquote>
<ul>
<li>Effective Receptive Field가 큰 Model은 대개 Downstream Vision Task에서 더 잘 수행된다는 것이 오랫동안 인식됨</li>
<li>3x3 Regular Convolution에 의해 Stacked CNN은 실질적인 Effective Field는 상대적으로 작음</li>
<li>Very Deep Model에서도 CNN Based Model은 Long-Range Dependencies를 얻을 수 없음</li>
</ul>
</blockquote>
</li>
<li>(2) Adaptive Spatial Aggregation<blockquote>
<ul>
<li>Weight가 Input에 의해 Dynamic하게 조정되는 MHSA와는 다르게 Regular Convolution은 Static Weight를 가지고 2D Locality, Neightborhood Structure, Translation Equivalence 특성을 가진 Operation</li>
<li>Bias가 높은 특성을 이용하여 Regular Convolution Model은 ViT에 비해 빨리 수렴되고 Training Data가 덜 필요할 수 있지만 CNN이 Web-Scale의 Large-Scale Data에 정보를 학습하는 것을 제한하기도 함</li>
</ul>
</blockquote>
</li>
</ul>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Object Detection (4) - Object Detection 성능 비교]]></title>
            <link>https://velog.io/@jjun-ho/Object-Detection-4-Transformer-%EB%AA%A8%EB%8D%B8-%EB%B9%84%EA%B5%90</link>
            <guid>https://velog.io/@jjun-ho/Object-Detection-4-Transformer-%EB%AA%A8%EB%8D%B8-%EB%B9%84%EA%B5%90</guid>
            <pubDate>Mon, 04 Sep 2023 05:31:31 GMT</pubDate>
            <description><![CDATA[<h2 id="object-detection-성능표">Object Detection 성능표</h2>
<h3 id="yolov1-2016">YOLOv1 (2016)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/1bc6d81d-31c8-4a97-b85c-2351091aa03f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/7121f686-9dba-4486-9bff-2508bab322c6/image.png" alt=""></p>
<br>

<h3 id="yolov2-2017">YOLOv2 (2017)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/2f0fbb93-2b75-4034-a8b5-ae94822c99b7/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/17fa4146-d428-4700-b1eb-a6880bb84904/image.png" alt=""></p>
<br>

<h3 id="yolov3-2018">YOLOv3 (2018)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/72aa0699-59fa-43de-bcb8-7a779e410bea/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/0368910c-aab0-4a4a-828b-1c3f9fb4b7ab/image.png" alt=""></p>
<br>

<h3 id="yolov4-202004">YOLOv4 (2020.04)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/66f79827-71b3-424e-a0b9-a5d244991836/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/b7caaf9d-bb44-44ea-b558-e681873c7cac/image.png" alt=""></p>
<br>

<h3 id="detr-202005">DETR (2020.05)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/0a7d03a6-c236-490b-9bfe-42ac30ca1977/image.png" alt=""></p>
<br>

<h3 id="yolov5-202006">YOLOv5 (2020.06)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/31ae3342-7e5d-45e8-b3da-d285fbe99108/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/b36ea84c-65a6-46a1-a319-186acc90e122/image.png" alt=""></p>
<br>

<h3 id="yolov7-202207">YOLOv7 (2022.07)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/06d9d4bf-dc11-46a8-967f-a3ea262a15f7/image.png" alt=""></p>
<br>

<h3 id="yolov6-202209">YOLOv6 (2022.09)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/25200bcb-ad95-4098-ae8d-725642077265/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/f9337872-2018-4f77-b883-e2293592e498/image.png" alt=""></p>
<br>

<h3 id="yolov8-202301">YOLOv8 (2023.01)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/fcdae5d9-378f-4412-9de6-e0e499bbb76b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/20944ff7-8817-4df1-aa16-591b8b22ea87/image.png" alt=""></p>
<br>

<h3 id="yolov6-v30-202301">YOLOv6-v3.0 (2023.01)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/38fcc725-9b44-428b-929e-c461787c58f5/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/37788506-9fd3-4e40-9eac-767823782feb/image.png" alt=""></p>
<br>

<h3 id="damo-yolo-202304">DAMO-YOLO (2023.04)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/30a383b3-a845-4580-b89b-9cf0f2cfbeed/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/6324a8ca-8e06-4f12-919d-f1c74ad4b272/image.png" alt=""></p>
<p><br><br></p>
<h2 id="object-detection--rea-time-object-detection">Object Detection / Rea-time Object Detection</h2>
<h3 id="object-detection--box-ap">Object Detection : Box AP</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/9f008a2a-4af9-4ead-9de0-008a32ca9842/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/a48c6c28-d45c-4ecb-a328-5c404f6e7770/image.png" alt=""></p>
<br>

<h3 id="real-time-object-detection--box-ap">Real-time Object Detection : Box AP</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/2bbea4c7-3719-45da-82bd-9ec7b022c996/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/871f677e-830c-4d70-8314-02861c4d8254/image.png" alt=""></p>
<br>

<h3 id="real-time-object-detection--fps">Real-time Object Detection : FPS</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/75a78ef9-0df0-4492-acd7-6dc0ad784ecc/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/7bb7a24b-0557-4553-9d2f-e9221dd262f3/image.png" alt=""></p>
<br>

<h3 id="real-time-object-detection--box-ap--fps">Real-time Object Detection : Box AP / FPS</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/9edf4438-55ef-44fe-b637-699649cd1caa/image.png" alt=""></p>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Object Detection (3) - Transformer 모델 비교]]></title>
            <link>https://velog.io/@jjun-ho/Object-Detection-3-Transformer-%EB%AA%A8%EB%8D%B8-%EB%B9%84%EA%B5%90</link>
            <guid>https://velog.io/@jjun-ho/Object-Detection-3-Transformer-%EB%AA%A8%EB%8D%B8-%EB%B9%84%EA%B5%90</guid>
            <pubDate>Fri, 01 Sep 2023 07:34:00 GMT</pubDate>
            <description><![CDATA[<h2 id="detr">DETR</h2>
<ul>
<li>Transformer를 Object Detection에 최초로 적용</li>
<li>기존의 Object Detection 모델들과 달리 Direct Prediction이 가능하여 Hand-crafted Process가 없어도 됨</li>
<li>하나의 Ground Truth에 오직 하나의 예측된 Bounding Box만 Matching(One-to-One) -&gt; Post-processing 과정 불필요</li>
</ul>
<br>

<h3 id="detr-장점과-단점">DETR 장점과 단점</h3>
<ul>
<li><p>장점</p>
<blockquote>
<ol>
<li><p>object detection에서 발생하는 문제들을 해결하기 위해 위의 기법들이 각각 적용되는데 이렇게 복잡해지는 과정을 direct prediction으로 아주 단순하게 만들어 버렸다.</p>
</li>
<li><p>CNN 이후 Transformer를 사용하면 되는 구조로 매우 단순한 구조를 취하게 된다.</p>
</li>
</ol>
</blockquote>
</li>
<li><p>단점</p>
<blockquote>
<ol>
<li><p>Transformer의 특성상 학습하는데 굉장히 많은 시간이 필요하다.</p>
</li>
<li><p>small object 탐지력이 약하다.</p>
</li>
</ol>
</blockquote>
</li>
</ul>
<br>

<h3 id="original-transformer-vs-detr-transformer">Original Transformer vs DETR Transformer</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/be8bd2e3-e5ab-465a-a10f-31a2d4acc6b5/image.png" alt=""></p>
<ul>
<li>positional encoding하는 위치가 다르다. Vaswani의 original transformer는 transformer module(encoder, decoder)에 한 번만 encoding을 하지만 DETR은 모든 encoder, decoder module에서 positional encoding을 한다. 이 때 attention에서만 positional encoding을 하는데 이 방법이 성능이 더 좋다는걸 이론적으로 설명하진 않고 실험적으로 증명하고 있다.</li>
<li>Vaswani의 transformer는 auto-regression방식으로 output하지만 DETR은 parallel 방식으로 output한다.</li>
</ul>
<ol>
<li><p>DETR는 encoder에서 이미지 feature map을 입력받는 반면, Transformer는 문장에 대한 embedding을 입력받습니다. Transformer는 sequence 정보를 입력받는데 적합하기 때문에 DETR은 CNN backbone에서 feature map을 추출한 이후, 1x1 convolution layer를 거쳐 차원을 줄인 다음, spatial dimension을 flatten하여 encoder에 입력합니다. h, w가 height, width이며, C가 channel 수, d가 C보다 작은 channel 수라고 할 때 C×h×w 크기의 feature map을 d×hw로 변환시켰다고 볼 수 있습니다. </p>
</li>
<li><p>positional encoding에서 차이가 있습니다. Transformer는 입력 embedding의 순서와 상관 없이 동일한 값을 출력하는 permutation invariant한 성질을 가졌기 때문에 positional encoding을 더해줍니다. DETR은 x, y axis가 있는 2D 크기의 feature map을 입력받기 때문에 기존의 positional encoding을 2D 차원으로 일반화시켜 spatial positional encoding을 수행합니다. 입력값의 차원이 d라고 할 때 x, y 차원에 대하여, row-wise, column wise로 2/d 크기로 sine, cosine 함수를 적용합니다. 이후 channel-wise하게 concat하여 d channel의 spatial positional encoding을 얻은 후 입력값에 더해줍니다. </p>
</li>
<li><p>Transformer는 decoder에 target embedding을 입력하는 반면, DETR은 object queries를 입력합니다.  object queries는 길이가 
N인  학습 가능한 embedding입니다. object query에 대한 구체적인 설명은 Method 파트에서 살펴보겠습니다. </p>
</li>
<li><p>Transformer는 decoder에서 첫 번째 attention 연산 시 masked multi-head attention을 수행하는 반면, DETR은 multi-head self-attention을 수행합니다. 이는 Transformer는 auto-regressive하게 다음 token을 예측하기 때문에 attention 연산 시 다음 token에 대한 정보를 활용하는 것을 방지하기 위해 후속 token에 대한 정보를 masking합니다. masking은 attention 연산에서 softmax 함수 입력에 후속 token 위치에 -inf를 입력하는 방식으로 수행됩니다. 하지만 DETR은 입력된 이미지에 동시에 모든 객체의 위치를 예측하기 때문에 별도의 masking 과정을 필요로 하지 않습니다. </p>
</li>
<li><p>Transformer는 Decoder 이후 하나의 head를 가지는 반면, DETR는 두 개의 head를 가집니다.  Transformer는 다음 token에 대한 class probability를 예측하기 때문에 하나의 linear layer를 가지는 반면, DETR은 이미지 내 객체의 bounding box와 class probability를 예측하기 때문에 각각을 예측하는 두 개의 linear layer를 가집니다.</p>
</li>
</ol>
<br>

<h3 id="method">Method</h3>
<p>본 논문에서는 object detection 시 direct set prediction을 위해 두 가지 요소가 필수적이라고 합니다. </p>
<ol>
<li><p>predicted bounding box와 ground truth box 사이의 unique matching을 가능하도록 하는 set prediction loss</p>
</li>
<li><p>한 번의 forward pass로 object model 사이의 relation을 예측하는 architecture</p>
</li>
</ol>
<br>

<h4 id="object-detection-set-prediction-loss">Object detection set prediction loss</h4>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/9cd819d8-01ed-4125-94e9-a4b38ecf5c8a/image.png" alt="">
loss를 계산하는 과정은 두 단계로 구분됩니다. 첫 번째로, predicted bounding box와 ground truth box 사이의 unique한 matching을 수행하는 과정입니다. 두 번째 단계에서는 matching된 결과를 기반으로 hungarian loss를 연산합니다. </p>
<blockquote>
<p>Hungarian algorithm은 두 집합 사이의 일대일 대응 시 가장 비용이 적게 드는 bipartite matching(이분 매칭)을 찾는 알고리즘</p>
</blockquote>
<br>

<h4 id="system-architecture">System Architecture</h4>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/1bb3a546-ea06-43c3-a58e-d2f54a01b57d/image.png" alt=""></p>
<ul>
<li>Backbone + Transformer + MLP 구조로 이루어져 있다</li>
<li>transformer encoder는 image feature vector를 입력으로 받는다. image feature vector는 CNN으로 부터 오는데 AvgPooling Layer를 거치기 전의 input이미지의 stride 32 크기를 가진 feature map를 가져온다. 예를 들어 input image resolution이 224x224 라면 7x7 feature map을 가져오게 된다. 그러나 transformer encoder는 3차원 tensor가 아닌 2차원으로 이루어진 sequence를 입력으로 받기 때문에 flatten 하는 과정이 필요하다. 즉 49개의 feature vector를 encoder에 넣게된다 </li>
<li>Decoder는 object query를 입력으로 받게되는데 이 때 object 는 DETR이 prediction하고자 하는 모든 object class를 의미한다.</li>
</ul>
<br>

<h5 id="transformer">Transformer</h5>
<ul>
<li>Attention을 통해 전체 이미지의 문맥 정보를 이해</li>
<li>이미지 내 각 인스턴스의 상호작용(Interaction) 파악 용이</li>
<li>큰 Bounding Box에서의 거리가 먼 픽셀 간의 연관성 파악 용이</li>
</ul>
<h5 id="transformer-encoder">Transformer Encoder</h5>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/6f648d16-cd85-476f-ad0e-8c4f6de7a970/image.png" alt=""></p>
<ul>
<li>이미지의 특징(Feature) 정보를 포함하고 있는 각 픽셀 위치 데이터를 입력받아 인코딩 수행</li>
</ul>
<br>

<h5 id="transformer-decoder">Transformer Decoder</h5>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/d3b3d4e7-71e5-4a31-bb33-e0f3daca82e3/image.png" alt=""></p>
<ul>
<li>N개의 Object query를 초기 입력으로 받으며 인코딩된 정보를 활용</li>
<li>각 Object query는 이미지 내 서로 다른 고유한 인스턴스를 구별</li>
</ul>
<p><br><br></p>
<h2 id="group-detr">Group DETR</h2>
<blockquote>
<ul>
<li>End-to-End 방식으로 여러 개의 Positive 개체 쿼리를 지원</li>
<li>중복 예측을 피하기 위해 Group DETR에서는 그룹 별 One-to-Many를 도입</li>
</ul>
</blockquote>
<ul>
<li>One-to-One : 하나의 Ground Truth 객체는 정확히 하나의 Positive Sample에만 할당될 수 있다. </li>
<li>One-to-Many : 각 Ground Truth 객체는 여러 Positive Sample에 할당될 수 있다.<blockquote>
<p> One-to-Many 할당의 바람직하지 않은 효과 중 하나는 중복된 예측을 생성하여 Non-maximum suppresion(NMS)와 같은 후처리 단계가 제거되는 것을 방지한다는 것이다.</p>
<blockquote>
<p>DETR은 One-to-One 할당을 채택하여 End-to-End 훈련을 달성하였지만, 수렴 속도가 느린 문제점이 있다.</p>
</blockquote>
</blockquote>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/c421d8d6-b6e5-4ffb-a7d8-db95af4863bb/image.png" alt=""></p>
<blockquote>
<p>총 개체 쿼리 수와 Ground Truth 개체당 일치하는 긍정적인 개체 쿼리 수를 점차적으로 늘렸을 떄, 총 개체 쿼리 수와 일치하는 Positive 개체 쿼리 수가 증가할 수록 탐지 성능이 크게 향상되는 반면, 총 개체 쿼리 수만 늘리면 약간의 이득만 얻을 수 있다는 것을 확인할 수 있다.</p>
</blockquote>
<br>

<h3 id="training-process">Training Process</h3>
<ol>
<li>K개 그룹의 객체 쿼리 채택</li>
<li>동일한 매개변수를 사용하여 각 객체 쿼리 그룹에 대해 디코더 셀프 어텐션을 수행</li>
<li>각 그룹에 대해 One-to-One 할당을 수행하여 각 Ground Truth 개체에 대해 K개의 긍정적인 개체 쿼리로 이어짐.<blockquote>
<p>이 설계는 빠른 훈련 수렴을 달성하고 중복 예측을 제거하며 엔드투엔드 훈련을 가능하게 한다.</p>
<p>추론에 하나의 개체 쿼리 그룹만 사용하고 아키텍처나 프로세스를 수정하지 않으므로 원래 모델에 비해 추가 비용이 발생하지 않는다.</p>
</blockquote>
</li>
</ol>
<br>

<h3 id="related-works">RELATED WORKS</h3>
<ul>
<li>Label Assignment in Object Detection.</li>
<li>Accelerating DETR Training</li>
</ul>
<br>

<h3 id="original-detr-vs-our-group-detr">Original DETR vs Our Group DETR</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/85e25ed5-884e-41ef-ba42-86722177f54e/image.png" alt=""></p>
<blockquote>
<p>우리는 K개의 쿼리 그룹을 디코더에 제공하고 공유 매개변수를 사용하여 각 쿼리 그룹에 대해 self-attention을 수행한다. 그런 다음 각 그룹에 대해 일대일 할당을 수행한다.</p>
</blockquote>
<br>

<h3 id="group-wise-one-to-many-assignment">Group-wise One-to-Many Assignment</h3>
<p>중복 예측을 피하면서 긍정적인 쿼리 수를 늘리기 위해 그룹별 일대다 할당 전략을 제안한다. 각 gt 개체와 일치시키려는 긍정적인 쿼리 수 K가 주어지면 K개의 쿼리 그룹(원본 그룹 포함)을 생성한다.</p>
<p>총 K개의 그룹은 병렬로 디코더에 공급되지만, 동일한 매개변수로 디코더 self-attention을 수행할 때 각 그룹은 다른 그룹과 상호 작용하지 않는다. 그런 다음 일대일 할당이 각 그룹의 출력에 독립적으로 적용되고 K개의 일치 결과를 얻을 수 있다.</p>
<br>

<h3 id="conclusion">CONCLUSION</h3>
<p>우리는 여러 긍정적인 개체 쿼리를 지원하기 위해 그룹 DETR을 제시합니다. 그룹 DETR
엔드투엔드 개체 감지를 달성하기 위해 그룹별 일대다 레이블 할당을 도입합니다. 세부적으로는 다수의 긍정적 객체 쿼리를 다수의 독립적인 그룹으로 분리하고 각 그룹에서 일대일 할당을 수행합니다.</p>
<p><br><br></p>
<h2 id="co-detr">CO-DETR</h2>
<ul>
<li>end-to-end 장점을 유지하면서 기존의 detector보다 우수한 DETR 기반 detector를 만들려고 하였다. 이 문제를 해결하기 위해 덜 positive한 query를 탐색하는 일대일 집합 매칭의 직관적인 단점에 중점을 두었다.</li>
<li>Co-DETR의 핵심 통찰력은 다목적 일대다 레이블 할당을 사용하여 인코더와 디코더 모두의 학습 효율성과 효과를 개선하는 것이다.</li>
</ul>
<br>

<h3 id="related-works-1">RELATED WORKS</h3>
<ul>
<li>One-to-many label assignment</li>
<li>One-to-one set matching</li>
</ul>
<br>

<h3 id="method-1">Method</h3>
<ul>
<li>표준 DETR 프로토콜에 따라 입력 이미지가 backbone과 인코더에 공급되어 latent feature를 생성한다. 여러 사전 정의된 object query는 나중에 cross-attention을 통해 디코더에서 상호 작용한다. Co-DETR을 도입하여 인코더의 feature 학습과 디코더의 attention 학습을 공동 하이브리드 할당 학습 방식과 맞춤형 positive query 생성을 통해 개선한다.</li>
</ul>
<h4 id="collaborative-hybrid-assignments-trainingpermalink">Collaborative Hybrid Assignments TrainingPermalink</h4>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/64abeff9-b1a7-479e-ac0e-f1e042291f71/image.png" alt=""></p>
<p>디코더에서 적은 수의 positive query로 인해 발생하는 인코더 출력에 대한 희박한 supervision을 완화하기 위해 다양한 일대일 레이블 할당 패러다임 (ex. ATSS, Faster R-CNN)이 있는 다목적 보조 head를 통합한다. </p>
<br>

<h4 id="customized-positive-queries-generation">Customized Positive Queries Generation</h4>
<p>일대일 집합 매칭 패러다임에서 각 ground-truth 박스는 supervised 타겟으로 하나의 특정 query에만 할당된다. Positive query가 너무 적으면 transformer 디코더에서 비효율적인 cross-attention 학습이 발생한다.이를 완화하기 위해 충분한 맞춤형 positive query를 정교하게 생성한다</p>
<br>

<h4 id="인코더의-supervision-강화">인코더의 Supervision 강화</h4>
<p>직관적으로 positive query가 너무 적으면 각 ground-truth에 대한 regression loss에 의해 하나의 query만 supervise되므로 supervision이 희박해진다. 일대다 레이블 할당 방식의 positive sample은 latent feature 학습을 향상시키는 데 도움이 되는 더 많은 localization supervision을 받는다. 저자들은 희박한 supervision이 모델 학습을 방해하는 방법을 자세히 알아보기 위해 인코더에서 생성된 latent feature를 자세히 조사하였다. 인코더 출력의 discriminability score를 양자화하기 위해 IoF-IoB 곡선을 도입하였다 (IoF: 전경 교차, IoB: 배경 교차).</p>
<br>

<h4 id="hungarian-매칭의-불안정성을-줄여-cross-attention-학습을-개선">Hungarian 매칭의 불안정성을 줄여 Cross-attention 학습을 개선</h4>
<p>Hungarian 매칭은 일대일 집합 매칭의 핵심이다. Cross-attention은 positive query가 풍부한 개체 정보를 인코딩하는 데 도움이 되는 중요한 task이다. 이를 위해서는 충분한 학습이 필요하다. 동일한 이미지의 특정 positive query에 할당된 ground-truth 정보가 학습 과정 중에 변경되기 때문에 Hungarian 매칭은 제어할 수 없는 불안정성을 도입한다.</p>
<h3 id="comparison-with-other-methodspermalink">Comparison with other methodsPermalink</h3>
<ul>
<li><p>Group-DETR, H-DETR, SQR은 중복된 그룹과 반복된 ground-truth 박스의 일대일 매칭을 통해 일대다 할당을 수행한다. Co-DETR은 여러 공간 좌표를 각 ground-truth에 대한 positive로 명시적으로 할당한다. 따라서 이러한 조밀한 supervision 신호는 latent feature map에 직접 적용되어 더 식별할 수 있다. 반대로 Group-DETR, H-DETR, SQR에는 이 메커니즘이 없다. 더 positive한 query가 이러한 상대에 도입되었지만 Hungarian 매칭에 의해 구현된 일대다 할당은 여전히 일대일 매칭의 불안정성 문제로 어려움을 겪고 있다.</p>
</li>
<li><p>본 논문의 방법은 기존 일대다 할당의 안정성으로부터 이점을 얻고 positive query와 ground-truth 박스 사이의 특정 매칭 방식을 상속한다. Group-DETR과 H-DETR은 일대일 매칭과 기존의 일대다 할당 사이의 상보성을 밝히지 못한다. 본 논문은 전통적인 일대다 할당과 일대일 매칭을 사용하여 detector에 대한 정량적 및 정성적 분석을 최초로 제공하였다. 이를 통해 차이점과 보완성을 더 잘 이해할 수 있으므로 추가로 전문화된 일대다 디자인 경험 없이 기존 일대다 할당 디자인을 활용하여 DETR의 학습 능력을 자연스럽게 향상시킬 수 있다</p>
</li>
<li><p>디코더에 negative query가 도입되지 않는다.Permalink</p>
<blockquote>
<p>중복된 object query는 필연적으로 디코더에 대한 많은 양의 negative query와 GPU 메모리의 상당한 증가를 가져온다. 그러나 본 논문의 방법은 디코더에서 positive 좌표만 처리하므로 메모리를 덜 사용한다.</p>
</blockquote>
</li>
</ul>
<p><br><br></p>
<ul>
<li>참고 문헌</li>
</ul>
<blockquote>
<p>DETR
-&gt; End-to-End Object Detection with Transformers, <a href="https://arxiv.org/pdf/2005.12872.pdf">https://arxiv.org/pdf/2005.12872.pdf</a>
-&gt; <a href="https://powerofsummary.tistory.com/205">https://powerofsummary.tistory.com/205</a>
-&gt; <a href="https://herbwood.tistory.com/26">https://herbwood.tistory.com/26</a></p>
</blockquote>
<blockquote>
<p>Group DETR
-&gt; GROUP DETR: FAST DETR TRAINING WITH GROUPWISE ONE-TO-MANY ASSIGNMENT, <a href="https://arxiv.org/pdf/2207.13085.pdf">https://arxiv.org/pdf/2207.13085.pdf</a></p>
</blockquote>
<blockquote>
<p>CO-DETR
-&gt; DETRs with Collaborative Hybrid Assignments Training, 
 <a href="https://arxiv.org/pdf/2211.12860v5.pdf">https://arxiv.org/pdf/2211.12860v5.pdf</a>
-&gt; <a href="https://kimjy99.github.io/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0/co-detr/">https://kimjy99.github.io/%EB%85%BC%EB%AC%B8%EB%A6%AC%EB%B7%B0/co-detr/</a> </p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Object Detection (2) - YOLO 모델 비교]]></title>
            <link>https://velog.io/@jjun-ho/Object-Detection-2-YOLO-%EB%AA%A8%EB%8D%B8-%EB%B9%84%EA%B5%90</link>
            <guid>https://velog.io/@jjun-ho/Object-Detection-2-YOLO-%EB%AA%A8%EB%8D%B8-%EB%B9%84%EA%B5%90</guid>
            <pubDate>Mon, 21 Aug 2023 01:24:28 GMT</pubDate>
            <description><![CDATA[<h2 id="yolov1--yolov8">YOLOv1 ~ YOLOv8</h2>
<ul>
<li><p>YOLOv1 : 2016년에 발표된 최초 버전으로, 실시간 객체 검출을 위한 딥러닝 기반의 네트워크</p>
</li>
<li><p>YOLOv2 : 2017년에 발표된 두 번째 버전으로, Anchor Box가 도입되었으며, K-means로 Opti- mal한 크기와 개수를 정해줌. 또한 FC Layer가 사라져, 다양한 Size의 Input을 넣을 수 있게 됨. </p>
</li>
<li><p>YOLOv3 : 2018년에 발표된 세 번째 버전으로, 네트워크 구조와 학습 방법을 개선하여 객체 검출의 정확도와 속도를 모두 개선, YOLO의 고질적인 문제인 Small Object를 잘 못 찾는다는 문제점을 3 Scale로 예측하면서 크게 해소.</p>
</li>
<li><p>YOLOv4 : 2020년 4월에 발표된 네 번째 버전으로, Mosaic, MixUp 등 다양한 Augmentation을 적용하여 성능을 향상시킴. 또한  CSP Layer를 활용하여 정확도는 향상시키되, 속도는 줄이는데 큰 역할. SPP와 PAN 등의 기술이 적용되어 더욱 정확한 객체 검출과 더 높은 속도를 제공</p>
</li>
<li><p>YOLOv5 : 2020년 6월에 발표된 버전으로 YOLOv4와 비교하여 객체 검출 정확도에서 10% 이상 향상되었으며, 더 빠른 속도와 더 작은 모델 크기를 가짐. YOLO v4까지는 DarkNet 기반 Backbone을 사용했으나, YOLO v5부터 Pytorch로 구현된 Backbone을 사용.</p>
</li>
<li><p>YOLOv7 : 2022년 7월 발표된 버전으로, 훈련 과정의 최적화에 집중하여 훈련 cost를 강화화는 최적화된 모듈과 최적 기법인 trainable bag-of-freebies를 제안</p>
</li>
<li><p>YOLOv6 : 2022년 9월 발표된 버전으로, 여러 방법을 이용하여 알고리즘의 효율을 높이고, 특히 시스템에 탑재하기 위한 Quantization과 distillation 방식도 일부 도입하여 성능 향상</p>
</li>
<li><p>YOLOv8 : 2023년 1월 발표된 버전으로, YOLO 모델을 위한 완전히 새로운 리포지토리를 출시하여 개체 감지, 인스턴스 세분화 및 이미지 분류 모델을 train하기 위한 통합 프레임워크로 구축됨</p>
</li>
<li><p>20년 7월 PP-YOLO, 21년 2월 Scaled-YOLOv4, 21년 5월 YOLOR, 21년 7월 YOLOX라는 모델이 나왔다.</p>
</li>
</ul>
<p><br><br></p>
<h2 id="yolov1-2016">YOLOv1 (2016)</h2>
<ul>
<li><p>통합인식(Unified Detection) :  기존 Bounding Box 잡은 후 -&gt; 탐지된 Bounding Box에 대해 분류 수행하는 2 Stage Detection 이었지만 YOLOv1은 Bounding Box 조정 + 분류를 동일한 신경망 구조를 통해 동시에 실행하는 1 Stage Detection 이기 때문에 학습 파이프 라인이 기존 Detection 모델들에 비해 간단하기 때문에 학습과 예측의 속도가 빠름</p>
</li>
<li><p>n모든 학습 과정이 이미지 전체를 통해 일어나기 때문에 단일 대상의 특징 뿐만 아니라 이미지 전체의 맥락을 학습하고, 대상의 일반적인 특징을 학습하기 때문에 다른 영영으로의 확장에서도 뛰어난 성능</p>
</li>
<li><p>S x S 크기의 Grid Cell로 Input Image를 분리하고, Cell 마다 B개의 Bounding boxes, Confidence score, Class probabilities를 예측 -&gt; 인접한 Cell이 같은 객체를 예측하는 Bounding Box를 생성하는 문제 발생 -&gt; Confidence score와 IOU를 계산하여 가장 높은 Confidence score의 Bounding Box 선택 (NMS) </p>
</li>
</ul>
<blockquote>
<p>YOLOv1의 한계:  </p>
</blockquote>
<ul>
<li>여러 물체들이 겹쳐 있으면 제대로 된 예측이 어렵</li>
<li>물체가 작을수록 정확도 감소</li>
<li>Bounding Box 형태가 data를 통해 학습되므로 새로운 형태의 Bounding Box의 경우 정확히 예측X</li>
</ul>
<br>

<h3 id="yolov1-architecture">YOLOv1 Architecture</h3>
<ul>
<li>Image -&gt; CNN -&gt; FC -&gt; PT(Prediction Tensor)</li>
<li>24개의 Conv layer와 2개의 FC layer로 구성되어 있다. Darknet network라고 부르며, 224x224 ImageNet dataset으로 Pre-trained된 network를 사용한다. 이후 448x448 이미지를 Input Image로 받아 1x1 Conv layer와 3x3 Conv layer의 교차를 통해 Parameter 감소시킨다.</li>
<li>Final Output : S x S x ( B * 5 + C ) [ S : Num of Cell, B : Num of Bounding boxes, C : Num of Classes]</li>
</ul>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/5672ab8f-18a3-418e-8067-0e9a3eac76d9/image.png" alt=""></p>
<br>

<h3 id="yolov1-loss">YOLOv1 Loss</h3>
<ul>
<li>MULTI Loss = Coordinate Loss + Confidence-Score Loss + No-object Penalties + Classification Loss</li>
<li>Coordinate Loss: x, y, w, h, Confidence-Score의 값이 예측값과 Ground-truth 값의 차를 구해 모두 더함</li>
<li>No-object Penalties: 찾지 못한 물체들에 대한 패널티를 부여합니다. 다시 말해 물체로 찾아냈어야 하는데 찾지 못한 인덱스에 대해 C의 값의 차를 구해 loss에 더함</li>
<li>Classification Loss: 마지막 단락에서 모든 물체가 있다고 판단된 인덱스들에 대해 모든 클래스들에 대해 예측 값과 실제 값의 차를 구해서 더해줍니다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/77e5c1d4-132d-4113-8ce8-3d954b87b0d3/image.png" alt=""></li>
</ul>
<p><br><br></p>
<h2 id="yolov2-2017">YOLOv2 (2017)</h2>
<ul>
<li><p>Batch Normalization 적용:  기존 모델에서 Dropout Layer를 제거하고 Convolution Layer에 Batch Normalization을 적용하였다.</p>
</li>
<li><p>High Resolution Classifier: YOLOv1은 VGG16 모델을 기반으로 224x224 크기의 해상도로 학습을 하고, 448x448 크기의 이미지에 대해서 Object Detection을 수행하도록 설계되어 성능이 좋지 않았다. YOLOv2에서는 학습 전 이미지 분류 모델을 큰 해상도의 이미지에 대해 fine-tuning 단계를 거쳐 고해상도 이미지로 CNN 신경망을 학습 할 수 있었다.</p>
</li>
<li><p>Convolutional With Anchor Boxes: 기존의 YOLOv1은 24개의 Conv layer와 마지막 단락의 2개의 Fully Connected layer로부터 Bounding Box의 좌표 정보를 예측했다. YOLOv2는 마지막 단의 Fully Connected layer을 떼어내고 Convolutional Network 형태로 Prediction을 계산합니다. 또한, Faster R-CNN에서의 Anchor Box의 개념을 도입하여 Bounding Box의 좌표를 예측하기 보다는 사전에 정의한 앵커 박스에서 offset을 예측하여 더욱 간단하게 학습을 할 수 있게 되었다. Anchor Box의 핵심은 사전에 크기와 비율이 모두 결정되어 있는 박스를 전제로, Dimension Clustering(k-means Clustering)을 통해 Ground Truth Box 와 가장 유사한 Optimal Anchor box를 탐색함으로써 데이터셋 특성에 적합한 Anchor Box를 생성한다.
클러스터링 개수 k가 커지면 높은 정확도를 얻을 수 있지만 속도가 느려지기 때문에 YOLOv2에서는 k=5라는 값을 사용합니다.(= Anchor Box 5개 사용)</p>
</li>
<li><p>Direct location prediction: YOLOv2에서는 앵커 박스에 따라 하나의 셀에서 5차원 벡터로 이루어진 바운딩 박스를 예측하며, 경계 박스가 그리드 Cell에서 벗어나지 않도록 제약을 둔다. 기존의 YOLOv1가 그리드의 중심점을 예측하였다면 v2에서는 Left Top 꼭지점으로부터 얼마나 이동하는지 예측하게 된다.</p>
</li>
<li><p>Fine-Grained Features: YOLOv2는 13x13 Feature Map을 출력한다. 하지만 13x13의 크기는 작은 물체 검출에 대해서 약하다는 단점이 있다. 이와 같은 문제 해결을 위해 상위 레이어의 Feature Map을 하위 Feature Map에 합쳐주는 Passthrough Layer를 도입했다. 이전 Layer의 26x26 Feature Map을 가지고 와서 13x13 Feature Map에 이어 붙인다. 크기가 달라 그냥 이어 붙일 수 없으므로 26x26x512의 Feature Map을 13x13x(512*4)의 Feature Map으로 변환합니다. 26x26 크기의 Feature Map에 고해상도 특징(지역적 특성)이 담겨 있기때문에 이를 활용 하는 것이다.</p>
</li>
<li><p>Multi-Scale Training: YOLOv2는 작은 물체도 Detection 하기 위해 여러 스케일의 이미지를 학습하도록 하였다. 10 epoch 마다 {320, 352, …, 608} 과 같이 32 픽셀 간격으로 입력 이미지의 해상도를 바꿔주며 학습을 진행한다. 따라서 다양한 입력 크기에도 예측을 잘할 수 있다.</p>
</li>
</ul>
<br>

<h3 id="yolov2-architecture">YOLOv2 Architecture</h3>
<ul>
<li>YOLOv2는 기존의 Darknet을 개선한 Darknet 19 신경망을 구축하여 이용했습니다. VGG-16 신경망에서 대부분의 가중치가 쓰인 FC layer를 제거하여 1✕1 Convolution Layer로 대체하였다. Global Average Pooling을 사용해 가중치 파라미터 수를 줄여 때문에 훨씬 빠른 속도로 detection이 가능하게 되었다.</li>
<li>Anchor Box 도입으로 인해 학습이 안정화되었다.</li>
<li>YOLOv1에서는 Grid 당 2개의 B-Box 좌표를 예측하는 방식이었다면 YOLOv2에서는 Grid 당 5개의 Anchor Box를 찾는다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/2333fead-3163-4ef0-a851-9f26a9ea047e/image.png" alt=""></li>
</ul>
<p><br><br></p>
<h2 id="yolov3-2018">YOLOv3 (2018)</h2>
<ul>
<li>Multilabel Classification: 한 물체에 대해 Multi Class Label을 가질 수 있다. 그러나 Softmax는 한 박스 안에서 여러 객체가 존재할 경우 적절하게 포착할 수 없었다. 따라서 v3에서는 이것이 가능하도록 마지막에 Loss function을 Softmax가 아닌 모든 Class에 대해 Sigmoid를 취해 각 Class별로 Binary Classification을 하도록 바꾸었다(Binary cross entropy)</li>
</ul>
<br>

<h3 id="yolov3-architecture">YOLOv3 Architecture</h3>
<ul>
<li>Backbone 네트워크를 Darknet-19에서 Darknet-53로 변경하였다.</li>
<li>이전 Darknet-19에 ResNet에서 제안된 Skip Connection 개념을 적용하고 Pooling layer를 삭제하였다.</li>
<li>SSD 모델의 Multi-Scale Feature Layer와 Retinanet의 FPN(Feature Pyramid Network)과 유사한 기법을 적용하였다. (SSD의 Multi-Scale Feature Layer는 서로 다른 크기의 Feature Map에 각 포인트마다 Object Detection을 수행해주는 기법)
<img src="https://velog.velcdn.com/images/jjun-ho/post/b4e09bd8-b92d-4991-9e1f-1b6d11a3278e/image.png" alt=""></li>
</ul>
<p><br><br></p>
<h2 id="yolov4-202004">YOLOv4 (2020.04)</h2>
<ul>
<li><p>기존 YOLO 시리즈의 작은 객체 검출 문제를 해결하고자 했다.</p>
</li>
<li><p>YOLO v4 =  YOLO v3 +  CSPDarknet53(Backbone) +  SPP + PAN + BoF + BoS </p>
</li>
<li><p>다양한 작은 Object들을 잘 검출하기 위해 Input 해상도를 크게 사용하였다. 기존에는 224, 256 등의 해상도를 이용하여 학습을 시켰다면, YOLOv4에서는 512을 사용하였다.</p>
</li>
<li><p>Receptive field를 물리적으로 키워 주기 위해 Layer 수를 늘렸으며, 하나의 Image에서 다양한 종류, 다양한 크기의 Object들을 동시에 검출하려면 높은 표현력이 필요하기 때문에 Parameter 수를 키워주었다.</p>
</li>
<li><p>YOLOv4는 다양한 데이터셋을 이용한 데이터 증강 기술과 Quantization 기술도 함께 도입하여 더 높은 성능과 더 낮은 모델 크기를 가지게 되었다.</p>
</li>
</ul>
<br>

<h3 id="yolov4-architecture">YOLOv4 Architecture</h3>
<ul>
<li>정확도를 높이는 반면에 있어서의 속도 문제는 아키텍처의 변경을 통해 해결하였다.</li>
<li>FPN(Feature Pyramid Network)과 PAN(Path Aggregation Network) 기술을 도입했다.</li>
<li>CSP (Cross Stage Partial connections) 기반의 Backbone 연결과 SPP (Spatial Pyramid Pooling) 등의 새로운 네트워크 구조를 도입하여 성능을 향상하였다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/3f9c0f72-35cb-475f-9421-042cc39f260a/image.png" alt=""><blockquote>
<ul>
<li>Bag of Freebies (BOF)
 BOF는 inference cost의 변화 없이 (공짜로) 성능 향상(better accuracy)을 꾀할 수 있는 딥러닝 기법들이다. 대표적으로 데이터 증강(CutMix, Mosaic 등)과 BBox(Bounding Box) Regression의 loss 함수(IOU loss, CIOU loss 등)이 있다.</li>
<li>Bag of Specials (BOS)
 BOS는 BOF의 반대로, inference cost가 조금 상승하지만, 성능 향상이 되는 딥러닝 기법들이다. 대표적으로 enhance receptive filed(SPP, ASPP, RFB), feature integration(skip-connection, hyper-column, Bi-FPN) 그리고 최적의 activation function(P-ReLU, ReLU6, Mish)이 있다.</li>
<li>FPN: 이 방법은 각 레벨에서 독립적으로 특징을 추출하여 객체를 탐지하는 방법이다. </li>
<li>PAN: 하위 계층 정보를 상위로 더 쉽게 전파할 수 있도록 하는 방법이다.</li>
<li>CSP(Cross-Stage Partial connections) : 기존의 CNN 네트워크의 연산량을 줄이는 기법으로, 학습할 때 중복으로 사용되는 기울기 정보를 없앰으로써 연산량을 줄이면서도 성능을 높인다.</li>
<li>SPP는 local spatial bins를 pooling함으로써 spatial 정보를 유지할 수 있다. 여기에서 spatial bins란, spatial pyramid(1<em>1 회색, 4</em>4 녹색, 16*16 파란색)에서 1칸짜리 공간을 의미한다. SPP를 이용함으로써, image size는 어떤 크기든 사용할 수 있다. 이것은 임의의 aspect ratiois와 scales을 사용할 수 있게 한다. 따라서 우리는 어떤 scale로든 input image를 resize할 수 있다. </li>
</ul>
</blockquote>
</li>
</ul>
<p><br><br></p>
<h2 id="yolov5-202006">YOLOv5 (2020.06)</h2>
<ul>
<li><p>Yolo v5는 Yolo v4와 마찬가지로 CSPNet을 이용하는데, BottleneckCSP를 사용하여 각 계층의 연산량을 균등하게 분배해서 연산 Bottleneck을 없애고 CNN layer의 연산 활용을 업그레이드 시켰다.</p>
</li>
<li><p>다른 Yolo 모델들과 다른 점은 Backbone을 Depth multiple과 Width multiple를 기준으로 하여 크기별로 yolo v5 s, yolo v5 m yolo v5 l, yolo v5 x로 나눈다는 것이다. 이는 아래 그림과 같이 yolo v5 s가 가장 빠르지만 정확도가 비교적 떨어지며 yolo v5 x는 가장 느리지만 정확도는 향상된다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/5fdb8a70-3f56-49bc-ae59-0706f577af91/image.png" alt=""></p>
</li>
</ul>
<p><br><br></p>
<h2 id="yolov7-202007">YOLOv7 (2020.07)</h2>
<ul>
<li><p>Real-time Object Detection 이면서 Inference Cost를 증가시키지 않고도 정확도를 향상시킬 수 있는 Trainable Bag-of-freebies 방법을 제안하는데, 해당 방법들이 적용된 모델이 YOLOv7이다.</p>
</li>
<li><p>Model reparameterization: 학습 시 여러 개의 레이어들을 학습하고 Inference시에는 해당 레이어들을 하나의 레이어로 Fusing하였다.</p>
</li>
<li><p>Label assignment: Ground truth를 그냥 사용하는 것이 아니라 모델의 Prediction, Ground truth의 Distribution을 고려하여 새로운 Soft Label 생성한다.</p>
</li>
<li><p>Parameters와 Computation을 효과적으로 활용할 수 있는 Real-time Object Detector를 위한 ‘Extend&#39; 및 ‘Compound Scaling&#39; 방법을 제안한다.</p>
</li>
<li><p>기존 연구들에서 제안된 ELAN은 Computation block을 어느정도 많이 쌓아도 잘 학습되지만 무한대 가까이로 쌓을 경우 Parameter Utilization이 낮아지는 문제가 있었다. 따라서 YOLOv7에서는 마음껏 쌓아도 학습이 잘되도록 하기 위해 E-ELAN을 제안하였다.</p>
</li>
</ul>
<br>

<h3 id="yolov7-architecture">YOLOv7 Architecture</h3>
<ul>
<li>E-ELAN은 오직 Computational Block만 바뀌고(Scaling에 따라), Transition Layer는 절대 바뀌지 않음</li>
<li>Expand, Shuffle, Merge Cardinality를 통해 Computational Block을 많이 쌓아도 학습능력이 뛰어남</li>
<li>Process</li>
</ul>
<ol>
<li>Computational Block들에 대해 Channel 수를 Multiplier 하는 Group Conv를 적용</li>
<li>CSP로 나눠진 Feature와 Computational Block의 Output Feature들이 Shuffle 후 Concatenate됨</li>
<li>Merge Cardinality 수행</li>
</ol>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/006a11b2-6f8e-4cb4-9aaf-750b3a9cde5d/image.png" alt=""></p>
<p><br><br></p>
<h2 id="yolov6-202009">YOLOv6 (2020.09)</h2>
<ul>
<li><p>Yolov6는 여러 방법을 이용하여 알고리즘의 효율을 높이고, 특히 시스템에 탑재하기 위한 Quantization과 Distillation 방식도 일부 도입하여 성능을 높혔다.</p>
</li>
<li><p>자기 증류 기법 수행 시 모든 학습 단계에서 학생 모델이 지식을 보다 효율적으로 학습할 수 있도록 교사와 레이블의 지식을 동적으로 조정 가능</p>
</li>
<li><p>RepOptimizer 및 채널 별 증류로 객체 탐지를 위한 양자화 체계를 개선하였다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/19b98a7f-fcaf-4dd4-8881-c3a55286060f/image.png" alt=""></p>
</li>
</ul>
<br>

<h3 id="yolov6-architecture">YOLOv6 Architecture</h3>
<ul>
<li><p>Backbone은 EfficientRep Backbone이 사용되었다. Neck 부분은 Rep-PAN이 사용되었다. Head는 Efficient Decoupled Head가 사용되었다.</p>
</li>
<li><p>먼저 네트워크 구조에서 가장 핵심이 되는 기여는 CSPstackRep Block이다. CSPstackRep Block은 CSP(cross stage partial) + RepVGG 방식이다. 이 방식은 Backbone에 사용된다.</p>
</li>
<li><p>소형 모델은 일반 단일 경로 백본을 특징으로 하고 대형 모델은 효율적인 다중 분기 블록을 기반으로 구축
<img src="https://velog.velcdn.com/images/jjun-ho/post/c59f190d-b120-4f15-b70f-50fad05f2eed/image.png" alt=""></p>
</li>
<li><p>Backbone: 이전 YOLO Backbone보다 higher Parallelism을 자랑하는 EfficientRep 사용
<img src="https://velog.velcdn.com/images/jjun-ho/post/4934e191-c0a4-4272-89c6-091eb23f8867/image.png" alt=""></p>
</li>
<li><p>Neck: RepBlocks으로 강화된 PAN 사용(더 큰 모델의 경우 CSPStackRep Block을 사용)
<img src="https://velog.velcdn.com/images/jjun-ho/post/d6893685-ed30-4e4c-b864-342015eaff5b/image.png" alt=""></p>
</li>
<li><p>Head: Efficient Decoupled Head 사용 (from YOLOX)
<img src="https://velog.velcdn.com/images/jjun-ho/post/52636ea3-9355-4877-8260-27e52c28c249/image.png" alt=""></p>
</li>
</ul>
<blockquote>
<ul>
<li><p>다양한 크기의 모델을 수용하기 위해 2개의 재 매개변수가 가능한 Backbone과 Neck를 제시하였고, Head 부분에 하이브리드 채널 전략을 사용하는 Decoupled Head를 사용했습니다.</p>
</li>
<li><p>Backbone – EfficientREP:RepVGG는 작은 network에서는 inference time을 크게 증가시키지 않으면서 좋은 feature representation 능력을 가지고 있으나, 큰 네트워크에서는 single path로 인해 parameter와 computation cost가 크게 증가하는 단점이 있습니다.(Residual Connection을 없앴으므로)따라서 작은 네트워크에서는 RepBlock을, 큰 네트워크에서는 CSPStackRep block을 사용했습니다.</p>
</li>
<li><p>Neck - RepPAN(RepBlocks으로 강화된 PAN):YOLO v4, v5 에서 사용된 PAN이 v6의 base가 되었고, 위에서 설명한 이유로 작은 모델에는 RepBlock을, 큰 모델에는 CSPStackRep을 사용하였고 이를 YOLO v6에서는 Rep-PAN이라고 칭합니다.</p>
</li>
<li><p>2021년에 나온 YOLOR에서 사용된 기법으로, 이전에는 Classification branch와 Regression branch가 parameter를 공유했으나 classification confidence와 localization accuracy 간의 misalignment가 있을 수 있어 두 branch를 각각 다른 head로 분리하였습니다.</p>
</li>
</ul>
</blockquote>
<br>

<h3 id="yolov6-loss">YOLOv6 Loss</h3>
<ul>
<li><p>메인 스트림 앵커가 없는 객체 탐지 모델의 손실 함수에는 Classification Loss, Box Regression Loss, Object Loss가 포함된다.</p>
</li>
<li><p>New classification and regression losses.</p>
</li>
<li><blockquote>
<p>Classification : VariFocal Loss</p>
</blockquote>
</li>
<li><blockquote>
<p>Regression : SIoU / GIoU Loss</p>
</blockquote>
</li>
<li><p>A self-distillation strategy: For the regression and classification tasks</p>
</li>
<li><p>A quantization scheme: For detection using RepOptimizer and channel-wise distillation that helped to achieve a faster detector.
<img src="https://velog.velcdn.com/images/jjun-ho/post/65f7e857-b322-4522-9387-c4d48819cca8/image.png" alt=""></p>
<blockquote>
<ul>
<li><p>VariFocalLoss를 분류 손실로, SIoU/GIoU 손실을 회귀 손실로 선택하였습니다. </p>
</li>
<li><p>Classification Loss로는 VFL(VariFocal Loss)을 사용했다. 기존의 객체 검출에서 사용되던 Cross-Entropy 손실 함수는 모든 예측 박스에 대해 동일한 가중치를 부여하는 데 비해, VariFocalLoss는 예측 박스의 어려운 예제에 더 높은 가중치를 부여하여, 예측 오류가 큰 예제에 더 많은 비중을 둬서 모델 학습을 개선하려는 목적을 가지고 있습니다.</p>
</li>
<li><p>Box regression loss는 큰 모델에는 GIoU, 작은 모델에는 SIoU를 사용했습니다.</p>
</li>
<li><p>Object Loss는 FCOS(Fully Convolutional One-Stage Object Detection)라는 방식을 사용했지만, 부정적인 효과가 나타나기 때문에 최종적으로는 사용하지 않았습니다.</p>
</li>
<li><p>Post-training Quantization(PTQ)과 Quantization-aware Training (QAT) 두가지 방법을 사용하여 실험을 진행하였습니다. PTQ는 작은 Calibration Data Set 만을 사용해서 학습이 완료된 후에 Model 의 Weight를 Quantize 하는 방법이고, QAT는 Training Set을 사용해서 학습 도중에 Quantize 하였을 때를 시뮬레이션하여 최적의 weight를 구하는 것과 동시에 Quantization을 하는 방법입니다. QAT는 주로 Distillation과 함께 사용합니다.</p>
</li>
</ul>
</blockquote>
</li>
</ul>
<p><br><br></p>
<h2 id="yolov8-202301">YOLOv8 (2023.01)</h2>
<ul>
<li><p>YOLO 모델을 위한 완전히 새로운 리포지토리를 출시하여 개체 감지, 인스턴스 세분화 및 이미지 분류 모델을 train하기 위한 통합 프레임워크로 구축되었다.</p>
</li>
<li><p>YOLOv5와 비교했을 때 변경된 사항</p>
<blockquote>
<ul>
<li>C3 모듈을 C2f 모듈로 교체</li>
<li>Backbone에서 첫 번째 6x6 Conv를 3x3 Conv으로 교체</li>
<li>두 개의 컨볼루션 레이어 삭제</li>
<li>ConvBottleneck에서 첫 번째 1x1 Conv를 3x3 Conv로 교체</li>
<li>분리된 Head 사용 및 Objectness 분기 삭제</li>
</ul>
</blockquote>
</li>
<li><p>Anchor Free Detection</p>
</li>
</ul>
<br>

<h3 id="yolov8-architecture">YOLOv8 Architecture</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/44acfbe3-016f-4ace-9bec-ae8b29cc6f0c/image.png" alt=""></p>
<p><br><br></p>
<h2 id="yolov6-v30202301">YOLOv6-v3.0(2023.01)</h2>
<p>YOLOv6-v3.0 모델은 Real-time Object Detection의 SOTA 모델입니다. 
<img src="https://velog.velcdn.com/images/jjun-ho/post/8154255a-8adf-4a06-8a31-a32ccc7538c6/image.png" alt=""></p>
<ul>
<li><p>Renew the neck of the detector with a Bi-directional Concatenation (BiC)
<img src="https://velog.velcdn.com/images/jjun-ho/post/3305b043-9c76-4b35-aa77-4c2aafce332b/image.png" alt=""></p>
<blockquote>
<p>Detector의 neck을 BiC로 대체한다. 세개의 인접한 layer의 feature map을 Inregrate하기 위해 Bi-directional Concatenation(BiC) module을 제안합니다.</p>
</blockquote>
</li>
<li><p>Anchor-Aided Training (AAT)
<img src="https://velog.velcdn.com/images/jjun-ho/post/9f66153e-6330-48f1-8dc7-f70fe6eaf502/image.png" alt=""></p>
<blockquote>
<p>Inference efficiency에 영향을 주지 않으면서 Anchor-Based와 Anchor-Free의 장점을 모두 가져가기 위해 Anchor-Aided Training을 적용합니다. AAT는 Anchor-Based에서 오는 성능 향상을 위해 학습을 할 때 Anchor-Based를 사용하는 보조 브랜치를 함께 학습합니다. Inference할 때는 보조 브랜치를 제거하여 속도 감소를 피합니다.</p>
</blockquote>
</li>
<li><p>Deepen YOLOv6 to have another stage in the backbone and the neck</p>
<blockquote>
<p>Backbone과 Neck에 stage를 추가하여 모델의 깊이를 깊게 합니다.</p>
</blockquote>
</li>
<li><p>New self-distillation strategy, in which the heavier branch for DFL is taken as an Enhanced Auxiliary Regression Branch</p>
<blockquote>
<p>YOLOv6의 small model의 성능을 높이기 위해 새로운 self-distillation을 제안한다. 학습 중에는 regression branch의 DFL(Distribution Focal Loss)을 enhanced auxiliary regression branch로 바꾸어 사용하고 inference 시에는 속도를 위해 제거합니다.</p>
</blockquote>
</li>
</ul>
<br>

<h3 id="yolov6-v30-architecture">YOLOv6-v3.0 Architecture</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/243a721f-4a97-426e-ba47-73d4bcd87218/image.png" alt=""></p>
<br>

<h2 id="damo-yolo202304">DAMO-YOLO(2023.04)</h2>
<ul>
<li>MAE-NAS backbone</li>
<li>Efficient RepGFPN neck</li>
<li>ZeroHead</li>
<li>AlignedOTA label assignment</li>
<li>distillation enhancement.</li>
</ul>
<br>

<h3 id="damo-yolo-architecture">DAMO-YOLO Architecture</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/7bbf51fd-28ed-47ee-9354-403ca55c1ef6/image.png" alt=""></p>
<p><br><br></p>
<ul>
<li>참고 문헌</li>
<li><blockquote>
<p><a href="https://velog.io/@qtly_u/n4ptcz54">https://velog.io/@qtly_u/n4ptcz54</a></p>
</blockquote>
</li>
<li><blockquote>
<p><a href="https://velog.io/@dust_potato/YOLOv6-YOLOv6-v3.0-%EB%A6%AC%EB%B7%B0">https://velog.io/@dust_potato/YOLOv6-YOLOv6-v3.0-%EB%A6%AC%EB%B7%B0</a></p>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Object Detection (1) - 모델 정리 및 비교 ]]></title>
            <link>https://velog.io/@jjun-ho/Object-Detection-%EB%AA%A8%EB%8D%B8-%EC%A0%95%EB%A6%AC-%EB%B0%8F-%EB%B9%84%EA%B5%90</link>
            <guid>https://velog.io/@jjun-ho/Object-Detection-%EB%AA%A8%EB%8D%B8-%EC%A0%95%EB%A6%AC-%EB%B0%8F-%EB%B9%84%EA%B5%90</guid>
            <pubDate>Mon, 14 Aug 2023 08:27:11 GMT</pubDate>
            <description><![CDATA[<h2 id="object-detection-모델의-변화">Object Detection 모델의 변화</h2>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/ea01fb23-f880-47f5-a3bd-ba70d627f41f/image.png" alt=""></p>
<h3 id="r-cnn-2013">R-CNN (2013)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/5614b2f1-a1af-4b06-a01b-8f7f0f4289a3/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/ff999fed-263f-4c74-8900-56938ea53182/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1311.2524.pdf">https://arxiv.org/pdf/1311.2524.pdf</a></li>
</ul>
<br>

<h3 id="overfeat-2014">Overfeat (2014)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/5ac9152d-2bb8-4f35-b3a9-a11b13bd796f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/fa833cce-21c7-4074-a596-27613b766e60/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1312.6229.pdf">https://arxiv.org/pdf/1312.6229.pdf</a></li>
</ul>
<br>

<h3 id="fast-r-cnn-2015">Fast R-CNN (2015)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/a46f8e9e-4d12-459a-853c-85b8d270b33b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/4587b398-c033-4bdc-802f-d5fdd0b48a73/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1504.08083.pdf">https://arxiv.org/pdf/1504.08083.pdf</a></li>
</ul>
<br>

<h3 id="fater-r-cnn-2015">Fater R-CNN (2015)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/8f0a9f9c-5e58-4243-9e55-44084a6ef151/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/2144ab4c-4bd6-47e5-8359-5dceb35d360e/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1506.01497.pdf">https://arxiv.org/pdf/1506.01497.pdf</a></li>
</ul>
<br>

<h3 id="ohem-2016">OHEM (2016)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/7ce24bb9-b959-4345-b97c-deba524edd3c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/a878c1bf-cf02-4bb7-a997-1a2ba2e3cf8c/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1604.03540.pdf">https://arxiv.org/pdf/1604.03540.pdf</a></li>
</ul>
<br>

<h3 id="yolo-v1-2016">YOLO v1 (2016)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/92dc4056-c067-4bcb-b396-0f508e792081/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/b47d4f3d-6461-41b5-b610-e01c78d90596/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1506.02640.pdf">https://arxiv.org/pdf/1506.02640.pdf</a></li>
</ul>
<br>

<h3 id="ssd-2016">SSD (2016)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/c9de07dc-a6b3-4bd5-a93c-05abd8c5a763/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/e3b6c306-ce6b-4102-b1dc-ea8c35304d43/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1512.02325.pdf">https://arxiv.org/pdf/1512.02325.pdf</a></li>
</ul>
<br>

<h3 id="r-fcn-2016">R-FCN (2016)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/3c5bdb06-3197-4f3e-b8f4-4e516081273b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/ba992fea-7813-4a9c-9ceb-2b653659862d/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1605.06409.pdf">https://arxiv.org/pdf/1605.06409.pdf</a></li>
</ul>
<br>

<h3 id="yolo-v2-2017">YOLO v2 (2017)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/716fdd04-9275-4f2f-b17f-94b81e659c9f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/62e55d86-0536-4640-9fe7-23668ee597f4/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/f50d7c02-1ea5-4326-9983-e299a3c80568/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1612.08242.pdf">https://arxiv.org/pdf/1612.08242.pdf</a></li>
</ul>
<br>

<h3 id="fpn-2017">FPN (2017)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/3506c415-e9fb-420d-baa0-b78d02703d94/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/97909482-c56c-4b8b-9616-203dece9469b/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1612.03144.pdf">https://arxiv.org/pdf/1612.03144.pdf</a></li>
</ul>
<br>

<h3 id="retinanet-2017">RetinaNet (2017)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/b1c9e4fb-d960-4334-9ac1-debb5e0910e2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/d0d3bbe6-df63-475f-b175-351398e562eb/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1708.02002.pdf">https://arxiv.org/pdf/1708.02002.pdf</a></li>
</ul>
<br>

<h3 id="mask-r-cnn-2017">Mask R-CNN (2017)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/37b37e13-9b71-41a3-9f51-a4dc84225889/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/f9e9e931-9fa1-4d0f-9eec-ae571815b874/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1703.06870.pdf">https://arxiv.org/pdf/1703.06870.pdf</a></li>
</ul>
<br>

<h3 id="yolo-v3-2018">YOLO v3 (2018)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/68aaaf1e-8f60-49cc-ac3b-b1271b6a288e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/0ff56d52-2f57-40d8-9dc6-3a5adbcafe93/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1804.02767.pdf">https://arxiv.org/pdf/1804.02767.pdf</a></li>
</ul>
<br>

<h3 id="refinedet-2018">RefineDet (2018)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/50d3d6c4-b255-4a7d-ad37-7019cad44108/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/4860ee4f-97d4-4274-8d78-94afdcd9525a/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1711.06897.pdf">https://arxiv.org/pdf/1711.06897.pdf</a></li>
</ul>
<br>

<h3 id="m2det-2019">M2Det (2019)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/38a51935-eec8-4d35-91cc-17580b948876/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/4fac787b-bb3c-44e1-b4fc-23f9240ddb61/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1811.04533.pdf">https://arxiv.org/pdf/1811.04533.pdf</a></li>
</ul>
<br>

<h3 id="yolo-v4-2020">YOLO v4 (2020)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/576eb0f7-2e73-444a-a596-0b5918b13165/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/d391ea9c-d629-45dd-a58c-18dcd9ffc3f7/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/a01f6972-bd7f-4fa9-afb9-833f07afef2f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/6fc32c2b-470c-4c11-a703-f063de6c52f7/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/2004.10934v1.pdf">https://arxiv.org/pdf/2004.10934v1.pdf</a></li>
</ul>
<br>

<h3 id="efficientdet-2020">EfficientDet (2020)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/2bef035d-5dc5-423a-80b6-fdbb67b69a2d/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/64f420fd-88e2-403a-8428-d77b17a032e2/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/1911.09070.pdf">https://arxiv.org/pdf/1911.09070.pdf</a></li>
</ul>
<br>

<h3 id="detr-2020">DETR (2020)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/a1c3b393-4779-4e03-b60e-dd165f85ce51/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/af84e860-3a57-4478-962e-b1532554a40b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/a469d7c5-e1ed-4c81-b237-0e83a66d4524/image.png" alt=""></p>
<ul>
<li><a href="https://arxiv.org/pdf/2005.12872.pdf">https://arxiv.org/pdf/2005.12872.pdf</a></li>
</ul>
<br>

<h3 id="deformable-detr-2020----swin-transformer2021----yolor-2021">Deformable DETR (2020) -&gt; Swin Transformer(2021) -&gt; YOLOR (2021)</h3>
<p><br><br></p>
<h2 id="yolo-모델-비교">YOLO 모델 비교</h2>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/a8008725-e303-4e78-a029-6f58b73a4d79/image.png" alt=""></p>
<p><br><br></p>
<ul>
<li>참고 문헌</li>
<li><blockquote>
<p><a href="https://herbwood.tistory.com/2">https://herbwood.tistory.com/2</a>,  &#39;Object Detection&#39; 시리즈</p>
</blockquote>
</li>
<li><blockquote>
<p><a href="https://leedakyeong.tistory.com/entry/Object-Detection-YOLO-v1v6-%EB%B9%84%EA%B5%90">https://leedakyeong.tistory.com/entry/Object-Detection-YOLO-v1v6-%EB%B9%84%EA%B5%90</a></p>
</blockquote>
</li>
<li><blockquote>
<p><a href="https://leedakyeong.tistory.com/entry/Object-Detection-YOLO-v1v6-%EB%B9%84%EA%B5%902">https://leedakyeong.tistory.com/entry/Object-Detection-YOLO-v1v6-%EB%B9%84%EA%B5%902</a></p>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Iron View (5) -  Epipolar Geometry]]></title>
            <link>https://velog.io/@jjun-ho/Iron-View-5-Epipolar-Geometry</link>
            <guid>https://velog.io/@jjun-ho/Iron-View-5-Epipolar-Geometry</guid>
            <pubDate>Mon, 20 Feb 2023 07:03:13 GMT</pubDate>
            <description><![CDATA[<h3 id="camera-calibration">Camera Calibration</h3>
<p>카메라의 파라미터(parameters)를 추정하는 과정을 카메라 캘리브레이션이라고 한다.</p>
<p>실세계의 3D 점과 캘리브레이션된 카메라로 캡처한 이미지의 해당 2D 투영(픽셀)간의 정확한 관계를 결정하는데 필요한, 카메라에 대한 모든 정보(파라미터 또는 계수)를 의한다.</p>
<p>일반적으로 이것은 두 종류의 파라미터를 복구하는 것을 의미한다.</p>
<ol>
<li><p>카메라/렌즈 시스템의 내부 파라미터(Internal parameters): 초점 거리(focal length), 광학 중심(optical center), 렌즈의 방사 왜곡 계수(radial distortion coefficients of the lens).</p>
</li>
<li><p>외부 파라미터(External parameters): 이것은 일부 세계 좌표계에 대한 카메라의 방향(회전 및 이동, Rotation and translation)을 나타냅니다.</p>
</li>
</ol>
<p>첫 번째 게시물인, Camera Calibration 게시물에서 Camera Calibration을 계산하고 카메라에 내부 파라미터(Intrinsic Parameter)을 구하는 방법에 대해 학습하였다.</p>
<blockquote>
</blockquote>
<p>[<a href="https://velog.io/@jjun-ho/Iron-View-1-Image-Stiching%5D">https://velog.io/@jjun-ho/Iron-View-1-Image-Stiching]</a></p>
<h3 id="self-calibration">Self-Calibration</h3>
<blockquote>
<p>Self-calibration refers to the process of calculating all the intrinsic parameters of the camera using only the information available in the images taken by that camera. No calibration frame or known object is needed: the only requirement is that there is a static object in the scene, and the camera moves around taking images. Thus self-calibration is ideal for a mobile camera, such as a camera mounted on a mobile robot.</p>
</blockquote>
<p>Self-calibration 은 카메라가 촬영한 이미지에서 사용할 수 있는 정보만을 사용하여 카메라의 모든 고유 매개 변수를 계산하는 과정을 말합니다.</p>
<p>일반적으로 알고있는 camera calibration이 카메라 보정을 위한 격자나 보정판이 필요하다면 self-calibration은 이런 것 없이 카메라 보정을 할 수 있는 방법이다.</p>
<p>단지 영상에서 특징점을 추출하여 fundamental matrix를 구하여 카메라 보정을 하는 방법(fundamental matrix를 계산하면 epipole, projective space에서의 camera matrix, essential matrix를 계산할 수 있다)인데 유클리디안 공간으로 업데이트 하는데 어려움이 있겠지만 유용한 방법인 것 같다.</p>
<p>Self-calibration를 Epipolar Geometry의 개념을 알아야한다.</p>
<blockquote>
<p>Epipolar Geometry 개념은 &#39;다크 프로그래머&#39;님의 [영상 Geometry #7] Epipolar Geometry 게시물을 참고하였습니다. </p>
</blockquote>
<h3 id="epipolar-geometry">Epipolar Geometry</h3>
<p>Epipolar geometry는 동일한 사물 또는 장면에 대한 영상을 서로 다른 두 지점에서 획득했을 때, 영상 A와 영상 B의 매칭쌍들 사이의 기하학적 관계를 다루는 것이다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/ef972549-56da-4ddf-ad9f-ef43953ab03d/image.png" alt=""></p>
<h4 id="용어-및-기본-개념">용어 및 기본 개념</h4>
<p>3차원 공간상의 한 점 P가 영상 A에서는 p에 투영되고, 영상 B에서는 p&#39;에 투영됐다고 하겠습니다. 이 때, 두 카메라 원점을 잇는 선과 이미지 평면이 만나는 점 e, e&#39;을 epipole이라 부르고 투영점과 epipole을 잇는 직선 l, l&#39;을 epiline (또는 epipolar line)이라 부릅니다. Epiline은 3차원의 점 P와 두 카메라 원점을 잇는 평면(epipolar plane)과 이미지 평면과의 교선으로도 볼 수 있습니다.</p>
<p>두 카메라 위치 사이의 기하학적 관계 [R|t]를 알고 있고 영상 A에서의 영상좌표 p를 알고 있을 때, 영상 B에서 대응되는 점 p&#39;의 좌표를 구하는 문제를 생각해 보겠습니다. 이 때, 점 P까지의 거리(depth) 정보를 모른다면 영상좌표 p로부터 투영되기 전의 3차원 좌표 P를 복원할 수는 없습니다. 따라서 점 P가 영상 B에 투영된 좌표 p&#39; 또한 유일하게 결정할 수 없습니다. 하지만 점 P는 A 카메라의 원점과 p를 잇는 직선(ray) 상에 존재하기 때문에 이 직선을 영상 B에 투영시키면 점 p&#39;이 이 투영된 직선 위에 있음은 알 수 있습니다. 이 투영된 직선이 바로 epiline l&#39; 입니다.</p>
<p>정리하면, A의 영상좌표 p로부터 대응되는 B의 영상좌표 p&#39;을 유일하게 결정할 수는 없지만 p&#39;이 지나는 직선인 epiline l&#39;은 유일하게 결정할수 있다&#39; 입니다. 그리고 한 영상좌표로부터 다른 영상에서의 대응되는 epiline을 계산해주는 변환행렬이 Fundamental Matrix, Essential Matrix 입니다. 즉, 서로 다른 두 시점에서 찍은 영상좌표들 사이에는 Fundamental Matrix, Essential Matrix를 매개로 하는 어떤 변환 관계가 성립하는데, Epipolar Geometry에서는 이 변환관계를 바탕으로 여러 기하학적 문제를 풀게 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/4247d39c-b870-46ca-81e0-f3bbd490120f/image.jpeg" alt=""></p>
<p>주어진 점 x에 Essential matrix라는 것을 곱하므로써 epipolar line을 얻을 수 있다</p>
<blockquote>
<p>Ex = l&#39;</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/a1c7f503-b4c2-4f05-86c2-a6a132afb740/image.jpeg" alt=""></p>
<h4 id="essential-matrix">Essential Matrix</h4>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/aaba974a-b670-4aa1-abba-3d388fafbd96/image.jpeg" alt=""></p>
<p>3D 공간상의 한 점 P가 영상 A에서는 p에 투영되고, 영상 B에서는 p&#39;에 투영됐다고 하면 두 영상 좌표 p와 p&#39; 사이에는 다음 관계를 만족하는 행렬이 항상 존재한다는 것이 epipolar geometry의 핵심입니다 (단, p, p&#39;은 normalized 이미지 평면에서의 homogeneous 좌표임).</p>
<blockquote>
<p>(1)<img src="https://velog.velcdn.com/images/jjun-ho/post/f8d8d934-06f3-40ec-bb14-d76c42c5b89c/image.png" alt=""> </p>
</blockquote>
<blockquote>
<p>(2)<img src="https://velog.velcdn.com/images/jjun-ho/post/5564b36a-a40d-4f8b-ae8a-1253b8d41537/image.png" alt=""></p>
</blockquote>
<p>즉, 임의의 두 지점에서 찍은 영상의 매칭점들은 항상 식 (1)을 통해 관계지을 수 있으며, 이 때 식 (1)을 epipolar constraint (또는 essential constraint), 이 3×3 행렬 E를 Essential Matrix라 부릅니다.</p>
<p>Essential Matrix E가 항상 존재하는 이유는 다음과 같습니다. 임의의 두 카메라 좌표축 사이의 관계는 회전, 평행이동에 의해 관계지을 수 있기 때문에 두 카메라 좌표축 사이의 3 × 3 회전행렬을 R, 3 × 1 평행이동 벡터를 t라 했을 때, 외부 공간상의 한 점을 두 카메라 좌표계에서 봤을 때의 관계를</p>
<blockquote>
<p>(3)<img src="https://velog.velcdn.com/images/jjun-ho/post/0343d842-d9f5-4952-a186-9724dee15b6c/image.png" alt=""></p>
</blockquote>
<p>와 같이 잡을 수 있습니다 (단, P는 외부 공간 상의 점을 A 카메라 좌표계에서 봤을 때의 3차원 좌표, P&#39;은 B 카메라 좌표계에서 봤을 때의 3차원 좌표).</p>
<p>이 때, essential matrix E를 다음과 같이 잡으면</p>
<blockquote>
<p>(4)<img src="https://velog.velcdn.com/images/jjun-ho/post/b3f87543-a606-437b-9f7f-62c0e3f22a38/image.png" alt=""></p>
</blockquote>
<p>아래의 식 (5)가 만족됨을 알 수 있습니다. 단, 식 (4)에서 [t]x는 벡터 t와의 벡터 외적(outer product)을 의미합니다. 또한, [t]xR은 t와 R과의 외적을 의미하는게 아니라 먼저 R로 회전을 시킨 후 다음에 t와 외적을 시키는 일련의 변환을 의미합니다. 즉, Ep = [t]xRp = t × (Rp) 입니다.</p>
<blockquote>
<p>(5)<img src="https://velog.velcdn.com/images/jjun-ho/post/e614416a-5934-47a6-a41c-8ef9ef04dd3f/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>(6)<img src="https://velog.velcdn.com/images/jjun-ho/post/4928cea5-7128-413a-a6a1-f135f7f60a6c/image.png" alt=""></p>
</blockquote>
<p>식 (5)의 좌변에 E = [t]xR을 대입해 보면 다음과 같이 항상 0이 나옴을 알 수 있습니다.</p>
<blockquote>
<p>(7)<img src="https://velog.velcdn.com/images/jjun-ho/post/36dc64c3-a90f-4592-ba62-9d592470cf8e/image.png" alt=""></p>
</blockquote>
<p>이제 식 (5)의 카메라 좌표를 정규 이미지 좌표로 바꾸면 식 (1)이 성립함을 알 수 있습니다.</p>
<blockquote>
<p>(8)<img src="https://velog.velcdn.com/images/jjun-ho/post/39a6f932-b676-4af9-bb01-ecd8b17aef70/image.png" alt=""></p>
</blockquote>
<h4 id="fundamental-matrix">Fundamental Matrix</h4>
<p>앞서 설명한 Essential Matrix는 정규화된 이미지 평면에서의 매칭 쌍들 사이의 기하학적 관계를 설명하는 행렬입니다. 즉, 카메라 내부 파라미터 행렬인 K가 제거된 좌표계에서의 변환관계입니다.</p>
<p>반면 fundamental matrix는 카메라 파라미터까지 포함한 두 이미지의 실제 픽셀(pixel) 좌표 사이의 기하학적 관계를 표현하는 행렬입니다.</p>
<p>임의의 두 이미지 A, B에 대하여, 매칭되는 픽셀 좌표 pimg, pimg&#39; 사이에는 항상 다음과 같은 관계를 만족하는 행렬 F가 존재하고, 이러한 행렬 F를 fundamental matrix라 부릅니다.</p>
<blockquote>
<p>(9)<img src="https://velog.velcdn.com/images/jjun-ho/post/f881702a-72f6-4e47-9201-0085ec7c0546/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>(10)<img src="https://velog.velcdn.com/images/jjun-ho/post/a488862f-f7c9-4049-9689-cf8e80aa4783/image.png" alt=""></p>
</blockquote>
<p>이 때, 이미지 A에 대한 카메라 내부 파라미터 행렬을 K, 이미지 B에 대한 카메라 행렬을 K&#39;, 이미지 A, B 사이의 essential matrix를 E라 하면 fundamental matrix F는 다음과 같이 주어집니다.</p>
<blockquote>
<p>(11)<img src="https://velog.velcdn.com/images/jjun-ho/post/44b129a0-1bc0-4bdc-869e-d22d3ef328c4/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>(12)<img src="https://velog.velcdn.com/images/jjun-ho/post/bf6ba012-e957-46c2-96f1-aef9a4232f51/image.png" alt=""></p>
</blockquote>
<p>만일 이미지 A, B를 동일한 카메라로 촬영했다면 카메라 행렬(K)이 동일하기 때문에 식 (11), 식 (12)는 다음과 같이 좀더 단순화됩니다.</p>
<blockquote>
<p>(13)<img src="https://velog.velcdn.com/images/jjun-ho/post/bc9ff041-fcfc-4ed1-a761-07987c922147/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>(14)<img src="https://velog.velcdn.com/images/jjun-ho/post/6700da7a-01ff-45ee-a0c8-200564a5cd25/image.png" alt=""></p>
</blockquote>
<hr>
<p>[부연설명]</p>
<p>이미지 픽셀좌표 pimg와 normalized 좌표 p 사이에는 camera matrix K에 대해 다음과 같은 변환관계를 가집니다.</p>
<blockquote>
<p>(15)<img src="https://velog.velcdn.com/images/jjun-ho/post/aa5d501a-11a5-4149-974a-52cb79e8e02f/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>(16)<img src="https://velog.velcdn.com/images/jjun-ho/post/7f1e6933-a9ca-47d3-a143-612f369fb0b9/image.png" alt=""></p>
</blockquote>
<p>따라서 이미지 A의 카메라 파라미터 행렬을 K, 이미지 B의 카메라 파라미터 행렬을 K&#39;라 놓으면 다음 관계가 성립합니다.</p>
<blockquote>
<p>(17)<img src="https://velog.velcdn.com/images/jjun-ho/post/7d42381b-b6db-43df-8daf-1eec0e27caef/image.png" alt=""></p>
</blockquote>
<p>이제 식 (17)를 식 (1)에 대입하면 다음과 같이 fundamental matrix가 구해짐을(존재함을) 알 수 있습니다.</p>
<blockquote>
<p>(18)<img src="https://velog.velcdn.com/images/jjun-ho/post/46e93b5e-c71b-4645-a530-1018c595e94a/image.png" alt=""></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Iron View (4) - Cylinder Projection]]></title>
            <link>https://velog.io/@jjun-ho/Iron-View-4-Cylinder-Projection</link>
            <guid>https://velog.io/@jjun-ho/Iron-View-4-Cylinder-Projection</guid>
            <pubDate>Wed, 08 Feb 2023 15:06:31 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jjun-ho/post/781eafe1-3565-45d8-b8bd-38d9b05f8f55/image.png" alt=""></p>
<h2 id="concept-1">Concept 1</h2>
<p>카메라를 원형(팔각형)으로 설치하고 -&gt; 이미지 스티칭 및 블랜딩 -&gt; 그거 자체로 원기둥 이미지의 효과</p>
<h2 id="concept-2">Concept 2</h2>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/0d89eba0-ed80-4233-8330-8348de13b352/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/d3b0c59a-42fc-42cd-a553-15b59547ca01/image.png" alt=""></p>
<p>기존의 원통 및 구면 파노라마 영상을 생성하는 방법 에는 전제 조건이 있는데, 카메라가 동일한 높이에서 좌우로 영상을 찍어야만 하며 초점거리 f 값을 알아야한다. 
초점거리 f 값이 주어졌을 때 일반적으로 2차원 공간상영상의 모든 점 p=(x, y)의 좌표를 3차원 공간 상의 p=(x, y, f) 점으로 보고 직교(Cartesain) 좌표계 에서 구면 좌표계로 수식 (8)과 같이 변환한다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/da53856a-60c9-4374-887d-f1d54a7416c1/image.png" alt=""></p>
<p>여기서 f는 초점거리, s는 scaling factor 값인데 보통 f와 같은 값을 갖는다. 구면 좌표계로 변환된 (x&#39;,y&#39;) 값을 다시 수식 (9)과 같이 직교 좌표계 (x&quot;,y&quot;)로 역 변환하여 구면 영상을 얻는다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/68cbbb2e-d634-4ac5-a9ff-c426f910786e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/5a6a4094-1fd3-4ed8-9c2f-6d0b67342663/image.png" alt=""></p>
<p>(a)와 같은 영상을 초점거리 f=700으로 가정하여 수식 (8)로 변환시키면 직교 좌표계의 영상을 구면 좌표계상에서 보는 것이 되므로 (b)와 같이 영상의 양 옆 부분은 커지고 더 가까워져 보이게 된다. 수식(9)로 역변환을 시키면 구면 좌표계상에서 보던 영상을 다시 직교 좌표계로 가져오는 것이 되며 (c)와 같이 된다. 이때 모든 수평선들은 곡선 을 이루게 된다.</p>
<p> 일반적인 구면 파노마라 영상 생성 방법은 이와 같이 먼저 모든 영상에 대해서 구면 영상 변환을 수행하고 x, y축으로의 이동(t_x, t_y) 두 개의 매개변수만으로 매 칭을 하여 합성한다. 이때 사용자는 고정된 높이의 카 메라를 통해 어떠한 회전이나 스케일 변화 없이 좌우상 하이동만으로 영상을 찍어야 한다. 이동 외의 회전 및 스케일 변화가 생기면 영상 매칭이 어려워지고 정보 손실이 더 커질 수 밖에 없으며 사용자가 카메라를 손에 쥐고 있으면 회전이나 스케일의 변화를 안주고 x, y축 으로만 돌려 촬영한다는 보장은 없다.</p>
<p> 사용자에 의해 생길 수 있는 여러 변화에 강건한 구면 파노라마 영상 생성하는 방법 즉, 어떤 카메라든 상관없이 동영상을 촬영한 후 손 흔들림으로 인한 회전, 스케일의 변화가 있더라도 효과적으로 구면 파노라마 단일 영상을 생성하는 방법을 제안한다.</p>
<blockquote>
<p>먼저 모든 프레임에 대해서 영상을 호모그래피로 변 환한 후, 단일 영상을 얻었을 때 수식 (9)의 구면 좌표계 역변환을 한번만 수행하여 구면 파 노라마 영상을 얻는 방법을 제안한다. 평면 파노마라 영상은 자유도가 8인 호모그래피로 합성되기 때문에 이동, 회전, 스케일, 원근 변화에서도 최적의 변환을 수 행할 수 있어서 기존의 원통 및 구면 파노라마 영상에 비해 정보 손실이 작은 편이다. 기존의 구면 파노라마 영상 생성 방법과 달리 각 영상에 대해서 먼저 구면 영상 변환을 하지 않고 호모그래피를 통해 평면 파노라마 영상을 얻은 후에 초점거리 정보를 이용해 구면 좌표계 역변환 수식 (9)로 한번 변환시켜 원하는 구면 파노라 마 영상을 생성하는 방법이다. 여기서 수식 (9)의 구면 좌표계 역변환만을 하는 것은 일반 영상과 다르게 평면 파노라마 영상에 구면 좌표계상에서 보는 것과 같은 원근 정보가 포함되어 있기 때문이다. 카메라의 초점거리 정보를 모르는 상태에서는 호모 그래피 행렬 매개변수들을 이용해 이를 계산할 수 있 다. 각 호모그래피는 수식 (10)와 같이 표현될 수 있다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/e5b59617-86dd-4a61-90c5-d73371b71da1/image.png" alt=""></p>
</blockquote>
<p>여기서 K0, K1은 두 영상에 대한 초점거리와 중심점 매 개변수를 갖는 카메라 내부(intrinsic)행렬, R는 회전 매개변수들을 갖는 외부(extrinsic)행렬이며 간단한 연산을 통해 초점거리 f0, f1을 쉽게 구할 수 있다. 추 정된 두 개의 초점거리 f0, f1의 기하학적 평균을 최종 초점거리 f로 택한다. 예시에서는 모든 호모그래피 에서 초점거리를 각각 계산하고 중간(Median)값을 최종적으로 선택하였다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/53aa1e56-4792-4002-8d86-809b17a99d77/image.jpg" alt=""></p>
<h2 id="concept-3">Concept 3</h2>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/ad754273-9d8c-4f91-8bbf-ad4b7fc55205/image.png" alt=""></p>
<p>오목한 원통이 앞에 있는 평면 이미지가 있다고 가정</p>
<p>첫 번쨰 단계는, 이미지를 곡면으로 직교 투영을 수행하는 것입니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/b19f6207-3c6c-4503-8271-73c75abb5aee/image.png" alt=""></p>
<p>그런 다음 해당 점은 이미지 평면에 다시 원근법으로 투영됩니다. 이 경우 실린더의 모든 부분이 이미지 평면보다 큰 z 좌표를 가지기 때문에 전체 이미지가 축소됩니다. 귀하의 경우 실린더가 왼쪽 및 오른쪽 가장자리의 이미지 평면에 닿아 축소가 발생하지 않습니다. 포인트가 다시 투영되면 이미지 평면에서 더 이상 평평한 선을 형성하지 않으며 x에 따라 달라지는 원통의 z 좌표 때문에 곡선이 있습니다.</p>
<p> <img src="https://velog.velcdn.com/images/jjun-ho/post/41b0dfd8-0c1e-4211-bc61-f3faa5b3685d/image.png" alt=""></p>
<p>첫 번째 트릭은 실제로 이 프로세스를 거꾸로 표현하려는 것입니다. 먼저 원본 이미지의 모든 픽셀을 가져와 새 이미지로 옮기고 싶다고 생각할 수 있습니다. 이전 이미지에 나타난 새 이미지의 모든 픽셀을 확인하고 색상을 설정하면 실제로 훨씬 더 잘 작동합니다. 즉, 3가지 작업을 수행해야 합니다.</p>
<ol>
<li>실린더 매개변수 설정</li>
<li>카메라에서 광선을 투사하여 새 이미지의 각 지점을 통과하고 실린더에서 x,y,z 좌표를 찾습니다.</li>
<li>직교 투영을 사용하여 해당 광선을 이미지 평면으로 다시 이동합니다(단지 z 구성 요소를 드롭한다는 의미임).</li>
</ol>
<p>모든 것을 추적하는 것은 약간 까다로울 수 있으므로 일관된 용어를 사용하려고 노력할 것입니다. 우선, 실린더가 가장자리에서 이미지에 닿도록 보장하고 싶다고 가정합니다. 이것이 사실이라면 선택할 수 있는 2개의 자유 매개변수는 실린더 반경과 초점 거리입니다.</p>
<p>zx 평면에서 원의 방정식은 다음과 같습니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/85c89403-4b17-468b-927f-bfecad91cefd/image.png" alt=""></p>
<p>원의 중심이 z축에 있다고 가정합니다. 실린더의 가장자리가 너비가 w이고 초점 거리가 f인 이미지 평면의 가장자리에 닿을 경우</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/85b9b428-16c2-4294-8fea-8b3aed0a32eb/image.png" alt=""></p>
<p>이제 우리는 카메라에서 xim의 이미지 평면을 통해 xc의 실린더로 라인을 투사하는 2단계로 이동하는 실린더의 모든 매개변수를 알고 있습니다. 다음은 용어의 빠른 다이어그램입니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/0b327b17-d45d-4192-a337-b038dcd7c170/image.png" alt=""></p>
<p>우리가 투사하는 선이 원점에서 시작하여 xim에서 이미지 평면을 가로지르는 것을 알고 있습니다. 방정식을 다음과 같이 쓸 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/95a34189-9c38-410b-8469-5e6f2a6adcb3/image.png" alt=""></p>
<p>원통을 통과할 때 x 좌표를 원하므로 방정식을 결합합니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/79225381-b0ff-4df2-ae03-e71d6e961485/image.png" alt=""></p>
<p>이차방정식을 사용하여 z를 구한 다음 다시 선 방정식에 연결하여 x를 얻을 수 있습니다. 두 솔루션은 선이 원에 닿는 두 위치에 해당합니다. 우리는 이미지 평면 이후에 발생하는 하나에만 관심이 있고 하나는 항상 더 큰 x 좌표를 가지므로 -b + sqrt(...)를 사용하십시오. . 그 다음에</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/577cce13-0a92-4bd8-a4be-9093b5f24148/image.png" alt=""></p>
<p>직교 투영을 제거하는 마지막 단계는 간단합니다. z 구성 요소를 놓으면 완료됩니다.</p>
<p>참고링크
<a href="https://stackoverflow.com/questions/12017790/warp-image-to-appear-in-cylindrical-projection">https://stackoverflow.com/questions/12017790/warp-image-to-appear-in-cylindrical-projection</a></p>
<p><a href="http://paulbourke.net/panorama/cylinder">http://paulbourke.net/panorama/cylinder</a></p>
<p><a href="https://chamcham.tistory.com/25">https://chamcham.tistory.com/25</a></p>
<p><a href="https://www.morethantechnical.com/2018/10/30/cylindrical-image-warping-for-panorama-stitching/">https://www.morethantechnical.com/2018/10/30/cylindrical-image-warping-for-panorama-stitching/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Iron View (3) - Geometry]]></title>
            <link>https://velog.io/@jjun-ho/Iron-View-4-Geometry</link>
            <guid>https://velog.io/@jjun-ho/Iron-View-4-Geometry</guid>
            <pubDate>Thu, 02 Feb 2023 05:45:15 GMT</pubDate>
            <description><![CDATA[<h3 id="좌표계-coordinate-system">좌표계 (Coordinate System)</h3>
<p>직각 좌표계, 원통 좌표계, 구 좌표계</p>
<h4 id="직각-좌표계-cartesian-coordinate-system">직각 좌표계 (cartesian coordinate system</h4>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/d270c5cb-c3fc-4263-af62-dbf6caee6ff8/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/9dbf964f-e929-467c-9a05-2e969c3f31fb/image.png" alt=""></p>
<h4 id="원통-좌표계-circular-cylindrical-coordinate-system">원통 좌표계 (circular cylindrical coordinate system)</h4>
<p>원통좌표계 (cylindrical coordinate system)는 3차원 공간을 나타내기 위한 좌표계이다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/0b0b3926-b7b8-4738-b862-c076045eef4a/image.png" alt=""></p>
<p>원통좌표계는 반지름r(반경), 방위각Φ, 높이z 의 변수로 좌표를 표현한다.</p>
<blockquote>
<p>r은 원점 O에서 P의 xy평면으로의 사영 p까지의 거리를 나타낸다. 다시 말하면, r은 z축에서 P까지의 거리이다.</p>
<p>$\theta$ 는 양의 x축 방향에서 반시계 방향으로 측정한 OP까지의 각이다.</p>
<p>z는 z와 같다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/7ac1bb49-a78c-42d0-9023-9ebc6349dea6/image.png" alt=""></p>
<p>좌표계가 직교좌표계이므로 세 단위벡터는 서로 수직이다.</p>
<h3 id="직교좌표계에서-원통좌표계로의-변환">직교좌표계에서 원통좌표계로의 변환</h3>
<ol>
<li>점 변환하기</li>
</ol>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/5692c0a1-c8ba-4a3b-8962-063713ebef24/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/65db637f-9481-46b2-a7e2-9991a2b0590a/image.png" alt=""></p>
<p>z축은 동일하다. </p>
<ol start="2">
<li>단위벡터 변환하기
<img src="https://velog.velcdn.com/images/jjun-ho/post/31faa06d-fc8f-4540-a64e-ffdde8aacb70/image.png" alt=""></li>
</ol>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/71b4905e-8c07-4903-8982-8aabc3812f0c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/16d3ee92-b23f-44a8-a9a6-55e62e276660/image.png" alt=""></p>
<ol start="3">
<li>벡터 변환하기
단위벡터 변환한 것을 그대로 대입해서 정리하면 된다</li>
</ol>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/cf6467da-6e31-48f6-82c4-4d5f8b231565/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/dd55834c-b551-4d7a-9057-7bd19b0e8123/image.png" alt=""></p>
<blockquote>
<p>추가 공식
<img src="https://velog.velcdn.com/images/jjun-ho/post/70dad60c-c7f2-4a7f-a4e4-5fc3b1c794d4/image.png" alt=""></p>
</blockquote>
<p><br><br></p>
<h3 id="영상-좌표계-coordinate-system">영상 좌표계 (Coordinate System)</h3>
<p>영상 Geometry에서는 크게 4가지 좌표계가 존재한다.</p>
<blockquote>
<p>월드 좌표계, 카메라 좌표계, 정규 좌표계, 픽셀 좌표계
<img src="https://velog.velcdn.com/images/jjun-ho/post/335e201c-f617-40c8-9f80-b818c330f435/image.png" alt="">
월드 좌표계와 카메라 좌표계는 3차원 좌표계이고, 정규좌표계와 픽셀좌표계는 2D 좌표계입니다</p>
</blockquote>
<h4 id="월드-좌표계-world-coordinate-system">월드 좌표계 (World Coordinate System)</h4>
<p>우리가 사물(물체)의 위치를 표현할 때 기준으로 삼는 좌표계입니다. 월드좌표계는 어디 하늘에서 주어져 있는 것이 아니라 문제에 따라서 우리가 임의로 잡아서 사용할 수 있는 좌표계입니다. 예를 들어, 자신의 안방 한쪽 모서리를 원점으로 잡고 한쪽 벽면 방향을 X축, 다른쪽 벽면 방향을 Y축, 하늘을 바라보는 방향을 Z축으로 잡을 수 있습니다. 좌표의 단위(unit)는 미터(meter)로 해도 되고 센티미터(centimeter)로 해도 됩니다. 중요한 점은 좌표계는 일종의 약속(protocol)이기 때문에 제시한 점이 어떤 위치인지 그 문제 내에서 만큼은 유일하게 결정될 수 있으면 되는 것입니다. 이 글에서는 월드좌표계 상의 점을 다음과 같이 대문자로 표기합니다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/84e3ba08-3649-4890-b0c6-935017a13ed4/image.png" alt=""></p>
<h4 id="카메라-좌표계-camera-coordinate-system">카메라 좌표계 (Camera Coordinate System)</h4>
<p>월드 좌표계가 우리가 살고 있는 공간의 한 지점을 기준으로 한 좌표계라면 카메라 좌표계는 카메라를 기준으로 한 좌표계입니다. 카메라 좌표계는 아래 그림과 같이 카메라의 초점(렌즈의 중심)을 원점, 카메라의 정면 광학축 방향을 Z축, 카메라 아래쪽 방향을 Y축, 오른쪽 방향을 X축으로 잡습니다. 기호는 월드좌표계와 구분하기 위해 아랫첨자 c를 사용하겠습니다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/6c8b4c88-19db-4734-8efe-ca84c76aa11c/image.png" alt=""></p>
<p>카메라 좌표계의 단위는 물론 월드좌표계와 동일해야 할 것입니다. 즉, 월드 좌표계에서 meter 단위를 사용한다면 카메라 좌표계도 meter 단위를 사용합니다. 이 글에서는 카메라 좌표계를 기준으로 한 점의 좌표는 다음과 같이 아랫첨자 c를 사용한 대문자로 표기합니다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/364ce971-44e7-4ca6-9706-45137176bdba/image.png" alt=""></p>
<h4 id="픽셀-좌표계-pixel-image-coordinate-system">픽셀 좌표계 (Pixel Image Coordinate System)</h4>
<p>보통은 영상좌표계(Image Coordinate System)라고 불립니다. 픽셀 좌표계는 우리가 실제 눈으로 보는 영상에 대한 좌표계로서 이미지의 왼쪽상단(left-top) 모서리를 원점, 오른쪽 방향을 x축 증가방향, 아래쪽 방향을 y축 증가방향으로 합니다. 그리고 픽셀 좌표계의 x축, y축에 의해 결정되는 평면을 이미지 평면 (image plane)이라 부릅니다.</p>
<p>기하학적으로 볼 때, 3D 공간상의 한 점 P = (X,Y,Z)는 카메라의 초점 (또는 렌즈의 초점)을 지나서 이미지 평면의 한 점 pimg = (x, y)에 투영(projection) 됩니다. 알다시피 점 P와 점 pimg를 잇는 선(ray) 상에 있는 모든 3D 점들은 모두 pimg로 투영됩니다. 따라서 3D 점 P로부터 pimg는 유일하게 결정할 수 있지만, 반대로 영상 픽셀 pimg로부터 P를 구하는 것은 부가적인 정보 없이는 불가능합니다.</p>
<p>어쨌든 픽셀 좌표계의 단위는 픽셀(pixel)이며, 픽셀 좌표는 다음과 같이 소문자로 표기합니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/e6c861cf-7f11-4376-959c-cf02b2f2ee58/image.png" alt=""></p>
<h4 id="정규-좌표계-normalized-image-coordinate-system">정규 좌표계 (Normalized Image Coordinate System)</h4>
<p>마지막으로 가장 중요한 정규좌표계입니다. 원래는 정규 이미지 좌표계이지만 줄여서 정규 좌표계로 쓰겠습니다. 지금까지 나온 좌표계는 모두 매우 직관적인 좌표계이지만 정규 좌표계는 편의상 도입된 가상의 좌표계입니다.</p>
<p>정규 좌표계를 한마디로 설명하자면 카메라의 내부 파라미터(intrinsic parameter)의 영향을 제거한 이미지 좌표계로 볼 수 있습니다. 또한 정규 좌표계는 좌표계의 단위를 없앤(정규화된) 좌표계이며 카메라 초점과의 거리가 1인 가상의 이미지 평면을 정의하는 좌표계입니다.</p>
<p>좀더 쉽게 생각하자면, 원래의 이미지 평면을 평행이동시켜서 카메라 초점과의 거리가 1인 지점으로 옮겨놓은 이미지 평면을 생각하면 됩니다.</p>
<p>정규 좌표계의 원점은 정규 이미지 평면의 중점(광학축 Zc와의 교점)입니다 (그림 1 참조). 픽셀 좌표계와 원점의 위치가 다름에 주의하기 바랍니다. 그리고 좌표축은 픽셀 좌표계와 구분하기 위해 u, v를 사용하겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/28438665-b4ed-461b-8b8c-f687bc53d2fc/image.png" alt=""></p>
<p>카메라 내부 파라미터를 알면 다음과 같이 픽셀 좌표와 정규 좌표 사이의 변환이 가능합니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/5814d1db-4355-483c-ba5e-7ffe90c67d60/image.png" alt=""></p>
<p>여기서 fx, fy는 초점거리, cx, cy는 주점(principal point, 광학축과 영상평면이 만나는 픽셀좌표)이며, 가운데 3 x 3 행렬을 camera matrix라 부릅니다. 위 식을 정리하면 다음과 같은 식이 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/fc0badeb-998d-4a81-a1fb-771785ab9fb9/image.png" alt=""></p>
<p>역으로, 이미지 상의 픽셀 (x, y)에 대응하는 정규좌표는 다음과 같이 계산됩니다.</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/4f0739cd-12f0-4956-9661-08f68a6dd559/image.png" alt=""></p>
<blockquote>
<p> 굳이 정규 이미지 평면과 정규 좌표계를 도입한 이유</p>
</blockquote>
<p>우리가 동일한 장면을 동일한 위치와 동일한 각도에서 찍더라도 사용한 카메라에 따라서 또는 카메라 세팅에 따라서 서로 다른 영상을 얻게 됩니다. 그런데, 이러한 카메라 간의 차이는 어떤 일관된 기하학적인 해석을 하는데 있어서 불필요한 요소일 것입니다. 따라서, 이러한 요소를 제거한 정규화된 이미지 평면에서 공통된 기하학적 특성을 분석하고 이론을 수립하는 것이 보다 효과적이기 때문입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Iron View (2) - Homography]]></title>
            <link>https://velog.io/@jjun-ho/Iron-View-2-Homography</link>
            <guid>https://velog.io/@jjun-ho/Iron-View-2-Homography</guid>
            <pubDate>Wed, 25 Jan 2023 12:57:52 GMT</pubDate>
            <description><![CDATA[<h3 id="이미지-변환image-transformation">이미지 변환(Image Transformation)</h3>
<p>이미지 변환은 주어진 영상에 특정 알고리즘을 적용하여 변환된 이미지를 얻어내는 것을 의미한다. 주어진 영상을 평행이동(translation), 회전(rotation), 크기(scale), 시점(perspective)등을 적용해 원하는 이미지를 얻어내는 방식이다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/882db110-8a5e-4851-a75a-fa0ea9252028/image.png" alt=""></p>
<h4 id="rigid-tranformation">Rigid Tranformation</h4>
<p>이미지 변환의 가장 기본적인 형태로, 이미지의 크기를 고정시킨 변환이다. 즉, 평행이동(translation)과 회전(rotation)만을 허용한 변환이다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/85724a1c-f720-4495-a8d3-1916cc7e453f/image.png" alt=""></p>
<blockquote>
<p>평행이동(Translation)<img src="https://velog.velcdn.com/images/jjun-ho/post/34a7ba21-78b8-4b8a-8b79-909781bfbdcf/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>회전(Rotation)<img src="https://velog.velcdn.com/images/jjun-ho/post/50b2feea-9bbe-4675-9505-0e534763c1a9/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>평행이동 + 회전<img src="https://velog.velcdn.com/images/jjun-ho/post/f0d0f90c-1f52-4f2e-9791-f966095787cd/image.png" alt=""></p>
</blockquote>
<h4 id="similar-transformation">Similar Transformation</h4>
<p>rigid transformation에 물체의 크기 변화, 즉 scale의 변화를 추가적으로 고려한 변환이며, 이때 물체의 모양은 보존된다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/95385858-c19e-4519-8dc7-502db26afd72/image.png" alt=""><img src="https://velog.velcdn.com/images/jjun-ho/post/3f83154f-54aa-41c8-a969-58689fd14327/image.png" alt=""></p>
<h4 id="affine-transformation">Affine Transformation</h4>
<p>affine transformation은 similiarity transformation에 선형성을 보존하는 특징을 더한 변환이다. 따라서 직선의 평행 관계, 길이와 거리의 비 등이 보존된다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/4dbfdee4-3418-4033-b335-a5c001a48d87/image.png" alt=""><img src="https://velog.velcdn.com/images/jjun-ho/post/2017a386-85b8-46a2-9da5-6452b217f32f/image.png" alt=""></p>
<h4 id="projective-transformation">Projective Transformation</h4>
<p>3D 공간에서의 이미지를 2D 공간으로 투영시킨 변환이다. 즉, 3D 공간에서 서로 다른 두 시점에서 바라본 두 개의 이미지를 서로 변환하는 방법이다. 이때 서로 다른 두 이미지의 관계를 표현한 행렬을 homography라 한다.
<img src="https://velog.velcdn.com/images/jjun-ho/post/925eb2f1-21d1-4388-a3af-85f72c034daf/image.png" alt=""></p>
<h3 id="homographyprojective-transformation">Homography(Projective Transformation)</h3>
<p>Planer surface 물체의 경우에는 3D 공간에서의 2D 이미지로의 임의의 원근투영변환을 두 이미지 사이의 Homography로 모델링할 수 있다. 즉, 어떤 planar surface가 서로 다른 카메라 위치에 대해 이미지 A와 이미지 B로 투영되었다면 이미지 A와 이미지 B의 관계를 Homography로 표현할 수 있다.</p>
<blockquote>
<p>Homography는 homogeneous 좌표계에서 정의되며 그 일반식은 다음과 같습니다.<img src="https://velog.velcdn.com/images/jjun-ho/post/4ac75c3d-341d-4b6d-ad4d-57d77f91498c/image.png" alt=""></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Iron View (1) - Camera Calibration]]></title>
            <link>https://velog.io/@jjun-ho/Iron-View-1-Image-Stiching</link>
            <guid>https://velog.io/@jjun-ho/Iron-View-1-Image-Stiching</guid>
            <pubDate>Mon, 23 Jan 2023 16:22:22 GMT</pubDate>
            <description><![CDATA[<h3 id="카메라-캘리브레이션camera-calibration이란">카메라 캘리브레이션(Camera Calibration)이란</h3>
<blockquote>
<p>실제 눈으로 보는 3차원 세상 -&gt; &#39;카메라&#39; -&gt; 2차원 이미지 </p>
</blockquote>
<p>3차원의 점들이 이미지 상에서 어디에 맺히는지 결정하는 요인</p>
<blockquote>
<p>영상을 찍을 당시의 카메라의 위치 및 방향 </p>
</blockquote>
<blockquote>
<p>카메라 내부의 기구적인 부분</p>
<blockquote>
<p>사용된  렌즈 
렌즈와 이미지 센서와의 거리 
렌즈와 이미지 센서가 이루는 각</p>
</blockquote>
</blockquote>
<p>3차원 점들이 영상에 투영된 위치를 구하거나 역으로 영상좌표로부터 3차원 공간좌표를 복원할 때에는 이러한 내부 요인을 제거해야하만 정확한 계산이 가능한다. 따라서 이러한 내부요인의 파라미터 값을 구하는 과정을 카메라 캘리브레이션이라 부른다.</p>
<h3 id="투영projection">투영(Projection)</h3>
<p>카메라 영상은 3차원 공간상의 점들을 2차원 이미지 평면에 투사(Perspective Projection)함으로써 얻어집니다.</p>
<h4 id="pin-hole-camera-model">Pin-hole Camera Model</h4>
<p>실제: 상하좌우 반전
<img src="https://velog.velcdn.com/images/jjun-ho/post/d0ec2c46-0b75-4df1-b1c7-f881cc2e4182/image.png" alt="">
편의를 위한 좌표계 일치 = 실제
<img src="https://velog.velcdn.com/images/jjun-ho/post/453d0d02-f660-4177-82c6-85c9d8aaf7d2/image.png" alt="">
이미지센서는 실제로는 렌즈 뒤쪽에 있지만, 기하학적 연산을 단순화하기 위해 위 그림처럼 앞쪽에 위치시키는 것이 일반적이다</p>
<h4 id="ideal-perspective-projection">Ideal Perspective Projection</h4>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/1e7c9131-d7d5-4ad9-852a-f8ee4ca3a151/image.png" alt=""></p>
<blockquote>
<p>핀홀(Pinhole) 카메라 모델에서 변환 관계
<img src="https://velog.velcdn.com/images/jjun-ho/post/66b7eb18-c8ed-4842-bd28-a37aebe306f1/image.png" alt="">
<img src="https://velog.velcdn.com/images/jjun-ho/post/4c123279-5fb2-418c-b645-ef9b6061a70e/image.png" alt=""></p>
<blockquote>
<p>+) 현대의 카메라의 초점거리는 fx=fy로 계산해도 무방하다
+) 현대의 카메라의 비대칭계수 skew=0으로 계산해도 무방하다</p>
</blockquote>
</blockquote>
<p>카메라 외부 파라미터 (Extrinsic Parameter)</p>
<blockquote>
<p>카메라의 설치 높이, 방향(팬, 틸트) 등 카메라와 외부 공간과의 기하학적 관계에 관련된 파라미터이다</p>
</blockquote>
<p>카메라 내부 파라미터 (Intrinsic Parameter)</p>
<blockquote>
<p>카메라의 초점 거리, aspect ratio, 중심점 등 카메라 자체의 내부적인 파라미터를 의미한다.</p>
</blockquote>
<h3 id="렌즈-왜곡-lens-distortion">렌즈 왜곡 (Lens Distortion)</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/b5fa7e14-e96c-4f2d-bb6b-5a04a0d31b09/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/3ee25367-0095-497b-bfc3-f11d4556d728/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/c0703b3c-47c2-41ca-a7ad-f1f3402abfe6/image.png" alt=""></p>
<h3 id="zhangs-camera-calibration">Zhang&#39;s Camera Calibration</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/2a0ab11c-05ef-4aae-b7aa-4f3488e76b2f/image.png" alt=""></p>
<blockquote>
<p>Perspective Projection
<img src="https://velog.velcdn.com/images/jjun-ho/post/e4c725f0-7631-4dc9-89e9-fddaaa6f820d/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>Principal Point offset
<img src="https://velog.velcdn.com/images/jjun-ho/post/7cf65f46-539e-4aec-ba1c-4963392286ea/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>3차원의 점을 2차원의 이미지 Plane으로 투영
Calibration Matrix
<img src="https://velog.velcdn.com/images/jjun-ho/post/741c406a-d444-4afe-be77-8a815f61773b/image.png" alt=""></p>
</blockquote>
<blockquote>
<p>Zhang&#39;s Method: 2차원의 체커보드 판 위에 점을 2차원의 Plane으로 투영 
-&gt; Calibration Matrix
<img src="https://velog.velcdn.com/images/jjun-ho/post/01ff7979-a9c8-4280-b77c-4b239ed72136/image.png" alt=""></p>
</blockquote>
<blockquote>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/6cbe989c-5850-41cf-8166-ccb5515c8c00/image.jpeg" alt=""></p>
<p>평면 위에 점을 투영하기 때문에 z=0이 되기 때문에 r1과 r2를 구하고 각 회전축은 수직인 성질을 이용하여 r1과 r2의 외적은 r3이다</p>
<blockquote>
<p>$$r1 * r2 = r3$$</p>
</blockquote>
</blockquote>
<blockquote>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/78965908-a1a6-4fdd-8d40-fd07f6100153/image.jpeg" alt=""></p>
<p>위 식에서 구한 H = [h1 h2 h3] 라 할 때, </p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/9fd3616a-321b-4b1f-80f6-cc3cd4ffa0a7/image.png" alt=""></p>
<p>여기서 λ는 Scale (스케일에 따라 위 식이 하나로 정의 안되기 때문에 λ는 스칼라)</p>
<p>위 식에서 </p>
<blockquote>
<p>$$h_1 =  λ<em>A</em>r1$$ 
-&gt; $$r_1 = (1/λ)<em>A^{-1}</em>h_1$$ 
-&gt; $$r^T_1 = (1/λ)<em>h^{T}_1</em>A^{-T}$$ </p>
<p>$$h_2 =  λ<em>A</em>r2$$ 
-&gt; $$r_2 = (1/λ)<em>A^{-1}</em>h_2$$ 
-&gt; $$r^T_2 = (1/λ)*h^{T}_2 * A^{-T}$$</p>
<p>$$h_3 =  λ<em>A</em>t$$</p>
</blockquote>
</blockquote>
<blockquote>
<p>회전축은 서로 수직이고 크기는 1로 같기때문에 </p>
<blockquote>
<p>$$r_1•r_2 = r^{T}_1<em>r_2 = 0$$
$$||r_1||^2 = ||r_2||^2 = r^T_1</em>r_1 = r^T_2*r_2$$</p>
</blockquote>
<p>를 이용하면</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/ef138615-d097-4126-bc2e-f706d592db63/image.png" alt=""></p>
</blockquote>
<p> 위 수식을 다시 표현하면 </p>
<blockquote>
<p>$$h^T_1<em>K^{-T}</em>K^{-1}<em>h_2 = 0$$
$$h^T_1</em>K^{-T}<em>K^{-1}</em>h_1 = h^T_2<em>K^{-T}</em>K^{-1}*h_2$$</p>
</blockquote>
<p>K는 카메라의 내부 파라미터로, 즉 Intrinsic Parameter 이므로 K와 K의 역행렬은 다음과 같다</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/703f3a18-377d-4184-bea4-242782993f79/image.png" alt=""></p>
<p>추가적으로, 만약 비대칭계수 skew가 0이 아니라면 K의 역행렬은 다음과 같이 표현 할 수 있다 </p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/9a904ece-1361-44a2-a9d6-b4c47f0d943a/image.png" alt=""></p>
<p>행렬 $$K^{-T}*K^{-1}$$ 을 A로 표현하면</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/1b38fa0d-e16e-4e3b-8363-fa03fe6f761a/image.png" alt=""></p>
<p>행렬 A를 구했다고 하면 A로부터</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/32bf689c-b921-4618-983f-60b1c80566d5/image.png" alt=""></p>
<p>인 식에 의해서 카메라 내부 변수 값을 구할 수 있다.</p>
<p>r1, r2의 크기가 1이고, r1, r2, r3가 회전축으로 각각 직교하기 때문에 $$r_3 = r_1 X r_2$$ 이다</p>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/d1b0def9-ea47-455d-9d4a-c6826e89fc32/image.png" alt=""></p>
<p>여기까지가 카메라 렌즈 왜곡을 제외한 카메라 Calibration 식이다.</p>
<h3 id="stereo-camera-calibration">Stereo Camera Calibration</h3>
<p><img src="https://velog.velcdn.com/images/jjun-ho/post/524d04e7-4282-4762-be02-18cfdccde2db/image.png" alt=""></p>
<p>참고링크
<a href="https://m.blog.naver.com/jang_hwan_im/221223291713">https://m.blog.naver.com/jang_hwan_im/221223291713</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PyTorch로 딥러닝 배우기 7]]></title>
            <link>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-7</link>
            <guid>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-7</guid>
            <pubDate>Tue, 17 Aug 2021 15:15:57 GMT</pubDate>
            <description><![CDATA[<h1 id="트랜스포머transformer">트랜스포머(Transformer)</h1>
<blockquote>
<p>트랜스포머(Transformer)는 2017년 구글이 발표한 논문인 &quot;Attention is all you need&quot;에서 나온 모델로 기존의 seq2seq의 구조인 인코더-디코더를 따르면서도, 논문의 이름처럼 어텐션(Attention)만으로 구현한 모델이다. 이 모델은 RNN을 사용하지 않고, 인코더-디코더 구조를 설계하였음에도 성능도 RNN보다 우수하다는 특징을 갖고있다.</p>
</blockquote>
<h2 id="기존의-seq2seq-모델의-한계">기존의 seq2seq 모델의 한계</h2>
<blockquote>
<p>기존의 seq2seq 모델은 인코더-디코더 구조로 구성되어져 있었다. 여기서 인코더는 입력 시퀀스를 하나의 벡터 표현으로 압축하고, 디코더는 이 벡터 표현을 통해서 출력 시퀀스를 만들어냈다. 하지만 이러한 구조는 인코더가 입력 시퀀스를 하나의 벡터로 압축하는 과정에서 입력 시퀀스의 정보가 일부 손실된다는 단점이 있었고, 이를 보정하기 위해 어텐션이 사용되었다.
 그런데 어텐션을 RNN의 보정을 위한 용도가 아니라 아예 어텐션으로 인코더와 디코더를 만든 것이 Transformer이다. </p>
</blockquote>
<p><br><br></p>
<h2 id="transformer">Transformer</h2>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/30b30460-dc5d-42a0-91d9-34256c846a50/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%202.15.53.png" alt="">트랜스포머는 RNN을 사용하지 않지만 기존의 seq2seq처럼 인코더에서 입력 시퀀스를 입력받고, 디코더에서 출력 시퀀스를 출력하는 인코더-디코더 구조를 유지하고 있다. 다만 다른 점은 인코더와 디코더라는 단위가 N개가 존재할 수 있다는 점이다.</p>
</blockquote>
<blockquote>
</blockquote>
<p>*<em>인코더로부터 정보를 전달받아 디코더가 출력 결과를 만들어내는 트랜스포머 구조 *</em> <img src="https://images.velog.io/images/jjun-ho/post/fdb39af4-c9a8-4d72-9a1c-617621be75af/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%202.16.34.png" alt="">디코더는 마치 기존의 seq2seq 구조처럼 시작 심볼 &lt;sos&gt;를 입력으로 받아 종료 심볼 &lt;eos&gt;가 나올 때까지 연산을 진행한다. 이는 RNN은 사용되지 않지만 여전히 인코더-디코더의 구조는 유지되고 있음을 보여준다.</p>
<p><br><br></p>
<h2 id="트랜스포머의-주요-수치값사용자가-임의로-변경-가능">트랜스포머의 주요 수치값(사용자가 임의로 변경 가능)</h2>
<blockquote>
<ul>
<li>dmodel : 트랜스포머의 인코더와 디코더에서의 정해진 입력과 출력의 크기를 의미</li>
</ul>
</blockquote>
<ul>
<li>num_layers : 트랜스포머 모델에서 인코더와 디코더가 총 몇층으로 구성되었는지를 의미</li>
<li>num_heads : 트랜스포머에서는 어텐션을 사용할 때 병렬로 어텐션을 수행하고결과값을 다시 하나로 합치는 방식을 택했는데, 이 병렬의 개수를 의미</li>
<li>dff : 트랜스포머 내부에는 피드 포워드 신경망이 존재하는데, 그 은닉층의 크기를 의미
<img src="https://images.velog.io/images/jjun-ho/post/8a1deccc-fc0a-47f1-b194-a8a5250c1af4/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-19%20%EC%98%A4%ED%9B%84%202.30.52.png" alt=""></li>
</ul>
<p><br><br></p>
<h2 id="포지셔널-인코딩positional-encoding">포지셔널 인코딩(Positional Encoding)</h2>
<blockquote>
<p>단어를 순차적으로 입력받아 단어의 위치 정보를 갖는 RNN과 달리 트랜스포머는 단어 입력을 순차적으로 받는 방식이 아니므로 단어의 위치 정보를 다른 방식으로 알려줄 필요가 있다. 트랜스포머는 단어의 위치 정보를 얻기 위해서 각 단어의 임베딩 벡터에 위치 정보들을 더하여 모델의 입력으로 사용하는데, 이를 포지셔널 인코딩(positional encoding)이라고 한다.
<img src="https://images.velog.io/images/jjun-ho/post/f0856d64-b257-413a-9db0-21348af42f4d/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%202.23.00.png" alt=""><img src="https://images.velog.io/images/jjun-ho/post/100334fe-b4af-48eb-bbb1-eb020574f0e9/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%202.23.55.png" alt="">위의 그림은 입력으로 사용되는 임베딩 벡터들이 트랜스포머의 입력으로 사용되기 전에 포지셔널 인코딩값이 더해지는 것을 보여준다.</p>
</blockquote>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/761f91d6-8653-4663-b808-886d0950529c/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%203.02.33.png" alt=""></p>
<ul>
<li>pos는 입력 문장에서의 임베딩 벡터의 위치를 나타내며, i는 임베딩 벡터 내의 차원의 인덱스를 의미한다.</li>
<li>위의 식에서 dmodel은 트랜스포머의 모든 층의 출력 차원을 의미하는 트랜스포머의 하이퍼파라미터이다.<br></li>
<li><ul>
<li>포지셔널 인코딩 값 ** <img src="https://images.velog.io/images/jjun-ho/post/212fa965-104c-4b2d-8079-420bf6970873/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%202.27.50.png" alt=""></li>
</ul>
</li>
<li>트랜스포머는 사인 함수와 코사인 함수의 값을 임베딩 벡터에 더해주므로서 단어의 순서 정보를 더하여 준다.</li>
<li>위의 식에 따르면 임베딩 벡터 내의 각 차원의 인덱스가 짝수인 경우에는 사인 함수의 값을 사용하고 홀수인 경우에는 코사인 함수의 값을 사용한다.</li>
</ul>
<p>각 임베딩 벡터에 포지셔널 인코딩값을 더하면 같은 단어라고 하더라도 문장 내의 위치에 따라서 트랜스포머의 입력으로 들어가는 임베딩 벡터의 값이 달라진다. 결국 트랜스포머의 입력은 순서 정보가 고려된 임베딩 벡터라고 보면 된다.</p>
</blockquote>
<p><br><br></p>
<h2 id="어텐션attention">어텐션(Attention)</h2>
<blockquote>
<p>** 트랜스포머에서 사용되는 세 가지의 어텐션 ** 
<img src="https://images.velog.io/images/jjun-ho/post/59d0089c-ff58-4096-94ae-94783377eaf0/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%203.28.46.png" alt=""><img src="https://images.velog.io/images/jjun-ho/post/11e5971b-b524-4342-a234-110ad2f37b1c/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%203.33.15.png" alt="">  주의할 점은 여기서 Query, Key 등이 같다는 것은 벡터의 값이 같다는 것이 아니라 벡터의 출처가 같다는 의미이다.</p>
</blockquote>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/a3db9923-74dc-419d-b361-b62eec7b813f/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%203.34.24.png" alt=""></p>
<ul>
<li>위 그림은 트랜스포머의 아키텍처에서 세 가지 어텐션이 각각 어디에서 이루어지는지를 보여준다.  </li>
<li>세 개의 어텐션에 추가적으로 &#39;멀티 헤드&#39;라는 이름이 붙어있다. 이는 트랜스포머가 어텐션을 병렬적으로 수행하는 방법을 의미한다.</li>
</ul>
</blockquote>
<p><br><br></p>
<h2 id="인코더encoder">인코더(Encoder)</h2>
<blockquote>
<p>** 인코더의 구조 **
<img src="https://images.velog.io/images/jjun-ho/post/80a5fe1e-190f-45f0-acec-b25502e92860/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%203.37.59.png" alt="">트랜스포머는 하이퍼파라미터인 num_layers 개수의 인코더 층을 쌓는다. 인코더를 하나의 층이라는 개념으로 생각한다면, 하나의 인코더 층은 크게 총 2개의 서브층(sublayer)으로 나뉘어집니다. 바로 셀프 어텐션과 피드 포워드 신경망이다.</p>
</blockquote>
<p><br><br></p>
<h2 id="인코더의-셀프-어텐션">인코더의 셀프 어텐션</h2>
<p>** 셀프 어텐션의 의미 **</p>
<blockquote>
<p>어텐션 함수는 주어진 &#39;쿼리(Query)&#39;에 대해서 모든 &#39;키(Key)&#39;와의 유사도를 각각 구한다. 그리고 구해낸 이 유사도를 가중치로 하여 키와 맵핑되어있는 각각의 &#39;값(Value)&#39;에 반영해준다. 그리고 유사도가 반영된 &#39;값(Value)&#39;을 모두 가중합하여 리턴한다.<img src="https://images.velog.io/images/jjun-ho/post/a0f8a60d-7c57-4303-8055-09f6847a1701/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%203.41.46.png" alt="">
어텐션 중에서는 셀프 어텐션(self-attention)이라는 것이 있다. 단지 어텐션을 자기 자신에게 수행한다는 의미한다.</p>
</blockquote>
<blockquote>
<p>seq2seq에서 어텐션을 사용할 경우의 Q, K, V의 정의 
<img src="https://images.velog.io/images/jjun-ho/post/6a9e5fc2-eb32-4ea2-8ed4-5f14df969193/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%204.09.05.png" alt=""></p>
</blockquote>
<blockquote>
<p>트랜스포머의 셀프 어텐션 
<img src="https://images.velog.io/images/jjun-ho/post/a0644051-8fc4-4fa4-bc8d-51401c2f785f/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%204.06.34.png" alt="">셀프 어텐션에서는 Q, K, V가 전부 동일하다.</p>
</blockquote>
<br>

<p>** Q, K, V 벡터 얻기 **</p>
<blockquote>
<p>셀프 어텐션은 인코더의 초기 입력인 dmodel의 차원을 가지는 단어 벡터들을 사용하여 셀프 어텐션을 수행하는 것이 아니라 우선 각 단어 벡터들로부터 Q벡터, K벡터, V벡터를 얻는 작업을 거칩니다. 이때 이 Q벡터, K벡터, V벡터들은 초기 입력인 dmodel의 차원을 가지는 단어 벡터들보다 더 작은 차원을 가진다.
<img src="https://images.velog.io/images/jjun-ho/post/8f3f0f0d-20dc-4255-b50f-86c42341885e/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%204.02.12.png" alt="">기존의 벡터로부터 더 작은 벡터는 가중치 행렬을 곱하므로서 완성된다. 각 가중치 행렬은 dmodel×(dmodel/num_heads)의 크기를 가진다. 이 가중치 행렬은 훈련 과정에서 학습된다.</p>
</blockquote>
<br>

<p>** 스케일드 닷-프로덕트 어텐션(Scaled dot-product Attention) **</p>
<blockquote>
<p>어텐션 함수의 종류는 매우 다양한데, 트랜스포머에서는 내적만 사용하지않고 내적값을 특 정값으로 나눠준 어텐션함수(score(q,k) = q⦁k/n^1/2) 즉 스케일드 닷-프로덕트 어텐션을 사용한다.</p>
</blockquote>
<br>

<p>** 행렬 연산으로 일괄 처리하기 **</p>
<blockquote>
<p>각 단어 벡터마다 일일히 가중치 행렬을 곱하는 것이 아니라 문장 행렬에 가중치 행렬을 곱하여 Q 행렬, K 행렬, V행렬을 구한다.<img src="https://images.velog.io/images/jjun-ho/post/b00eca33-a433-460f-9cad-da94a435c299/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%204.37.26.png" alt="">
행렬 연산을 통해 어텐션 스코어를 구한다. Q 행렬을 K 행렬을 전치한 행렬과 곱해준다.
<img src="https://images.velog.io/images/jjun-ho/post/4db47ea2-689e-4152-a873-c2cd993be9a0/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%204.40.02.png" alt="">
이제 어텐션 분포를 구하고, 이를 사용하여 모든 단어에 대한 어텐션 값을 구한다. 이는 어텐션 스코어 행렬에 소프트맥스 함수를 사용하고, V 행렬을 곱하는 것으로 해결된다.<img src="https://images.velog.io/images/jjun-ho/post/b5f0b9e8-5983-468c-91aa-75bf7fc32d23/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%204.43.22.png" alt=""><img src="https://images.velog.io/images/jjun-ho/post/b099bb45-8747-49e5-a2b6-a391fd5e8a2d/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%204.43.44.png" alt=""></p>
</blockquote>
<br>

<p>** 멀티 헤드 어텐션(Multi-head Attention) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/7fd03de1-5bfc-41a6-a95d-d16a3da580f9/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%204.49.00.png" alt="">
트랜스포머 연구진은 한 번의 어텐션을 하는 것보다 여러번의 어텐션을 병렬로 사용하는 것이 더 효과적이라고 판단하였다. 그래서 dmodel의 차원을 num_heads개로 나누어 dmodel/num_heads의 차원을 가지는 Q, K, V에 대해서 num_heads개의 병렬 어텐션을 수행한다. 이때 각각의 어텐션 값 행렬을 어텐션 헤드라고 부른다.</p>
</blockquote>
<br>

<p>** 패딩 마스크(Padding Mask) **</p>
<blockquote>
<p>트랜스포머에서는 Key의 경우에 &lt;PAD&gt; 토큰이 존재한다면 이에 대해서는 유사도를 구하지 않도록 마스킹(Masking)을 해주기로 했다. 여기서 마스킹이란 어텐션에서 제외하기 위해 값을 가린다는 의미이다. 어텐션 스코어 행렬에서 행에 해당하는 문장은 Query이고, 열에 해당하는 문장은 Key이다. 그리고 Key에 &lt;PAD&gt;가 있는 경우에는 해당 열 전체를 마스킹을 해준다.
<img src="https://images.velog.io/images/jjun-ho/post/0b660cb4-9549-4d6b-bd6f-910fe7c15c43/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%204.53.59.png" alt="">마스킹을 하는 방법은 어텐션 스코어 행렬의 마스킹 위치에 -무한대에 가까운 매우 작은 음수값을 넣어주는 것이다. 
현재 마스킹 위치에 매우 작은 음수 값이 들어가 있으므로 어텐션 스코어 행렬이 소프트맥스 함수를 지난 후에는 해당 위치의 값은 0에 굉장히 가까운 값이 되어 단어 간 유사도를 구하는 일에 &lt;PAD&gt; 토큰이 반영되지 않게 된다.</p>
</blockquote>
<p><br><br></p>
<h2 id="포지션-와이즈-피드-포워드-신경망position-wise-ffnn">포지션-와이즈 피드 포워드 신경망(Position-wise FFNN)</h2>
<blockquote>
<p>포지션 와이즈 FFNN은 인코더와 디코더에서 공통적으로 가지고 있는 서브층이다. 완전 연결 FFNN(Fully-connected FFNN)이라고 해석 할 수 있다.<img src="https://images.velog.io/images/jjun-ho/post/555205cb-af77-4680-be7c-92983bb59780/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%2011.18.01.png" alt=""><img src="https://images.velog.io/images/jjun-ho/post/4d35e984-1456-45ac-8a45-7c5028b815bd/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%2011.18.28.png" alt="">
매개변수 W1, b1, W2, b2는 하나의 인코더 층 내에서는 다른 문장, 다른 단어들마다 정확하게 동일하게 사용된다. 하지만 인코더 층마다는 다른 값을 가진다.
<img src="https://images.velog.io/images/jjun-ho/post/37d26eae-97a4-4467-9b46-d7671026583c/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%2011.52.32.png" alt="">두번째 서브층을 지난 인코더의 최종 출력은 여전히 인코더의 입력의 크기였던 (seq_len, dmodel)의 크기가 보존되고 있다.</p>
</blockquote>
<p><br><br></p>
<h2 id="잔차-연결residual-connection과-층-정규화layer-normalization">잔차 연결(Residual connection)과 층 정규화(Layer Normalization)</h2>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/a730a670-980b-45bc-b570-e36910f88ed2/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%2011.54.40.png" alt="">트랜스포머에서는 이러한 두 개의 서브층을 가진 인코더에 추가적으로 사용하는 기법이 있는데, 바로 Add &amp; Norm입니다. 더 정확히는 잔차 연결(residual connection)과 층 정규화(layer normalization)를 의미한다.</p>
</blockquote>
<p>** 잔차 연결(Residual connection) **</p>
<blockquote>
<p>트랜스포머에서 서브층의 입력과 출력은 동일한 차원을 갖고 있으므로, 서브층의 입력과 서브층의 출력은 덧셈 연산을 할 수 있다.<img src="https://images.velog.io/images/jjun-ho/post/03f0c8dc-52bf-4f27-89c8-dea75c271d34/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%2011.58.25.png" alt=""></p>
</blockquote>
<br>

<p>** 층 정규화(Layer Normalization) **</p>
<blockquote>
<p>층 정규화는 텐서의 마지막 차원에 대해서 평균과 분산을 구하고, 이를 가지고 어떤 수식을 통해 값을 정규화하여 학습을 돕는다.<img src="https://images.velog.io/images/jjun-ho/post/13ee33c2-e429-4123-9226-85af379086ab/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%2011.59.26.png" alt=""><img src="https://images.velog.io/images/jjun-ho/post/e4ca21fe-09b5-47bf-adcd-a06c6c3936e4/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-18%20%EC%98%A4%EC%A0%84%2012.00.03.png" alt=""></p>
</blockquote>
<p><br><br></p>
<h2 id="인코더에서-디코더로from-encoder-to-decoder">인코더에서 디코더로(From Encoder To Decoder)</h2>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/af023a3a-3909-47c3-9701-0842353db13d/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-18%20%EC%98%A4%EC%A0%84%2012.01.25.png" alt="">인코더는 총 num_layers만큼의 층 연산을 순차적으로 한 후에 마지막 층의 인코더의 출력을 디코더에게 전달한다.</p>
</blockquote>
<p><br><br></p>
<h2 id="디코더의-첫번째-서브층--셀프-어텐션과-룩-어헤드-마스크">디코더의 첫번째 서브층 : 셀프 어텐션과 룩-어헤드 마스크</h2>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/7fc66f4c-3eeb-4189-b2fe-475c5670b5ea/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-18%20%EC%98%A4%EC%A0%84%2012.03.13.png" alt="">디코더도 인코더와 동일하게 임베딩 층과 포지셔널 인코딩을 거친 후의 문장 행렬이 입력된다.
<br>
seq2seq의 디코더에 사용되는 RNN 계열의 신경망은 입력 단어를 매 시점마다 순차적으로 받으므로 다음 단어 예측에 현재 시점 이전에 입력된 단어들만 참고할 수 있다. 반면, 트랜스포머는 문장 행렬로 입력을 한 번에 받으므로 현재 시점의 단어를 예측하고자 할 때, 입력 문장 행렬로부터 미래 시점의 단어까지도 참고할 수 있는 현상이 발생한다. 
이를 위해 트랜스포머의 디코더에서는 현재 시점의 예측에서 현재 시점보다 미래에 있는 단어들을 참고하지 못하도록 룩-어헤드 마스크(look-ahead mask)를 도입했다.
<br>
미래에 있는 단어들은 참고하지 못하도록 다음과 같이 마스킹한다.
<img src="https://images.velog.io/images/jjun-ho/post/d8448d7c-a446-4198-a3fd-47e0b0951c79/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-18%20%EC%98%A4%EC%A0%84%2012.08.11.png" alt=""></p>
</blockquote>
<p><br><br></p>
<h2 id="디코더의-두번째-서브층--인코더-디코더-어텐션">디코더의 두번째 서브층 : 인코더-디코더 어텐션</h2>
<blockquote>
<p>디코더의 두번째 서브층은 멀티 헤드 어텐션을 수행한다는 점에서는 이전의 어텐션들(인코더와 디코더의 첫번째 서브층)과 같지만, 셀프 어텐션은 아니다.
셀프 어텐션은 Query, Key, Value가 같은 경우를 말하는데, 인코더-디코더 어텐션은 Query가 디코더인 행렬인 반면, Key와 Value는 인코더 행렬이기 때문이다.
<img src="https://images.velog.io/images/jjun-ho/post/7dbd6410-e4d8-4735-b686-9c50199201a9/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-18%20%EC%98%A4%EC%A0%84%2012.14.13.png" alt="">
<br>
디코더의 두번째 서브층을 확대해보면<img src="https://images.velog.io/images/jjun-ho/post/1e0ab3ad-7071-4dc5-ab3b-484dd44f7ed2/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-18%20%EC%98%A4%EC%A0%84%2012.46.55.png" alt="">
두 개의 화살표는 각각 Key와 Value를 의미하며, 이는 인코더의 마지막 층에서 온 행렬로부터 얻는다. 반면, Query는 디코더의 첫번째 서브층의 결과 행렬로부터 얻는다는 점이 다르다.
<br>
이 때, 어텐션 스코어 행렬을 구하는 과정 <img src="https://images.velog.io/images/jjun-ho/post/dde680c3-6d66-430c-bf82-706ae9cbe555/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-18%20%EC%98%A4%EC%A0%84%2012.14.49.png" alt=""></p>
</blockquote>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PyTorch로 딥러닝 배우기 6]]></title>
            <link>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-7-j0m2dy96</link>
            <guid>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-7-j0m2dy96</guid>
            <pubDate>Tue, 17 Aug 2021 04:43:59 GMT</pubDate>
            <description><![CDATA[<h1 id="순환-신경망recurrent-neural-network-rnn">순환 신경망(Recurrent Neural Network, RNN)</h1>
<blockquote>
<p>RNN(Recurrent Neural Network)은 입력과 출력을 시퀀스 단위로 처리하는 모델이다.</p>
</blockquote>
<h2 id="rnn">RNN</h2>
<blockquote>
<p>RNN은 은닉층의 노드에서 활성화 함수를 통해 나온 결과값을 출력층 방향으로도 보내면서, 다시 은닉층 노드의 다음 계산의 입력으로 보내는 특징을 갖고있다.
<img src="https://images.velog.io/images/jjun-ho/post/1871050a-8647-4af3-a765-dbcfd0c1c216/image.png" alt=""> RNN에서 은닉층에서 활성화 함수를 통해 결과를 내보내는 역할을 하는 노드를 셀(cell)이라고 한다. 이 셀은 이전의 값을 기억하려고 하는 일종의 메모리 역할을 수행하므로 이를 메모리 셀 또는 RNN 셀이라고 표현한다.
<img src="https://images.velog.io/images/jjun-ho/post/a5118303-e510-4c7d-8b97-3a01f8e321c4/image.png" alt="">
은닉층의 메모리 셀은 각각의 시점(time step)에서 바로 이전 시점에서의 은닉층의 메모리 셀에서 나온 값을 자신의 입력으로 사용하는 재귀적 활동을 하고 있다. 
메모리 셀이 출력층 방향으로 또는 다음 시점의 보내는 값을 은닉 상태(hidden state)라고 한다.</p>
</blockquote>
<p><br><br></p>
<h2 id="usages-of-rnn">Usages of RNN</h2>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/483bbf7f-35f5-44ee-a368-5cefb3f5e404/image.png" alt="">
RNN은 입력과 출력의 길이를 다르게 설계 할 수 있으므로 다양한 용도로 사용할 수 있다.</p>
</blockquote>
<blockquote>
<p>** one-to-many **
<img src="https://images.velog.io/images/jjun-ho/post/ee424f3f-86de-4ac2-91c7-1767e3dbf107/image.png" alt=""></p>
</blockquote>
<ul>
<li>하나의 이미지 입력에 대해서 사진의 제목을 출력하는 이미지 캡셔닝(Image Captioning) 작업에 사용 할 수 있다.</li>
<li>하나의 이미지 입력에 대해서 문장을 출력하는 작업에 사용 할 수 있다.</li>
</ul>
<blockquote>
<p>** many-to-one **
<img src="https://images.velog.io/images/jjun-ho/post/4b1383ef-596e-415c-82b9-717d6c1a418c/image.png" alt=""></p>
</blockquote>
<ul>
<li>입력 문서가 긍정적인지 부정적인지 판별하는 감성 분류(sentiment classification) 작업에 사용 할 수 있다.</li>
<li>메일이 정상 메일인지 스팸 메일인지 판별하는 스팸 메일 분류(spam detection)에 사용 할 수 있다.</li>
</ul>
<blockquote>
<p>** many-to-many **
<img src="https://images.velog.io/images/jjun-ho/post/a1016eac-5864-4398-8691-b59e3341dcc6/image.png" alt=""></p>
</blockquote>
<ul>
<li>입력 문장으로부터 대답 문장을 출력하는 챗봇에 사용 할 수 있다.</li>
<li>입력 문장으로부터 번역된 문장을 출력하는 번역기에 사용 할 수 있다.</li>
</ul>
<p><br><br></p>
<h2 id="rnn-수식">RNN 수식</h2>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/c3dc5471-89e0-4491-8939-d5b87007908a/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%201.37.59.png" alt="">
현재 시점 t에서의 은닉 상태값을 ht라고 할 때, 은닉층의 메모리 셀은 ht를 계산하기 위해서 총 두 개의 가중치를 갖게 된다. 하나는 입력층에서 입력값을 위한 가중치 Wx이고, 하나는 이전 시점 t-1의 은닉 상태값인 ht−1을 위한 가중치 Wh이다.
은닉층 : ht=tanh(Wxxt+hht−1+b)
출력층 : yt=f(Wyht+b)
단, f는 비선형 활성화 함수 중 하나
(이진 분류를 해야하는 경우라면 시그모이드 함수를 사용할 수 있고 다양한 카테고리 중에서 선택해야하는 문제라면 소프트맥스 함수를 사용하게 될 수 있다.)
<img src="https://images.velog.io/images/jjun-ho/post/2de88977-8848-4684-ad8b-c20ae30cfe11/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-17%20%EC%98%A4%ED%9B%84%201.41.22.png" alt="">.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[PyTorch로 딥러닝 배우기 5]]></title>
            <link>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-5</link>
            <guid>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-5</guid>
            <pubDate>Fri, 13 Aug 2021 16:19:05 GMT</pubDate>
            <description><![CDATA[<h1 id="vggnet">VGGNet</h1>
<blockquote>
<p>2012년, 2013년 우승 모델들은 8개의 층으로 구성된 반면 2014년의 VGGNet(VGG19)은 19 층으로, GoogleNet은 22층으로 구성되었다. 그리고 2015년에 이르러서는 152개의 층으로 구 성된 ResNet이 제안되었다. 이를 통해 네크워크가 깊어질수록 성능이 좋아졌음을 확인할 수 있다. VGGNet은 간단한 구조와 단일 네트워크에서의 좋은 성능 덕분에 GoogleNet보다 많은 네트워크에서 응용되고 있다.
<img src="https://images.velog.io/images/jjun-ho/post/cfd15d51-d2f8-44c5-9773-e5238774d7c2/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.07.29.png" alt="">
VGGNet은 네트워크의 깊이가 성능에 어떤 영향을 미치는지 연구하기 위해 설계되었다. VG G 연구팀은 깊이의 영향만을 최대한 확인하고자 컨볼루션 필터의 커널 사이즈를 가장 작은 3 x3으로 고정하고 패딩 사이즈를 1로 고정했다. 또한 컨볼루션을 통해 이미지 resize를 하는 것이 아닌 max pooling을 사용해서 이미지 resize를 하는데, 이때 max pooling의 커널 사 이즈는 2x2이고, stride는 2로 이미지를 절반으로 resize 한다.
<img src="https://images.velog.io/images/jjun-ho/post/ba14a79f-db13-413c-a269-79fa76f664fe/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.09.34.png" alt="">
VGG 연구팀은 original 논문에서 깊이에 따른 성능 변화를 비교하기 위해 총 6개의 구조를 만들어서 성능을 비교했다. 이중 D 구조를 VGG16, E 구조를 VGG19라고 보면 되며, 네트워 크의 깊이는 컨볼루션 레이어를 추가함으로써 깊어진다.
<img src="https://images.velog.io/images/jjun-ho/post/d18e4bbb-ff5a-40dd-ab75-cae6612a7d90/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.10.02.png" alt="">
3x3 필터로 두 번 컨볼루션 하는 것과 5x5 필터로 한 번 컨볼루션 하는 것은 결과적으로 동 일한 사이즈의 특성맵을 산출한다. 즉, 3x3 필터로 두 번 컨볼루션 하는 것은 5x5 필터로 한 번 컨볼루션 하는 것과 대응된다. 그러나 성능에서는 3x3 필터로 두 번 컨볼루션 하는 것이 더 좋다.
<img src="https://images.velog.io/images/jjun-ho/post/171ce7ed-a8e5-48a1-9f45-c0a49b3d3f44/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.10.25.png" alt=""></p>
</blockquote>
<p>3x3 필터가 2개일 때 5x5 필터가 1개일 때보다 적은 수의 가중치를 갖는다. CNN에서 가중 치는 모두 훈련이 필요하므로, 가중치가 적을수록 훈련을 적게 하게 되어 학습의 속도가 빨라 진다. 동시에 층의 수가 늘어나면서 비선형 함수 ReLU가 더 많이 들어가서 학습이 더 잘 된 다. 하지만 최종단에 fully-connected 3개가 붙어있어서 parameter의 수가 너무 많아진다는 단점이 있다.</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/856282e2-31e7-44b8-8033-a3eae5050c8d/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.10.45.png" alt="">
깊이가 11층, 13층, 16층, 19층으로 깊어지면서 분류 에러가 감소하며, 이는 층이 깊어질수 록 성능이 좋아짐을 의미한다. 하지만 D와 E를 비교하면 에러가 비슷하거나 더 나빠지는 것 을 볼 수 있다. 이를 보완하여 설계한 네트워크가 다음에 나올 ResNet이다.</p>
</blockquote>
<p><br><br></p>
<h1 id="resnet">ResNet</h1>
<blockquote>
<p>ResNet은 마이크로소프트에서 개발한 알고리즘으로, 층수에 있어서 급속도로 깊어진다. 201 4년의 GoogleNet이 22개의 층으로 구성된 것에 비해 ResNet은 약 7배나 깊어진 152개의 층 을 갖는다. 또한 네트워크가 깊어지면서 top-5 error가 낮아지고 성능이 좋아진다.
<img src="https://images.velog.io/images/jjun-ho/post/a0db8143-adee-47da-ba23-0ebcfcc1b9be/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.11.38.png" alt="">
ResNet의 저자들은 망이 깊어질수록 무조건 성능이 좋아지는 것인지 확인하기 위해 20-lay er와 56-layer에 대해서 성능을 비교하는 테스트 진행했다. 그 결과 더 깊은 구조를 갖는 56 -layer가 20-layer보다 더 나쁜 성능을 보였다.
<img src="https://images.velog.io/images/jjun-ho/post/f682728a-3872-4c47-9d81-d7d8a4e2f52c/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.12.30.png" alt="">
ResNet의 저자들은 새로운 방법을 이용하여 망을 깊게 만들어야 효과를 볼 수 있다는 것을 깨달았고, ResNet의 핵심인 Residual Block을 설계했다. 기존의 망과 차이가 있다면 입력값 을 출력값에 더해줄 수 있도록 지름길을 하나 만들어준 것뿐이다.
<img src="https://images.velog.io/images/jjun-ho/post/870aed5c-6c9c-4cc7-be1d-2958dd3699cf/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.13.32.png" alt="">
왼쪽과 같은 평범한 망은 입력 x를 받아 2개의 weighted layer를 거쳐 출력 H(x)를 내며, 다음 layer의 입력으로 적용된다. 반면, ResNet은 layer의 입력을 출력에 바로 연결시키는 ‘s kip connection’을 사용한다.
<img src="https://images.velog.io/images/jjun-ho/post/dd64bbd0-1210-4a65-a7df-84a80b4d7cc0/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.13.50.png" alt="">
기존의 신경망은 입력값 x를 출력값 y로 매핑하는 함수 H(x)를 얻는 것이 목적이었다. 그러 나 ResNet은 F(x) + x를 최소화하는 것을 목적으로 한다. x는 현시점에서 변할 수 없는 값이 므로 F(x)를 0에 가깝게 만드는 것이 목적이 된다. F(x)가 0이 되면 출력과 입력이 모두 x로 같아지게 된다. F(x) = H(x) - x이므로 F(x)를 최소로 해준다는 것은 H(x) - x를 최소로 해주 는 것과 동일한 의미를 지닌다. 여기서 H(x) - x를 잔차(residual)라고 한다. 즉, 잔차를 최소 로 하는 것이 목적이므로 ResNet이란 이름이 붙게 되었다. x가 그대로 skip connection이 되기 때문에 연산의 증가가 없고, F(x)가 몇 개의 layer를 포함할지 선택이 가능하다. 또한 x 와 H(x)의 dimension이 다르면 dimension을 맞추기 위해 parameter를 추가해서 학습시킨 다.
<img src="https://images.velog.io/images/jjun-ho/post/57cd196f-4a2c-45a4-8cce-b4f1720d7c06/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-14%20%EC%98%A4%EC%A0%84%201.14.17.png" alt=""></p>
</blockquote>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PyTorch로 딥러닝 배우기 4
]]></title>
            <link>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-4</link>
            <guid>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-4</guid>
            <pubDate>Thu, 05 Aug 2021 12:41:59 GMT</pubDate>
            <description><![CDATA[<h1 id="합성곱-신경망convolutional-neural-network">합성곱 신경망(Convolutional Neural Network)</h1>
<blockquote>
<p>합성곱 신경망(Convolutional Neural Network)은 이미지 처리에 탁월한 성능을 보이는 신경망이다.
합성곱 신경망은 크게 합성곱층과(Convolution layer)와 풀링층(Pooling layer)으로 구성된다.</p>
</blockquote>
<h2 id="합성곱-신경망의-대두">합성곱 신경망의 대두</h2>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/65db5b4d-cfb4-43f7-a741-b1f27e0c92fa/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.07.41.png" alt="">사람이 보기에는 두 그림 모두 알파벳 Y로 손쉽게 판단이 가능하지만, 기계가 보기에는 각 픽셀마다 가진 값이 거의 상이하므로 완전히 다른 값을 가진 입력이다. 
<img src="https://images.velog.io/images/jjun-ho/post/f2e00ee4-4c94-4b0f-9913-807100d61a51/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.08.30.png" alt="">이미지를 1차원 텐서인 벡터로 변환하고 다층 퍼셉트론의 입력층으로 사용해야한다. 위와 같이 결과는 변환 전에 가지고 있던 공간적인 구조(spatial structure) 정보가 유실된 상태이다. 여기서 공간적인 구조 정보라는 것은 거리가 가까운 어떤 픽셀들끼리는 어떤 연관이 있고, 어떤 픽셀들끼리는 값이 비슷하거나 등을 포함하고 있다. 결국 이미지의 공간적인 구조 정보를 보존하면서 학습할 수 있는 방법이 필요해졌고, 이를 위해 사용하는 것이 합성곱 신경망이다.</p>
</blockquote>
<p><br><br></p>
<h2 id="cnn">CNN</h2>
<p>** 채널(Channel) **</p>
<blockquote>
<p>이미지는 (높이, 너비, 채널)이라는 3차원 텐서이다.
높이는 이미지의 세로 방향 픽셀 수, 너비는 이미지의 가로 방향 픽셀 수, 채널은 색 성분을 의미한다.</p>
</blockquote>
<p>손글씨 데이터는 흑백 이미지므로 채널 수가 1개이다.</p>
<blockquote>
</blockquote>
<p>컬러 이미지는 적색(Red), 녹색(Green), 청색(Blue) 채널 수가 3개<img src="https://images.velog.io/images/jjun-ho/post/3ab3eb1b-3ae7-4f9d-b1f1-6e47732f6b40/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.16.00.png" alt=""></p>
<br>

<p>** 합성곱 연산(Convolution operation) **</p>
<blockquote>
<p>합성곱층은 합성곱 연산을 통해서 이미지의 특징을 추출하는 역할을 한다.
합성곱은 영어로 컨볼루션이라고도 불리는데, 커널(kernel) 또는 필터(filter)라는 n×m크기의 행렬로 높이×너비 크기의 이미지를 처음부터 끝까지 겹치며 훑으면서 n×m크기의 겹쳐지는 부분의 각 이미지와 커널의 원소의 값을 곱해서 모두 더한 값을 출력으로 하는 것을 말한다. 이때, 이미지의 가장 왼쪽 위부터 가장 오른쪽까지 순차적으로 훑는다.<img src="https://images.velog.io/images/jjun-ho/post/4755d40e-5812-4256-9906-ef55d9962a04/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.20.37.png" alt="">
커널을 사용하여 합성곱 연산을 통해 나온 결과를 특성 맵(feature map)이라고 한다.
이위 예시에서는 총 9번의 스텝까지 마쳤을 때 특성맵이다. 
<img src="https://images.velog.io/images/jjun-ho/post/385a9a04-aee2-4141-80d8-220a3c2400b5/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.21.49.png" alt=""></p>
</blockquote>
<br>

<p>** 스프라이드(Stride) **</p>
<blockquote>
<p>커널의 이동 범위이다. 사용자가 정할 수 있다.<img src="https://images.velog.io/images/jjun-ho/post/8a70a919-893b-4164-aaeb-00157581f073/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.24.42.png" alt="">
커널로 합성곱 연산을 하였을 때, 스프라이드 크기에 따라 합성곱 연산의 결과로 얻은 특성 맵은 입력보다 크기가 작아진다는 특징이 있다.
<img src="https://images.velog.io/images/jjun-ho/post/dfb9d1ad-b5ca-4a6a-88b2-d9e7f5dbfae2/image.png" alt=""></p>
</blockquote>
<br>

<p>** 패딩(Padding) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/b8eda8f4-23aa-4814-8b37-18ed0dd10829/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.24.58.png" alt="">
합성곱 연산 이후에도 특성 맵의 크기가 입력의 크기와 동일하게 유지되도록 하고 싶다면 패딩(padding)을 사용하면 된다.
패딩은 (합성곱 연산을 하기 전에) 입력의 가장자리에 지정된 개수의 폭만큼 행과 열을 추가해주는 것이다.
주로 값을 0으로 채우는 제로 패딩(zero padding)을 사용한다.</p>
</blockquote>
<br>

<p>** 합성곱 신경망의 편향 **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/e66d89c9-a719-41e9-99c5-5c796d46e29d/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.32.12.png" alt="">
편향을 사용한다면 커널을 적용한 뒤에 더해진다. 편향은 하나의 값만 존재하며, 커널이 적용된 결과의 모든 원소에 더해진다.</p>
</blockquote>
<br>

<p>** 다수의 채널을 가질 경우의 합성곱 연산(3차원 텐서의 합성곱 연산) **</p>
<blockquote>
<p>다수의 채널을 가진 입력 데이터를 가지고 합성곱 연산을 한다고 하면 커널의 채널 수도 입력의 채널 수만큼 존재해야 한다. 다시 말해 입력 데이터의 채널 수와 커널의 채널 수는 같아야 한다.
합성곱 연산을 채널마다 수행한다. 그리고 그 결과를 모두 더하여 최종 특성 맵을 얻는다.<img src="https://images.velog.io/images/jjun-ho/post/efb312fb-dd47-4f82-a850-a20ac4ef56d2/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.34.41.png" alt=""></p>
</blockquote>
<br>

<p>** 풀링(Pooling) **</p>
<blockquote>
<p>풀링 층에서는 특성 맵을 다운샘플링하여 특성 맵의 크기를 줄이는 풀링 연산이 이루어진다.</p>
<ul>
<li>최대 풀링(max pooling)
일반적으로 최대 풀링(max pooling)을 사용한다.<img src="https://images.velog.io/images/jjun-ho/post/1b234623-a3b0-4b2c-b84d-fccd2c9488c8/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-05%20%EC%98%A4%ED%9B%84%209.36.30.png" alt="">맥스 풀링은 커널과 겹치는 영역 안에서 최대값을 추출하는 방식으로 다운샘플링</li>
<li>평균 풀링(average pooling)
평균값을 추출하는 연산이 된다.</li>
</ul>
</blockquote>
<p>풀링 연산은 커널과 스트라이드 개념이 존재한다는 점에서 합성곱 연산과 유사하지만, 합성곱 연산과의 차이점은 학습해야 할 가중치가 없으며 연산 후에 채널 수가 변하지 않는다는 점이다. 풀링을 사용하면, 특성 맵의 크기가 줄어드므로 특성 맵의 가중치의 개수를 줄여준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PyTorch로 딥러닝 배우기 3]]></title>
            <link>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-3</link>
            <guid>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-3</guid>
            <pubDate>Mon, 26 Jul 2021 18:47:15 GMT</pubDate>
            <description><![CDATA[<h1 id="neural-network-인공-신경망">Neural Network (인공 신경망)</h1>
<h2 id="머신-러닝-용어-정리">머신 러닝 용어 정리</h2>
<p>** 분류(Classification)와 회귀(Regression) **</p>
<blockquote>
<p>**  회귀(Regression) **
어떠한 연속적인 값의 범위 내에서 예측값이 나오는 경우.</p>
<ul>
<li>선형 회귀(Lineare Regression)</li>
<li>로지스틱 회귀(Logistic Rgression)<br></li>
<li><ul>
<li>분류(Classification) **</li>
</ul>
</li>
<li>이진 분류(Binary Classification)
주어진 입력에 대해서 둘 중 하나의 답을 정하는 문제이다.</li>
<li>다중 레이블 분류(Multi-lable Classification)
주어진 입력으로부터 정해진 클래스 중 하나로 판단하는 것을 다중 클래스 분류 문제라고 한다.</li>
</ul>
</blockquote>
<br>

<p>** 지도 학습(Supervised Learning)과 비지도 학습(Unsupervised Learning) **</p>
<blockquote>
<ul>
<li>지도 학습(Supervised Learning)
레이블(Label)이라는 정답과 함께 학습하는 것을 말합니다.
레이블이라는 말 외에도 y, 실제값 등으로 부르기도 한다.</li>
<li>비지도 학습(Unsupervised Learning)
기본적으로 목적 데이터(또는 레이블)이 없는 학습 방법이다.</li>
<li>+)자기지도 학습(Self-Supervised Learning, SSL)
레이블이 없는 데이터가 주어지면, 모델이 학습을 위해서 스스로 데이터로부터 레이블을 만들어서 학습하는 경우</li>
<li>+)강화 학습
어떤 환경 내에서 정의된 에이전트가 현재의 상태를 인식하여, 선택 가능한 행동들 중 보상을 최대화하는 행동 혹은 행동 순서를 선택하는 방법이다.</li>
</ul>
</blockquote>
<br>

<p>** 샘플(Sample)과 특성(Feature) **</p>
<blockquote>
<p>많은 머신 러닝 문제가 1개 이상의 독립 변수 
x를 가지고 종속 변수 y를 예측하는 문제이다.
머신 러닝에서는 하나의 데이터, 하나의 행을 샘플(Sample)이라고 부른다.종속 변수 y를 예측하기 위한 각각의 독립 변수 x를 특성(Feature)이라고 한다.</p>
</blockquote>
<br>

<p>** 정확도(Accuracy) **</p>
<blockquote>
<p>머신 러닝에서는 맞춘 문제수를 전체 문제수로 나눈 값</p>
</blockquote>
<br>

<p>** 과적합(Overfitting)과 과소 적합(Underfitting) **</p>
<blockquote>
<ul>
<li>과적합(Overfitting)
훈련 데이터를 과하게 학습한 경우를 말한다.
훈련 데이터는 실제로 존재하는 많은 데이터의 일부이다. 그런데 기계가 훈련 데이터에 대해서만 과하게 학습하면 테스트 데이터나 실제 서비스에서의 데이터에 대해서는 정확도가 좋지 않은 현상이 발생한다.<img src="https://images.velog.io/images/jjun-ho/post/3ab8b5de-c055-4755-a473-b07c2adc2461/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%201.43.26.png" alt="">
훈련 데이터에 대한 정확도는 높지만, 테스트 데이터는 정확도가 낮은 상황이다. 즉, 테스트 데이터의 오차가 증가하기 전이나, 정확도가 감소하기 전에 훈련을 멈추는 것이 좋다.
과적합을 막을 수 있는 드롭아웃(Dropout), 조기 종료(Early Stopping)과 같은 몇 가지 방법이 존재한다.</li>
<li>과소 적합(Underfitting)
훈련 자체가 부족한 상태이므로 과대 적합과는 달리 훈련 데이터에 대해서도 보통 정확도가 낮다는 특징이 있다.</li>
</ul>
</blockquote>
<p><br><br></p>
<h2 id="퍼셉트론perceptron">퍼셉트론(Perceptron)</h2>
<p>** 퍼셉트론(Perceptron) **</p>
<blockquote>
<p>초기의 인공 신경망으로 다수의 입력으로부터 하나의 결과를 내보내는 알고리즘이다.
실제 뇌를 구성하는 신경 세포 뉴런의 동작과 유사하다.<img src="https://images.velog.io/images/jjun-ho/post/4f9b6c3e-69ce-4556-a25c-5d4df55dc021/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%201.51.35.png" alt=""></p>
</blockquote>
<blockquote>
<p>다수의 입력을 받는 퍼셉트론<img src="https://images.velog.io/images/jjun-ho/post/9d0ff3ae-f686-4075-8f8a-931db1084dd3/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%201.52.20.png" alt=""></p>
<blockquote>
<p>x는 입력값, W는 가중치(Weight), y는 출력값</p>
</blockquote>
</blockquote>
<p>가중치가 신호를 전달하는 역할을 한다.
각각의 입력값에는 각각의 가중치가 존재하는데, 이때 가중치의 값이 크면 클수록 해당 입력 값이 중요하다는 것을 의미한다.</p>
<blockquote>
</blockquote>
<p>각 입력값이 가중치와 곱해져서 인공 뉴런에 보내지고,각 입력값과 그에 해당되는 가중치의 곱의 전체 합이 임계치(threshold)를 넘으면 종착지에 있는 인공 뉴런은 출력 신호로서 1을 출력하고, 그렇지 않을 경우에는 0을 출력합니다. 이러한 함수를 계단 함수(Step function)라고 한다.
<img src="https://images.velog.io/images/jjun-ho/post/881ab5f9-5035-47c7-bcd2-3c7fbc392f34/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%201.57.29.png" alt=""><img src="https://images.velog.io/images/jjun-ho/post/1b7b71ba-8054-431f-b2e0-5069a5997e9c/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%201.57.44.png" alt=""></p>
<br>

<p>** 활성화 함수(Activation Function) **</p>
<blockquote>
<p>뉴런에서 출력값을 변경시키는 함수
계단 함수, 시그모이드 함수, 소프트맥스 함수</p>
</blockquote>
<br>

<p>** 단층 퍼셉트론(Single-Layer Perceptron) **</p>
<blockquote>
<p>값을 보내는 단계과 값을 받아서 출력하는 두 단계로만 이루어져있다. 이때 이 각 단계를 보통 층(layer)라고 부르며, 이 두 개의 층을 입력층(input layer)과 출력층(output layer)이라고 한다.
단층 퍼셉트론은 AND 게이트, NAND 게이트, OR 게이트 또한 구현할 수 있다. 하지만 XOR 게이트는 구현이 불가능하다. 그 이유는 단층 퍼셉트론은 직선 하나로 두 영역을 나눌 수 있는 문제에 대해서만 구현이 가능하기 때문이다.</p>
</blockquote>
<br>

<p>** 다층 퍼셉트론(MultiLayer Perceptron, MLP) **</p>
<blockquote>
<p>MLP<img src="https://images.velog.io/images/jjun-ho/post/22ee5e85-5f6a-4ef9-9c45-04dde827bc10/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%202.15.55.png" alt=""></p>
</blockquote>
<p>심층 신경망(Deep Neural Network, DNN)<img src="https://images.velog.io/images/jjun-ho/post/0e7c8934-5500-44a4-a013-9c3876076514/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%202.17.24.png" alt="">
은닉층이 2개 이상인 신경망</p>
<br>

<p>** 딥러닝 **</p>
<blockquote>
<p>퍼셉트론이 정답을 출력할 때까지 가중치를 바꿔보면서 맞는 가중치를 찾았다. 즉, 가중치를 수동으로 찾았다. 하지만 이제는 기계가 가중치를 스스로 찾아내도록 자동화시켜야하는데, 이것이 머신 러닝에서 말하는 학습(training) 단계이다. 선형 회귀와 로지스틱 회귀와 같이 손실 함수(Loss function)와 옵티마이저(Optimizer)를 사용한다. 그리고 만약 학습을 시키는 인공 신경망이 심층 신경망일 경우에는 이를 심층 신경망을 학습시킨다고 하여 딥러닝(Deep Learning)이라고 한다.</p>
</blockquote>
<p><br><br></p>
<h2 id="역전파backpropagation">역전파(BackPropagation)</h2>
<p>** 순전파(Forward Propagation) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/aefa6c82-cfbe-4bc0-a263-dcdb03f2629f/image.png" alt="">진행방향 -&gt;</p>
</blockquote>
<p>각 입력은 입력층에서 은닉층 방향으로 향하면서 각 입력에 해당하는 가중치와 곱해지고, 결과적으로 가중합으로 계산되어 은닉층 뉴런의 시그모이드 함수의 입력값이 된다.</p>
<br>

<p>** 역전파(BackPropagation) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/aefa6c82-cfbe-4bc0-a263-dcdb03f2629f/image.png" alt="">진행방향 &lt;-</p>
</blockquote>
<p>순전파가 입력층에서 출력층으로 향한다면 역전파는 반대로 출력층에서 입력층 방향으로 계산하면서 가중치를 업데이트한다.
이를 계산하기 위해 미분의 연쇄 법칙(Chain rule)을 사용한다.<img src="https://images.velog.io/images/jjun-ho/post/7324e178-473e-4d36-bb58-9ca69eab1cce/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%202.35.35.png" alt=""></p>
<p><br><br></p>
<h2 id="비선형-활성화-함수activation-function">비선형 활성화 함수(Activation function)</h2>
<p>** 활성화 함수의 특징 - 비선형 함수(Nonlinear function) **</p>
<blockquote>
<p>입력을 받아 수학적 변환을 수행하고 출력을 생성하는 함수이다.
시그모이드 함수나 소프트맥스 함수는 대표적인 활성화 함수이다.</p>
</blockquote>
<blockquote>
<p>인공 신경망의 능력을 높이기 위해서는 은닉층을 계속해서 추가해야 한다. 그런데 만약 활성화 함수로 선형 함수를 사용하게 되면 은닉층을 쌓을 수가 없다.</p>
</blockquote>
<br>

<p>** 시그모이드 함수(Sigmoid function)와 기울기 소실 **</p>
<blockquote>
<p>시그모이드 함수를 사용한 인공 신경망<img src="https://images.velog.io/images/jjun-ho/post/426e08ba-9d7b-436b-a07d-d70f6243a02e/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%202.49.15.png" alt="">인공 신경망의 학습과정
입력에 대해서 순전파(forward propagation) 연산을 하고, 그리고 순전파 연산을 통해 나온 예측값과 실제값의 오차를 손실 함수(loss function)을 통해 계산하고, 그리고 이 손실(loss)을 미분을 통해서 기울기(gradient)를 구하고, 이를 통해 역전파(back propagation)를 수행한다.</p>
</blockquote>
<blockquote>
<p>** 시그모이드 함수의 문제점 **
미분을 해서 기울기(gradient)를 구할 때 발생한다.<img src="https://images.velog.io/images/jjun-ho/post/256bbe2b-09b2-4c4a-85e8-b1d864f84fc5/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%202.51.15.png" alt="">
주황색 부분은 기울기를 계산하면 0에 가까운 아주 작은 값이 나오게 된다. 그런데 역전파 과정에서 0에 가까운 아주 작은 기울기가 곱해지게 되면, 앞단에는 기울기가 잘 전달되지 않게 됩니다. 이러한 현상을 기울기 소실(Vanishing Gradient) 문제라고 한다.
<img src="https://images.velog.io/images/jjun-ho/post/3d68d332-40b0-4604-90b3-eaf9df03b295/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%202.52.48.png" alt="">시그모이드 함수를 사용하는 은닉층의 개수가 다수가 될 경우에는 0에 가까운 기울기가 계속 곱해지면 앞단에서는 거의 기울기를 전파받을 수 없게 된다. 다시 말해 매개변수 W가 업데이트 되지 않아 학습이 되지않는다. 
시그모이드 함수는 원점 중심이 아니어서 시그모이드 함수는 항상 양수를 출력하기 때문에 출력의 가중치 합이 입력의 가중치 합보다 커질 가능성이 높다. 이를 편향 이동(bias shift)이라 한다.
결론적으로 시그모이드 함수를 은닉층에서 사용하는 것은 지양된다.</p>
</blockquote>
<br>

<p>** 하이퍼볼릭탄젠트 함수(Hyperbolic tangent function **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/e308e859-a01c-4ab1-a6e3-4efa65a10ea3/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%202.55.12.png" alt="">하이퍼볼릭탄젠트 함수(tanh)는 입력값을 -1과 1사이의 값으로 변환한다.
시그모이드 함수와는 달리 0을 중심으로 하고 있는데, 이 때문에 시그모이드 함수와 비교하면 반환값의 변화폭이 더 크다. 그래서 시그모이드 함수보다는 기울기 소실 증상이 적은 편이다.</p>
</blockquote>
<br>

<p>** 렐루 함수(ReLU) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/51ced36c-2b28-4b5f-bb45-6c4905928436/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%202.55.49.png" alt="">수식은 f(x)=max(0,x)이다.
음수를 입력하면 0을 출력하고, 양수를 입력하면 입력값을 그대로 반환한다.
특정 양수값에 수렴하지 않으므로 깊은 신경망에서 시그모이드 함수보다 훨씬 더 잘 작동한다.
렐루 함수는 시그모이드 함수와 하이퍼볼릭탄젠트 함수와 같이 어떤 연산이 필요한 것이 아니라 단순 임계값이므로 연산 속도도 빠르다.</p>
<p>** 문제점 **
입력값이 음수면 기울기도 0이 된다. 이 문제를 죽은 렐루(dying ReLU)라고 한다.</p>
</blockquote>
<br>

<p>** 리키 렐루(Leaky ReLU) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/4818ea1c-57cc-4a15-9010-cd58220e0174/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%203.02.02.png" alt="">죽은 렐루를 보완하기 위해 만들어진 변형 함수이다.
Leaky ReLU는 입력값이 음수일 경우에 0이 아니라 0.001과 같은 매우 작은 수를 반환한다.
수식은 f(x)=max(ax,x)이다.</p>
</blockquote>
<br>

<p>** 소프트맥스 함수(Softamx function) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/123a816a-2e70-49d4-a582-327cab468c46/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%203.02.52.png" alt="">소프트맥스 함수는 시그모이드 함수처럼 출력층의 뉴런에서 주로 사용된다. 시그모이드 함수가 이진 분류 (Binary Classification) 문제에 사용된다면 소프트맥스 함수는 다중 클래스 분류(MultiClass Classification) 문제에 주로 사용된다.</p>
</blockquote>
<p><br><br></p>
<h2 id="과적합overfitting을-막는-방법들">과적합(Overfitting)을 막는 방법들</h2>
<p>** 데이터의 양을 늘리기 **</p>
<blockquote>
<p>모델은 데이터의 양이 적을 경우, 해당 데이터의 특정 패턴이나 노이즈까지 쉽게 암기하기 되므로 과적합 현상이 발생할 확률이 늘어난다. 그렇기 때문에 데이터의 양을 늘릴 수록 모델은 데이터의 일반적인 패턴을 학습하여 과적합을 방지할 수 있다.</p>
</blockquote>
<br>

<p>** 모델의 복잡도 줄이기 **</p>
<blockquote>
<p>복잡도는 은닉층(hidden layer)의 수나 매개변수의 수 등으로 결정된다.</p>
</blockquote>
<br>

<p>** 가중치 규제(Regularization) 적용하기 **</p>
<blockquote>
<p>복잡한 모델이 간단한 모델보다 과적합될 가능성이 높다. 그리고 간단한 모델은 적은 수의 매개변수를 가진 모델이다. 복잡한 모델을 좀 더 간단하게 하는 방법으로 가중치 규제(Regularizaiton)가 있다.</p>
</blockquote>
<br>


<p>** 드롭아웃(Dropout) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/0a4f35cf-4542-450a-abaf-aa171eeeebac/image.png" alt="">드롭아웃은 학습 과정에서 신경망의 일부를 사용하지 않는 방법이다. 드롭아웃의 비율을 0.5로 한다면 학습 과정마다 랜덤으로 절반의 뉴런을 사용하지 않고, 절반의 뉴런만을 사용한다.
드롭아웃은 신경망 학습 시에만 사용하고, 예측 시에는 사용하지 않는 것이 일반적이다. 학습 시에 인공 신경망이 특정 뉴런 또는 특정 조합에 너무 의존적이게 되는 것을 방지해주고, 매번 랜덤 선택으로 뉴런들을 사용하지 않으므로 서로 다른 신경망들을 앙상블하여 사용하는 것 같은 효과를 내어 과적합을 방지한다.</p>
</blockquote>
<p><br><br></p>
<h2 id="기울기-소실gradient-vanishing과-폭주exploding">기울기 소실(Gradient Vanishing)과 폭주(Exploding)</h2>
<p>** Gradient Vanishing / Exploding</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/89e6f2ae-dd46-41c0-93f9-624fae9c99ca/image.jpeg" alt="">
** Solutions **</p>
</blockquote>
<ul>
<li>Change activation function</li>
<li>Careful initialization</li>
<li>Small learning rate</li>
<li>Batch Normalization</li>
</ul>
<br>

<p>** 가중치 초기화(Weight initialization) **</p>
<blockquote>
<p>Restricted Boltzmann Machine<img src="https://images.velog.io/images/jjun-ho/post/9b885eda-cc71-4611-844e-99e4ca4cd630/image.png" alt=""></p>
</blockquote>
<ul>
<li>세이비어 초기화(Xavier Initialization)</li>
<li>He 초기화(He initialization)<img src="https://images.velog.io/images/jjun-ho/post/1c020a1c-0c0e-48b9-a938-accd0df4f17d/image.png" alt=""></li>
</ul>
<br>

<p>** 배치 정규화(Batch Normalization) **</p>
<blockquote>
<p>배치 정규화는 인공 신경망의 각 층에 들어가는 입력을 평균과 분산으로 정규화하여 학습을 효율적으로 만든다.</p>
</blockquote>
<blockquote>
<p>** 내부 공변량 변화(Internal Covariate Shift) **
공변량 변화는 훈련 데이터의 분포와 테스트 데이터의 분포가 다른 경우를 의미한다.
내부 공변량 변화는 신경망 층 사이에서 발생하는 입력 데이터의 분포 변화를 의미한다.</p>
</blockquote>
<blockquote>
<p>** 배치 정규화(Batch Normalization) **
한 번에 들어오는 배치 단위로 정규화하는 것을 말한다. 배치 정규화는 각 층에서 활성화 함수를 통과하기 전에 수행된다. 배치 정규화를 요약하면 입력에 대해 평균을 0으로 만들고, 정규화를 한다. 그리고 정규화 된 데이터에 대해서 스케일과 시프트를 수행한다.<img src="https://images.velog.io/images/jjun-ho/post/79902a66-7c21-4f4f-a65b-ee166ca2fb25/image.jpeg" alt="">배치 정규화는 학습 시 배치 단위의 평균과 분산들을 차례대로 받아 이동 평균과 이동 분산을 저장해놓았다가 테스트 할 때는 해당 배치의 평균과 분산을 구하지 않고 구해놓았던 평균과 분산으로 정규화를 한다.</p>
</blockquote>
<br>

<p>** 배치 정규화(Batch Normalization) 특징 **</p>
<blockquote>
<ul>
<li>배치 정규화를 사용하면 시그모이드 함수나 하이퍼볼릭탄젠트 함수를 사용하더라도 기울기 소실 문제가 크게 개선된다.</li>
<li>가중치 초기화에 훨씬 덜 민감해진다.</li>
<li>훨씬 큰 학습률을 사용할 수 있어 학습 속도를 개선시킨다.</li>
<li>미니 배치마다 평균과 표준편차를 계산하므로 훈련 데이터에 일종의 잡음을 넣는 부수 효과로 과적합을 방지하는 효과도 낸다. 하지만 부수적 효과이므로 드롭 아웃과 함께 사용하는 것이 좋다.</li>
</ul>
</blockquote>
<blockquote>
<p>** 배치 정규화의 한계 **</p>
<ul>
<li>배치 정규화는 모델을 복잡하게 하며, 추가 계산을 하는 것이므로 테스트 데이터에 대한 예측 시에 실행 시간이 느려집니다. 그래서 서비스 속도를 고려하는 관점에서는 배치 정규화가 꼭 필요한지 고민이 필요하다.</li>
<li>미니 배치 크기에 의존적이다.
너무 작은 배치 크기에서는 잘 동작하지 않을 수 있다.</li>
<li>RNN에 적용하기 어렵다.</li>
</ul>
</blockquote>
<br>

<p>** 층 정규화(Layer Normalization) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/2bd97943-4025-483e-a40f-67fa69730366/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-27%20%EC%98%A4%EC%A0%84%203.46.11.png" alt=""></p>
</blockquote>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PyTorch로 딥러닝 배우기 2]]></title>
            <link>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-2</link>
            <guid>https://velog.io/@jjun-ho/PyTorch%EB%A1%9C-%EB%94%A5%EB%9F%AC%EB%8B%9D-%EB%B0%B0%EC%9A%B0%EA%B8%B0-2</guid>
            <pubDate>Thu, 22 Jul 2021 15:38:54 GMT</pubDate>
            <description><![CDATA[<h1 id="logistic-regression">Logistic Regression</h1>
<p>** Binary Classification **</p>
<blockquote>
<ul>
<li>합격 / 불합격</li>
<li>정사 메일 / 스팸 메일</li>
<li>진짜 / 가짜
둘 중 하나를 결정하는 문제를 Binary Classification라고 하고, 이를 풀기 위한 대표적인 알고리즘으로 Logistic Regression가 있다.</li>
</ul>
</blockquote>
<br>

<p>** Logistic vs Linear **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/8bbafdf5-5bab-4b7b-9b19-c2705af9f452/image.jpeg" alt=""></p>
</blockquote>
<br>

<p>** Hypothesis Representation ** </p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/52ce4cb7-914d-438f-8a1c-3e4844b0ad9d/image.jpeg" alt=""><img src="https://images.velog.io/images/jjun-ho/post/603c44c1-9092-498b-8c4c-47546ba4010f/image.jpeg" alt="">
H(x) = Wx+b가 아니라, 위와 같이 S자 모양의 그래프를 만들 수 있는 어떤 특정 함수 f를 추가적으로 사용하여 H(x) = f(Wx+b)의 가설을 사용한다. 그리고 위와 같이 S자 모양의 그래프를 그릴 수 f는 시그모이드함수이다.</p>
</blockquote>
<br>

<p>** Sigmoid **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/672e90d4-7a5e-48f3-a429-1f18e2bfeb40/image.png" alt="">Hypothesis, H(x)가 0과 1 사이 값만 나타내게 하기위해 시그모이드 함수를 이용한다.
<img src="https://images.velog.io/images/jjun-ho/post/23c8a7e0-1ffb-40e0-b403-04975dae3da9/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-22%20%EC%98%A4%ED%9B%84%2011.42.30.png" alt=""></p>
</blockquote>
<br>

<p>** Decision Boundary **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/3f5f5c6e-e81c-4f08-bd7a-3d722e3eee48/image.png" alt=""></p>
</blockquote>
<br>

<p>** Cost Function **</p>
<blockquote>
<p>선형 회귀에서 사용했던 평균 제곱 오차의 수식<img src="https://images.velog.io/images/jjun-ho/post/90870028-8587-4fe3-8cbe-c3af510ba7c9/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-22%20%EC%98%A4%ED%9B%84%2011.48.29.png" alt="">
H(x) = Wx+b가 아니라 H(x) = sigmoid(Wx+b)
이다. 이 비용 함수를 미분하면 선형 회귀때와 달리 심한 비볼록(non-convex) 형태의 그래프가 나온다.
<img src="https://images.velog.io/images/jjun-ho/post/a5d50841-fae2-48ba-bfc2-6bcf7927fb45/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-22%20%EC%98%A4%ED%9B%84%2011.50.51.png" alt="">
시그모이드 함수의 특징은 함수의 출력값이 0과 1사이의 값이라는 점이다. 즉, 실제값이 1일 때 예측값이 0에 가까워지면 오차가 커져야 하며, 실제값이 0일 때, 예측값이 1에 가까워지면 오차가 커져야 한다. 이를 충족하는 함수가 로그함수이다.<img src="https://images.velog.io/images/jjun-ho/post/e69dd952-dc20-4815-b436-f439752af84f/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-22%20%EC%98%A4%ED%9B%84%2011.54.01.png" alt=""><img src="https://images.velog.io/images/jjun-ho/post/3e476d6c-3d76-4f37-9fb1-53942df462ce/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-22%20%EC%98%A4%ED%9B%84%2011.56.39.png" alt="">
이를 하나의 식으로 통합 할 수 있다.<img src="https://images.velog.io/images/jjun-ho/post/ae885fad-c86d-48b2-b1af-bd15cf0ec3d5/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-22%20%EC%98%A4%ED%9B%84%2011.57.22.png" alt=""></p>
</blockquote>
<br>

<p>** Optimization **</p>
<blockquote>
<p>선형 회귀에서는 모든 오차의 평균을 구해 평균 제곱 오차를 사용했었다. 마찬가지로 여기에서도 모든 오차의 평균을 구한다.<img src="https://images.velog.io/images/jjun-ho/post/a5c0b61e-f13d-46ca-94b8-266cf08ca286/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-23%20%EC%98%A4%EC%A0%84%2012.00.56.png" alt="">
비용 함수는 실제값 y와 예측값 H(x)의 차이가 커지면 cost가 커지고, 실제값 y와 예측값 H(x)의 차이가 작아지면 cost는 작아진다. 이제 위 비용 함수에 대해서 경사 하강법을 수행하면서 최적의 가중치 W를 찾는다.
<img src="https://images.velog.io/images/jjun-ho/post/9e84fb29-c1d0-4140-b65e-3470863ea699/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-23%20%EC%98%A4%EC%A0%84%2012.01.14.png" alt=""></p>
</blockquote>
<p><br><br></p>
<h1 id="softmax-regression">Softmax Regression</h1>
<p>** Multinomial Classification **</p>
<blockquote>
<p>세 개 이상의 답 중 하나를 고르는 문제를 다중 클래스 분류(Multi-class Classification)라고 한다.</p>
</blockquote>
<br>

<p>** Softmax Regression **</p>
<blockquote>
<p>소프트맥스 회귀는 확률의 총 합이 1이 되는 이 아이디어를 다중 클래스 분류 문제에 적용한다. 소프트맥스 회귀는 각 선택지마다 소수 확률을 할당한다. 이때 총 확률의 합은 1이 되어야 한다.<img src="https://images.velog.io/images/jjun-ho/post/5fc82edf-8ec8-4554-b953-6cd79e936b46/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-23%20%EC%98%A4%EC%A0%84%2012.10.12.png" alt="">
소프트맥스 회귀는 선택지의 개수만큼의 차원을 가지는 벡터를 만들고, 해당 벡터가 벡터의 모든 원소의 합이 1이 되도록 원소들의 값을 변환시키는 어떤 함수를 지나게 만들어야 한다. 이 함수를 소프트맥스(softmax) 함수라고 한다.</p>
</blockquote>
<br>

<p>** Softmax Function **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/84f080c8-fde1-4cce-9727-5c188699763d/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-23%20%EC%98%A4%EC%A0%84%2012.17.27.png" alt=""><img src="https://images.velog.io/images/jjun-ho/post/c9fec679-ed5d-4150-b6f4-ef5fe9020128/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-23%20%EC%98%A4%EC%A0%84%2012.18.20.png" alt=""><img src="https://images.velog.io/images/jjun-ho/post/0121a99a-0d4d-4bdb-9146-83ab481b641c/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-23%20%EC%98%A4%EC%A0%84%2012.18.38.png" alt=""></p>
</blockquote>
<br>

<p>** Cost Function **</p>
<blockquote>
<p>소프트맥스 회귀에서는 비용 함수로 크로스 엔트로피 함수를 사용한다.</p>
</blockquote>
<br>

<p>** Cross-entropy Function **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/08e75aee-f11c-498c-8e77-a6d38a79b28a/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-23%20%EC%98%A4%EC%A0%84%2012.24.46.png" alt="">y는 실제값을 나타내며, k는 클래스의 개수로 정의한다. yj는 실제값 원-핫 벡터의 j번째 인덱스를 의미하며, pj는 샘플 데이터가 j번째 클래스일 확률을 나타낸다. 
<br>
이를 n개의 전체 데이터에 대한 평균을 구한다고 하면 최종 비용 함수는 다음과 같다.<img src="https://images.velog.io/images/jjun-ho/post/d7c1aeb5-7cab-4561-85b0-6ced238ea00b/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-23%20%EC%98%A4%EC%A0%84%2012.27.45.png" alt=""></p>
</blockquote>
<p><br><br></p>
<h1 id="application">Application</h1>
<p>** Overfitting **</p>
<blockquote>
<p>Solutions</p>
<ul>
<li>Set a features 
특징을 더 추가한다.</li>
<li>Regularization 정규화</li>
<li>More Data and Data Augmentation</li>
<li>Dropout</li>
<li>Batch Normalization</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[OpenCV 배우기 5]]></title>
            <link>https://velog.io/@jjun-ho/OpenCV-%EB%B0%B0%EC%9A%B0%EA%B8%B0-5</link>
            <guid>https://velog.io/@jjun-ho/OpenCV-%EB%B0%B0%EC%9A%B0%EA%B8%B0-5</guid>
            <pubDate>Wed, 21 Jul 2021 13:50:07 GMT</pubDate>
            <description><![CDATA[<h1 id="6-컨투어-contour">6. 컨투어 (Contour)</h1>
<h2 id="컨투어">컨투어</h2>
<pre><code>import cv2 as cv

img_color = cv.imread(&#39;test.png&#39;)
img_gray = cv.cvtColor(img_color,  cv.COLOR_BGR2GRAY)
ret, img_binary =cv.threshold(img_gray,127, 255, 0)
contours, hierarchy =cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

cv.imshow(&#39;result&#39;,img_color)
cv.waitKey(0)</code></pre><blockquote>
<p>실행 결과<img src="https://images.velog.io/images/jjun-ho/post/13e467f1-bed7-400d-b1c0-6b2cd256358d/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%206.19.49.png" alt=""></p>
</blockquote>
<br>

<p>** contours, hierarchy =cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) **</p>
<blockquote>
<p>contours, hierarchy =cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]]) </p>
<ul>
<li>image 
입력 이미지이다. 
검은색과 흰색만으로 구성되는 Binary 이미지이어야 한다.</li>
<li>contours
각각의 컨투어에는 오브젝트 외각선을 구성하는 점들의 x,y 좌표를 저장하고있다. 리스트로 저장된다. </li>
<li>hierarchy
검출된 컨투어의 정보를 구조적으로 저장하고있다.
리스트로 저장된다.</li>
<li>mode
Contour Retrieval Mode.</li>
<li>method
Contour Approximation Method.</li>
<li>offset
지정한 크기만큼 컨투어를 구성하는 포인티 좌표를 이동한다.</li>
</ul>
</blockquote>
<p><br><br></p>
<h2 id="컨투어-그리기">컨투어 그리기</h2>
<pre><code>import cv2 as cv

img_color = cv.imread(&#39;test.png&#39;)
img_gray = cv.cvtColor(img_color,  cv.COLOR_BGR2GRAY)
ret, img_binary =cv.threshold(img_gray,127, 255, 0)
contours, hierarchy =cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

image = cv.drawContours(img_color, contours, -1, (0, 255 ,0), 3)

cv.imshow(&#39;result&#39;,img_color)
cv.waitKey(0)</code></pre><blockquote>
<p>실행 결과<img src="https://images.velog.io/images/jjun-ho/post/cb201fee-f5bd-44da-baac-d3821ae53abb/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%206.36.53.png" alt=""></p>
</blockquote>
<br>

<p>*<em>image = cv.drawContours(img_color, contours, -1, (0, 255 ,0), 3) *</em></p>
<blockquote>
<p>image = cv.drawContours( image, contours, contourldx, color[, thickness[,lineType[, hierarchy[, maxLevel[, offset]]]]])</p>
<ul>
<li>image 
컨투어를 그릴 대상 이미지이다.
컬러 이미지를 선택해야한다.</li>
<li>contours
이미지 위에 그릴 컨투어가 저장된 리스트이다.</li>
<li>contourldx
이미지에 그릴 특정 컨투어의 인덱스이다.
음수로 지정하면 모든 컨투어를 그리게 된다.<blockquote>
<p>image = cv.drawContours(img_color, contours, 0, (0, 255 ,0), 3)
image = cv.drawContours(img_color, contours, 1, (255,0,0), 3)
<img src="https://images.velog.io/images/jjun-ho/post/545e8099-5e42-4768-aa0e-b0be9834e959/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%206.32.47.png" alt=""></p>
</blockquote>
</li>
<li>color
컨투어를 그릴 때 사용 할 색상 지정한다.
B,G,R 순서이다.</li>
<li>thickness
컨투어를 그릴 때 선의 굵기이다.
음수이면 내부를 채운다.</li>
</ul>
</blockquote>
<p><br><br></p>
<h2 id="contour-approximation-method">Contour Approximation Method</h2>
<p>** contours, hierarchy =cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/efaa315b-60d1-448e-ae46-6350572d0efc/IMG_0265.jpeg" alt="">
컨투어를 구성하는 포인트를 저장하는 방법을 결정한다.</p>
</blockquote>
<p><br><br></p>
<h2 id="contour-retrieval-mode">Contour Retrieval Mode</h2>
<p>** contours, hierarchy =cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE) **</p>
<pre><code>import cv2 as cv

img_color = cv.imread(&#39;test.png&#39;)
img_gray = cv.cvtColor(img_color,  cv.COLOR_BGR2GRAY)
ret, img_binary =cv.threshold(img_gray,127, 255, 0)
contours, hierarchy =cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    cv.drawContours(img_color,[cnt],0,(255,0,0),3)
print(hierarchy)

cv.imshow(&#39;result&#39;,img_color)
cv.waitKey(0)</code></pre><blockquote>
<p>실행 결과<img src="https://images.velog.io/images/jjun-ho/post/21198f6f-2947-47aa-b6c8-e43588a20726/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%2010.09.00.png" alt="">
hierarchy 값 = [Next, Previous, First_child, Parent]</p>
</blockquote>
<blockquote>
<ul>
<li>RETR_TREE
컨투어 내부에 다른 커투어가 있을 경우, 계층 구조로 만들어준다.
<img src="https://images.velog.io/images/jjun-ho/post/f17ade99-95f9-44f4-ae82-247ff7939807/IMG_0266.jpeg" alt=""></li>
<li>RETR_LIST
모든 컨투어가 같은 계층 레벨을 갖는다.(계층적인 특성이 필요없는 경우 사용)
<img src="https://images.velog.io/images/jjun-ho/post/9f830439-1054-4294-be39-5496a90c8f11/IMG_0267.jpeg" alt=""></li>
<li>RETR_EXTERNAL
가장 외각에 있는 컨투어만 리턴한다. 컨투어 내부에 있는 자식 컨투어는 무시된다.
<img src="https://images.velog.io/images/jjun-ho/post/6a196e1a-238b-46d5-9225-1b5304a6c976/IMG_0268.jpeg" alt=""></li>
<li>RETR_CCOMP
모든 컨투어를 두 개의 레벨 계층으로 재구성한다. 외부에 있는 컨투어 레벨 1, 오브젝트 내부에 있는 컨투어 레벨 2가 된다.
<img src="https://images.velog.io/images/jjun-ho/post/665f1610-9be2-4ffd-a96e-cdeb1be01a51/IMG_0269.jpeg" alt=""></li>
</ul>
</blockquote>
<p><br><br></p>
<h2 id="컨투어-특징-사용하기">컨투어 특징 사용하기</h2>
<h3 id="영역-크기">영역 크기</h3>
<p>컨투어 영역 크기 출력한다.</p>
<pre><code>import cv2 as cv

img_color = cv.imread(&#39;test.png&#39;)
img_gray = cv.cvtColor(img_color, cv.COLOR_BGR2GRAY)
ret, img_binary = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    cv.drawContours(img_color, [cnt], 0, (255, 0, 0), 3)  # blue

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)

for cnt in contours:
    area = cv.contourArea(cnt)
    print(area)

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)</code></pre><blockquote>
<p>실행 결과<img src="https://images.velog.io/images/jjun-ho/post/964d6136-cdd5-4eca-aa6a-dcd9524f9eb1/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%2010.32.47.png" alt=""></p>
</blockquote>
<br>

<h3 id="근사화">근사화</h3>
<p>곡선을 1차함수, 즉 직선으로 바꿔준다.</p>
<pre><code>import cv2 as cv
import numpy as np

img_color = cv.imread(&#39;square.png&#39;)
img_gray = cv.cvtColor(img_color, cv.COLOR_BGR2GRAY)
ret, img_binary = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    cv.drawContours(img_color, [cnt], 0, (255, 0, 0), 3)  # blue

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)

for cnt in contours:
    epsilon = 0.02 * cv.arcLength(cnt, True)
    approx = cv.approxPolyDP(cnt, epsilon, True)
    print( len(approx))

    cv.drawContours(img_color,[approx],0,(0,255,255),5)

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)</code></pre><blockquote>
<p>실행 결과<img src="https://images.velog.io/images/jjun-ho/post/0b2f76ec-dfa2-4189-8887-aece742013f0/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%2010.34.45.png" alt=""></p>
</blockquote>
<br>

<h3 id="무게중심">무게중심</h3>
<p>모멘트를 사용하여, 영역의 무게중심을 그려준다.</p>
<pre><code>import cv2 as cv

img_color = cv.imread(&#39;test.png&#39;)
img_gray = cv.cvtColor(img_color, cv.COLOR_BGR2GRAY)
ret, img_binary = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    cv.drawContours(img_color, [cnt], 0, (255, 0, 0), 3)  # blue

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)

for cnt in contours:
    M = cv.moments(cnt)
    cx = int(M[&#39;m10&#39;]/M[&#39;m00&#39;])
    cy = int(M[&#39;m01&#39;]/M[&#39;m00&#39;])

    cv.circle(img_color, (cx, cy), 10, (0,0,255), -1)

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)</code></pre><blockquote>
<p>실행 결과<img src="https://images.velog.io/images/jjun-ho/post/26cbff85-2e52-46e6-bcaf-dfee71a849ff/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%2010.36.14.png" alt=""></p>
</blockquote>
<br>

<h3 id="경계-사각형-bounding-rectangle">경계 사각형 (Bounding Rectangle)</h3>
<p>오브젝트를 둘러 싸는 최소 직사각형이다.</p>
<pre><code>import cv2 as cv
import numpy as np

img_color = cv.imread(&#39;test.png&#39;)
img_gray = cv.cvtColor(img_color, cv.COLOR_BGR2GRAY)
ret, img_binary = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    cv.drawContours(img_color, [cnt], 0, (255, 0, 0), 3)  # blue

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)

for cnt in contours:
    x, y, w, h = cv.boundingRect(cnt)
    cv.rectangle(img_color, (x, y), (x + w, y + h), (0, 255, 0), 2)

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)

for cnt in contours:
    rect = cv.minAreaRect(cnt) #도형의 방향 고려-&gt;경계 사각형 그려줌.
    box = cv.boxPoints(rect)
    box = np.int0(box)
    cv.drawContours(img_color,[box],0,(0,0,255),2)

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)</code></pre><blockquote>
<p>실행 결과<img src="https://images.velog.io/images/jjun-ho/post/492a603d-7483-4c40-af25-36f62bd44547/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%2010.37.37.png" alt=""></p>
</blockquote>
<br>

<h3 id="convex-hull">Convex Hull</h3>
<p>컨투어를 모두 포함하는 볼록 사각형 그려준다.</p>
<pre><code>import cv2 as cv
import numpy as np

img_color = cv.imread(&#39;hand.png&#39;)
img_gray = cv.cvtColor(img_color, cv.COLOR_BGR2GRAY)
ret, img_binary = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    cv.drawContours(img_color, [cnt], 0, (255, 0, 0), 3)  # blue

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)

for cnt in contours:
    hull = cv.convexHull(cnt)
    cv.drawContours(img_color, [hull], 0, (255, 0, 255), 5)

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)</code></pre><blockquote>
<p>실행 결과<img src="https://images.velog.io/images/jjun-ho/post/1e899745-4bb6-4be2-b6df-f7bf5627ebf4/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%2010.39.02.png" alt=""></p>
</blockquote>
<br>

<h3 id="convexity-defects">Convexity Defects</h3>
<p>볼록 다각형 내부에 오목하게 들어간 부분이다.</p>
<pre><code>import cv2 as cv
import numpy as np

img_color = cv.imread(&#39;hand.png&#39;)
img_gray = cv.cvtColor(img_color, cv.COLOR_BGR2GRAY)
ret, img_binary = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(img_binary, cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)

for cnt in contours:
    cv.drawContours(img_color, [cnt], 0, (255, 0, 0), 3)  # blue

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)

for cnt in contours:
    hull = cv.convexHull(cnt)
    cv.drawContours(img_color, [hull], 0, (255, 0, 255), 5)

cv.imshow(&quot;result&quot;, img_color)
cv.waitKey(0)

for cnt in contours:
    hull = cv.convexHull(cnt, returnPoints = False)
    defects = cv.convexityDefects(cnt, hull)

    for i in range(defects.shape[0]):
        s,e,f,d = defects[i,0]
        start = tuple(cnt[s][0])
        end = tuple(cnt[e][0])
        far = tuple(cnt[f][0])

        print(d)

        if d &gt; 500:
            cv.line(img_color, start, end, [0, 255, 0], 5)
            cv.circle(img_color, far, 5, [0,0,255], -1)

        cv.imshow(&quot;result&quot;, img_color)
        cv.waitKey(0)</code></pre><blockquote>
<p>실행 결과<img src="https://images.velog.io/images/jjun-ho/post/01816c2a-5a82-4387-9c75-da20cc36665e/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-21%20%EC%98%A4%ED%9B%84%2010.40.06.png" alt=""></p>
</blockquote>
<p><br><br></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OpenCV 배우기 4]]></title>
            <link>https://velog.io/@jjun-ho/OpenCV-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EA%B8%B0-4</link>
            <guid>https://velog.io/@jjun-ho/OpenCV-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EA%B8%B0-4</guid>
            <pubDate>Mon, 19 Jul 2021 16:32:39 GMT</pubDate>
            <description><![CDATA[<h1 id="5-웹캠에서-실시간으로-특정색-물체-추적하기">5. 웹캠에서 실시간으로 특정색 물체 추적하기</h1>
<pre><code>import cv2 as cv
import numpy as np

hsv = 0
lower_blue1 = 0
upper_blue1 = 0
lower_blue2 = 0
upper_blue2 = 0
lower_blue3 = 0
upper_blue3 = 0

# 콜백 함수 정의, 트랙바 생성시 필요로 하는 더미 함수.
def nothing(x):
    pass


def mouse_callback(event, x, y, flags, param):
    global hsv, lower_blue1, upper_blue1, lower_blue2, upper_blue2, lower_blue3, upper_blue3, threshold

    # 마우스 왼쪽 버튼 누를시 위치에 있는 픽셀값을 읽어와서 HSV로 변환.
    if event == cv.EVENT_LBUTTONDOWN:
        print(img_color[y, x])
        color = img_color[y, x]

        one_pixel = np.uint8([[color]])
        hsv = cv.cvtColor(one_pixel, cv.COLOR_BGR2HSV)
        hsv = hsv[0][0]

        # 트랙바의 현재값을 가져와 threshold에 대입.
        threshold = cv.getTrackbarPos(&#39;threshold&#39;, &#39;img_result&#39;)

        # HSV 색공간에서 마우스 클릭으로 얻은 픽셀값과 유사한 필셀값의 범위를 정함.
        if hsv[0] &lt; 10:
            print(&quot;case1&quot;)
            lower_blue1 = np.array([hsv[0] - 10 + 180, threshold, threshold])
            upper_blue1 = np.array([180, 255, 255])
            lower_blue2 = np.array([0, threshold, threshold])
            upper_blue2 = np.array([hsv[0], 255, 255])
            lower_blue3 = np.array([hsv[0], threshold, threshold])
            upper_blue3 = np.array([hsv[0] + 10, 255, 255])
            #     print(i-10+180, 180, 0, i)
            #     print(i, i+10)

        elif hsv[0] &gt; 170:
            print(&quot;case2&quot;)
            lower_blue1 = np.array([hsv[0], threshold, threshold])
            upper_blue1 = np.array([180, 255, 255])
            lower_blue2 = np.array([0, threshold, threshold])
            upper_blue2 = np.array([hsv[0] + 10 - 180, 255, 255])
            lower_blue3 = np.array([hsv[0] - 10, threshold, threshold])
            upper_blue3 = np.array([hsv[0], 255, 255])
            #     print(i, 180, 0, i+10-180)
            #     print(i-10, i)
        else:
            print(&quot;case3&quot;)
            lower_blue1 = np.array([hsv[0], threshold, threshold])
            upper_blue1 = np.array([hsv[0] + 10, 255, 255])
            lower_blue2 = np.array([hsv[0] - 10, threshold, threshold])
            upper_blue2 = np.array([hsv[0], 255, 255])
            lower_blue3 = np.array([hsv[0] - 10, threshold, threshold])
            upper_blue3 = np.array([hsv[0], 255, 255])
            #     print(i, i+10)
            #     print(i-10, i)

        print(hsv[0])
        print(&quot;@1&quot;, lower_blue1, &quot;~&quot;, upper_blue1)
        print(&quot;@2&quot;, lower_blue2, &quot;~&quot;, upper_blue2)
        print(&quot;@3&quot;, lower_blue3, &quot;~&quot;, upper_blue3)


cv.namedWindow(&#39;img_color&#39;)
cv.setMouseCallback(&#39;img_color&#39;, mouse_callback)

# 트랙바를 추가하여 채도(Saturation),명도(Value) 값(0~ 255)을 조정하도록 수정.
cv.namedWindow(&#39;img_result&#39;)
cv.createTrackbar(&#39;threshold&#39;, &#39;img_result&#39;, 0, 255, nothing)

# 트랙바의 초기값 설정.
cv.setTrackbarPos(&#39;threshold&#39;, &#39;img_result&#39;, 30)

# 웹캠으로부터 입력을 받기 위해 비디오 캡처 객체 생성.
cap = cv.VideoCapture(0)

while (True):
    # img_color = cv.imread(&#39;2.jpg&#39;)
    # 이미지를 웹캠으로부터 캡처하게 함.
    ret, img_color = cap.read()
    height, width = img_color.shape[:2]
    img_color = cv.resize(img_color, (width, height), interpolation=cv.INTER_AREA)

    # 원본 영상을 HSV 영상으로 변환.
    img_hsv = cv.cvtColor(img_color, cv.COLOR_BGR2HSV)

    # 범위 값으로 HSV 이미지에서 마스크를 생성.
    img_mask1 = cv.inRange(img_hsv, lower_blue1, upper_blue1)
    img_mask2 = cv.inRange(img_hsv, lower_blue2, upper_blue2)
    img_mask3 = cv.inRange(img_hsv, lower_blue3, upper_blue3)
    img_mask = img_mask1 | img_mask2 | img_mask3

    # OPEN-영상의 점으로 보이는 노이즈 제거, CLOSE-물체의 생긴 검은 구멍들을 메움.
    kernel = np.ones((11, 11), np.uint8)
    img_mask = cv.morphologyEx(img_mask, cv.MORPH_OPEN, kernel)
    img_mask = cv.morphologyEx(img_mask, cv.MORPH_CLOSE, kernel)

    # 마스크 이미지로 원본 이미지에서 범위값에 해당되는 영상 부분을 획득.
    img_result = cv.bitwise_and(img_color, img_color, mask=img_mask)

    # 물체의 위치를 추적하는 코드를 추가. 라벨링이 필요.
    numOfLabels, img_label, stats, centroids = cv.connectedComponentsWithStats(img_mask)

    # 라벨링-&gt;물체의 중심 좌표, 영역의 크기, 외각 박스 좌표를 얻을 수 있음.
    for idx, centroid in enumerate(centroids):
        if stats[idx][0] == 0 and stats[idx][1] == 0:
            continue

        if np.any(np.isnan(centroid)):
            continue

        x, y, width, height, area = stats[idx]
        centerX, centerY = int(centroid[0]), int(centroid[1])
        print(centerX, centerY)

        if area &gt; 50:
            cv.circle(img_color, (centerX, centerY), 10, (0, 0, 255), 10)
            cv.rectangle(img_color, (x, y), (x + width, y + height), (0, 0, 255))

    cv.imshow(&#39;img_color&#39;, img_color)
    cv.imshow(&#39;img_mask&#39;, img_mask)
    cv.imshow(&#39;img_result&#39;, img_result)

    # ESC 키누르면 종료
    if cv.waitKey(1) &amp; 0xFF == 27:
        break

cv.destroyAllWindows()</code></pre><br>

<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/30d6f9d8-3e9e-4f5f-96be-9c2d8805acca/image.jpeg" alt="">
조명차이 등 TEST 환경 차이로 HSV 값이 다를 수 있다.
색조(Hue) 값이 같더라도 채도(Saturation),명도(Value)에 따라 결과가 다를 수 있기 때문에 추가한 트랙바를 이용하여 채도(Saturation),명도(Value) 값을 수정한다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[OpenCV 배우기 3]]></title>
            <link>https://velog.io/@jjun-ho/OpenCV-%EB%B0%B0%EC%9A%B0%EA%B8%B0-3</link>
            <guid>https://velog.io/@jjun-ho/OpenCV-%EB%B0%B0%EC%9A%B0%EA%B8%B0-3</guid>
            <pubDate>Mon, 19 Jul 2021 14:40:12 GMT</pubDate>
            <description><![CDATA[<h1 id="4-hsv-색공간에서-특정색-검출하기">4. HSV 색공간에서 특정색 검출하기</h1>
<h2 id="픽셀-pixel">픽셀 (Pixel)</h2>
<p>이미지 파일에 숫자로 저장되어있다. 화면에 보여질 때에는 숫자를 컬러의 강도로 변환하여 보여진다. 이미지는 픽셀로 구성되며 하나의 픽셀은 B,G,R 3개의 채널로 구성된다.
 opencv에서는 RGB가 아니라 BGR로 채널 순서가 다르다.
<img src="https://images.velog.io/images/jjun-ho/post/7cc52566-f3de-431f-927c-92adf6fd3c8a/IMG_0259.jpeg" alt=""></p>
<p><br><br></p>
<h2 id="색공간-color-space">색공간 (Color Space)</h2>
<blockquote>
<p>색공간은 색을 표현하는 방법을 3차원 좌표계로 표시한 것이다.
<img src="https://images.velog.io/images/jjun-ho/post/0db35a6c-e38d-45d2-af43-2c5477472174/IMG_0260.jpeg" alt="">RGB 색공간 / HSV 색공간</p>
</blockquote>
<blockquote>
<p>HSV
<img src="https://images.velog.io/images/jjun-ho/post/5edd72bd-5721-444d-a085-93dd8f5ec637/IMG_0261.jpeg" alt=""></p>
</blockquote>
<ul>
<li>색조(Hue): HSV의 색공간의 Hue 성분은 특정색의 컬러가 일정한 범위를 갖기 때문에 원하는 색의 범위를 정하기가 쉽다.
opencv에서는 0 ~ 179 범위를 가지기 때문에, 원하는 색의 그림에 표시된 Hue 값에 0.5를 곱한 값이 opencv에서의 Hue 값이다. </li>
<li>채도(Saturation): 색상의 진함(값이 클수록 진함), opencv에서는 0 ~ 255 가진다.               </li>
<li>명도(Value): 색상의 밝은 정도(값이 클수록 밝음), opencv에서는 0 ~255 값 가진다.</li>
</ul>
<p><br><br></p>
<h2 id="bgr-to-hsv">BGR to HSV</h2>
<pre><code>import numpy as np
import cv2

color = [255,0,0] #파란색
pixel = np.uint8([[color]])

hsv = cv2.cvtColor(pixel, cv2.COLOR_BGR2HSV)
hsv = hsv[0][0]

print(&#39;bgr: &#39;,color)
print(&#39;hsv: &#39;,hsv)</code></pre><blockquote>
<p>실행결과
<img src="https://images.velog.io/images/jjun-ho/post/dd523322-a2fc-4d88-87a8-b88c64794862/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-19%20%EC%98%A4%ED%9B%84%205.16.07.png" alt=""></p>
</blockquote>
<p>** pixel = np.uint8([[color]]) **
cvtColor 함수의 입력으로 사용 할 수 있도록 한 픽셀로 구성된 이미지로 변환한다.</p>
<br>

<p>** hsv = cv2.cvtColor(pixel, cv2.COLOR_BGR2HSV) **
cvtColor 함수를 이용하여 HSV 색공간으로 변환한다.</p>
<br>

<p>** hsv = hsv[0][0] **
HSV 값을 출력하기 위해 픽셀 값만 가져온다.</p>
<br>

<p>** 이미지에서 파란색을 검출하는 코드 **</p>
<pre><code>import cv2

img_color =cv2.imread(&#39;1.png&#39;)
height,width = img_color.shape[:2]

img_hsv = cv2.cvtColor(img_color, cv2.COLOR_BGR2HSV)

lower_blue = (120-10,30,30)
upper_blue = (120+10,255,255)
img_mask =cv2.inRange(img_hsv, lower_blue, upper_blue)

img_result = cv2.bitwise_and(img_color, img_color, mask = img_mask)

cv2.imshow(&#39;img_color&#39;,img_color)
cv2.imshow(&#39;img_mask&#39;,img_mask)
cv2.imshow(&#39;img_result&#39;,img_result)

cv2.waitKey(0)
cv2.destroyAllWindows()</code></pre><blockquote>
<p>실행 결과
<img src="https://images.velog.io/images/jjun-ho/post/634e0fd4-3a5a-4406-b865-b7e665ea4224/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-19%20%EC%98%A4%ED%9B%84%205.33.03.png" alt=""></p>
<blockquote>
<p>파란색에 대한 채도(Saturation),명도(Value) 변화를 주어도 같은 값으로 인식한다.</p>
</blockquote>
</blockquote>
<br>

<p>** height,width = img_color.shape[:2] ** 
이미지의 높이와 너비를 가져온다.</p>
<br>

<p>** lower_blue = (120-10,30,30) **
범위를 정하여 HSV 이미지에서 원하는 색영역을 Binary 이미지로 생성한다. 
너무 어두워서 검은색에 가까운 색과 색이 옅어서 흰색에 가까운 값을 제외시키기 위해 채도(Saturation),명도(Value) 값은 30으로 한다. 
** upper_blue = (120+10,255,255) **
채도(Saturation),명도(Value) 값은 255로 한다.</p>
<br>

<p>** img_mask =cv2.inRange(img_hsv, lower_blue, upper_blue) **
inRange 함수에 앞에서 정의한 범위값을 사용하여 Binary 이미지를 얻는다. 범위 내에 있는 픽셀들은 흰색, 나머지는 검은색이 된다.</p>
<br>

<p>** img_result = cv2.bitwise_and(img_color, img_color, mask = img_mask) **
Binary 이미지를 마스크로 사용하여 원본 이미지에서 범위 값에 해당하는 영상 부분을 획득한다.</p>
<br>

<p>** 한계 **
2 ~ 3개 경계에 있는 값을 인식시키려고 하는 경우 두가지 색이 같은 범위에 포함 될 수 있다.-&gt; 좀 더 좁은 범위를 사용해야한다.
조명 범위에 따라 색이 다르게 보이는 것도 인식시키기 어렵다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OpenCV 배우기 2]]></title>
            <link>https://velog.io/@jjun-ho/OpenCV-%EB%B0%B0%EC%9A%B0%EA%B8%B0-2</link>
            <guid>https://velog.io/@jjun-ho/OpenCV-%EB%B0%B0%EC%9A%B0%EA%B8%B0-2</guid>
            <pubDate>Mon, 19 Jul 2021 07:52:01 GMT</pubDate>
            <description><![CDATA[<h1 id="3-이진화">3. 이진화</h1>
<h2 id="배경과-오브젝트-분리하기">배경과 오브젝트 분리하기</h2>
<pre><code>import cv2

def nothing(x):
    pass

cv2.namedWindow(&#39;Binary&#39;)
cv2.createTrackbar(&#39;threshold&#39;,&#39;Binary&#39;,0,255,nothing)
cv2.setTrackbarPos(&#39;threshold&#39;, &#39;Binary&#39;,127)

img_color = cv2.imread(&#39;red_ball.jpg&#39;,cv2.IMREAD_COLOR)

cv2.imshow(&#39;Color&#39;,img_color)
cv2.waitKey(0)

img_gray = cv2.cvtColor(img_color,cv2.COLOR_BGR2GRAY)

cv2.imshow(&#39;Gray&#39;,img_gray)
cv2.waitKey(0)

while(True):
    low= cv2.getTrackbarPos(&#39;threshold&#39;,&#39;Binary&#39;)
    ret,img_binary =cv2.threshold(img_gray,low,255,cv2.THRESH_BINARY_INV)

   cv2.imshow(&#39;Binary&#39;,img_binary)
   img_result = cv2.bitwise_or(img_color,img_color,mask =img_binary)
   cv2.imshow(&#39;Result&#39;, img_result)

   if cv2.waitKey(1)&amp;0xff == 27:
        break

cv2.destroyAllWindows()</code></pre><br>

<p>** def nothing(x):
    pass **
더미 함수로 사용하지는 않지만 트랙바를 생성하기 위해 필요하다.</p>
<br>

<p>** cv2.namedWindow(&#39;Binary&#39;) **
트랙바를 붙일 윈도우 생성한다.</p>
<br>

<p>** cv2.createTrackbar(&#39;threshold&#39;,&#39;Binary&#39;,0,255,nothing) **</p>
<blockquote>
<p>cv.createTrackbar(트랙바의 식별자, 트랙바를 이름이 &#39;Binary&#39; 윈도우에 붙임, 트랙바로 조종 가능한 최소값, 최대값, 더미함수)</p>
</blockquote>
<p>트랙바로 조종 가능한 최소값 0, 최대값 255로 설정</p>
<br>

<p>** cv2.setTrackbarPos(&#39;threshold&#39;, &#39;Binary&#39;,127) **
트랙바의 초기값(127)로 설정한다.</p>
<br>

<p>** img_color = cv2.imread(&#39;red_ball.jpg&#39;,cv2.IMREAD_COLOR) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/5c0ef013-1db0-40cb-9025-fc4c3bbc5a62/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-19%20%EC%98%A4%ED%9B%84%203.42.37.png" alt=""></p>
<blockquote>
<p>cv2.imshow(&#39;Color&#39;,img_color)</p>
</blockquote>
</blockquote>
<p>하나의 픽셀은 3개의 채널로 구성된다.
R,G,B 3개의 채널이 각각 0 ~ 255 값을 가질 수 있다.</p>
<br>

<p>** img_gray = cv2.cvtColor(img_color,cv2.COLOR_BGR2GRAY) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/69290246-9b4a-47a4-a240-6d3906015b92/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-19%20%EC%98%A4%ED%9B%84%203.42.51.png" alt=""></p>
<blockquote>
<p>cv2.imshow(&#39;Gray&#39;,img_gray) </p>
</blockquote>
</blockquote>
<p>하나의 픽셀은 1개의 채널을 가진다.
가장 어두운 검은색(0) ~ 가장 밝은 흰색(255) 값을 가질 수 있다.</p>
<br>

<p>** while(True): **
트랙바를 이동시 결과를 바로 확인 할 수 있도록 추가한다.</p>
<br>

<p>** low= cv2.getTrackbarPos(&#39;threshold&#39;,&#39;Binary&#39;) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/83e2e672-cfeb-48f4-a52b-2ffabbf97aa9/image.jpeg" alt="">
트랙바의 현재값을 가져와 TRESH HOLD 함수의 임계값으로 사용 할 수 있도록 한다.</p>
</blockquote>
<br>

<p>** ret,img_binary =cv2.threshold(img_gray,low,255,cv2.THRESH_BINARY_INV) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/9976aa6c-61c6-4024-8e7f-b13c196f752d/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-19%20%EC%98%A4%ED%9B%84%203.43.29.png" alt=""></p>
<blockquote>
<p>cv2.imshow(&#39;Binary&#39;,img_binary)</p>
</blockquote>
</blockquote>
<blockquote>
<p>cv2.threshold(이진화할 대상이미지-Gray Scale 이미지 이어야함, Thresh Hold 함수의 임계값 - 이 값을 기준으로 검정색 / 흰색 결정, 4번째 인자의 결과 이미지 픽셀 값, THRESH_BINARY_INV )</p>
</blockquote>
<blockquote>
<p>Thresh Hold 값과 입력 이미지 픽셀 값을 비교 후 결과에 따라 결과 이미지 픽셀 값을 결정</p>
<ul>
<li>THRESH_BINARY<blockquote>
<p>THRESH HOLD &lt; 입력 이미지 픽셀 -&gt; 결과 이미지 픽셀 값 = 3번 째 인자 값(255)
THRESH HOLD &lt; 입력 이미지 픽셀 -&gt; 결과 이미지 픽셀 값 = 0</p>
</blockquote>
</li>
<li>THRESH_BINARY_INV<blockquote>
<p>THRESH_BINARY의 반전</p>
</blockquote>
</li>
</ul>
</blockquote>
<p>임계값을 기준으로 흰색(255)과 검은색(0) 두 가지 픽셀 값만 가진다.</p>
<br>

<p>** img_result = cv2.bitwise_or(img_color,img_color,mask =img_binary) **</p>
<blockquote>
<p><img src="https://images.velog.io/images/jjun-ho/post/2ba274a5-b1e3-4d3b-b6c0-ad859835cd8f/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-07-19%20%EC%98%A4%ED%9B%84%203.43.21.png" alt=""></p>
<blockquote>
<p>cv2.imshow(&#39;Result&#39;, img_result)</p>
</blockquote>
</blockquote>
<p>원본 이미지와 Binary 이미지를 AND 연산한다.</p>
<br>

<p>** 한계 **
Gray Scale 이미지로 변환하면서 픽셀 색의 컬러 유사성을 고려 하지 않기 때문에 컬러 이미지에서는 전혀 다른색도 Gray Scale 이미지에서는 유사한 색으로 보인다.
 이 문제를 개선하기 위해 이미지를 HSV 색공간으로 변환해야한다.</p>
<br>

















]]></description>
        </item>
    </channel>
</rss>