<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>XMJ&#39;s BLOG</title>
  <icon>https://www.gravatar.com/avatar/b4732351bcb62113965d6b51e3f2245a</icon>
  <subtitle>Writing, Coding, Researching, and Thinking</subtitle>
  <link href="https://blog.xiemingjie.cn/atom.xml" rel="self"/>
  
  <link href="https://blog.xiemingjie.cn/"/>
  <updated>2023-02-13T07:24:42.000Z</updated>
  <id>https://blog.xiemingjie.cn/</id>
  
  <author>
    <name>XMJ</name>
    <email>xiemingjie.cn@gmail.com</email>
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>论文赏析 | Oriented RepPoints：点集表示的旋转目标检测</title>
    <link href="https://blog.xiemingjie.cn/posts/6f41176a.html"/>
    <id>https://blog.xiemingjie.cn/posts/6f41176a.html</id>
    <published>2023-02-13T07:24:42.000Z</published>
    <updated>2023-02-13T07:24:42.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题：<code>《Oriented RepPoints for Aerial Object Detection Wentong》</code></p><blockquote><p>论文发表：CVPR2022<br>论文链接：<a href="http://openaccess.thecvf.com/content/CVPR2022/html/Li_Oriented_RepPoints_for_Aerial_Object_Detection_CVPR_2022_paper.html">http://openaccess.thecvf.com</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20230131112137.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@inproceedings&#123;li2022oriented,</span><br><span class="line">  title=&#123;Oriented reppoints for aerial object detection&#125;,</span><br><span class="line">  author=&#123;Li, Wentong and Chen, Yijie and Hu, Kaixuan and Zhu, Jianke&#125;,</span><br><span class="line">  booktitle=&#123;Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition&#125;,</span><br><span class="line">  pages=&#123;1829--1838&#125;,</span><br><span class="line">  year=&#123;2022&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><table><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><tr><td>标签</td><td>#旋转目标检测 #标签分配</td></tr><tr><td>数据集</td><td>#DOTA #HRSC2016 #UCAS-AOD #DIOR-R</td></tr><tr><td>目的</td><td>设计面向航拍图像的旋转目标检测器</td></tr><tr><td>方法</td><td>基于RepPoint实现</td></tr></tbody></table><h1>2. 问题背景</h1><p>作者提到航拍图像中目标具有非水平，任意方向，密集分布，背景复杂等困难，主流的方法大多将其视为简单的旋转目标检测问题。其中基于角度回归的方法最受欢迎，然而这种增加了角度预测的方法会面临损失的不连续性以及回归的不一致性问题。这是因为角度的有界周期性和旋转框的方向定义造成的。因此为了避免这种问题，一些方法重新定义了目标旋转框的表示方法。例如，基于点集表示的方法RepPoints可以捕获关键的语义特征。但是这种简单的转换函数只产生垂直-水平边界框，无法精确估计航拍图像中旋转物体的方位。同时RepPoint在忽略学到的点集的质量的同时只根据语义特征回归关键点集，会导致旋转的、密集分布的和复杂背景下的目标精度较差。</p><h1>3. 主要工作</h1><p>针对上述问题，作者提出Oriented RepPoints方法，其引入自适应点表示不同的方向，形状和姿势。同时该方法不仅可以精确定位任意方向目标，还可以捕获目标的底层几何结构。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20230131115920.png" alt=""></p><p>文章贡献点如下：</p><ul><li>提出了一个高效的航拍目标检测器Oriented RepPoint</li><li>提出了一个质量评估和样本选择机制用于自适应学习点集</li><li>在四个具有挑战的数据集上实验并展现出不错的性能</li></ul><h2 id="3-1-模型结构">3.1 模型结构</h2><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20230131134539.png" alt=""></p><p>与传统直接回归方向的方法不同，Oriented RepPoint利用自适应点集来细致地表征目标，甚至能够表征目标的几何结构。为了这个目的，Oriented RepPoint引入了可微分转换函数，其可以使点集自适应地移动到合适的位置。为了在没有直接点对点监督的情况下有效地学习高质量的自适应点，提出了一种在训练阶段选择高质量的方向点的质量度量策略。</p><h2 id="3-2-自适应方位点集学习">3.2 自适应方位点集学习</h2><p>为了将点集表示转换成旋转框表示，Oriented RepPoint引入了转换函数。在文章中，作者测试了三种转换函数，分别是：</p><ul><li>MinAreaRect：点集的最小外接矩形构成边界框</li><li>NearestGTCorner：距离真值顶点最近的四个点构成边界框</li><li>ConvexHull：通过Jarvis March算法，从点集中取能包含所有点的最大凸四边形作为边界框</li></ul><p>其中MinAreaRect不可微分，其他两个可微分，因此作者在推理时使用MinAreaRect，在训练时从NearestGTCorner和ConvexHull中任选一个。</p><p>Oriented RepPoint包含两个阶段，第一个阶段根据特征点生成自适应点集，第二个阶段为精炼阶段，对点集进行优化。损失函数如下：<br>$$L=L_{cls}+\lambda_1L_{s1}+\lambda_2L_{s2}$$<br>其中$\lambda_1,\lambda_2$是平衡权重，$L_{cls}$是分类损失：<br>$$L_{cls}=\frac{1}{N_{cls}}\sum\limits_iF_{cls}(R_i^{cls}(\theta),b_j^{cls})$$<br>其中$R_{i}^{cls}(\theta)$代表预测类别置信度，$b_j^{cls}$是真实类别，$F_{cls}$是focal loss。<br>$L_{s1},L_{s2}$分别代表第一阶段和第二阶段的空间定位损失，对于每一阶段定位损失计算为：<br>$$L_s=L_{loc}+L_{s.c.}$$<br>其中$L_{loc},L_{s.c.}$分别代表基于转换后边界框的定位损失（localization loss based on converted oriented boxes）和空间限制损失(spatial constraint loss)。其中<br>$$L_{loc}=\frac{1}{N_{loc}}\sum\limits_i[b_j^{cls}\geq1]F_{loc}(OB_i^{loc}(\theta),b_j^{cls})$$<br>其中$F_{loc}$代表GIoU损失，$N_{loc}$代表全部正样本点数。<br>$$L_{s.c.}=\frac{1}{N_a}\frac{1}{N_o}\sum\limits_{i=1}\sum\limits_{j=1}\rho_{ij}$$<br>其中$N_a,N_o$分别代表对每个目标分配的正样本点数以及在真值框外的点数。<br>$$\rho=\begin{cases}<br>||p_o-p_c|| , &amp; \text{$p_{o}$ is outside GT} \\<br>0 , &amp; \text{otherwise}<br>\end{cases}<br>$$<br>其中$p_o$代表GT外的点，$p_c$代表GT的中心点</p><h2 id="3-3-APAA">3.3 APAA</h2><p>首先，APAA定义了一个质量评估值Q，该值从四个方法来度量学到的自适应点集的质量。<br>$$Q=Q_{cls}+\mu_1Q_{loc}+\mu_2Q_{ori}+\mu_3Q_{poc}$$</p><p>其中$Q_{cls},Q_{loc},Q_{ori},Q_{poc}$分别代表分类置信度（classification confidence），空间位置距离（spatial location distance），Chamfer距离（Chamfer distance）以及特征多样性（point-wise feature diversity）。<br>Chamfer距离计算如下：<br>$$CD(R^v,R^g)=\frac{1}{2n}\sum _ {i=1}^n min _ {j}||(x _ i^v,y _ j^v)-(x _ i^g,y _ j^g)|| _ 2+\frac{1}{2n}\sum _ {j=1}^n min _ {i}||(x _ i^v,y _ j^v)-(x _ i^g,y _ j^g)|| _ 2$$</p><p>特征多样性计算如下：<br>$$Q _ {poc}=1-\frac{1}{N _ p}\sum _ {k}cos&lt;e^\star _ {i,k},e^\star _ i&gt;=1-\frac{1}{N _ p}\sum _ k\frac{e^\star _ {i,k}\cdot{e^\star _ i}}{||e^\star _ {i,k}||\times||e^\star _ i||}$$</p><p>之后针对每个目标，利用Q值，选择前k个样本作为正样本。</p><h1>4. 实验结果</h1><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20230206141139.png" alt=""></p>]]></content>
    
    
    <summary type="html">论文将 RepPoints 的&quot;点集表示&quot;思想扩展到旋转目标检测，通过自适应方位点集学习实现更准确的航拍目标定位。</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="旋转目标检测" scheme="https://blog.xiemingjie.cn/tags/%E6%97%8B%E8%BD%AC%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="点集表示" scheme="https://blog.xiemingjie.cn/tags/%E7%82%B9%E9%9B%86%E8%A1%A8%E7%A4%BA/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | SASM：形状自适应的样本选择策略</title>
    <link href="https://blog.xiemingjie.cn/posts/7dc5beaf.html"/>
    <id>https://blog.xiemingjie.cn/posts/7dc5beaf.html</id>
    <published>2023-02-12T07:08:42.000Z</published>
    <updated>2023-02-12T07:08:42.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题：<code>《Shape-Adaptive Selection and Measurement for Oriented Object Detection》</code></p><blockquote><p>论文发表：AAAI 2022<br>论文链接：<a href="https://ojs.aaai.org/index.php/AAAI/article/view/19975">https://ojs.aaai.org/index.php/AAAI/article/view/19975</a><br>论文代码：<a href="https://github.com/houliping/SASM">https://github.com/houliping/SASM</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20230130190417.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">@inproceedings&#123;hou2022shape,</span><br><span class="line">  title=&#123;Shape-adaptive selection and measurement for oriented object detection&#125;,</span><br><span class="line">  author=&#123;Hou, Liping and Lu, Ke and Xue, Jian and Li, Yuqiu&#125;,</span><br><span class="line">  booktitle=&#123;Proceedings of the AAAI Conference on Artificial Intelligence&#125;,</span><br><span class="line">  volume=&#123;36&#125;,</span><br><span class="line">  number=&#123;1&#125;,</span><br><span class="line">  pages=&#123;923--932&#125;,</span><br><span class="line">  year=&#123;2022&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><table><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><tr><td>标签</td><td>#标签分配 #旋转目标检测</td></tr><tr><td>数据集</td><td>#DOTA #HRSC2016 #UCAS-AOD #ICDAR2015</td></tr><tr><td>目的</td><td>解决旋转目标检测中样本选择没有考虑目标形状信息、没有区分不同质量正样本的问题</td></tr><tr><td>方法</td><td>提出shape-adaptive selection以及shape-adaptive measurement</td></tr></tbody></table><h1>2. 问题背景</h1><p>作者提到旋转目标检测仍然面临挑战，其中最主要的挑战来自目标的形状（如长宽比）。在通用目标检测任务中，样本选择（sample selection，也叫标签分配，label assignment）对于性能提升具有重要作用。然而现有的样本选择策略存在以下不足：</p><ul><li>忽视了目标的形状信息</li><li>没有对选择的正样本的做潜在的区分</li><li>大多数方法只能用于anchor-free或者anchor-based，不能同时适用</li></ul><h1>3. 主要工作</h1><p>针对上述问题，作者提出了shape-adaptive selection（SA-S）和shape-adaptive measurement（SA-M）策略。</p><ul><li>SA-S：根据目标形状信息和特征分布动态地选择样本</li><li>SA-M：度量定位能力，针对所选正样本增加质量信息</li></ul><h2 id="3-1-模型结构">3.1 模型结构</h2><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20230131100409.png" alt=""></p><h2 id="3-2-Motivation">3.2 Motivation</h2><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20230131102608.png" alt=""></p><p>作者做了一个实验，分析不同正负样本IoU划分阈值对不同长宽比类别性能的影响，可以发现当长宽比变大时，IoU阈值越小越好，这可以说明传统的固定IoU阈值的划分方式并不是最优的。</p><h2 id="3-3-Shape-Adaptive-Selection">3.3 Shape-Adaptive Selection</h2><p>根据ATSS，目标真值和预测值的IoU均值和方法可以用于计算动态的IoU阈值，因此对于第i个真值框，IoU阈值可以计算为:<br>$$\tau_i^{IoU}=f(y_i)\times(\mu+\sigma)$$</p><p>其中:<br>$$\mu = \frac{1}{J}\sum\limits^{J} _ {j=1} I _ {i,j}$$</p><p>而<br>$$\sigma=\sqrt{\frac{1}{J}\sum _ {j=1}^J(I _ {i,j}-\mu)^2}$$</p><p>其中J是候选样本的数量，$I_{i,j}$是第i个真值框和第j个预测框之间的IoU值，$y_{i}$代表真值框的长宽比。 根据上面的分析，权重应该随着纵横比的增加而减小，因此长宽比较大的目标被分配一个较低的IoU阈值，故而:<br>$$f(y_i)=e^{-\frac{y_i}{\omega}}$$</p><p>其中ω是一个权重参数，默认为4。当数据集包含大量大长宽比目标时，较大的ω通常可以获得更好的性能。这样，当IoU大于等于$\tau_i^{IoU}$时，认为其是正样本。</p><h2 id="3-4-Shape-Adaptive-Measurement">3.4 Shape-Adaptive Measurement</h2><p>作者认为与位于物体内部的点相比，位于物体边界附近的点包含更多关于杂波背景，甚至附近物体的信息。因此，位于物体内部的点，特别是位于物体中心周围的点，比位于物体边界附近的点更能代表物体的特征。因此如果用所有正样本都有同样的权重会导致一些高质量正样本被远离物体中心的低质量样本点抑制，且每个样本点的质量与物体的形状密切相关，而不仅仅与每个点到物体中心的距离有关。</p><p>因此作者提出了一种基于归一化形状距离的Shape-Adaptive Measurement策略。其具体做法如下：<br>针对每一个真值框$(x,y,w,h,\theta)$，其分别代表中心点坐标，宽度，高度和角度。归一化形状距离计算如下：<br>$$<br>\Delta d _ {ij}=<br>\begin{equation}<br>\begin{array}{lr}<br>\sqrt{\frac{(x _ i-x _ j)^2}{w _ i}+\frac{(y _ i-y _ j)^2}{h _ i}}, &amp; 0\leqslant\theta _ i\leqslant\frac{\pi}{2} \\<br>\sqrt{\frac{(x _ i-x _ j)^2}{h _ i}+\frac{(y _ i-y _ j)^2}{w _ i}}, &amp; otherwise<br>\end{array}<br>\end{equation}<br>$$<br>正样本的质量计算为$\bar{Q} _ {ij}=e^{-\Delta{d _ {ij}}}$.</p><h2 id="3-5-损失函数">3.5 损失函数</h2><p>作者认为较大偏差的孤立点会极大地影响凸包(convex hull，其由预测点集计算得到)的质量，并对精确定位产生不利影响，因此提出了边界中心损失（Boundary-Center Loss），其从点集中选取最左点、最右点、最上点和最下点，用点集中所有点的x坐标和y坐标的平均值来计算平均中心点：<br>$$L^{bc}=\sum\limits _ {i=1}^{5}L _ {smooth}(p _ i,g _ i)$$</p><p>因此总损失为：<br>$$L=\lambda _ 1L^c+\lambda _ 2L^1+\lambda _ 3L^2$$</p><p>其中$L^c,L^1,L^2$分别代表分类损失，初始检测损失，精炼检测损失。$\lambda_1,\lambda_2,\lambda_3$是权重系数，根据经验设为1.0，0.375和1.0. 其中分类损失计算为：<br>$$L _ i^c=\frac{1}{N^+}\frac{1}{\sum _ {p _ j\in{P^+}}\bar{Q} _ {ij}}\sum\limits _ {ij}\bar{Q} _ {ij}$$</p><p>其中$j,N^+,P^+$分别代表序号，总数和预测值。$L^{cls}$代表focal loss。<br>初始检测损失为：<br>$$L^1 _ i=\frac{1}{N^+}\frac{1}{\sum _ {p _ j\in{P^+}}\bar{Q} _ {ij}}\sum\limits _ {ij}\bar{Q} _ {ij}L _ {ij}^{reg}+L^{bc} _ {ij}$$</p><p>其中$L^{reg}=1-GIoU$代表GIoU Loss。<br>精炼阶段检测损失为：<br>$$L^2 _ i=\frac{1}{N^+}\frac{1}{\sum _ {p _ j\in{P^+}}\bar{Q} _ {ij}}\sum\limits _ {ij}\bar{Q} _ {ij}L _ {ij}^{reg}$$</p><h1>4. 实验结果</h1><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20230131111744.png" alt=""></p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20230131111810.png" alt=""></p>]]></content>
    
    
    <summary type="html">论文提出形状自适应的样本选择与度量策略（SASM），缓解旋转目标检测中形状极端对标签分配的影响。</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="旋转目标检测" scheme="https://blog.xiemingjie.cn/tags/%E6%97%8B%E8%BD%AC%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="标签分配" scheme="https://blog.xiemingjie.cn/tags/%E6%A0%87%E7%AD%BE%E5%88%86%E9%85%8D/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | GGHL：旋转目标检测的标签分配策略</title>
    <link href="https://blog.xiemingjie.cn/posts/d990ca76.html"/>
    <id>https://blog.xiemingjie.cn/posts/d990ca76.html</id>
    <published>2023-01-10T07:24:42.000Z</published>
    <updated>2023-01-10T07:24:42.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题：<code>《A General Gaussian Heatmap Label Assignment for Arbitrary-Oriented Object Detection》</code></p><blockquote><p>论文发表：2022 IEEE TRANSACTIONS ON IMAGE PROCESSING<br>论文链接：<a href="https://ieeexplore.ieee.org/document/9709203">https://ieeexplore.ieee.org/document/9709203</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915141751.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">@article&#123;huang2022general,</span><br><span class="line">  title=&#123;A general gaussian heatmap label assignment for arbitrary-oriented object detection&#125;,</span><br><span class="line">  author=&#123;Huang, Zhanchao and Li, Wei and Xia, Xiang-Gen and Tao, Ran&#125;,</span><br><span class="line">  journal=&#123;IEEE Transactions on Image Processing&#125;,</span><br><span class="line">  volume=&#123;31&#125;,</span><br><span class="line">  pages=&#123;1895--1910&#125;,</span><br><span class="line">  year=&#123;2022&#125;,</span><br><span class="line">  publisher=&#123;IEEE&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><table><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><tr><td>标签</td><td>#遥感 #标签分配 #旋转目标检测</td></tr><tr><td>数据集</td><td>#DOTA #DOTAv2 #SKU10-R #SSDD</td></tr><tr><td>目的</td><td>解决旋转目标检测任务中，采样策略没有考虑目标的形状和方向特性的问题。</td></tr><tr><td>方法</td><td>提出了GGHL，其包含OLA,ORC以及JOL</td></tr></tbody></table><h1>2. 问题背景</h1><p>作者提到近年来，大多数做旋转目标检测的方法都是设计复杂的网络结构以使得提取的特征分布接近GT的分布。然而改进模型结构不是提升性能的唯一解决途径。下图可见，一个完整的检测流程包括：数据；标签分配（正负样本划分）；模型结构；目标函数（损失）。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915141907.png" alt=""></p><p>对于CNN-Based检测器而言，如何提升标签分配也很重要，不同的策略将会通过影响生成的样本空间来直接影响模型的性能。因此，要想提升检测性能，一个方法是使用复杂的CNN结构（复杂的近似估计函数），另一个方法是设计标签分配策略从而构建更好的能够反映目标特性的样本空间。</p><p>目前一些工作采用的标签分配策略如下：</p><p>（1）Anchor-Based Label Assignment<br>SCRDet，LO-Det，DAL，CenterMap，DCL以及Oriented R-CNN等使用的基于Anchor的标签分配策略。（计算IoU，通过和阈值比较来判断）这种方法会导致正负样本误分。</p><p>（2）Dense-Points Assignment<br>FCOS，IENet，AOPG等使用更宽松的采样策略，会导致样本空间中混入负样本。</p><p>（3）Key-Point Assignment<br>CenterNet，BBAVector以及O2DNet等使用更严格的采样策略，导致正负样本严重不平衡。</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915141959.png" alt=""></p><p>因此一个上述标签分配策略都没有考虑目标的旋转和形状特性，故而存在很多不足。此外，即便得到了更好的训练样本空间，还需要一个合适的目标函数来引导模型学到更高质量的特征。而目前，主流的目标函数都是独立优化分类和回归分支。因此其可能导致精准定位的预测框只有很低的分类得分，或者高得分的目标定位不准。因此，PISA，Free-Anchor，以及AutoAssign等方法将不同子任务联合训练来实现更理想的性能。</p><h1>3. 主要工作</h1><p>针对上述问题，作者提出了通用高斯热力图标签分配策略（GGHL），其主要包括三个部分：</p><ul><li>一个目标自适应的采样策略（OLA），基于2D旋转高斯热力图，使得采样策略更能反映目标的尺寸和方向特性。</li><li>一个旋转边界框表示组件（ORC），基于正样本点到OBB顶点的距离构建OBB的表示方法。此外，还使用了一个目标自适应加权调整机制（OWAM），用于自适应调整不同位置的高斯中心权重以加权不同位置的损失。</li><li>一个带有面积归一化和动态加权的联合优化损失（JOL），用于精炼正负样本间未对齐的优化目标，并可以平衡模型对于不同位置不同大小的不同类别的目标的学习能力。</li></ul><h2 id="3-1-模型结构">3.1 模型结构</h2><p>下图为GGHL的结构框架。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142030.png" alt=""></p><h2 id="3-2-目标自适应采样策略（OLA）">3.2 目标自适应采样策略（OLA）</h2><p>作者提到，之前的标签分配（Label Assignment，LA）存在样本误匹配的问题，并且存在大量超参数。如GWD使用2D高斯来计算损失，其LA仍基于Anchor实现。CenterNet，BBAvector，DRN等使用标准高斯分布（圆形）不能反映目标的形状和方向特性，并且其只使用高斯峰值点作为正样本加剧了正负样本不平衡，并且使用高分辨率特征图加大了计算复杂性。因此作者提出的OLA采用旋转椭圆高斯区域来采样。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142057.png" alt=""></p><p>（1）与标准高斯分布不同，OLA使用整个高斯区域作为正样本采样区域，再根据高斯密度函数对不同位置加权。高斯概率密度函数如下：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142110.png" alt=""><br>其中$X=[x,y]^T\sim N(\mu,C)$，$\mu\in R^2$代表平均向量，$C\in R^{2\times2}$为非负半定实矩阵，代表两个变量的协方差矩阵。实对称矩阵$C$正交对角分解为：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142225.png" alt=""><br>其中Q为实对称矩阵，$\Lambda$代表由降序特征值组成的对角矩阵。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142249.png" alt=""><br>高斯概率密度函数变换为：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142302.png" alt=""></p><p>如果$f(x,y)&gt;0$，该位置定义为正样本，且其值代表该位置的权重。</p><p>（2）对于重叠问题，如果一个位置包含在不同的高斯区域内，则将其分配给$f(x,y)$最大的那个高斯区域。</p><p>（3）空间和尺度范围。对于空间范围，设高斯峰值的边界框为C-BBox，此时其他位置的边界框与C-BBox的IoU大于阈值$T_{IoU}$则视为正位置（positive location）。这些正位置构成了原始高斯候选区域的一个子集(表现为一个较小的椭圆，与原始高斯椭圆共心)，其半轴长度为：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142356.png" alt=""><br>其中$r_i$代表原始高斯椭圆的半轴长度。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142422.png" alt=""><br>而对于尺度范围，假设不同特征层的下采样率为$stride_m=2^{m+3},m=1,2,3$，同时为了保证在空间尺度上正样本的数量，定义$max_i(r_i^c)/stride_m\geq 1$，即$max_i(2r_i)\geq \frac{2\times stride_m}{1-T_{IoU}}$。定义OBB的四条边长为$d_j,j=1,2,3,4$，则有$max_j(d_j)=max_i(2r_i)\geq \frac{2\times stride_m}{1-T_{IoU}}$。定义一个超参数$\tau=3$，得到两个阈值：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142554.png" alt=""><br>此时，当$max_j(d_j)\in (1,range_1)$时，目标分配给$stride_1$。当$max_j(d_j)\in(range_1,range_2]$时，目标分配给$stride_2$。当$max_j(d_j)\in(range_2,\sqrt{2}len^{img}]$时，目标分配给$stride_3$。</p><h2 id="3-3-旋转边界框表示组件（ORC）">3.3 旋转边界框表示组件（ORC）</h2><p>作者提到，现有的OBB表示方法有两类，一类是基于角度的，如CenterMap，另一类是基于点的，如Gliding Vertex。ORC如下图，使用$l_{x,y,m}=[l_1,l_2,l_3,l_4]$以及$s_{x,y,m}=[s_1,s_2,s_3,s_4]$来表示一个位于$(x,y) _ {m}$的点所表示的OBB。其中与Gliding Vertex一样，使用$ar_{x,y,m}\in[0,1]$表示HBB和OBB的面积比例，因此ORC相当于使用一个9维的向量表示OBB：$obb_{x,y,m}=[l_{x,y,m},s_{x,y,m},ar_{x,y,m}]$。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142827.png" alt=""><br>除此之外，并不是每一个凸四边形都能被ORC表示，还需要讨论顶点不在HBB上的情况以及ORC中顶点的隐式排序。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142841.png" alt=""><br>此外，直接使用高斯分布来加权并不适合部分目标，如港口等等。因此需要设计一种自适应的加权调整策略，如AutoAssign以及IQDet等等。因此借鉴此思想，作者提出了OWAM。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142856.png" alt=""></p><h2 id="3-4-联合优化损失（JOL）">3.4 联合优化损失（JOL）</h2><p>包括：</p><ul><li>联合概率密度函数</li><li>面积归一化和损失重加权机制</li><li>用于实现整个联合优化函数的极大似然估计</li></ul><h1>4. 实验结果</h1><p>（1）消融实验</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142916.png" alt=""><br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142921.png" alt=""><br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142926.png" alt=""></p><p>（2）可视化结果<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142941.png" alt=""></p><p>（3）对比实验<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915142955.png" alt=""></p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.11/20220915143004.png" alt=""></p>]]></content>
    
    
    <summary type="html">论文提出通用高斯热图标签分配（GGHL），为任意方向的目标检测设计了一套自适应的标签分配策略。</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="旋转目标检测" scheme="https://blog.xiemingjie.cn/tags/%E6%97%8B%E8%BD%AC%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="标签分配" scheme="https://blog.xiemingjie.cn/tags/%E6%A0%87%E7%AD%BE%E5%88%86%E9%85%8D/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | FSDet：遥感旋转目标检测</title>
    <link href="https://blog.xiemingjie.cn/posts/201349fc.html"/>
    <id>https://blog.xiemingjie.cn/posts/201349fc.html</id>
    <published>2022-10-10T11:32:42.000Z</published>
    <updated>2022-10-10T11:32:42.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题：<code>《Object Detection for Aerial Images With Feature Enhancement and Soft Label Assignment》</code></p><blockquote><p>论文发表：2022 IEEE TRANSACTIONS ON GEOSCIENCE AND REMOTE SENSING<br>论文链接：<a href="https://ieeexplore.ieee.org/document/9780146">https://ieeexplore.ieee.org/document/9780146</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915134858.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@article&#123;yu2022object,</span><br><span class="line">  title=&#123;Object Detection for Aerial Images with Feature Enhancement and Soft Label Assignment&#125;,</span><br><span class="line">  author=&#123;Yu, Ying and Yang, Xi and Li, Jie and Gao, Xinbo&#125;,</span><br><span class="line">  journal=&#123;IEEE Transactions on Geoscience and Remote Sensing&#125;,</span><br><span class="line">  year=&#123;2022&#125;,</span><br><span class="line">  publisher=&#123;IEEE&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><table><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><tr><td>标签</td><td>#遥感 #特征增强 #标签分配 #旋转目标检测</td></tr><tr><td>数据集</td><td>DOTA1.0；DOTA1.5；HRSC2016；UCAS-AOD;</td></tr><tr><td>目的</td><td>解决遥感图像中旋转特征不对齐以及正负样本不平衡的问题</td></tr><tr><td>方法</td><td>提出旋转特征精炼，类感知上下文聚合以及软标签分配策略</td></tr></tbody></table><h1>2. 问题背景</h1><p>作者提到，航拍图像目标检测任务存在目标方向任意以及前景与背景极不平衡的问题。并且提到Anchor-Based方法受超参数影响较大。因此作者的工作主要基于Anchor-Free模型实现。</p><p>（1）目标方向任意<br>由于航拍图像的鸟瞰视角，目标具有任意方向的性质。因此，通过标准2D卷积的水平感受野所获得特征并不能准确描述旋转目标的特征。下图可见，水平感受野和OBB不能很好的对齐。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135010.png" alt=""><br>（2）正负样本<br>作者发现不同空间位置的正样本展现出不一致的检测能力。下图可见，在不同位置检测出的OBB在IoU和Cls Score得到的结果差距很大。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135029.png" alt=""><br>并且作者发现遥感图像中前景和背景不平衡问题极其突出，导致模型不能学到很强的（strong）、公正的（unbiased）特征。下图可见，遥感图像中的前后景不平衡，导致的FP。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135044.png" alt=""></p><h1>3. 主要工作</h1><p>为解决上诉问题，作者提出了FSDet，其包含：<br>（1）旋转特征精炼（oriented feature refinement，OFR），利用几何信息解决特征未对齐问题<br>（2）类感知上下文聚合（class-aware context aggregation，CCA），提高类内前景特征的分辨能力<br>（3）软标签分配（soft label assignment，SLA），解决训练过程中不同位置样本得到结果不一致问题</p><h2 id="3-1-模型结构">3.1 模型结构</h2><p>FSDet基于FCOS构建，并加入了其所提出的OFR，CCA以及SLA模块。</p><ul><li>Head之前和FCOS一致，使用了5层FPN，包括P3-P7；</li><li>替换了centerness分支，改用IoU分支来预测IoU的值；</li><li>Baseline使用的label assignment是原始的FCOS的策略，即采样范围为Bounding Box;</li></ul><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135302.png" alt=""></p><p>目标框表示方法为$d=(l,t,r,b,\theta)$，如下图所示：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135352.png" alt=""></p><p>损失函数如下:<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135410.png" alt=""></p><p>其中分类损失为focal loss，回归损失包括HBB损失（使用的GIoU loss）以及角度损失：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135423.png" alt=""><br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135433.png" alt=""></p><h2 id="3-2-旋转特征精炼（OFR）">3.2 旋转特征精炼（OFR）</h2><p>OFR：利用旋转目标框的空间几何信息，学习更有效的特征表示。<br>OFR包括辅助回归分支和框特征注意机制。</p><ul><li>辅助回归分支输出特征图每个位置的$(l,t,r,b,\theta)$，得到一个初始Box；</li><li>基于此初始Box使用框特征注意机制来生成精炼特征图，以获取更准确的信息；如下图，作者表示了同一位置（红点）使用不同3×3卷积核所获取的特征（蓝点），例如：标准卷积会明显与GT Box不对齐，可形变卷积在没有显式监督信息的条件下不能保证特征点落在目标上。因此作者取该初始Box的9个点来辅助特征对齐。受启发于Transformer的多头注意力，其按照顺时针顺序取这9个点（位于中心点的第二象限的边为上边缘，以此边开始顺时针取点），令红点$f^q_i\in\mathbb{R}^{d_f}$为Query，蓝点$f^v_i\in\mathbb{R}^{9\times d_f}$为Value，输入到多头注意力模块中。输出为特征$f_i^{o}\in\mathbb{R}^{d_f}$的计算如下：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135611.png" alt=""><br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135646.png" alt=""></li></ul><h2 id="3-3-类感知上下文聚合（CCA）">3.3 类感知上下文聚合（CCA）</h2><p>CCA模块包括一个辅助分类分支和特征增强处理。</p><ul><li>辅助分类分支预测一个C维的向量表示初始类别得分。</li><li>基于此初始类别得分，网络开始聚合类感知上下文信息来丰富特征图，用于最后的分类。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135719.png" alt=""></li></ul><p>首先特征图F输入到辅助分类分支得到粗糙的分类结果$\hat{c}={p_{i,k}|k=1,…,C}$，然后输入到一个门函数（gating function）来抑制负样本和低质量正样本，如下图：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135757.png" alt=""><br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135804.png" alt=""><br>其中t是预设阈值，A是放大系数，默认20。然后得到新的分类结果$\hat{p} _ {i,k}$，使用它来聚合每一层上此类的特征：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915135835.png" alt=""><br>之后使用 $v_{k}$ 表示获取了更多类内语义信息的特征。同时为了计算每个位置的上下文特征，挖掘分类和位置的联系，使用每个位置$i$的特征$f_{i}$和类别$c^{\ast}$以及聚合特征$v _ {cls}$，计算两者的相似性：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140010.png" alt=""><br>并且希望$f_{i}$和其他类的相似性低于$f_{i}$和$c^{\ast}$。在计算特征的相似性后，得到类感知上下文特征$z_i$。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140123.png" alt=""><br>并且作者验证了CCA模块的有效性：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140142.png" alt=""></p><h2 id="3-4-软标签分配（SLA）">3.4 软标签分配（SLA）</h2><p>由于高质量样本能够产生比低质量样本更准确预测的结果，SLA对每个样本的损失分配了一个软权重，使模型更关注高质量样本点。样本的质量$Q_{i,n}$定义为：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140408.png" alt=""><br>其中$p_{i,c^{(n)}}$代表样本$i$属于第n个Box的类别的概率，$IoU(\hat{B} _ i,B_n)$代表预测OBB$\hat{B} _ i$和真值OBB$B_n$之间的IoU值。超参$\alpha\in[0,1]$用于控制分类和回归之间的权重。$x$表示坐标$(x,y)$,$G_{n}(x)$代表高斯分布：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140620.png" alt=""><br>其中$\mu$和$\sum$代表均值和高斯分布的协方差矩阵。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140652.png" alt=""><br>其中<strong>R</strong>代表旋转矩阵，$\Lambda$代表特征值的对角矩阵。特征值$\lambda_{1}$和$\lambda_{2}$分别是椭圆半轴的平方，将OBB内切椭圆外的位置的$G_{n}(x)$值设为0。高斯分布将高值分配给靠近物体中心的位置，而低值分配给远离中心的位置。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140800.png" alt=""><br>根据样本的质量$Q_{i,n}$，可得正样本权重：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140833.png" alt=""><br>负样本权重：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140904.png" alt=""><br>加权后的损失：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140850.png" alt=""><br>辅助分支的损失：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140930.png" alt=""><br>总损失：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915140940.png" alt=""></p><h1>4. 实验结果</h1><p>（1）消融实验：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915141004.png" alt=""><br>（2）不同层的正样本权重可视化：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915141018.png" alt=""><br>（3）其他实验<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915141027.png" alt=""><br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915141038.png" alt=""><br>（4）对比试验<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.10/20220915141054.png" alt=""></p>]]></content>
    
    
    <summary type="html">论文提出 FSDet，通过旋转特征精炼、类感知上下文聚合与软标签分配，解决遥感图像中旋转特征不对齐与正负样本不平衡的问题。</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="旋转目标检测" scheme="https://blog.xiemingjie.cn/tags/%E6%97%8B%E8%BD%AC%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="标签分配" scheme="https://blog.xiemingjie.cn/tags/%E6%A0%87%E7%AD%BE%E5%88%86%E9%85%8D/"/>
    
  </entry>
  
  <entry>
    <title>闲聊日常 | 国庆北京随手拍：动物园与奥体公园</title>
    <link href="https://blog.xiemingjie.cn/posts/4d2d3e0a.html"/>
    <id>https://blog.xiemingjie.cn/posts/4d2d3e0a.html</id>
    <published>2022-10-06T12:40:41.000Z</published>
    <updated>2022-10-06T12:40:41.000Z</updated>
    
    <content type="html"><![CDATA[<h1>长安街、故宫附近</h1><p>本打算9月30日晚上去天安门看看，结果去太晚了不让进，只能在附近转转…</p><div class="gallery-container waterfall">        <div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/20221006202507.jpg alt="中南海" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/202210062025071.jpg alt="故宫一角" /></div>      </div><h1>北京动物园</h1><p>不知道是因为动物园太老了，还是天气太冷了，好多动物都没看见，比如长颈鹿…</p><div class="gallery-container waterfall">        <div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/202210062025072.jpg alt="牛" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/202210062025073.jpg alt="海洋馆" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/202210062025074.jpg alt="有点像波妞" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/202210062025075.jpg alt="白鲸" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/202210062025076.jpg alt="🐟" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/202210062025077.jpg alt="海归" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/202210062025078.jpg alt="企鹅" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/202210062025079.jpg alt="长鼻子鱼" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250710.jpg alt="水母" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250711.jpg alt="水母" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250712.jpg alt="魔术表演" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250713.jpg alt="表演" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250714.jpg alt="表演" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250715.jpg alt="表演" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250716.jpg alt="表演" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250717.jpg alt="大象" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250718.jpg alt="河马" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250719.jpg alt="狐狸" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250720.jpg alt="猴" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250721.jpg alt="熊猫" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250722.jpg alt="熊猫" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250723.jpg alt="北极熊" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250724.jpg alt="羊驼" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250725.jpg alt="树懒" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250726.jpg alt="角马？" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250727.jpg alt="斑马" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250728.jpg alt="鹿" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250729.jpg alt="蛇" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250730.jpg alt="蛇" /></div>      </div><h1>奥林匹克公园</h1><div class="gallery-container waterfall">        <div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250731.jpg alt="鸟巢" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250733.jpg alt="鸟巢" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250735.jpg alt="鸟巢" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250732.jpg alt="水立方" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.9/2022100620250734.jpg alt="鸟巢" /></div>      </div>]]></content>
    
    
      
      
    <summary type="html">&lt;h1&gt;长安街、故宫附近&lt;/h1&gt;
&lt;p&gt;本打算9月30日晚上去天安门看看，结果去太晚了不让进，只能在附近转转…&lt;/p&gt;
&lt;div class=&quot;gallery-container waterfall&quot;&gt;
        &lt;div class=&quot;gallery-item&quot;&gt;&lt;im</summary>
      
    
    
    
    <category term="闲聊日常" scheme="https://blog.xiemingjie.cn/categories/%E9%97%B2%E8%81%8A%E6%97%A5%E5%B8%B8/"/>
    
    
    <category term="旅拍" scheme="https://blog.xiemingjie.cn/tags/%E6%97%85%E6%8B%8D/"/>
    
    <category term="Plog" scheme="https://blog.xiemingjie.cn/tags/Plog/"/>
    
    <category term="北京" scheme="https://blog.xiemingjie.cn/tags/%E5%8C%97%E4%BA%AC/"/>
    
  </entry>
  
  <entry>
    <title>闲聊日常 | 北京实习随拍：故宫、颐和园与阳台山</title>
    <link href="https://blog.xiemingjie.cn/posts/20083b4c.html"/>
    <id>https://blog.xiemingjie.cn/posts/20083b4c.html</id>
    <published>2022-09-28T15:40:41.000Z</published>
    <updated>2022-09-28T15:40:41.000Z</updated>
    
    <content type="html"><![CDATA[<p>从七月初开始被导师派到北京研究所实习，上班之余逛了逛北京的几个著名景点，比如说颐和园，天安门，故宫，北海公园等等，随手拍了拍照，设备是：iPhone 12以及Sony a6000.</p><h1>颐和园</h1><p>去的那天下着小雨，烟雨朦胧…</p><div class="gallery-container waterfall">        <div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220814000001.jpg alt="黑天鹅" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220814000002.jpg alt="雾气" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220814000003.jpg alt="十七孔桥" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220814000004.jpg alt="花" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220814000005.jpg alt="荷花" /></div>      </div><h1>天安门</h1><p>去故宫那天正好赶上了天安门开音乐喷泉，录了视频，不过没拍照…<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000000.jpg" alt="天安门"></p><h1>故宫</h1><p>护城河里的锦鲤，见者好运…，以及集福门…</p><div class="gallery-container waterfall">        <div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000001.jpg alt="故宫护城河" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000002.jpg alt="故宫以及北海公园的白塔" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000003.jpg alt="午门" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000005.jpg alt="城门" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000006.jpg alt="螭首" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000007.jpg alt="集福门" /></div>      </div><h1>北海公园</h1><p>把白塔拍出了小清新的感觉…</p><div class="gallery-container waterfall">        <div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000008.jpg alt="墙" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000009.jpg alt="白塔" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000010.jpg alt="鸭子" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000011.jpg alt="白塔远景" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220820000012.jpg alt="荷花" /></div>      </div><h1>北京近郊 - 阳台山</h1><p>位于北京六环边上，周末踏青，强身健体…</p><div class="gallery-container waterfall">        <div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220904000001.jpg alt="山路" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220904000002.jpg alt="牵牛花" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220904000003.jpg alt="祈愿" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220904000004.jpg alt="铁轨" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220904000005.jpg alt="蝴蝶" /></div><div class="gallery-item"><img class="nolazyload" src=https://npm.elemecdn.com/justlovesmile-post@1.0.8/20220904000006.jpg alt="警示牌" /></div>      </div>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;从七月初开始被导师派到北京研究所实习，上班之余逛了逛北京的几个著名景点，比如说颐和园，天安门，故宫，北海公园等等，随手拍了拍照，设备是：iPhone 12以及Sony a6000.&lt;/p&gt;
&lt;h1&gt;颐和园&lt;/h1&gt;
&lt;p&gt;去的那天下着小雨，烟雨朦胧…&lt;/p&gt;
&lt;div cl</summary>
      
    
    
    
    <category term="闲聊日常" scheme="https://blog.xiemingjie.cn/categories/%E9%97%B2%E8%81%8A%E6%97%A5%E5%B8%B8/"/>
    
    
    <category term="旅拍" scheme="https://blog.xiemingjie.cn/tags/%E6%97%85%E6%8B%8D/"/>
    
    <category term="Plog" scheme="https://blog.xiemingjie.cn/tags/Plog/"/>
    
    <category term="北京" scheme="https://blog.xiemingjie.cn/tags/%E5%8C%97%E4%BA%AC/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | SCRDet：旋转、密集、小目标检测器</title>
    <link href="https://blog.xiemingjie.cn/posts/8f7eb979.html"/>
    <id>https://blog.xiemingjie.cn/posts/8f7eb979.html</id>
    <published>2022-07-04T07:21:48.000Z</published>
    <updated>2022-07-04T07:21:48.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题：<code>《SCRDet: Towards More Robust Detection for Small, Cluttered and Rotated Objects》</code></p><blockquote><p>论文发表：ICCV2019<br>论文链接：<a href="https://openaccess.thecvf.com/content_ICCV_2019/papers/Yang_SCRDet_Towards_More_Robust_Detection_for_Small_Cluttered_and_Rotated_ICCV_2019_paper.pdf">https://openaccess.thecvf.com</a><br>论文代码：<a href="https://github.com/DetectionTeamUCAS">https://github.com/DetectionTeamUCAS</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306124344.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@inproceedings&#123;yang2019scrdet,</span><br><span class="line">  title=&#123;Scrdet: Towards more robust detection for small, cluttered and rotated objects&#125;,</span><br><span class="line">  author=&#123;Yang, Xue and Yang, Jirui and Yan, Junchi and Zhang, Yue and Zhang, Tengfei and Guo, Zhi and Sun, Xian and Fu, Kun&#125;,</span><br><span class="line">  booktitle=&#123;Proceedings of the IEEE/CVF International Conference on Computer Vision&#125;,</span><br><span class="line">  pages=&#123;8232--8241&#125;,</span><br><span class="line">  year=&#123;2019&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>2. 归纳总结</h1><table><thead><tr><th>标签</th><th>目的</th><th>方法</th><th>总结</th></tr></thead><tbody><tr><td>#遥感 #注意力机制 #旋转目标检测</td><td>解决了遥感目标角度边界问题</td><td>IoU SmoothL1 Loss，多维注意力</td><td>从遥感目标的难点出发</td></tr></tbody></table><h1>3. 问题背景</h1><p>遥感目标检测的难点：</p><ul><li>小目标（small size）</li><li>密集（dense distribution）</li><li>方向任意（arbitrary direction）</li></ul><h1>4. 主要工作</h1><p>针对上述问题进行改进：</p><ul><li>对于小目标：通过特征融合和anchor采样角度出发设计了一个特征融合结构。</li><li>对于密集排列问题：设计了一个有监督的多维注意力网络（supervised pixel attention network and the channel attention network）以减少背景噪声的不利影响。</li><li>对于任意方向问题：通过添加IoU常数因子设计了一种改进的平滑L1损失，该因子专门用于解决旋转边界框回归的边界问题。</li></ul><h1>5. 相关工作</h1><p>目标检测经典模型：</p><ul><li>两阶段：Fast R-CNN，Faster R-CNN，R-FCN</li><li>单阶段：YOLO，SSD</li></ul><p>针对小目标：RP-Faster R-CNN</p><h1>6. 模型方法</h1><p>整个框架基于Faster R-CNN based R2CNN实现，模型结构如下图：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306125233.png" alt=""></p><p>主要包含三个部分：</p><ul><li>SF-Net</li><li>MDA-Net</li><li>Rotation-Branch</li></ul><h2 id="6-1-SF-Net">6.1 SF-Net</h2><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306130142.png" alt=""><br>针对小目标检测，作者认为<strong>特征融合</strong>和<strong>有效采样</strong>是关键。对于anchor-based来说，anchor的铺设方式直接影响正样本采样率。经典的anchor铺设方式和特征图的分辩率有关，也就是anchor铺设的步长（C2-C5上的anchor步长分别是4,8,16,32）。随着网络加加深，特征图分辨率下降，anchor的步长扩大，常常会导致小目标的采样丢失，如下图所示：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306125943.png" alt=""><br>文章通过resize的方式选取了一个合适的特征图分别率，尽可能保证小目标都被采样到，再加上简单的特征融合保证丰富的语义信息和位置信息。在这里之所以不使用C2，是因为遥感目标检测会设置较多的尺度和比例，那么在C2这个特征图上面的anchor就变得太多了，而且在遥感数据集中最小的目标一般也都在10像素以上（特指<a href="https://arxiv.org/abs/1807.02700">DOTA1.0</a>，<a href="https://captain-whu.github.io/DOAI2019/dataset.html">DOTA1.5</a>则给出了像素10以下的标注）。</p><h2 id="6-2-MAD-Net">6.2 MAD-Net</h2><p>由于遥感图像背景的复杂性，RPN产生的建议区域可能引入大量噪声信息，如下图所示:<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306130354.png" alt=""><br>过多的噪音可能会混淆物体信息，物体之间的界限将变得模糊，导致漏检并增加虚警。因此，有必要增强物体特征并削弱非物体特征。为了更有效地捕捉复杂背景下小物体的特征，文章设计了一种有监督的多维注意力网络（MDA-Net），如下图所示。具体来说，在基于像素的注意网络中，特征图F3通过具有不同大小卷积核进行卷积运算，学习得到双通道的显著图（参见上图d）。这个显著图显示了前景和背景的分数。选择显著图中的一个通道与F3相乘，得到新的信息特征图A3（参见上图c）。需要注意的是，Softmax函数之后的显着图的值在[0,1]之间。换句话说，它可以降低噪声并相对的增强对象信息。由于显著图是连续的，因此不会完全消除背景信息，这有利于保留某些上下文信息并提高鲁棒性。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306130420.png" alt=""><br>其实这个模块现在也是被用的比较烂了，就是空间注意力加通道注意力的组合。但在实际的应用过程中，空间注意力在遥感检测真的是非常有用的；</p><h2 id="6-3-IoU-Smooth-L1-Loss">6.3 IoU-Smooth L1 Loss</h2><p>首先我们要先了解一下两种旋转边界框的两种常见的方式，下图来自这篇文章的作者yangxue：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306130754.png" alt=""><br>SCRDet是采用的opencv 表示法。在当前常用的旋转检测框的角度定义下，由于存在旋转角度的边界问题，会产生不必要的损失，如下图所示：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306130911.png" alt=""></p><p>最理想的角度回归路线是由蓝色框逆时针旋转到红色框，但由于角度的周期性，导致按照这个回归方式的损失非常大（参见上图右边的Example）。此时模型必须以更复杂的形式回归（例如蓝色框顺时针旋转，同时缩放w和h），增加了回归的难度。为了更好地解决这个问题，我们在传统的smooth L1 损失函数中引入了IoU常数因子。在边界情况下，新的损失函数近似等于0，消除了损失的突增。新的回归损失可分为两部分，smooth L1回归损失函数取单位向量确定梯度传播的方向，而IoU表示梯度的大小，这样loss函数就变得连续。此外，使用IoU优化回归任务与评估方法的度量标准保持一致，这比坐标回归更直接和有效。IoU-Smooth L1 loss公式如下：</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306131108.png" alt=""></p><p>可以看一下两种loss在边界情况下的效果对比：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306131310.png" alt=""></p><p>导致这种原因的根本原因是角度的预测超出了所定义范围。其实解决这种问题的方法并不唯一，<a href="https://arxiv.org/abs/1703.01086">RRPN</a>和<a href="https://www.mdpi.com/2072-4292/10/1/132">R-DFPN</a>在论文的loss公式中就判断了是不是在定义范围内，通过加减$k\pi$来缓解这个问题，但这种做法明显不优美而且仍然存在问题，主要是较难判断超出预测范围几个角度周期。当然可以通过对角度部分的loss加一个周期性函数，比如tan、cos等三角函数来做，但是我在实际使用过程中常常出现不收敛的情况。对于边界问题，我其实还做了其他方法的研究，会在以后的文章中详细讨论。</p><h1>7. 实验结果</h1><p>消融实验：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306131425.png" alt=""></p><p>对比实验：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.7/20220306131447.png" alt=""></p><h1>8. 参考文献</h1><p><a href="https://zhuanlan.zhihu.com/p/107400817">旋转目标检测方法解读 （SCRDet, ICCV2019） - 知乎 (zhihu.com)</a></p>]]></content>
    
    
    <summary type="html">在遥感图像目标检测中感兴趣目标不再像COCO，VOC中那样在水平方向上垂直放置。对于场景文本检测，文本可以在任何方向和位置上进行检测。尤其是遥感图像面临以上三个挑战：①小目标②杂乱无章的排列③任意方向...</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="旋转目标检测" scheme="https://blog.xiemingjie.cn/tags/%E6%97%8B%E8%BD%AC%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="遥感图像" scheme="https://blog.xiemingjie.cn/tags/%E9%81%A5%E6%84%9F%E5%9B%BE%E5%83%8F/"/>
    
  </entry>
  
  <entry>
    <title>代码编程 | 自动下载、压缩并批量替换博客外链图片</title>
    <link href="https://blog.xiemingjie.cn/posts/7a5857a0.html"/>
    <id>https://blog.xiemingjie.cn/posts/7a5857a0.html</id>
    <published>2022-07-01T02:52:43.000Z</published>
    <updated>2022-07-01T02:52:43.000Z</updated>
    
    <content type="html"><![CDATA[<p>由于前段时间JsdelivrCDN加速的崩盘，博主存在Github上的图片全部访问失败，文章阅读体验极差，于是2022年以后的文章全部采用npm做图床，在此之前的文章由于数量过多并没有替换。再加上之前一直忙着研一阶段的期末考，懒得动博客。幸好这段时间有空，于是写了个python小工具来替换博客中外链图片，具体流程如下：</p><ul><li>首先，遍历<code>hexo\source\_posts\</code>文件夹中的全部文章，把里面含有<code>https://cdn.jsdelivr.net/gh</code>的图片全部下载下来，并替换链接为npm的CDN链接。</li><li>其次，对下载下来的图片做简单的压缩。</li><li>最后，把压缩后的图片上传npm。</li></ul><p>总体流程非常简单，下面是具体实现。</p><h1>1. 下载并替换图片外链</h1><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">import</span> os.path <span class="keyword">as</span> osp</span><br><span class="line"><span class="keyword">import</span> shutil <span class="keyword">as</span> sh</span><br><span class="line"><span class="keyword">import</span>  re</span><br><span class="line"><span class="keyword">from</span> tqdm.auto <span class="keyword">import</span> tqdm</span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">makedir</span>(<span class="params">root</span>):</span><br><span class="line">    <span class="keyword">if</span> <span class="keyword">not</span> osp.exists(root):</span><br><span class="line">        os.mkdir(root)  </span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">save_img</span>(<span class="params">root,img_url</span>):</span><br><span class="line">    path=root+img_url.split(<span class="string">&#x27;/&#x27;</span>)[-<span class="number">1</span>]</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> osp.exists(path):</span><br><span class="line">            s = requests.session()</span><br><span class="line">            s.keep_alive = <span class="literal">False</span> <span class="comment"># 关闭多余连接</span></span><br><span class="line">            r = s.get(img_url) <span class="comment"># 你需要的网址</span></span><br><span class="line">            <span class="comment">#r=requests.get(img_url)</span></span><br><span class="line">            <span class="keyword">with</span> <span class="built_in">open</span>(path,<span class="string">&#x27;wb&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">                f.write(r.content)</span><br><span class="line">                f.close()</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="built_in">print</span>(path+<span class="string">&quot;文件已存在！&quot;</span>)</span><br><span class="line">            <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        <span class="built_in">print</span>(img_url+<span class="string">&quot;, 爬取失败！&quot;</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span></span><br><span class="line">    <span class="built_in">print</span>(img_url+<span class="string">&quot;已下载&quot;</span>)</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">findimg</span>(<span class="params">line,ori_pre</span>):</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        img = re.findall(<span class="string">f&quot;(<span class="subst">&#123;ori_pre&#125;</span>.*?(\.jfif|\.svg|\.webp|\.gif|\.jpeg|\.jpg|\.png|\.PNG|\.JPEG|\.JPG))&quot;</span>,line)[<span class="number">0</span>][<span class="number">0</span>]</span><br><span class="line">        name = img.split(<span class="string">&#x27;/&#x27;</span>)[-<span class="number">1</span>]</span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;已自动忽略：&quot;</span>,line)</span><br><span class="line">        img,name = <span class="literal">None</span>,<span class="literal">None</span></span><br><span class="line">    <span class="keyword">return</span> img,name</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">changeurl</span>(<span class="params">ori_root,save_root,down_root,ori_pre,new_pre</span>):</span><br><span class="line">    <span class="keyword">assert</span> ori_pre[-<span class="number">1</span>]==<span class="string">&#x27;/&#x27;</span> <span class="keyword">and</span> new_pre[-<span class="number">1</span>]==<span class="string">&quot;/&quot;</span></span><br><span class="line">    <span class="keyword">if</span> osp.isdir(ori_root):</span><br><span class="line">        files = os.listdir(ori_root)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        file = osp.basename(ori_root)</span><br><span class="line">        ori_root = ori_root.split(file)[<span class="number">0</span>]</span><br><span class="line">        files = [file]</span><br><span class="line">    makedir(save_root)</span><br><span class="line">    makedir(down_root)</span><br><span class="line">    <span class="keyword">for</span> file <span class="keyword">in</span> tqdm(files):</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">&quot;Starting... &quot;</span>,file)</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(ori_root+file,<span class="string">&#x27;r&#x27;</span>,encoding = <span class="string">&#x27;utf-8&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            content = f.readlines()</span><br><span class="line">        <span class="keyword">with</span> <span class="built_in">open</span>(save_root+file,<span class="string">&#x27;w&#x27;</span>,encoding=<span class="string">&#x27;utf-8&#x27;</span>) <span class="keyword">as</span> f:</span><br><span class="line">            <span class="keyword">for</span> line <span class="keyword">in</span> content:</span><br><span class="line">                <span class="keyword">if</span> ori_pre <span class="keyword">in</span> line:</span><br><span class="line">                    img,name = findimg(line,ori_pre)</span><br><span class="line">                    <span class="keyword">if</span> img!=<span class="literal">None</span>:</span><br><span class="line">                        change = new_pre + name</span><br><span class="line">                        <span class="built_in">print</span>(line,<span class="string">&quot;==&gt;&quot;</span>,line.replace(img,change))</span><br><span class="line">                        code = save_img(down_root,img)</span><br><span class="line">                        <span class="keyword">if</span> code == <span class="number">0</span>:</span><br><span class="line">                            line = line.replace(img,change)</span><br><span class="line">                f.write(line)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">main</span>():</span><br><span class="line">    ori_root = <span class="string">&#x27;./hexo/source/_posts/&#x27;</span></span><br><span class="line">    save_root = <span class="string">&#x27;./markdown/&#x27;</span></span><br><span class="line">    down_root = <span class="string">&#x27;./download/&#x27;</span></span><br><span class="line">    ori_pre = <span class="string">&#x27;https://cdn.jsdelivr.net/gh/&#x27;</span></span><br><span class="line">    new_pre = <span class="string">&#x27;https://unpkg.com/justlovesmile-post@1.0.3/&#x27;</span></span><br><span class="line">    changeurl(ori_root,save_root,down_root,ori_pre,new_pre)</span><br><span class="line">    </span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&quot;__main__&quot;</span>:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure><h1>2. 压缩图片</h1><p>由第一步已经下载好图片了，这一步需要对图片进行简单的压缩，这里我采用最简单的图片缩放，通过<code>缩小图片来压缩(有损)</code>，需要无损压缩的可以用软件或者其他方法（百度、CSDN）。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> PIL <span class="keyword">import</span> Image</span><br><span class="line"><span class="keyword">from</span> glob <span class="keyword">import</span> glob</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"><span class="keyword">from</span> tqdm <span class="keyword">import</span> tqdm</span><br><span class="line"><span class="keyword">import</span> shutil</span><br><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"><span class="keyword">from</span> itertools <span class="keyword">import</span> chain</span><br><span class="line"> </span><br><span class="line"><span class="keyword">from</span> multiprocessing <span class="keyword">import</span> Pool</span><br><span class="line"> </span><br><span class="line"><span class="comment"># image_dir = &quot;image_dir&quot;</span></span><br><span class="line">template_dir = <span class="string">&#x27;template&#x27;</span></span><br><span class="line">output_dir = <span class="string">&#x27;output&#x27;</span></span><br><span class="line">error_dir = <span class="string">&#x27;error&#x27;</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">def</span> <span class="title function_">clean_dir</span>(<span class="params">dir_name</span>):</span><br><span class="line">    <span class="keyword">if</span> os.path.exists(dir_name):</span><br><span class="line">        shutil.rmtree(dir_name)</span><br><span class="line">        os.makedirs(dir_name)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        os.makedirs(dir_name)</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="comment"># image_file_list = glob(f&quot;&#123;image_dir&#125;/*&quot;)</span></span><br><span class="line"><span class="comment"># image_file_list</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">def</span> <span class="title function_">imagesize</span>(<span class="params">filepath</span>):</span><br><span class="line">    <span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">    获得文件的磁盘大小</span></span><br><span class="line"><span class="string">    :param filepath:</span></span><br><span class="line"><span class="string">    :return:</span></span><br><span class="line"><span class="string">    &quot;&quot;&quot;</span></span><br><span class="line">    <span class="keyword">return</span> os.path.getsize(filepath) / <span class="number">1024</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">def</span> <span class="title function_">compress_image</span>(<span class="params">image_path, target_size=<span class="number">500</span></span>):</span><br><span class="line">    raw_image = Image.<span class="built_in">open</span>(image_path)</span><br><span class="line">    temp_image_name = image_path.split(os.sep)[-<span class="number">1</span>]</span><br><span class="line">    template_image = os.path.join(template_dir, temp_image_name)</span><br><span class="line">    output_image = os.path.join(output_dir, temp_image_name)</span><br><span class="line">    error_image = os.path.join(error_dir, temp_image_name)</span><br><span class="line"> </span><br><span class="line">    target_size = target_size  <span class="comment"># kb</span></span><br><span class="line"> </span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line"> </span><br><span class="line">        <span class="keyword">if</span> imagesize(image_path) &lt; target_size:</span><br><span class="line">            shutil.copyfile(image_path, output_image)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            width, height = raw_image.size</span><br><span class="line">            raw_image.resize((<span class="built_in">int</span>(width * <span class="number">0.9</span>), <span class="built_in">int</span>(height * <span class="number">0.9</span>)), Image.ANTIALIAS).save(template_image)</span><br><span class="line">            <span class="keyword">while</span> imagesize(template_image) &gt; target_size:</span><br><span class="line">                template_iamge2 = Image.<span class="built_in">open</span>(template_image)</span><br><span class="line">                width_2, height_2 = template_iamge2.size</span><br><span class="line">                template_iamge2.resize((<span class="built_in">int</span>(width_2 * <span class="number">0.9</span>), <span class="built_in">int</span>(height_2 * <span class="number">0.9</span>)), Image.ANTIALIAS).save(template_image)</span><br><span class="line"> </span><br><span class="line">            shutil.copyfile(template_image, output_image)</span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> e:</span><br><span class="line">        shutil.copyfile(image_path, error_image)</span><br><span class="line">        <span class="built_in">print</span>(<span class="string">f&#x27;文件保存失败: <span class="subst">&#123;image_path&#125;</span>&#x27;</span>)</span><br><span class="line">        <span class="comment"># print(e)</span></span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="comment"># 批量创建文件夹</span></span><br><span class="line">    [clean_dir(i) <span class="keyword">for</span> i <span class="keyword">in</span> [template_dir, output_dir, error_dir]]</span><br><span class="line"> </span><br><span class="line">    image_dir = <span class="built_in">input</span>(<span class="string">&#x27;dir path:&#x27;</span>)</span><br><span class="line">    target_size = <span class="built_in">int</span>(<span class="built_in">input</span>(<span class="string">&#x27;target size (kb):&#x27;</span>))</span><br><span class="line"> </span><br><span class="line">    image_file_list = <span class="built_in">list</span>(chain(*[glob(os.path.join(image_dir, i)) <span class="keyword">for</span> i <span class="keyword">in</span> [<span class="string">&#x27;*.png&#x27;</span>, <span class="string">&#x27;*.jpg&#x27;</span>, <span class="string">&#x27;*.jpeg&#x27;</span>]]))</span><br><span class="line"> </span><br><span class="line">    <span class="comment">#for temp_image_path in tqdm(image_file_list):</span></span><br><span class="line">    <span class="comment">#     compress_image(temp_image_path)</span></span><br><span class="line"> </span><br><span class="line">    <span class="built_in">print</span>(<span class="string">f&#x27;\n\n文件保存父目录: <span class="subst">&#123;os.getcwd()&#125;</span>\n&#x27;</span></span><br><span class="line">          <span class="string">f&#x27;输出文件位置:<span class="subst">&#123;os.path.join(os.getcwd(), output_dir)&#125;</span>\n\n&#x27;</span>)</span><br><span class="line"> </span><br><span class="line">    <span class="comment"># parallel</span></span><br><span class="line">    P = Pool(processes=<span class="number">10</span>)</span><br><span class="line">    pbar = tqdm(total=<span class="built_in">len</span>(image_file_list))</span><br><span class="line"> </span><br><span class="line">    res_temp = [P.apply_async(func=compress_image, args=(i,target_size), callback=<span class="keyword">lambda</span> _: pbar.update(<span class="number">1</span>)) <span class="keyword">for</span> i <span class="keyword">in</span></span><br><span class="line">                image_file_list]</span><br><span class="line"> </span><br><span class="line">    _ = [res.get() <span class="keyword">for</span> res <span class="keyword">in</span> res_temp]</span><br></pre></td></tr></table></figure><h1>3. 上传npm</h1><p>到这一步就很简单了，把之前压缩好的图片放在一个文件夹里，如：</p><figure class="highlight txt"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">- mj-img\</span><br><span class="line">    - 1.jpg</span><br><span class="line">    - 2.png</span><br><span class="line">      ...</span><br><span class="line">    - xxx.jpeg</span><br></pre></td></tr></table></figure><p>之前用过npm的，可以直接在文件夹里打开<code>bash</code>，输入<code>npm init</code>与<code>npm publish</code>.</p><p>没有使用过npm的，可以参考<a href="https://akilar.top/posts/3e956346/">Akilar的npm图床使用技巧</a>.</p>]]></content>
    
    
    <summary type="html">写一个小工具，把文章中的 jsDelivr 外链图片批量下载、压缩并替换为 npm 图床链接。</summary>
    
    
    
    <category term="代码编程" scheme="https://blog.xiemingjie.cn/categories/%E4%BB%A3%E7%A0%81%E7%BC%96%E7%A8%8B/"/>
    
    
    <category term="Python" scheme="https://blog.xiemingjie.cn/tags/Python/"/>
    
    <category term="爬虫" scheme="https://blog.xiemingjie.cn/tags/%E7%88%AC%E8%99%AB/"/>
    
    <category term="图床" scheme="https://blog.xiemingjie.cn/tags/%E5%9B%BE%E5%BA%8A/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | IENet：单阶段 Anchor-Free 旋转目标检测</title>
    <link href="https://blog.xiemingjie.cn/posts/afb37b1d.html"/>
    <id>https://blog.xiemingjie.cn/posts/afb37b1d.html</id>
    <published>2022-06-30T02:35:40.000Z</published>
    <updated>2022-06-30T02:35:40.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题：《IENet: Interactive Embranchment Network Based One-Stage Anchor Free Detector for Orientational Aerial Object Detection》</p><blockquote><p>论文发表：arxiv 2019<br>论文链接：<a href="https://arxiv.org/pdf/1912.00969">https://arxiv.org/pdf/1912.00969</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220420214710.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">@article&#123;lin2019ienet,</span><br><span class="line">  title=&#123;IENet: Interacting embranchment one stage anchor free detector for orientation aerial object detection&#125;,</span><br><span class="line">  author=&#123;Lin, Youtian and Feng, Pengming and Guan, Jian and Wang, Wenwu and Chambers, Jonathon&#125;,</span><br><span class="line">  journal=&#123;arXiv preprint arXiv:1912.00969&#125;,</span><br><span class="line">  year=&#123;2019&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>2. 归纳总结</h1><table><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><tr><td>标签</td><td>#遥感 #目标检测</td></tr><tr><td>数据集</td><td>DOTA,HRSC2016</td></tr><tr><td>目的</td><td>两阶段方法计算量大，单阶段方法性能不足</td></tr><tr><td>方法</td><td>基于自注意力的互动分支</td></tr></tbody></table><h1>3. 问题背景</h1><p>作者提到，遥感图像的目标检测任务的难点在于：</p><ul><li>和自然图像相比，物体形状相似且可见特征稀少</li><li>目标具有不同的旋转角度</li><li>具有更多的小目标和密集目标</li></ul><p>而目前最好的性能都是两阶段算法实现的，但是两阶段算法通常在第一阶段定位，在第二阶段分类，因此计算量是非常大的，尤其是对旋转目标检测而言，因为Anchor匹配（涉及IoU计算）和RoI特征提取的计算量大。</p><h1>4. 主要工作</h1><p>针对上诉问题，作者提出了<strong>IENet</strong>（interactive embranchment network），其是一个<strong>单阶段</strong>的<strong>Anchor-Free旋转目标</strong>检测器，其包含如下贡献点：</p><ul><li>一个新的geometric transformation（几何变换），用于更好地表示旋转目标框</li><li>一个基于自注意力机制的分支交互模块（a branch interactive module with a self-attention mechanism）</li><li>一个针对旋转框检测改进的IoU Loss</li></ul><h2 id="4-1-模型结构">4.1 模型结构</h2><h3 id="（1）-Baseline模型结构-FCOS-O">（1） Baseline模型结构(FCOS-O)</h3><p>在FCOS的基础上增加了一个独立的角度回归分支（Orientation Regression）<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220420221515.png" alt=""></p><h3 id="（2）-IENet">（2） IENet</h3><p>由于独立的角度分支不能很好的利用位置等信息，因此检测性能下降，基于此IENet提出了基于自注意力机制的分支交互模块即IE（Interactive Embranchment） Module，用于利用分类和位置回归信息。<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220420221600.png" alt=""></p><h2 id="4-2-旋转框几何变换">4.2 旋转框几何变换</h2><p>IENet使用HBB+几何变换来表征OBB，如下图所示：</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220422192914.png" alt=""></p><p>IENet使用HBB加h,w来表示一个OBB，其中GT OBB是一个8维的向量$[x_1,y_1,x_2,y_2,x_3,y_3,x_4,y_4]$，HBB可由$[x_{min},y_{min},x_{max},y_{max}]$表示，h和w计算如下：<br>$$w=x_{max}-x_2$$<br>$$h=y_{max}-y_1$$<br>基于上述几何变化，可将OBB回归问题转换成HBB回归和方向回归的问题，其中HBB回归和FCOS的一致，为Box的偏移量$R_b=[l,t,r,b]$，方向回归为$R_o=[w,h]$.</p><h2 id="4-3-IE-Module">4.3 IE Module</h2><p>IE模块结构图：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220420221612.png" alt=""></p><p>在获得了分类和位置回归的特征图$F^m$后，使用1x1的卷积层和softmax层来构建自注意力模块：</p><ul><li>首先利用三个1x1的卷积层$f(F^m),g(F^m),h(F^m)$将特征映射到三个特征空间</li><li>将$f(\cdot)$和$g(\cdot)$和并通过softmax层组成注意力图$\gamma= softmax(f(F^m)^Tg(F^m))$，因此特征图之间的关系为$\gamma_{q,p}= \frac{exp(\delta_{pq})}{\sum_{p=1}^{N}exp(\delta_{pq})}$，其中$q,p\in{1,…,N}$为注意力图的行号和列号，$\delta$代表$f(F^m)^Tg(F^m)$输出的NxN的矩阵</li><li>然后，注意图可以用来表示输入特征之间的关系，并对$h(\cdot)$的起作用，得到$\theta=(\theta_1,\theta_2,…,\theta_1,…,\theta_N)$，且$\theta_q=\sum_{p=1}^N\gamma_{q,p}h(f_p^m)$</li><li>为了保留原始特征信息，最后输出的特征为$\mathbb{Y}=\gamma\theta+F^m$</li></ul><h2 id="4-4-损失函数">4.4 损失函数</h2><p>总损失为：<br>$$L = \frac{1}{N_{pos}}L_{cls}+\frac{\lambda}{N_pos}L_{reg}+\frac{\omega}{N_{pos}}L_{ori}$$<br>其中分类损失为Focal Loss损失<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220422200843.png" alt=""><br>位置回归损失为centerness损失加smoothL1<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220422200856.png" alt=""><br>角度回归损失为smoothL1损失<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220422200905.png" alt=""></p><h1>5. 实验结果</h1><p>DOTA_v1<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220420222408.png" alt=""></p><p>HRSC2016<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220420222445.png" alt=""></p><p>同时IENet在推理和训练时的速度上也有优势：</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220630104801.png" alt=""></p><p>消融实验：</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220630104802.png" alt=""></p><p>特征可视化：</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.2/20220630104803.png" alt=""></p>]]></content>
    
    
    <summary type="html">IENet（interactive embranchment network），是一个单阶段的Anchor-Free旋转目标检测器，其包含如下贡献点：一个新的geometric transformation（几何变换），用于更好地表示旋转目标框; 一个基于自注意力机制的分支交互模块（a branch interactive module with a self-attention mechanism）; 一个针对旋转框检测改进的IoU Loss;</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="Anchor-Free" scheme="https://blog.xiemingjie.cn/tags/Anchor-Free/"/>
    
    <category term="旋转目标检测" scheme="https://blog.xiemingjie.cn/tags/%E6%97%8B%E8%BD%AC%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | ATSS：自适应训练样本选择</title>
    <link href="https://blog.xiemingjie.cn/posts/c9c6591.html"/>
    <id>https://blog.xiemingjie.cn/posts/c9c6591.html</id>
    <published>2022-06-29T06:47:13.000Z</published>
    <updated>2022-06-29T06:47:13.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题：<code>《Bridging the Gap Between Anchor-based and Anchor-free Detection via Adaptive Training Sample Selection》</code></p><blockquote><p>论文发表：<code>CVPR2020</code><br>论文链接：<a href="https://openaccess.thecvf.com/content_CVPR_2020/papers/Zhang_Bridging_the_Gap_Between_Anchor-Based_and_Anchor-Free_Detection_via_Adaptive_CVPR_2020_paper.pdf">https://openaccess.thecvf.com</a><br>论文代码：<a href="https://github.com/sfzhang15/ATSS">https://github.com/sfzhang15/ATSS</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220308201514.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@inproceedings&#123;zhang2020bridging,</span><br><span class="line">  title=&#123;Bridging the gap between anchor-based and anchor-free detection via adaptive training sample selection&#125;,</span><br><span class="line">  author=&#123;Zhang, Shifeng and Chi, Cheng and Yao, Yongqiang and Lei, Zhen and Li, Stan Z&#125;,</span><br><span class="line">  booktitle=&#123;Proceedings of the IEEE/CVF conference on computer vision and pattern recognition&#125;,</span><br><span class="line">  pages=&#123;9759--9768&#125;,</span><br><span class="line">  year=&#123;2020&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>2. 归纳总结</h1><table><thead><tr><th style="text-align:center">Name</th><th style="text-align:center">Value</th></tr></thead><tbody><tr><td style="text-align:center">标签</td><td style="text-align:center">#正负样本 #目标检测</td></tr><tr><td style="text-align:center">数据集</td><td style="text-align:center"><code>MSCOCO</code></td></tr><tr><td style="text-align:center">目的</td><td style="text-align:center">通过实验发现<code>Anchor-Base</code>和<code>Anchor-Free</code>的区别在于正负样本定义，并提出了<code>ATSS</code></td></tr><tr><td style="text-align:center">方法</td><td style="text-align:center">使用IoU的均值和标准差作为判断正负样本的自适应<code>IoU</code>阈值</td></tr></tbody></table><h1>3. 问题背景</h1><p>论文指出单阶段<code>Anchor-Based</code>和<code>Center-Based Anchor-Free</code>检测算法的性能差异主要来自于<code>正负样本的选择策略不同</code>，基于此问题，作者提出了ATSS(Adaptive Training Sample Selection)方法，该方法能够自动根据真实框（GT）的相关统计特征自适应地选择合适的样本，进而提升模型性能…</p><h1>4. 主要工作</h1><ul><li>指出<code>Anchor-Free</code>和<code>Anchor-Based</code>方法的根本差异主要来源于正负样本的选择;</li><li>提出<code>ATSS</code>( <code>Adaptive Training Sample Selection</code>)方法来根据对象的统计特征自动选择正负样本;</li><li>证明每个位置设定多个<code>anchor</code>是无用的操作;</li><li>不引入其它额外的开销，在<code>MS COCO</code>上达到<code>SOTA</code>;</li></ul><h2 id="4-1-Anchor-Based和Anchor-Free的区别分析">4.1 <code>Anchor-Based</code>和<code>Anchor-Free</code>的区别分析</h2><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220311102454.png" alt=""></p><p>由于<code>FCOS</code>是基于<code>point</code>进行预测，故可以认为就是一个像素位置有一个<code>anchor</code>，为了公平对比，将<code>RetinaNet</code>的<code>anchor</code>也设置为1个(<code>#A=1</code>),将<code>FCOS</code>的训练策略移动到<code>RetinaNet</code>上面，可以发现性能依然是<code>RetinaNet</code>低于fcos 0.8mAP。 排除这个因素后，现在两个算法的区别是：</p><ul><li>1.<strong>正负样本定义；</strong><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220311102531.png" alt=""></li><li>2.**回归分支中从<code>point</code>回归还是从<code>anchor</code>回归；**从<code>point</code>回归就是指的每个点预测距离4条边的距离模式，而从<code>anchor</code>回归是指的<code>RetinaNet</code>那种基于<code>anchor</code>偏移量回归的模式。<img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220311102948.png" alt=""></li></ul><p>但作者通过实验分析可以知道回归分支中从point回归还是从anchor回归对最终影响很小，反而是正负样本定义对结果影响最大。</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220311103001.png" alt=""></p><h2 id="4-2-ATSS">4.2 ATSS</h2><p>算法流程如下：<br><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220311103116.png" alt=""></p><p>论文提出ATSS方法，该方法根据目标的相关统计特征自动进行正负样本的选择，具体逻辑如算法1所示。对于每个GT box  <code>g</code>，首先在每个特征层找到中心点最近的<code>k</code>个候选anchor boxes(非预测结果)，计算候选box与GT间的IoU $U_g$，计算IoU的均值$m_g$和标准差$v_g$，得到IoU阈值$t_g=m_g+v_g$，最后选择阈值大于$t_g$的box作为最后的输出。如果anchor box对应多个GT，则选择IoU最大的GT。</p><p>均值$m_g$表示预设的anchor与GT的匹配程度，均值高则应当提高阈值来调整正样本，均值低则应当降低阈值来调整正样本。标准差$v_g$表示适合GT的FPN层数，标准差高则表示高质量的anchor box集中在一个层中，应将阈值加上标准差来过滤其他层的anchor box，低则表示多个层都适合该GT，将阈值加上标准差来选择合适的层的anchor box，均值和标准差结合作为IoU阈值能够很好地自动选择对应的特征层上合适的anchor box;</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220311110826.png" alt=""></p><p>根据统计原理，大约16%的anchor box会落在$[m_g+v_g,1]$，尽管候选框的IoU不是标准正态分布，但统计下来每个GT大约有0.2×kL个正样本，与其大小和长宽比无关，而RetinaNet和FCOS则是偏向大目标有更多的正样本，导致训练不公平；其中ATSS仅有一个超参数k，并且实验表明ATSS的性能对k不敏感，参数<code>k</code>在区间$[7,17]$几乎是一样的，过大的设置会到导致过多的低质量候选anchor，而过小的设置则会导致过少的正样本，而且统计结果也不稳定。总体而言，参数<code>k</code>是相对鲁棒的，所以ATSS几乎是hyperparameter-free的。</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220311111137.png" alt=""></p><p>将ATSS应用到RetinaNet和FCOS上测试效果：</p><ul><li>将RetinaNet中的正负样本替换为ATSS，AP提升了2.9%，这样的性能提升几乎是没有任何额外消耗的</li><li>在FCOS上的应用主要用两种：lite版本采用ATSS的思想，从选取GT内的anchor point改为选取每层离GT最近的top-$k$个候选anchor point，提升了0.8%AP；full版本将FCOS的<code>anchor point</code>改为长宽为$8S$的<code>anchor box</code>来根据ATSS选择正负样本，但仍然使用原始的回归方法，提升了1.4%AP。两种方法找到的<code>anchor point</code>在空间位置上大致相同，但是在<code>FPN</code>层上的选择不太一样。从结果来看，自适应的选择方法比固定的方法更有效。</li></ul><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220629153201.png" alt=""></p><p>论文还补充测试了不同anchor数下的性能，并且其实验结果证明，在每个位置设定多个anchor box是无用的操作，关键在于选择合适的正样本；</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220629153202.png" alt=""></p><h1>5. 实验结果</h1><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.1/20220311111508.png" alt=""></p><h1>6. 参考文献</h1><p><a href="https://zhuanlan.zhihu.com/p/115407465">ATSS : 目标检测的自适应正负anchor选择，很扎实的trick | CVPR 2020 - 知乎 (zhihu.com)</a></p>]]></content>
    
    
    <summary type="html">论文指出单阶段Anchor-Based和Center-Based Anchor-Free检测算法的性能差异主要来自于正负样本的选择策略，基于此问题，作者提出了ATSS(Adaptive Training Sample Selection)方法，该方法能够自动根据真实框的相关统计特征自适应地选择合适的样本，进而提升模型性能...</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="目标检测" scheme="https://blog.xiemingjie.cn/tags/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="标签分配" scheme="https://blog.xiemingjie.cn/tags/%E6%A0%87%E7%AD%BE%E5%88%86%E9%85%8D/"/>
    
  </entry>
  
  <entry>
    <title>经验分享 | Hexo 首页顶部轮播图与文章推荐卡片教程</title>
    <link href="https://blog.xiemingjie.cn/posts/6a0d6454.html"/>
    <id>https://blog.xiemingjie.cn/posts/6a0d6454.html</id>
    <published>2022-06-28T01:05:11.000Z</published>
    <updated>2022-06-28T01:05:11.000Z</updated>
    
    <content type="html"><![CDATA[<p>最近看了<a href="https://blog.zhheo.com/">zhheo</a>大佬的博客首页，发现大佬的布局还是那么的好看，于是果断<code>COPY</code>，再加上我一直想要在我的博客首页加一个大画幅的轮播图插件，于是又参考了<a href="https://hassanwong.top/">Hassan</a>的文章轮播图…经过一番折腾，效果如下：</p><p><img src="https://npm.elemecdn.com/justlovesmile-post@1.0.0/2022062808552601.jpg" alt=""></p><h1>1. 创建首页顶部模块</h1><h2 id="1-1-创建hometop-pug">1.1 创建<code>hometop.pug</code></h2><p>在<code>themes/butterfly/layout/includes</code>路径下创建<code>hometop.pug</code>文件：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">if is_home()</span><br><span class="line">  #home_top</span><br><span class="line">    include bbTimeList.pug</span><br><span class="line">    .home_top_group</span><br><span class="line">      #homeTopGroup.homeTopGroup</span><br><span class="line">        #banner_group</span><br><span class="line">          #banners</span><br><span class="line">            include sticky.pug //轮播图</span><br><span class="line">          .category_group</span><br><span class="line">            .category_item</span><br><span class="line">              a.category_button(href=&lt;左下角标签1路径&gt;,style=&quot;background:linear-gradient(to right,#364f6b,#3fc1c9)&quot;)</span><br><span class="line">                span.category_button_text &lt;标签1名称&gt;</span><br><span class="line">                i.fas.fa-laptop-code</span><br><span class="line">            .category_item</span><br><span class="line">              a.category_button(href=&lt;左下角标签2路径&gt;,style=&quot;background:linear-gradient(to right,#6639a6,#3490de)&quot;)</span><br><span class="line">                span.category_button_text &lt;标签2名称&gt;</span><br><span class="line">                i.fas.fa-lightbulb</span><br><span class="line">            .category_item</span><br><span class="line">              a.category_button(href=&lt;左下角标签3路径&gt;,style=&quot;background:linear-gradient(to right,#f65,#ffbf37)&quot;)</span><br><span class="line">                span.category_button_text &lt;标签3名称&gt;</span><br><span class="line">                i.fas.fa-book</span><br><span class="line">        .top_post_group // 右侧文章推荐卡片</span><br><span class="line">          if site.data.slider</span><br><span class="line">            each i in site.data.slider</span><br><span class="line">              .top_post_item</span><br><span class="line">                .post_cover</span><br><span class="line">                  a(href=url_for(i.link) title=i.title)</span><br><span class="line">                    img.post_bg.entered.loaded(src=url_for(i.cover))</span><br><span class="line">                    .post_cover_info</span><br><span class="line">                      p.post_cover_text= i.description</span><br><span class="line"></span><br><span class="line">                .post_info(onclick=`&quot;window.open(`+url_for(i.link)+`,&quot;_self&quot;)&quot;`)</span><br><span class="line">                  a.article-title(href=url_for(i.link) title=i.title)= i.title</span><br></pre></td></tr></table></figure><p>其中第一行的<code>is_home()</code>是<code>Hexo</code>自带的辅助函数，用于判断是否为首页，但是其在<code>justlovesmile.top/</code>以及<code>justlovesmile.top/page/2/</code>等页面都返回<code>True</code>，因此如果你只想在首页的第一页显示该模块，可以使用<code>is_current('/')</code>。</p><h2 id="1-2-添加css样式">1.2 添加<code>css</code>样式</h2><p>在自己的<code>css</code>文件中添加：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-pseudo">:root</span>&#123;</span><br><span class="line">    <span class="attr">--mj-white</span>: <span class="number">#fff</span>;</span><br><span class="line">    <span class="attr">--mj-card-bg</span>: <span class="number">#fff</span>;</span><br><span class="line">    <span class="attr">--mj-theme</span>: <span class="number">#425AEF</span>;</span><br><span class="line">    <span class="attr">--mj-main</span>: <span class="number">#425AEF</span>;</span><br><span class="line">    <span class="attr">--mj-secondbg</span>: <span class="number">#ededed</span>;</span><br><span class="line">    <span class="attr">--mj-card-border</span>: <span class="number">#e3e8f7</span>;</span><br><span class="line">    <span class="attr">--style-border</span>: <span class="number">1px</span> solid <span class="built_in">var</span>(--mj-card-border);</span><br><span class="line">    <span class="attr">--style-hover-border</span>: <span class="number">1px</span> solid <span class="built_in">var</span>(--mj-theme);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">/* home top */</span></span><br><span class="line"><span class="selector-id">#home_top</span> &#123;</span><br><span class="line">    <span class="attribute">max-width</span>: <span class="number">1500px</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">margin-top</span>: .<span class="number">5rem</span>;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">15px</span>;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">0</span> auto;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.home_top_group</span> &#123;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">overflow</span>: auto;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">margin-bottom</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.homeTopGroup</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">flex-direction</span>: row;</span><br><span class="line">    <span class="attribute">flex-wrap</span>: nowrap;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">margin-top</span>: <span class="number">1rem</span>;</span><br><span class="line">    <span class="attribute">overflow</span>: auto;</span><br><span class="line">    <span class="attribute">overflow-x</span>: score;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.homeTopGroup</span>::-webkit-scrollbar &#123;</span><br><span class="line">    <span class="attribute">display</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.homeTopGroup</span> <span class="selector-id">#banner_group</span> &#123;<span class="attribute">display</span>: flex;&#125;</span><br><span class="line"><span class="selector-tag">div</span><span class="selector-id">#banners</span> &#123;<span class="attribute">display</span>: none;&#125;</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">min-width</span>: <span class="number">1300px</span>)&#123;</span><br><span class="line">  <span class="selector-class">.homeTopGroup</span> <span class="selector-id">#banner_group</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">100%</span> - <span class="number">600px</span> - <span class="number">1.5rem</span>);</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">flex-direction</span>: column;</span><br><span class="line">    <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-tag">div</span><span class="selector-id">#banners</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">var</span>(--mj-main);</span><br><span class="line">    <span class="attribute">margin-bottom</span>: .<span class="number">5rem</span>;</span><br><span class="line">    <span class="attribute">margin-right</span>: .<span class="number">5rem</span>;</span><br><span class="line">    <span class="attribute">border</span>: <span class="built_in">var</span>(--style-border);</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-tag">div</span><span class="selector-id">#banners</span><span class="selector-pseudo">:hover</span>&#123;</span><br><span class="line">    <span class="attribute">border</span>: <span class="built_in">var</span>(--style-hover-border);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-class">.homeTopGroup</span> <span class="selector-class">.category_group</span> &#123;</span><br><span class="line">    <span class="attribute">flex-direction</span>: row <span class="meta">!important</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-class">.homeTopGroup</span> <span class="selector-class">.category_item</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">100%</span> / <span class="number">3</span> - .<span class="number">33rem</span>);</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">100%</span> <span class="meta">!important</span>;</span><br><span class="line">    <span class="attribute">margin-right</span>: .<span class="number">5rem</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-class">.homeTopGroup</span> <span class="selector-class">.category_item</span><span class="selector-pseudo">:nth-child</span>(<span class="number">3</span>) &#123;</span><br><span class="line">    <span class="attribute">margin-right</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">display</span>: flex <span class="meta">!important</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-id">#banner-page</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-class">.top_post_group</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">flex-direction</span>: row;</span><br><span class="line">    <span class="attribute">flex-wrap</span>: wrap;</span><br><span class="line">    <span class="attribute">justify-content</span>: flex-end;</span><br><span class="line">    <span class="attribute">height</span>: <span class="built_in">calc</span>(<span class="number">328px</span> + .<span class="number">5rem</span>);</span><br><span class="line">    <span class="attribute">align-content</span>: space-between;</span><br><span class="line">    <span class="attribute">width</span>: <span class="built_in">calc</span>(<span class="number">600px</span> + <span class="number">1.5rem</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.homeTopGroup</span> <span class="selector-class">.category_group</span>&#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">flex-direction</span>: column;</span><br><span class="line">    <span class="attribute">justify-content</span>: space-between;</span><br><span class="line">    <span class="attribute">min-width</span>: <span class="number">200px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.homeTopGroup</span> <span class="selector-class">.category_item</span> &#123;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">scale</span>(<span class="number">1</span>);</span><br><span class="line">    <span class="attribute">transition</span>: .<span class="number">3s</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">48%</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.homeTopGroup</span> <span class="selector-class">.category_item</span><span class="selector-pseudo">:nth-child</span>(<span class="number">3</span>) &#123;</span><br><span class="line">    <span class="attribute">display</span>: none;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.homeTopGroup</span> <span class="selector-class">.category_item</span> <span class="selector-tag">a</span><span class="selector-class">.category_button</span> &#123;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">var</span>(--mj-card-bg);</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">display</span>: inline-block;</span><br><span class="line">    <span class="attribute">text-align</span>: left;</span><br><span class="line">    <span class="attribute">line-height</span>: <span class="number">4em</span>;</span><br><span class="line">    <span class="attribute">font-weight</span>: <span class="number">700</span>;</span><br><span class="line">    <span class="attribute">font-size</span>: .<span class="number">9rem</span>;</span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--mj-white);</span><br><span class="line">    <span class="attribute">transition</span>: all .<span class="number">4s</span> <span class="built_in">cubic-bezier</span>(.<span class="number">39</span>,.<span class="number">575</span>,.<span class="number">565</span>,<span class="number">1</span>);</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">scale</span>(<span class="number">1</span>);</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">font-family</span>: PingFang SC,Hiragino Sans GB,Microsoft YaHei;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.category_button_text</span> &#123;</span><br><span class="line">    <span class="attribute">padding-left</span>: <span class="number">25px</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">a</span><span class="selector-class">.category_button</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">3rem</span>;</span><br><span class="line">    <span class="attribute">opacity</span>: .<span class="number">3</span>;</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">right</span>: <span class="number">15px</span>;</span><br><span class="line">    <span class="attribute">top</span>: <span class="number">10%</span>;</span><br><span class="line">    <span class="attribute">transition</span>: .<span class="number">3s</span>;</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">rotate</span>(-<span class="number">10deg</span>);</span><br><span class="line">    <span class="comment">/*width: 100px;</span></span><br><span class="line"><span class="comment">    text-align: center;*/</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">a</span><span class="selector-class">.category_button</span><span class="selector-pseudo">:hover</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">    <span class="attribute">opacity</span>: .<span class="number">8</span>;</span><br><span class="line">    <span class="attribute">transition</span>: .<span class="number">8s</span>;</span><br><span class="line">    <span class="attribute">transition-delay</span>: .<span class="number">15s</span>;</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">scale</span>(<span class="number">1.1</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">a</span><span class="selector-class">.category_button</span><span class="selector-pseudo">:hover</span><span class="selector-pseudo">:after</span>&#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">3rem</span>;</span><br><span class="line">    <span class="attribute">transition</span>: .<span class="number">8s</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">a</span><span class="selector-class">.category_button</span><span class="selector-pseudo">:after</span> &#123;</span><br><span class="line">    <span class="attribute">top</span>: <span class="number">40px</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">1rem</span>;</span><br><span class="line">    <span class="attribute">left</span>: <span class="number">25px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">2px</span>;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">var</span>(--mj-white);</span><br><span class="line">    <span class="attribute">content</span>: <span class="string">&quot;&quot;</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">1px</span>;</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">transition</span>: .<span class="number">8s</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">768px</span>)&#123;</span><br><span class="line">  <span class="selector-id">#home_top</span>&#123;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0</span> <span class="number">5px</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-class">.homeTopGroup</span> <span class="selector-class">.category_group</span> &#123;</span><br><span class="line">    <span class="attribute">min-width</span>: <span class="number">130px</span><span class="meta">!important</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span>&#123;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">0</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span>&#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line">    <span class="attribute">min-width</span>: <span class="number">200px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">164px</span>;</span><br><span class="line">    <span class="attribute">max-height</span>: <span class="number">164px</span>;</span><br><span class="line">    <span class="attribute">flex-direction</span>: column;</span><br><span class="line">    <span class="attribute">align-items</span>: flex-start;</span><br><span class="line">    <span class="attribute">margin-left</span>: .<span class="number">5rem</span>;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">var</span>(--mj-card-bg);</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">border</span>: <span class="built_in">var</span>(--style-border);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span><span class="selector-pseudo">:hover</span> &#123;<span class="attribute">border</span>: <span class="built_in">var</span>(--style-hover-border);&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span> <span class="selector-class">.post_cover</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">110px</span>;</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span> <span class="selector-class">.post_cover</span> <span class="selector-tag">img</span> &#123;</span><br><span class="line">    <span class="attribute">object-fit</span>: cover;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">110px</span>;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">var</span>(--mj-secondbg);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span> <span class="selector-class">.post_cover</span> <span class="selector-class">.post_cover_info</span> &#123;</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">top</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">101%</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>,<span class="number">0.7</span>) <span class="meta">!important</span>;</span><br><span class="line">    <span class="attribute">transition</span>: all <span class="number">0.3s</span> ease;</span><br><span class="line">    <span class="attribute">display</span>: flex;</span><br><span class="line">&#125; </span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.post_cover</span> <span class="selector-class">.post_cover_info</span>&#123;</span><br><span class="line">    <span class="attribute">opacity</span>: <span class="number">1</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span> <span class="selector-class">.post_cover</span> <span class="selector-class">.post_cover_info</span> <span class="selector-class">.post_cover_text</span>&#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#fff</span>;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">12px</span> <span class="number">14px</span>;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">15px</span>;</span><br><span class="line">    <span class="attribute">font-weight</span>: <span class="number">400</span>;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">20px</span> <span class="number">0</span>;</span><br><span class="line">    -webkit-<span class="selector-tag">line</span>-clamp: <span class="number">2</span>;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">display</span>: -webkit-box;</span><br><span class="line">    -webkit-<span class="attribute">box-orient</span>: vertical;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.post_info</span>,</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span><span class="selector-pseudo">:focus</span> <span class="selector-class">.post_info</span>&#123;</span><br><span class="line">    <span class="comment">/*background: var(--mj-theme);*/</span></span><br><span class="line">    <span class="attribute">box-shadow</span>: inset <span class="number">0</span> -<span class="number">60px</span> <span class="number">0</span> <span class="number">0</span> <span class="built_in">var</span>(--mj-theme);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span> <span class="selector-class">.post_info</span> <span class="selector-tag">a</span>&#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--mj-fontcolor) <span class="meta">!important</span>;</span><br><span class="line">    <span class="attribute">transition</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.post_info</span> <span class="selector-tag">a</span>&#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="built_in">var</span>(--mj-white) <span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span> <span class="selector-class">.post_info</span> &#123;</span><br><span class="line">    <span class="attribute">padding</span>: .<span class="number">2rem</span> .<span class="number">5rem</span> .<span class="number">3rem</span> .<span class="number">5rem</span><span class="meta">!important</span>;</span><br><span class="line">    <span class="attribute">transition</span>: .<span class="number">3s</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.top_post_group</span> <span class="selector-class">.top_post_item</span> <span class="selector-class">.post_info</span> <span class="selector-class">.article-title</span> &#123;</span><br><span class="line">    -webkit-<span class="selector-tag">line</span>-clamp: <span class="number">2</span>;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">    <span class="attribute">display</span>: -webkit-box;</span><br><span class="line">    -webkit-<span class="attribute">box-orient</span>: vertical;</span><br><span class="line">    <span class="attribute">line-height</span>: <span class="number">1.4</span>;</span><br><span class="line">    <span class="attribute">justify-content</span>: center;</span><br><span class="line">    <span class="attribute">align-items</span>: flex-end;</span><br><span class="line">    <span class="attribute">align-content</span>: center;</span><br><span class="line">    <span class="attribute">font-weight</span>: <span class="number">600</span>;</span><br><span class="line">    <span class="attribute">font-size</span>: .<span class="number">8rem</span><span class="meta">!important</span>;</span><br><span class="line">    <span class="attribute">padding</span>: <span class="number">0</span><span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>2. 创建顶部轮播图</h1><h2 id="2-1-创建sticky-pug">2.1 创建<code>sticky.pug</code></h2><p>在<code>themes/butterfly/layout/includes</code>路径下创建<code>sticky.pug</code>文件：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">link(rel=&#x27;stylesheet&#x27; href=&#x27;https://unpkg.com/swiper/swiper-bundle.min.css&#x27;)</span><br><span class="line">#sticky</span><br><span class="line">  #stickyList.swiper-container</span><br><span class="line">    #stickyWrapper.swiper-wrapper</span><br><span class="line">      .swiper-slide(onclick=`window.open(&#x27;/random/&#x27;,&#x27;_self&#x27;)`)</span><br><span class="line">        .grid-img</span><br><span class="line">          iframe#banner-page(src=&quot;&lt;这里放iframe地址&gt;&quot; frameborder=&quot;0&quot; loading=&quot;eager&quot;) // 可以放iframe</span><br><span class="line">        .grid-title</span><br><span class="line">          span 随便逛逛</span><br><span class="line">          i.fas.fa-arrow-right</span><br><span class="line">      .swiper-slide(onclick=`window.open(&#x27;/video/&#x27;,&#x27;_self&#x27;)`)</span><br><span class="line">        .grid-img</span><br><span class="line">          img.cover.entered.loaded(alt=&#x27;VLOG&#x27; src=&#x27;https://npm.elemecdn.com/justlovesmile-photo/myvlog.gif&#x27;) // 可以放GIF</span><br><span class="line">        .grid-title</span><br><span class="line">          span 看看VLOG</span><br><span class="line">          i.fas.fa-arrow-right</span><br><span class="line">      .swiper-slide(onclick=`window.open(&#x27;/music/&#x27;,&#x27;_self&#x27;)`)</span><br><span class="line">        .grid-img</span><br><span class="line">          img.cover.entered.loaded(alt=&#x27;歌单&#x27; src=&#x27;https://npm.elemecdn.com/justlovesmile-img/gitar.jpg&#x27;) // 可以放图片</span><br><span class="line">        .grid-title</span><br><span class="line">          span 听听音乐</span><br><span class="line">          i.fas.fa-arrow-right</span><br><span class="line">    //- 分页器</span><br><span class="line">    .swiper-pagination</span><br><span class="line"></span><br><span class="line">.js-pjax</span><br><span class="line">  script(src=&#x27;https://unpkg.com/swiper/swiper-bundle.min.js&#x27;)</span><br><span class="line">  script(src=&#x27;/js/sticky.js&#x27;)</span><br><span class="line">link(rel=&#x27;stylesheet&#x27; href=&#x27;/css/sticky.css&#x27;)</span><br></pre></td></tr></table></figure><h2 id="2-2-创建sticky-js">2.2 创建<code>sticky.js</code></h2><p>在<code>themes/butterfly/source/js</code>路径下创建<code>sticky.js</code>文件：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> mySwiper = <span class="keyword">new</span> <span class="title class_">Swiper</span>(<span class="string">&#x27;#stickyList&#x27;</span>, &#123;</span><br><span class="line">      <span class="attr">direction</span>: <span class="string">&#x27;horizontal&#x27;</span>,</span><br><span class="line">      <span class="attr">speed</span>: <span class="number">600</span>,</span><br><span class="line">      <span class="attr">loop</span>: <span class="literal">true</span>,</span><br><span class="line">      effect : <span class="string">&#x27;fade&#x27;</span>,</span><br><span class="line">      <span class="attr">loopPreventsSlide</span>: <span class="literal">false</span>,</span><br><span class="line">      <span class="attr">autoplay</span>: &#123;</span><br><span class="line">        <span class="attr">delay</span>: <span class="number">20000</span>,</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">mousewheel</span>: <span class="literal">false</span>,</span><br><span class="line">      <span class="attr">pagination</span>: &#123;</span><br><span class="line">          <span class="attr">el</span>: <span class="string">&quot;.swiper-pagination&quot;</span>,</span><br><span class="line">          <span class="attr">dynamicBullets</span>: <span class="literal">true</span>,</span><br><span class="line">      &#125;,</span><br><span class="line">    &#125;)</span><br></pre></td></tr></table></figure><h2 id="2-3-创建sticky-css">2.3 创建<code>sticky.css</code></h2><p>在<code>themes/butterfly/source/css</code>路径下创建<code>sticky.css</code>文件：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-pseudo">:root</span>&#123;</span><br><span class="line">    <span class="attr">--mj-white</span>: <span class="number">#fff</span>;</span><br><span class="line">    <span class="attr">--mj-card-bg</span>: <span class="number">#fff</span>;</span><br><span class="line">    <span class="attr">--mj-theme</span>: <span class="number">#425AEF</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#sticky</span>,</span><br><span class="line"><span class="selector-id">#stickyList</span>,</span><br><span class="line"><span class="selector-id">#stickyWrapper</span>&#123;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.swiper-container</span><span class="selector-id">#stickyList</span> &#123;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span> &#123;</span><br><span class="line">  <span class="attribute">background</span>: <span class="built_in">var</span>(--mj-card-bg);</span><br><span class="line">  <span class="attribute">position</span>: relative;</span><br><span class="line">  <span class="attribute">border-radius</span>: <span class="number">12px</span>;</span><br><span class="line">  <span class="attribute">transition</span>: <span class="number">0.3s</span>;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span> <span class="selector-class">.grid-img</span> &#123;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">16.2rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span> <span class="selector-class">.grid-img</span> <span class="selector-tag">img</span> &#123;</span><br><span class="line">  <span class="attribute">transition</span>: <span class="number">0.3s</span>;</span><br><span class="line">  <span class="attribute">object-fit</span>: cover;</span><br><span class="line">  <span class="attribute">display</span>: block;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.grid-title</span>&#123;</span><br><span class="line">  <span class="attribute">opacity</span>: .<span class="number">8</span>;</span><br><span class="line">  <span class="attribute">cursor</span>: pointer <span class="meta">!important</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.grid-img</span>&#123;</span><br><span class="line">  <span class="attribute">filter</span>: <span class="built_in">blur</span>(<span class="number">5px</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.grid-title</span> <span class="selector-tag">span</span>,</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span><span class="selector-pseudo">:hover</span> <span class="selector-class">.grid-title</span> <span class="selector-tag">i</span>&#123;</span><br><span class="line">  <span class="attribute">transform</span>: <span class="built_in">translateX</span>(<span class="number">0px</span>);</span><br><span class="line">  <span class="attribute">transition</span>: .<span class="number">5s</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span> <span class="selector-class">.grid-title</span> <span class="selector-tag">span</span>,</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span> <span class="selector-class">.grid-title</span> <span class="selector-tag">i</span>&#123;</span><br><span class="line">  <span class="attribute">transform</span>: <span class="built_in">translateX</span>(-<span class="number">100px</span>);</span><br><span class="line">  <span class="attribute">transition</span>: .<span class="number">5s</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span> <span class="selector-class">.grid-title</span> &#123;</span><br><span class="line">  <span class="attribute">position</span>: absolute;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">height</span>: <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">top</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">left</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">overflow</span>: hidden;</span><br><span class="line">  <span class="attribute">background</span>: <span class="built_in">var</span>(--mj-theme);</span><br><span class="line">  <span class="attribute">color</span>: <span class="built_in">var</span>(--mj-white);</span><br><span class="line">  <span class="attribute">padding-left</span>: <span class="number">1.5rem</span>;</span><br><span class="line">  <span class="attribute">display</span>: flex;</span><br><span class="line">  <span class="attribute">flex-direction</span>: column;</span><br><span class="line">  <span class="attribute">justify-content</span>: center;</span><br><span class="line">  <span class="attribute">opacity</span>: <span class="number">0</span>;</span><br><span class="line">  <span class="attribute">transition</span>: .<span class="number">5s</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span> <span class="selector-class">.grid-title</span> <span class="selector-tag">span</span> &#123;</span><br><span class="line">  <span class="attribute">font-size</span>: <span class="number">5rem</span>;</span><br><span class="line">  <span class="attribute">font-weight</span>: <span class="number">700</span>;</span><br><span class="line">  <span class="attribute">line-height</span>: <span class="number">5rem</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#stickyList</span> <span class="selector-class">.swiper-slide</span> <span class="selector-class">.grid-title</span> <span class="selector-tag">i</span> &#123;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">4rem</span>;</span><br><span class="line">    <span class="attribute">opacity</span>: .<span class="number">6</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">@media</span> screen <span class="keyword">and</span> (<span class="attribute">max-width</span>: <span class="number">768px</span>) &#123;</span><br><span class="line">  <span class="selector-id">#sticky</span> &#123;</span><br><span class="line">    <span class="attribute">display</span>: none;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>3. 创建文章推荐卡片</h1><h2 id="3-1-创建slider-yml">3.1 创建<code>slider.yml</code></h2><p>在<code>hexo\source\_data\</code>路径下创建<code>slider.yml</code>文件，最好准备<code>6</code>个推荐文章，例如：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#- cover: 封面图片链接</span></span><br><span class="line"><span class="comment">#  timeline: &#x27;2020-10-01&#x27; # 日期，需要用&#x27;&#x27;包裹</span></span><br><span class="line"><span class="comment">#  link: 置顶文章链接，站内文章建议填相对链接</span></span><br><span class="line"><span class="comment">#  title: 置顶文章标题</span></span><br><span class="line"><span class="comment">#  description: 置顶文章描述</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">cover:</span> <span class="string">https://npm.elemecdn.com/justlovesmile-img/20200715201402.png</span></span><br><span class="line">  <span class="attr">timeline:</span> <span class="string">&#x27;2020-07-15&#x27;</span></span><br><span class="line">  <span class="attr">link:</span> <span class="string">/posts/c8972b63.html</span></span><br><span class="line">  <span class="attr">title:</span> <span class="string">必看</span> <span class="string">|</span> <span class="string">Hexo博客搭建超级指南</span></span><br><span class="line">  <span class="attr">description:</span> <span class="string">Hexo博客搭建全过程，环境部署，博客魔改等等...</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">cover:</span> <span class="string">https://npm.elemecdn.com/justlovesmile-img/090412-1557363852af44.jpg</span></span><br><span class="line">  <span class="attr">timeline:</span> <span class="string">&#x27;2020-04-09&#x27;</span></span><br><span class="line">  <span class="attr">link:</span> <span class="string">/posts/56163.html</span></span><br><span class="line">  <span class="attr">title:</span> <span class="string">Hexo博客</span> <span class="string">|</span> <span class="string">博客中能用到的代码（一）</span></span><br><span class="line">  <span class="attr">description:</span> <span class="string">这篇文章介绍了如何使用font</span> <span class="string">awesome图标字体库，使用动态图标，添加网页运行时间，全站变黑白，鼠标点击特效，网页标题的动态效果，网页樱花特效，鼠标触动音乐特效</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">cover:</span> <span class="string">https://npm.elemecdn.com/justlovesmile-img/095658-1562983018e455.jpg</span></span><br><span class="line">  <span class="attr">timeline:</span> <span class="string">&#x27;2020-04-09&#x27;</span></span><br><span class="line">  <span class="attr">link:</span> <span class="string">/posts/15391.html</span></span><br><span class="line">  <span class="attr">title:</span> <span class="string">Hexo博客</span> <span class="string">|</span> <span class="string">博客中能用到的代码（二）</span></span><br><span class="line">  <span class="attr">description:</span> <span class="string">这篇文章介绍了如何添加旋转小人和每日诗句</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">cover:</span> <span class="string">https://npm.elemecdn.com/justlovesmile-img/20220331192754.png</span></span><br><span class="line">  <span class="attr">timeline:</span> <span class="string">&#x27;2022-03-31&#x27;</span></span><br><span class="line">  <span class="attr">link:</span> <span class="string">/posts/a806bebe.html</span></span><br><span class="line">  <span class="attr">title:</span> <span class="string">推荐</span> <span class="string">|</span> <span class="string">计算机专业，大学课程「笔记归档」</span></span><br><span class="line">  <span class="attr">description:</span> <span class="string">本文是博主本科期间的专业课程学习笔记的整理和归档，适合计算机专业的同学阅读。</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">cover:</span> <span class="string">https://npm.elemecdn.com/justlovesmile-img/20220318183107.png</span></span><br><span class="line">  <span class="attr">timeline:</span> <span class="string">&#x27;2022-03-18&#x27;</span></span><br><span class="line">  <span class="attr">link:</span> <span class="string">/posts/589ec011.html</span></span><br><span class="line">  <span class="attr">title:</span> <span class="string">深度学习</span> <span class="string">|</span> <span class="string">Detectron2使用指南</span></span><br><span class="line">  <span class="attr">description:</span> <span class="string">Detectron2是Facebook</span> <span class="string">AI</span> <span class="string">Research的检测和分割框架，其主要基于PyTorch实现，但具有更模块化设计，因此它是灵活且便于扩展的。</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">cover:</span> <span class="string">https://npm.elemecdn.com/justlovesmile-img/202109111517311.jpg</span></span><br><span class="line">  <span class="attr">timeline:</span> <span class="string">&#x27;2021-09-11&#x27;</span></span><br><span class="line">  <span class="attr">link:</span> <span class="string">/posts/865c56ba.html</span></span><br><span class="line">  <span class="attr">title:</span> <span class="string">目标检测</span> <span class="string">|</span> <span class="string">常用数据集标注格式及生成脚本</span></span><br><span class="line">  <span class="attr">description:</span> <span class="string">目标检测是计算机视觉任务中的一个重要研究方向，是计算机视觉的根本性问题之一，是其他诸多计算机视觉任务的基础以及前提。本文主要介绍了目标检测数据集的几种标注格式和转换代码。</span></span><br></pre></td></tr></table></figure><h2 id="3-2-css样式">3.2 <code>css</code>样式</h2><p>见<code>1.2</code>中<code>.top_post_group</code>等样式类，不再赘述…</p><h1>4. 补充：zhheo大佬首页人来人往特效</h1><h2 id="4-1-创建people页面">4.1 创建<code>people</code>页面</h2><p>在<code>hexo\source\</code>路径下创建<code>people</code>文件夹，其中创建<code>index.html</code>:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">layout: false</span><br><span class="line">---</span><br><span class="line"></span><br><span class="line"><span class="meta">&lt;!doctype <span class="keyword">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">&quot;en&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">&quot;UTF-8&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">title</span>&gt;</span>MJ&#x27;s People Page<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">&quot;viewport&quot;</span> <span class="attr">content</span>=<span class="string">&quot;width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, minimal-ui&quot;</span> /&gt;</span><span class="comment">&lt;!--禁止缩放--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">link</span> <span class="attr">rel</span>=<span class="string">&quot;stylesheet&quot;</span> <span class="attr">href</span>=<span class="string">&quot;/people/style.css&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">canvas</span> <span class="attr">id</span>=<span class="string">&quot;canvas&quot;</span> <span class="attr">width</span>=<span class="string">&quot;808&quot;</span> <span class="attr">height</span>=<span class="string">&quot;244&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">canvas</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/gsap/3.9.1/gsap.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;/people/script.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="4-2-创建css样式">4.2 创建<code>css</code>样式</h2><p>在<code>hexo\source\people</code>路径下，创建<code>style.css</code>:</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">body</span>,</span><br><span class="line"><span class="selector-tag">html</span>&#123;</span><br><span class="line"><span class="attribute">height</span>:<span class="number">100%</span>;</span><br><span class="line"><span class="attribute">background-color</span>:<span class="number">#fff</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">body</span>&#123;</span><br><span class="line"><span class="attribute">margin</span>:<span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-id">#canvas</span>&#123;</span><br><span class="line"><span class="attribute">width</span>:<span class="number">100%</span>;</span><br><span class="line"><span class="attribute">height</span>:<span class="number">100%</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">body</span>::-webkit-scrollbar&#123;</span><br><span class="line"><span class="attribute">display</span>:none;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="4-3-创建js文件">4.3 创建<code>js</code>文件</h2><p>在<code>hexo\source\people</code>路径下，创建<code>script.js</code>:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&quot;use strict&quot;</span>;<span class="keyword">function</span> <span class="title function_">_toConsumableArray</span>(<span class="params">e</span>)&#123;<span class="keyword">return</span> <span class="title function_">_arrayWithoutHoles</span>(e)||<span class="title function_">_iterableToArray</span>(e)||<span class="title function_">_unsupportedIterableToArray</span>(e)||<span class="title function_">_nonIterableSpread</span>()&#125;<span class="keyword">function</span> <span class="title function_">_nonIterableSpread</span>(<span class="params"></span>)&#123;<span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&quot;Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.&quot;</span>)&#125;<span class="keyword">function</span> <span class="title function_">_unsupportedIterableToArray</span>(<span class="params">e,r</span>)&#123;<span class="keyword">if</span>(e)&#123;<span class="keyword">if</span>(<span class="string">&quot;string&quot;</span>==<span class="keyword">typeof</span> e)<span class="keyword">return</span> <span class="title function_">_arrayLikeToArray</span>(e,r);<span class="keyword">var</span> t=<span class="title class_">Object</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">toString</span>.<span class="title function_">call</span>(e).<span class="title function_">slice</span>(<span class="number">8</span>,-<span class="number">1</span>);<span class="keyword">return</span><span class="string">&quot;Object&quot;</span>===t&amp;&amp;e.<span class="property">constructor</span>&amp;&amp;(t=e.<span class="property">constructor</span>.<span class="property">name</span>),<span class="string">&quot;Map&quot;</span>===t||<span class="string">&quot;Set&quot;</span>===t?<span class="title class_">Array</span>.<span class="title function_">from</span>(e):<span class="string">&quot;Arguments&quot;</span>===t||<span class="regexp">/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/</span>.<span class="title function_">test</span>(t)?<span class="title function_">_arrayLikeToArray</span>(e,r):<span class="keyword">void</span> <span class="number">0</span>&#125;&#125;<span class="keyword">function</span> <span class="title function_">_iterableToArray</span>(<span class="params">e</span>)&#123;<span class="keyword">if</span>(<span class="string">&quot;undefined&quot;</span>!=<span class="keyword">typeof</span> <span class="title class_">Symbol</span>&amp;&amp;<span class="literal">null</span>!=e[<span class="title class_">Symbol</span>.<span class="property">iterator</span>]||<span class="literal">null</span>!=e[<span class="string">&quot;@@iterator&quot;</span>])<span class="keyword">return</span> <span class="title class_">Array</span>.<span class="title function_">from</span>(e)&#125;<span class="keyword">function</span> <span class="title function_">_arrayWithoutHoles</span>(<span class="params">e</span>)&#123;<span class="keyword">if</span>(<span class="title class_">Array</span>.<span class="title function_">isArray</span>(e))<span class="keyword">return</span> <span class="title function_">_arrayLikeToArray</span>(e)&#125;<span class="keyword">function</span> <span class="title function_">_arrayLikeToArray</span>(<span class="params">e,r</span>)&#123;(<span class="literal">null</span>==r||r&gt;e.<span class="property">length</span>)&amp;&amp;(r=e.<span class="property">length</span>);<span class="keyword">for</span>(<span class="keyword">var</span> t=<span class="number">0</span>,a=<span class="keyword">new</span> <span class="title class_">Array</span>(r);t&lt;r;t++)a[t]=e[t];<span class="keyword">return</span> a&#125;<span class="keyword">function</span> <span class="title function_">_classCallCheck</span>(<span class="params">e,r</span>)&#123;<span class="keyword">if</span>(!(e <span class="keyword">instanceof</span> r))<span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">TypeError</span>(<span class="string">&quot;Cannot call a class as a function&quot;</span>)&#125;<span class="keyword">function</span> <span class="title function_">_defineProperties</span>(<span class="params">e,r</span>)&#123;<span class="keyword">for</span>(<span class="keyword">var</span> t=<span class="number">0</span>;t&lt;r.<span class="property">length</span>;t++)&#123;<span class="keyword">var</span> a=r[t];a.<span class="property">enumerable</span>=a.<span class="property">enumerable</span>||!<span class="number">1</span>,a.<span class="property">configurable</span>=!<span class="number">0</span>,<span class="string">&quot;value&quot;</span><span class="keyword">in</span> a&amp;&amp;(a.<span class="property">writable</span>=!<span class="number">0</span>),<span class="title class_">Object</span>.<span class="title function_">defineProperty</span>(e,a.<span class="property">key</span>,a)&#125;&#125;<span class="keyword">function</span> <span class="title function_">_createClass</span>(<span class="params">e,r,t</span>)&#123;<span class="keyword">return</span> r&amp;&amp;<span class="title function_">_defineProperties</span>(e.<span class="property"><span class="keyword">prototype</span></span>,r),t&amp;&amp;<span class="title function_">_defineProperties</span>(e,t),e&#125;<span class="keyword">var</span> config=&#123;<span class="attr">src</span>:<span class="string">&quot;https://npm.elemecdn.com/guli-heo/others/open-peeps-sheet.png&quot;</span>,<span class="attr">rows</span>:<span class="number">15</span>,<span class="attr">cols</span>:<span class="number">7</span>&#125;,randomRange=<span class="keyword">function</span>(<span class="params">e,r</span>)&#123;<span class="keyword">return</span> e+<span class="title class_">Math</span>.<span class="title function_">random</span>()*(r-e)&#125;,randomIndex=<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="keyword">return</span> <span class="number">0</span>|<span class="title function_">randomRange</span>(<span class="number">0</span>,e.<span class="property">length</span>)&#125;,removeFromArray=<span class="keyword">function</span>(<span class="params">e,r</span>)&#123;<span class="keyword">return</span> e.<span class="title function_">splice</span>(r,<span class="number">1</span>)[<span class="number">0</span>]&#125;,removeItemFromArray=<span class="keyword">function</span>(<span class="params">e,r</span>)&#123;<span class="keyword">return</span> <span class="title function_">removeFromArray</span>(e,e.<span class="title function_">indexOf</span>(r))&#125;,removeRandomFromArray=<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="keyword">return</span> <span class="title function_">removeFromArray</span>(e,<span class="title function_">randomIndex</span>(e))&#125;,getRandomFromArray=<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="keyword">return</span> e[<span class="number">0</span>|<span class="title function_">randomIndex</span>(e)]&#125;,resetPeep=<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="keyword">var</span> r,t,a=e.<span class="property">stage</span>,n=e.<span class="property">peep</span>,o=<span class="number">.5</span>&lt;<span class="title class_">Math</span>.<span class="title function_">random</span>()?<span class="number">1</span>:-<span class="number">1</span>,i=<span class="number">100</span>-<span class="number">250</span>*gsap.<span class="title function_">parseEase</span>(<span class="string">&quot;power2.in&quot;</span>)(<span class="title class_">Math</span>.<span class="title function_">random</span>()),s=a.<span class="property">height</span>-n.<span class="property">height</span>+i;<span class="keyword">return</span> <span class="number">1</span>==o?(r=-n.<span class="property">width</span>,t=a.<span class="property">width</span>,n.<span class="property">scaleX</span>=<span class="number">1</span>):(r=a.<span class="property">width</span>+n.<span class="property">width</span>,t=<span class="number">0</span>,n.<span class="property">scaleX</span>=-<span class="number">1</span>),n.<span class="property">x</span>=r,n.<span class="property">y</span>=s,&#123;<span class="attr">startX</span>:r,<span class="attr">startY</span>:n.<span class="property">anchorY</span>=s,<span class="attr">endX</span>:t&#125;&#125;,normalWalk=<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="keyword">var</span> r=e.<span class="property">peep</span>,t=e.<span class="property">props</span>,a=(t.<span class="property">startX</span>,t.<span class="property">startY</span>),n=t.<span class="property">endX</span>,o=gsap.<span class="title function_">timeline</span>();<span class="keyword">return</span> o.<span class="title function_">timeScale</span>(<span class="title function_">randomRange</span>(<span class="number">.5</span>,<span class="number">1.5</span>)),o.<span class="title function_">to</span>(r,&#123;<span class="attr">duration</span>:<span class="number">10</span>,<span class="attr">x</span>:n,<span class="attr">ease</span>:<span class="string">&quot;none&quot;</span>&#125;,<span class="number">0</span>),o.<span class="title function_">to</span>(r,&#123;<span class="attr">duration</span>:<span class="number">.25</span>,<span class="attr">repeat</span>:<span class="number">40</span>,<span class="attr">yoyo</span>:!<span class="number">0</span>,<span class="attr">y</span>:a-<span class="number">10</span>&#125;,<span class="number">0</span>),o&#125;,walks=[normalWalk],<span class="title class_">Peep</span>=<span class="keyword">function</span>(<span class="params"></span>)&#123;<span class="keyword">function</span> <span class="title function_">a</span>(<span class="params">e</span>)&#123;<span class="keyword">var</span> r=e.<span class="property">image</span>,t=e.<span class="property">rect</span>;<span class="title function_">_classCallCheck</span>(<span class="variable language_">this</span>,a),<span class="variable language_">this</span>.<span class="property">image</span>=r,<span class="variable language_">this</span>.<span class="title function_">setRect</span>(t),<span class="variable language_">this</span>.<span class="property">x</span>=<span class="number">0</span>,<span class="variable language_">this</span>.<span class="property">y</span>=<span class="number">0</span>,<span class="variable language_">this</span>.<span class="property">anchorY</span>=<span class="number">0</span>,<span class="variable language_">this</span>.<span class="property">scaleX</span>=<span class="number">1</span>,<span class="variable language_">this</span>.<span class="property">walk</span>=<span class="literal">null</span>&#125;<span class="keyword">return</span> <span class="title function_">_createClass</span>(a,[&#123;<span class="attr">key</span>:<span class="string">&quot;setRect&quot;</span>,<span class="attr">value</span>:<span class="keyword">function</span>(<span class="params">e</span>)&#123;<span class="variable language_">this</span>.<span class="property">rect</span>=e,<span class="variable language_">this</span>.<span class="property">width</span>=e[<span class="number">2</span>],<span class="variable language_">this</span>.<span class="property">height</span>=e[<span class="number">3</span>],<span class="variable language_">this</span>.<span class="property">drawArgs</span>=[<span class="variable language_">this</span>.<span class="property">image</span>].<span class="title function_">concat</span>(<span class="title function_">_toConsumableArray</span>(e),[<span class="number">0</span>,<span class="number">0</span>,<span class="variable language_">this</span>.<span class="property">width</span>,<span class="variable language_">this</span>.<span class="property">height</span>])&#125;&#125;,&#123;<span class="attr">key</span>:<span class="string">&quot;render&quot;</span>,<span class="attr">value</span>:<span class="keyword">function</span>(<span class="params">e</span>)&#123;e.<span class="title function_">save</span>(),e.<span class="title function_">translate</span>(<span class="variable language_">this</span>.<span class="property">x</span>,<span class="variable language_">this</span>.<span class="property">y</span>),e.<span class="title function_">scale</span>(<span class="variable language_">this</span>.<span class="property">scaleX</span>,<span class="number">1</span>),e.<span class="property">drawImage</span>.<span class="title function_">apply</span>(e,<span class="title function_">_toConsumableArray</span>(<span class="variable language_">this</span>.<span class="property">drawArgs</span>)),e.<span class="title function_">restore</span>()&#125;&#125;]),a&#125;(),img=<span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&quot;img&quot;</span>);img.<span class="property">onload</span>=init,img.<span class="property">src</span>=config.<span class="property">src</span>;<span class="keyword">var</span> canvas=<span class="variable language_">document</span>.<span class="title function_">querySelector</span>(<span class="string">&quot;#canvas&quot;</span>),ctx=canvas.<span class="title function_">getContext</span>(<span class="string">&quot;2d&quot;</span>),stage=&#123;<span class="attr">width</span>:<span class="number">0</span>,<span class="attr">height</span>:<span class="number">0</span>&#125;,allPeeps=[],availablePeeps=[],crowd=[];<span class="keyword">function</span> <span class="title function_">init</span>(<span class="params"></span>)&#123;<span class="title function_">createPeeps</span>(),<span class="title function_">resize</span>(),gsap.<span class="property">ticker</span>.<span class="title function_">add</span>(render),<span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">&quot;resize&quot;</span>,resize)&#125;<span class="keyword">function</span> <span class="title function_">createPeeps</span>(<span class="params"></span>)&#123;<span class="keyword">for</span>(<span class="keyword">var</span> e=config.<span class="property">rows</span>,r=config.<span class="property">cols</span>,t=e*r,a=img.<span class="property">naturalWidth</span>/e,n=img.<span class="property">naturalHeight</span>/r,o=<span class="number">0</span>;o&lt;t;o++)allPeeps.<span class="title function_">push</span>(<span class="keyword">new</span> <span class="title class_">Peep</span>(&#123;<span class="attr">image</span>:img,<span class="attr">rect</span>:[o%e*a,(o/e|<span class="number">0</span>)*n,a,n]&#125;))&#125;<span class="keyword">function</span> <span class="title function_">resize</span>(<span class="params"></span>)&#123;stage.<span class="property">width</span>=canvas.<span class="property">clientWidth</span>,stage.<span class="property">height</span>=canvas.<span class="property">clientHeight</span>,canvas.<span class="property">width</span>=stage.<span class="property">width</span>*devicePixelRatio,canvas.<span class="property">height</span>=stage.<span class="property">height</span>*devicePixelRatio,crowd.<span class="title function_">forEach</span>(<span class="keyword">function</span>(<span class="params">e</span>)&#123;e.<span class="property">walk</span>.<span class="title function_">kill</span>()&#125;),crowd.<span class="property">length</span>=<span class="number">0</span>,availablePeeps.<span class="property">length</span>=<span class="number">0</span>,availablePeeps.<span class="property">push</span>.<span class="title function_">apply</span>(availablePeeps,allPeeps),<span class="title function_">initCrowd</span>()&#125;<span class="keyword">function</span> <span class="title function_">initCrowd</span>(<span class="params"></span>)&#123;<span class="keyword">for</span>(;availablePeeps.<span class="property">length</span>;)<span class="title function_">addPeepToCrowd</span>().<span class="property">walk</span>.<span class="title function_">progress</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>())&#125;<span class="keyword">function</span> <span class="title function_">addPeepToCrowd</span>(<span class="params"></span>)&#123;<span class="keyword">var</span> e=<span class="title function_">removeRandomFromArray</span>(availablePeeps),r=<span class="title function_">getRandomFromArray</span>(walks)(&#123;<span class="attr">peep</span>:e,<span class="attr">props</span>:<span class="title function_">resetPeep</span>(&#123;<span class="attr">peep</span>:e,<span class="attr">stage</span>:stage&#125;)&#125;).<span class="title function_">eventCallback</span>(<span class="string">&quot;onComplete&quot;</span>,<span class="keyword">function</span>(<span class="params"></span>)&#123;<span class="title function_">removePeepFromCrowd</span>(e),<span class="title function_">addPeepToCrowd</span>()&#125;);<span class="keyword">return</span> e.<span class="property">walk</span>=r,crowd.<span class="title function_">push</span>(e),crowd.<span class="title function_">sort</span>(<span class="keyword">function</span>(<span class="params">e,r</span>)&#123;<span class="keyword">return</span> e.<span class="property">anchorY</span>-r.<span class="property">anchorY</span>&#125;),e&#125;<span class="keyword">function</span> <span class="title function_">removePeepFromCrowd</span>(<span class="params">e</span>)&#123;<span class="title function_">removeItemFromArray</span>(crowd,e),availablePeeps.<span class="title function_">push</span>(e)&#125;<span class="keyword">function</span> <span class="title function_">render</span>(<span class="params"></span>)&#123;canvas.<span class="property">width</span>=canvas.<span class="property">width</span>,ctx.<span class="title function_">save</span>(),ctx.<span class="title function_">scale</span>(devicePixelRatio,devicePixelRatio),crowd.<span class="title function_">forEach</span>(<span class="keyword">function</span>(<span class="params">e</span>)&#123;e.<span class="title function_">render</span>(ctx)&#125;),ctx.<span class="title function_">restore</span>()&#125;</span><br></pre></td></tr></table></figure><h1>5. 参考文章</h1><p><a href="https://blog.zhheo.com/">张洪Heo - 分享设计与科技生活</a><br><a href="https://hassanwong.top/posts/9d49f75f/#%E9%A6%96%E9%A1%B5%E7%BD%AE%E9%A1%B6%E6%96%87%E7%AB%A0%E8%BD%AE%E6%92%AD%E7%BB%84%E4%BB%B6">Butterfly主题美化魔改集锦 | Hassan’s Blog</a></p>]]></content>
    
    
    <summary type="html">为 Butterfly 主题首页添加顶部轮播图与文章推荐卡片，附完整源码与配置步骤。</summary>
    
    
    
    <category term="经验分享" scheme="https://blog.xiemingjie.cn/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Hexo" scheme="https://blog.xiemingjie.cn/tags/Hexo/"/>
    
    <category term="前端开发" scheme="https://blog.xiemingjie.cn/tags/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    
    <category term="主题美化" scheme="https://blog.xiemingjie.cn/tags/%E4%B8%BB%E9%A2%98%E7%BE%8E%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>我的项目 | Hexo 视频点播页面</title>
    <link href="https://blog.xiemingjie.cn/posts/7127424c.html"/>
    <id>https://blog.xiemingjie.cn/posts/7127424c.html</id>
    <published>2022-05-04T02:26:47.000Z</published>
    <updated>2022-05-04T02:26:47.000Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>之前考虑到自己剪了一些vlog，但是直接用<code>iframe</code>嵌入的话页面会很长，而且点开这个页面会自动加载全部视频，感觉很奇怪，并且不能很好的展示，于是写了一个视频点播页面</p></blockquote><h2 id="1-新建路径页面">1. 新建路径页面</h2><p>首先使用命令新建一个页面：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">hexo new page video</span><br></pre></td></tr></table></figure><p>在<code>index.md</code>里面写入一下内容：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: 我的视频</span><br><span class="line">date: 2020-07-17 20:54:09</span><br><span class="line">comment: true</span><br><span class="line">top_img: false</span><br><span class="line">showToc: true</span><br><span class="line">aside: false</span><br><span class="line">type: &quot;video&quot;</span><br><span class="line">---</span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span> <span class="attr">src</span>=<span class="string">&quot;https://unpkg.com/jquery@latest/dist/jquery.min.js&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"><span class="keyword">function</span> <span class="title function_">selectVideo</span>(<span class="params">id</span>)&#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> src=$(<span class="string">&quot;#video-item-&quot;</span>+id).<span class="title function_">attr</span>(<span class="string">&quot;data-src&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">    $(<span class="string">&quot;#video-select&quot;</span>).<span class="title function_">html</span>(<span class="string">&quot;&lt;iframe id=&#x27;video-iframe&#x27; src=&#x27;&quot;</span>+src+<span class="string">&quot;&#x27; scrolling=&#x27;no&#x27; border=&#x27;0&#x27; frameborder=&#x27;no&#x27; framespacing=&#x27;0&#x27; allowfullscreen=&#x27;true&#x27;&gt; &lt;/iframe&gt;&quot;</span>);</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">var</span> iframe = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&quot;video-select&quot;</span>)</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">if</span>(iframe.<span class="property">attachEvent</span>)&#123;</span></span><br><span class="line"><span class="language-javascript">      iframe.<span class="title function_">attachEvent</span>(<span class="string">&quot;onreadystatechange&quot;</span>, <span class="keyword">function</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">if</span> (iframe.<span class="property">readyState</span> === <span class="string">&quot;complete&quot;</span> || iframe.<span class="property">readyState</span> == <span class="string">&quot;loaded&quot;</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          iframe.<span class="title function_">detachEvent</span>(<span class="string">&quot;onreadystatechange&quot;</span>, <span class="variable language_">arguments</span>.<span class="property">callee</span>);</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&#x27;video-mirror&#x27;</span>).<span class="property">length</span>&gt;<span class="number">0</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;1true&quot;</span>)</span></span><br><span class="line"><span class="language-javascript">          $(<span class="string">&quot;.video-mirror&quot;</span>).<span class="title function_">attr</span>(<span class="string">&quot;style&quot;</span>,<span class="string">&quot;transform:scaleX(-1);&quot;</span>)</span></span><br><span class="line"><span class="language-javascript">          &#125;</span></span><br><span class="line"><span class="language-javascript">        &#125;</span></span><br><span class="line"><span class="language-javascript">      &#125;);</span></span><br><span class="line"><span class="language-javascript">    &#125;<span class="keyword">else</span>&#123;</span></span><br><span class="line"><span class="language-javascript">      iframe.<span class="title function_">addEventListener</span>(<span class="string">&quot;load&quot;</span>, <span class="keyword">function</span>(<span class="params"></span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="title function_">removeEventListener</span>(<span class="string">&quot;load&quot;</span>, <span class="variable language_">arguments</span>.<span class="property">call</span>, <span class="literal">false</span>);</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="title function_">getElementsByClassName</span>(<span class="string">&#x27;video-mirror&#x27;</span>).<span class="property">length</span>&gt;<span class="number">0</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;2true&quot;</span>)</span></span><br><span class="line"><span class="language-javascript">        $(<span class="string">&quot;.video-mirror&quot;</span>).<span class="title function_">attr</span>(<span class="string">&quot;style&quot;</span>,<span class="string">&quot;transform:scaleX(-1);&quot;</span>)</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">      &#125;, <span class="literal">false</span>);</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">&#125;</span></span><br><span class="line"><span class="language-javascript">$(<span class="variable language_">document</span>).<span class="title function_">ready</span>(<span class="title function_">selectVideo</span>(<span class="number">0</span>));</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="2-新建主题页面">2. 新建主题页面</h2><p>在主题路径<code>themes\butterfly-dev\layout\includes\page</code>下新建<code>video.pug</code>：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br></pre></td><td class="code"><pre><span class="line">//if top_img === false</span><br><span class="line">//  h1.page-title= page.title</span><br><span class="line">#video-select.video-select</span><br><span class="line">hr</span><br><span class="line">h3= 视频列表</span><br><span class="line">.videos</span><br><span class="line">  if site.data.video</span><br><span class="line">    each i,index in site.data.video</span><br><span class="line">      div(class=&quot;myvideo&quot; onclick=`javascipt:selectVideo(`+index+`)`)</span><br><span class="line">        div(id=`video-item-`+index class=&quot;video-item&quot; data-src=url_for(i.link))</span><br><span class="line">          a(href=&quot;#video-select&quot;)</span><br><span class="line">            img.video-item-cover(src=url_for(i.cover))</span><br><span class="line">        .video-desc</span><br><span class="line">          .video-title</span><br><span class="line">            a(href=&quot;#video-select&quot;)= i.title</span><br><span class="line">          .video-info= i.description</span><br><span class="line"></span><br><span class="line">style.</span><br><span class="line">  .videos&#123;</span><br><span class="line">    display: grid;</span><br><span class="line">    grid-template-columns: repeat(4, 1fr);</span><br><span class="line">    grid-column-gap: 20px;</span><br><span class="line">    grid-row-gap: 20px;</span><br><span class="line">  &#125;</span><br><span class="line">  @media screen and (max-width: 1200px)&#123;</span><br><span class="line">    .videos&#123;</span><br><span class="line">      display: grid;</span><br><span class="line">      grid-template-columns: repeat(3, 1fr);</span><br><span class="line">      grid-column-gap: 20px;</span><br><span class="line">      grid-row-gap: 20px;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  @media screen and (max-width: 900px)&#123;</span><br><span class="line">    .videos&#123;</span><br><span class="line">      display: grid;</span><br><span class="line">      grid-template-columns: repeat(2, 1fr);</span><br><span class="line">      grid-column-gap: 20px;</span><br><span class="line">      grid-row-gap: 20px;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  @media screen and (max-width: 600px)&#123;</span><br><span class="line">    .videos&#123;</span><br><span class="line">      display: grid;</span><br><span class="line">      grid-template-columns: repeat(1, 1fr);</span><br><span class="line">      grid-column-gap: 20px;</span><br><span class="line">      grid-row-gap: 20px;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  .myvideo&#123;</span><br><span class="line">    position: relative;</span><br><span class="line">    width: 100%;</span><br><span class="line">    border: 1px solid var(--mj-card-border);</span><br><span class="line">    border-radius: 12px;</span><br><span class="line">  &#125;</span><br><span class="line">  .video-item&#123;</span><br><span class="line">    overflow: hidden;</span><br><span class="line">    height: 160px;</span><br><span class="line">    border-top-left-radius: 12px;</span><br><span class="line">    border-top-right-radius: 12px;</span><br><span class="line">  &#125;</span><br><span class="line">  .video-item img &#123;</span><br><span class="line">    position: relative;</span><br><span class="line">    width: 100%;</span><br><span class="line">    margin: 0 !important;</span><br><span class="line">    height: 100%;</span><br><span class="line">    transform: scale(1.0);</span><br><span class="line">    transition: .3s;</span><br><span class="line">    object-fit: cover;</span><br><span class="line">  &#125;</span><br><span class="line">  .myvideo:hover .video-item img &#123;</span><br><span class="line">    transition: .3s;</span><br><span class="line">    transform: scale(1.1);</span><br><span class="line">  &#125;</span><br><span class="line">  .video-title&#123;</span><br><span class="line">    padding: 5px 10px;</span><br><span class="line">    font-size: 18px;</span><br><span class="line">    font-weight: bold;</span><br><span class="line">  &#125;</span><br><span class="line">  .video-info&#123;</span><br><span class="line">    font-size: 14px;</span><br><span class="line">    padding: 0 10px;</span><br><span class="line">    color: var(--mj-secondtext);</span><br><span class="line">  &#125;</span><br><span class="line">  .video-select&#123;</span><br><span class="line">    position:relative;</span><br><span class="line">    width:100%;</span><br><span class="line">    height:0;</span><br><span class="line">    padding-bottom:75%;</span><br><span class="line">  &#125;</span><br><span class="line">  .video-select iframe&#123;</span><br><span class="line">    position:absolute;</span><br><span class="line">    width:100%;</span><br><span class="line">    height:100%;</span><br><span class="line">    left:0;</span><br><span class="line">    top:0;</span><br><span class="line">    border-radius: 12px;</span><br><span class="line">  &#125;</span><br><span class="line">!= page.content</span><br></pre></td></tr></table></figure><h2 id="3-注册video页面">3. 注册video页面</h2><p>在主题路径<code>butterfly/layout/</code>的<code>page.pug</code>文件中注册上述页面模板：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">extends includes/layout.pug</span><br><span class="line"></span><br><span class="line">block content</span><br><span class="line">  #page</span><br><span class="line">    if top_img === false</span><br><span class="line">      h1.page-title= page.title</span><br><span class="line"></span><br><span class="line">    case page.type</span><br><span class="line">      when &#x27;tags&#x27;</span><br><span class="line">        include includes/page/tags.pug</span><br><span class="line">      when &#x27;link&#x27;</span><br><span class="line">        include includes/page/flink.pug</span><br><span class="line">      when &#x27;categories&#x27;</span><br><span class="line">        include includes/page/categories.pug</span><br><span class="line">+     when &#x27;video&#x27;</span><br><span class="line">+       include includes/page/video.pug</span><br><span class="line">      default</span><br><span class="line">        include includes/page/default-page.pug</span><br><span class="line"></span><br><span class="line">    if page.comments !== false &amp;&amp; theme.comments &amp;&amp; theme.comments.use</span><br><span class="line">      - var commentsJsLoad = true</span><br><span class="line">      !=partial(&#x27;includes/third-party/comments/index&#x27;, &#123;&#125;, &#123;cache: true&#125;)</span><br></pre></td></tr></table></figure><h2 id="4-获取B站等平台视频嵌入代码">4. 获取B站等平台视频嵌入代码</h2><p>在视频播放页面通常会有分享按钮，并且一般会提供链接和<code>iframe</code>嵌入两种分享方式，例如我的（顺便求一波<a href="https://www.bilibili.com/video/BV18T4y1D7wj?zw">关注</a>）：<br><img src="https://npm.elemecdn.com/justlovesmile-img/20220504105540.png" alt=""></p><p>复制<code>iframe</code>代码，如下：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">iframe</span> <span class="attr">src</span>=<span class="string">&quot;//player.bilibili.com/player.html?aid=937145035&amp;bvid=BV18T4y1D7wj&amp;cid=545915013&amp;page=1&quot;</span> <span class="attr">scrolling</span>=<span class="string">&quot;no&quot;</span> <span class="attr">border</span>=<span class="string">&quot;0&quot;</span> <span class="attr">frameborder</span>=<span class="string">&quot;no&quot;</span> <span class="attr">framespacing</span>=<span class="string">&quot;0&quot;</span> <span class="attr">allowfullscreen</span>=<span class="string">&quot;true&quot;</span>&gt;</span> <span class="tag">&lt;/<span class="name">iframe</span>&gt;</span></span><br></pre></td></tr></table></figure><h2 id="5-新建data文件">5. 新建data文件</h2><p>在<code>hexo\source\_data</code>路径下(没有就创建一个文件夹)新建一个数据文件<code>video.yml</code>，把刚才的<code>iframe</code>代码内容转换成：</p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">cover:</span> <span class="string">https://npm.elemecdn.com/justlovesmile-img/33f7ad7c55b5df1e5bdb6a6ea3eb35b.jpg</span></span><br><span class="line">  <span class="attr">time:</span> <span class="number">2022</span><span class="string">/03/10</span></span><br><span class="line">  <span class="attr">link:</span> <span class="string">//player.bilibili.com/player.html?aid=937145035&amp;bvid=BV18T4y1D7wj&amp;cid=545915013&amp;page=1</span></span><br><span class="line">  <span class="attr">title:</span> <span class="string">雷神池，璃月雷神前来报道</span></span><br><span class="line">  <span class="attr">description:</span> <span class="string">【原神】20220310</span></span><br></pre></td></tr></table></figure><h2 id="6-结语">6. 结语</h2><p>至此，一个视频点播页面就做好了，该方法适用于一切提供iframe嵌入的视频平台，页面展示如下：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220504110304.png" alt=""></p>]]></content>
    
    
    <summary type="html">我写了一个视频点播页面，避免 iframe 直接嵌入导致页面过长、自动加载全部视频的问题，本文完整记录实现过程。</summary>
    
    
    
    <category term="我的项目" scheme="https://blog.xiemingjie.cn/categories/%E6%88%91%E7%9A%84%E9%A1%B9%E7%9B%AE/"/>
    
    
    <category term="Hexo" scheme="https://blog.xiemingjie.cn/tags/Hexo/"/>
    
    <category term="前端开发" scheme="https://blog.xiemingjie.cn/tags/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    
    <category term="视频" scheme="https://blog.xiemingjie.cn/tags/%E8%A7%86%E9%A2%91/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | R3Det：特征精炼的单阶段旋转目标检测</title>
    <link href="https://blog.xiemingjie.cn/posts/809258ef.html"/>
    <id>https://blog.xiemingjie.cn/posts/809258ef.html</id>
    <published>2022-04-09T07:00:34.000Z</published>
    <updated>2022-04-09T07:00:34.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题： R3det: Refined single-stage detector with feature refinement for rotating object</p><blockquote><p>论文发表：AAAI 2021<br>论文链接：<a href="https://ojs.aaai.org/index.php/AAAI/article/view/16426/16233">https://ojs.aaai.org/index.php/AAAI/article/view/16426/16233</a><br>论文代码：<a href="https://github.com/Thinklab-SJTU/R3Det_Tensorflow">https://github.com/Thinklab-SJTU/R3Det_Tensorflow</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220322100025.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">@article&#123;yang2019r3det,</span><br><span class="line">  title=&#123;R3det: Refined single-stage detector with feature refinement for rotating object&#125;,</span><br><span class="line">  author=&#123;Yang, Xue and Liu, Qingqing and Yan, Junchi and Li, Ang and Zhang, Zhiqiang and Yu, Gang&#125;,</span><br><span class="line">  journal=&#123;arXiv preprint arXiv:1908.05612&#125;,</span><br><span class="line">  volume=&#123;2&#125;,</span><br><span class="line">  number=&#123;4&#125;,</span><br><span class="line">  pages=&#123;2&#125;,</span><br><span class="line">  year=&#123;2019&#125;,</span><br><span class="line">  publisher=&#123;Aug&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>2. 归纳总结</h1><table><thead><tr><th>标签</th><th>目的</th><th>方法</th><th>总结</th></tr></thead><tbody><tr><td>#遥感 #单阶段 #Anchor</td><td>针对单阶段精炼检测器特征未对齐的问题，提出了FRM模块</td><td>RRetinaNet Based,FRM,SkewIou</td><td>精炼</td></tr></tbody></table><h1>3. 问题背景</h1><p>作者称对于旋转目标检测存在三个挑战：</p><ul><li>大宽高比</li><li>密集排列</li><li>方向任意</li></ul><h1>4. 主要工作</h1><p>针对上述问题，作者提出了R3Det，其主要工作如下：</p><ul><li>progressive regression： 作者发现旋转框在密集场景下的能有较好的目标检测精度，而水平框能达到更好的召回率，因此使用了这两种形式的框进行组合，具体做法是第一阶段检测水平框，从而提升检测速度，提高召回率，第二阶段也就是精炼阶段（refinement stage）检测旋转框，以适应密集目标的检测。</li><li>feature refinement module：针对现有的单阶段refined detector，作者发现他们存在特征没对齐的问题，因此设计了一个特征精炼模块，使用特征插值来获取精炼的位置信息并重建特征图实现特征对齐，并且该模块还可以减少精炼边界框的数量，提升检测速度。</li><li>approximate SkewIoU loss：为解决Skew IoU计算不可微的问题，设计了一种近似SkewIoU损失，以获得更精确的旋转估计。</li></ul><h2 id="4-1-模型结构">4.1 模型结构</h2><p>R3Det主要基于 RetinaNet 实现，结构如下：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220322120220.png" alt=""></p><h2 id="4-2-边界框定义">4.2 边界框定义</h2><p>对于边界框$(x,y,w,h,\theta)$，其中x，y代表中心点坐标，w，h代表宽和高，$\theta \in [-\frac{\pi}{2},0)$代表角度，边界框回归的值为：<br><img src="https://npm.elemecdn.com/justlovesmile-img/20220323144748.png" alt=""></p><p>其中$x,x_a,x’$分别代表gt，anchor以及预测值，其余同上。</p><p>损失函数为：<br><img src="https://npm.elemecdn.com/justlovesmile-img/20220323144809.png" alt=""></p><p>其中$v’$为预测的偏移量向量，v代表gt的偏移量向量。其中N表示Anchor的数目,超参数 $\lambda_1$， $\lambda_2$ 控制着这两个损失的平衡，并且默认值为1。$L_{cls}$ 和 $L_{reg}$ 分别是Focal Loss和smooth L1 Loss。</p><h2 id="4-3-精炼检测">4.3 精炼检测</h2><p>Skew IoU对于角度十分敏感，因此作者在第一阶段使用0.5为前景阈值，0.4为背景阈值，在精炼的第一阶段使用0.6为前景阈值，0.5为背景阈值，如果有多段精炼阶段，使用0.7以及0.6为阈值。总损失：<br>$$L_{total}=\sum_{i=1}^N\alpha_iL_i$$<br>其中$L_i$为第i个精炼阶段的损失，$\alpha_i$为平衡系数，默认为1.</p><h2 id="4-4-特征精炼模块">4.4 特征精炼模块</h2><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220323154129.png" alt=""></p><p>许多精炼检测器仍然使用相同的特征图来执行多个分类和回归，而没有考虑边界框位置变化引起的特征未对齐。因此作者提出将当前精炼边界框(橙色矩形)的位置信息重新编码为对应的特征点(红色点)，从而以逐像素的方式<strong>重构整个特征图</strong>，实现<strong>特征对齐</strong>。整个过程如上图（c）所示。为了准确地获取精炼后的包围框对应的位置特征信息，采用了双线性特征插值方法，如上图（a）所示。特征插值可以表示为:<br><img src="https://npm.elemecdn.com/justlovesmile-img/20220323154551.png" alt=""><br>其中A代表图（a）中的区域，$F\in \mathbb{R}^{C\times 1\times 1}$代表特征图上点的特征向量。</p><p>算法流程：<br><img src="https://npm.elemecdn.com/justlovesmile-img/20220323154753.png" alt=""></p><h1>5. 实验结果</h1><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220323155610.png" alt=""></p>]]></content>
    
    
    <summary type="html">作者称对于旋转目标检测存在三个挑战：大宽高比；密集排列；方向任意，因此针对上述问题，作者提出了R3Det，其通过特征精炼模块解决了精炼过程中特征未对齐的问题...</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="旋转目标检测" scheme="https://blog.xiemingjie.cn/tags/%E6%97%8B%E8%BD%AC%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="特征精炼" scheme="https://blog.xiemingjie.cn/tags/%E7%89%B9%E5%BE%81%E7%B2%BE%E7%82%BC/"/>
    
  </entry>
  
  <entry>
    <title>网站公告 | 博客运行超过 1000 天啦</title>
    <link href="https://blog.xiemingjie.cn/posts/d90df99b.html"/>
    <id>https://blog.xiemingjie.cn/posts/d90df99b.html</id>
    <published>2022-04-08T06:18:58.000Z</published>
    <updated>2022-04-08T06:18:58.000Z</updated>
    
    <content type="html"><![CDATA[<p>就在刚刚，我在整理阅读笔记、准备发到博客上的时候，突然瞟到博客右下角的运行时间，惊喜地发现博客已经运行超过1000天啦，心中突然有一种又开心又欣慰的情绪在弥漫…</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408143144.png" alt=""></p><h2 id="从wordpress到hexo">从wordpress到hexo</h2><p>时间过得真快呀，我还记得自己第一次建立博客那天，刚考完期末考试，回到寝室，室友说他发现了一个特别好看的个人网站，我看着那个网站，心中萌发出我也要拥有一个自己的博客的想法，于是在当天我搜索了很多建立个人网站的教程，最后因为自己课设用过python的flask框架并且写过静态的HTML，于是决定在阿里云上购买了一个轻量应用服务器（学生有优惠），然后自己写一个博客网页，因此当时的博客非常简单（并且非常丑）。</p><p>直到假期里我看见知乎上有人推荐wordpress，并且也是可以直接在阿里云的轻量应用服务器上直接部署的，因此我果断的开始了wordpress的踩坑之旅，中途先后使用了多个wordpress官网推荐的主题，一直没有找到自己喜欢的，后来还是在知乎上，看见了<code>sakura</code>主题，非常的漂亮，并且封面图也很好看，如下：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408144439.png" alt=""></p><p>并且在部署的过程中，从作者的博客友链看到了很多大佬的博客，也是第一次知道了原来博客还有<a href="/friends/">友链</a>这种东西…</p><p>再到假期末尾，又是我的室友（还是他😂），他给我看了他的博客，虽然只有一个首页（就是Hexo默认的主题）我突然感觉好像也不错，而且他告诉我这个不用租服务器，我突然感觉自己好像打开了新世界的大门，原来还有Hexo这种静态博客生成器…</p><p>于是我又开始了Hexo的踩坑之旅，先后用过了<code>yilia</code>、<code>Sakura-Hexo</code>、<code>Ayer</code>、以及现在的<code>Butterfly</code>主题，他们都是非常优秀的主题，如下图：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408150617.png" alt=""></p><p>除了主题外，自己还添加又卸载了很多插件（如live2d，我用的是下面这个👇），最后发现还是简单实用比较适合我。</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408145334.png" alt=""></p><h2 id="域名-justlovesmile-top">域名:justlovesmile.top</h2><p>从2019年9月6日开始，我的博客终于有了自己的域名，而为什么要买这个域名呢，主要是因为我的游戏id基本上都是这个，比如：<code>Justlovesmile</code>，<code>Just微笑</code>，<code>Justlove微笑</code>等等.</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408152830.png" alt=""></p><h2 id="博客魔改">博客魔改</h2><p>直到换到<code>Butterfly</code>主题，我突然发现他能满足我绝大部分的需求，不仅适配了黑暗模式，各个模块也写的非常简单明了，非常适合魔改，并且在不同博客的友链中找啊看啊，发现了很多非常棒非常好看的博客，还加入了Butterfly主题的QQ群（后来因为我基本上不聊天所以被踢了qwq），认识了很多大佬，也从他们的博客学到了很多东西，得到了很多帮助，如<a href="https://blog.zhheo.com/">zhheo博主</a>、<a href="https://zfe.space/">小冰博主</a>、<a href="https://akilar.top/">Akilar博主</a>等等，因此我的友链中专门开了一个模块<s>保存</s>（供奉）着他们博客。</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408152000.png" alt=""></p><p>在看了很多<a href="/posts/c8972b63.html">博客魔改和优化</a>的文章以及自己一点一点<a href="/update/">修改</a>之后，我的博客现在是这个样子的：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408152620.png" alt=""></p><h2 id="博客统计">博客统计</h2><p>从2019年7月10日至今，博客总共发布了<a href="/archives/">文章</a>85篇，<a href="/tags/">标签</a>57个，<a href="/categories/">分类</a>6个，详细见<a href="/charts/">统计页面</a>：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408153407.png" alt=""></p><p>其中2019年24篇，2020年39篇，2021年8篇，2022年目前14篇：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408153707.png" alt=""></p><p>博客共有<a href="/friends/">友链</a>51个，<a href="/donate/">打赏</a>2次。</p><p>博客共有评论355条，也随时欢迎大家能在<a href="/guestbook/">留言板</a>中留言。</p><h2 id="结语">结语</h2><p>本文是纪念、也是总结，纪念这1000个日日夜夜在个人博客分享学习笔记或者主题美化的时光，总结我的博客这1000天的一些数据统计。希望在下一个1000天里我的博客能变得越来越好、越来越合我心意。</p>]]></content>
    
    
    <summary type="html">时间过得真快，不知不觉中Justlovesmile的博客已经运行超过1000天啦，我还记得自己第一次建立博客那天，刚考完期末考试，回到寝室，室友说他发现了一个特别好看的个人网站，我看着那个网站，心中萌发出我也要拥有一个自己的博客的想法。</summary>
    
    
    
    <category term="网站公告" scheme="https://blog.xiemingjie.cn/categories/%E7%BD%91%E7%AB%99%E5%85%AC%E5%91%8A/"/>
    
    
    <category term="博客历程" scheme="https://blog.xiemingjie.cn/tags/%E5%8D%9A%E5%AE%A2%E5%8E%86%E7%A8%8B/"/>
    
    <category term="随笔" scheme="https://blog.xiemingjie.cn/tags/%E9%9A%8F%E7%AC%94/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | FPN：多尺度目标检测经典结构</title>
    <link href="https://blog.xiemingjie.cn/posts/4c29d81e.html"/>
    <id>https://blog.xiemingjie.cn/posts/4c29d81e.html</id>
    <published>2022-04-08T04:46:28.000Z</published>
    <updated>2022-04-08T04:46:28.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题： Feature Pyramid Networks for Object Detection</p><blockquote><p>论文发表：CVPR2017<br>论文链接：<a href="http://openaccess.thecvf.com/content_cvpr_2017/html/Lin_Feature_Pyramid_Networks_CVPR_2017_paper.html">CVPR2017 open access</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408112206.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@inproceedings&#123;lin2017feature,</span><br><span class="line">  title=&#123;Feature pyramid networks for object detection&#125;,</span><br><span class="line">  author=&#123;Lin, Tsung-Yi and Doll&#123;\&#x27;a&#125;r, Piotr and Girshick, Ross and He, Kaiming and Hariharan, Bharath and Belongie, Serge&#125;,</span><br><span class="line">  booktitle=&#123;Proceedings of the IEEE conference on computer vision and pattern recognition&#125;,</span><br><span class="line">  pages=&#123;2117--2125&#125;,</span><br><span class="line">  year=&#123;2017&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>2. 归纳总结</h1><table><thead><tr><th>Name</th><th>Value</th></tr></thead><tbody><tr><td>标签</td><td>#多尺度</td></tr><tr><td>目的</td><td>针对目标检测任务中，目标尺度变化的问题，设计了特征金字塔网络</td></tr><tr><td>方法</td><td>构建多层特征图之间的联系，合理利用高层语义信息和底层位置信息</td></tr><tr><td>总结</td><td>是目标检测模型的标配，较好地解决了多尺度检测问题</td></tr></tbody></table><h1>3. 问题背景</h1><p>作者提到，在2017年以前，目标检测中的一个基本挑战就是目标检测模型在处理目标多尺度变化问题的不足，因为在当时很多网络都使用了利用单个高层特征，(比如说Faster R-CNN利用下采样四倍的卷积层——Conv4，进行后续的物体的分类和bounding box的回归)，但是这样做有一个明显的缺陷，即小物体本身具有的像素信息较少，在下采样的过程中极易被丢失，而之前的图像金字塔结构虽然也能解决多尺度问题，但计算量大，内存消耗大，因此作者提出了特征金字塔结构，能在增加极小的计算量的情况下，处理好物体检测中的多尺度变化问题。</p><h1>4. 主要工作</h1><p>针对上述问题，作者提出了一个利用深度卷积神经网络固有的多尺度金字塔结构、以极小的计算量构建特征金字塔的网络结构，即 FPN。</p><h2 id="4-1-模型结构">4.1 模型结构</h2><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408115456.png" alt=""><br>作者对比了多种金字塔结构，其中：</p><ul><li>图（a）所示的是经典的图像金字塔结构，其通过对不同尺度的图像提取特征，来构建特征金字塔，因此其需要对不同尺度图像分别提取特征，计算量大且消耗内存多；</li><li>图（b）所示的是2017年常见的利用最后一层（高层）特征图检测目标的模型结构，其对于多尺度目标的检测能力不足；</li><li>图（c）是一种利用卷积神经网络固有的多尺度特征图构建的多尺度检测模型（如SSD），但是其没有结合高层语义信息和底层位置信息，因此检测精度一般；</li><li>图（d）即FPN结构，是一种具有侧向连接（lateral connections）的自上而下的网络结构，用来构建不同尺寸的具有高级语义信息的特征图，并且很好的利用了不同层特征的信息。</li></ul><p>下图是FPN的网络结构：<br><img src="https://npm.elemecdn.com/justlovesmile-img/20220408120130.png" alt=""></p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408122428.png" alt=""></p><p>其主要包含两个部分：</p><ul><li>自下而上的特征提取：即常规的前馈Backbone网络，以Faster R-CNN为例，假设选择ResNet每级最后一个Residual Block的输出，记为{C1,C2,C3,C4,C5}，那么FPN用2-5级参与预测，其中C2, C3, C4, C5表示conv2，conv3，conv4和conv5的输出层(最后一个残差block层)作为FPN的特征，分别对应于输入图片的下采样倍数为{4，8，16，32}。</li><li>自上而下的特征融合以及横向连接：即将高层的语义信息和本层的细节信息相融合。自上而下的过程通过上采样（Up-Sampling）实现，上采样的方法是<strong>最近邻插值法</strong>，如下图所示。具体过程为：C5层先经过1 x 1卷积，改变特征图的通道数(文章中设置d=256，与Faster R-CNN中RPN层的维数相同便于分类与回归)。然后通过上采样，再加上(特征图中每一个相同位置元素直接相加)C4经过1 x 1卷积后的特征图M4（固定通道256）。这个过程再做两次，分别得到C3对应的特征图M3（固定通道256）以及C2对应的特征图M2（固定通道256）。M层特征图再经过3 x 3卷积(减轻最近邻近插值带来的混叠影响，周围的数都相同)，得到最终的P2，P3，P4，P5层特征。</li></ul><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408122814.png" alt=""><br>图片来自<a href="https://zhuanlan.zhihu.com/p/92005927">【论文笔记】FPN —— 特征金字塔 - 知乎 (zhihu.com)</a></p><h2 id="4-2-代码">4.2 代码</h2><p>可参考Pytorch官方的代码<a href="https://github.com/pytorch/vision">https://github.com/pytorch/vision</a></p><h1>5. 实验结果</h1><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220408123357.png" alt=""></p><h1>6. 参考文献</h1><p><a href="https://zhuanlan.zhihu.com/p/92005927">【论文笔记】FPN —— 特征金字塔 - 知乎 (zhihu.com)</a></p>]]></content>
    
    
    <summary type="html">在2017年以前，目标检测中的一个基本挑战就是目标检测模型在处理目标多尺度变化问题的不足，因为在当时很多网络都使用了利用单个高层特征，而图像金字塔结构虽然也能解决多尺度问题，但计算量大，内存消耗大，因此作者提出了FPN结构。</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="目标检测" scheme="https://blog.xiemingjie.cn/tags/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="多尺度特征" scheme="https://blog.xiemingjie.cn/tags/%E5%A4%9A%E5%B0%BA%E5%BA%A6%E7%89%B9%E5%BE%81/"/>
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | ProtoNet：基于度量的少样本分类</title>
    <link href="https://blog.xiemingjie.cn/posts/286eabe4.html"/>
    <id>https://blog.xiemingjie.cn/posts/286eabe4.html</id>
    <published>2022-04-02T04:20:34.000Z</published>
    <updated>2022-04-02T04:20:34.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题：Prototypical Networks for Few-shot Learning</p><blockquote><p>论文发表：Advances in neural information processing systems, 2017<br>论文链接：<a href="https://proceedings.neurips.cc/paper/6996-prototypical-networks-for-few-shot-learning">https://proceedings.neurips.cc/paper/6996-prototypical-networks-for-few-shot-learning</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-img/image-20211202215720417.png" alt="image-20211202215720417"></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@article&#123;snell2017prototypical,</span><br><span class="line">  title=&#123;Prototypical networks for few-shot learning&#125;,</span><br><span class="line">  author=&#123;Snell, Jake and Swersky, Kevin and Zemel, Richard&#125;,</span><br><span class="line">  journal=&#123;Advances in neural information processing systems&#125;,</span><br><span class="line">  volume=&#123;30&#125;,</span><br><span class="line">  year=&#123;2017&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>2. 归纳总结</h1><table><thead><tr><th>标签</th><th>目的</th><th>方法</th><th>总结</th></tr></thead><tbody><tr><td>#度量学习 #嵌入网络</td><td>解决小样本问题</td><td>学习一个低纬嵌入空间</td><td>将分类问题转换成度量问题</td></tr></tbody></table><h1>3. 主要工作</h1><p>ProtoNet，即原型网络，其想法非常直接但有效，即对每张图像都先用神经网络得到一个特征表示，然后对支持集中每个类别的所有特征取一个平均，作为这个类别的类中心，最后比较查询集和各个类中心之间的距离，取最近的一个类别作为预测结果。</p><p>作者的思想是构建一个映射函数，可以将每一类映射到一个简单的原型特征点集中。因此作者使用神经网络学习了一个非线性映射，将输入映射到嵌入空间中，并且规定每一类的原型特征为每个嵌入空间的均值。之后就可以将分类任务看作是在嵌入空间中寻找距离最近的原型特征。</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/202110071602172.png" alt="image-20211007160201702">定义样本为S，类别为k，原型特征为$c_k=\frac{1}{S_k}\sum_{(x_i,y_i)\in{S_k}}f_{\phi}(x_i)$，衡量距离的函数为d，那么对于输入样本，其在嵌入空间的分布为$p_\phi(y=k|x)=\frac{\exp(-d(f_\phi(x),c_k))}{\sum_{k^\prime}\exp(-d(f_\phi(x),c_{k^{\prime}}))}$，学习的过程就是最小化负对数损失$J(\phi)=-\log{p_\phi(y=k|x)}$。</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/202110271603163.png" alt="image-20211027160339284"></p><h1>4. 实验结果</h1><p>其实验结果如下：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/image-20211202220308120.png" alt="image-20211202220308120"></p><p><img src="https://npm.elemecdn.com/justlovesmile-img/image-20211202220326742.png" alt="image-20211202220326742"></p>]]></content>
    
    
    <summary type="html">ProtoNet，即原型网络，其想法非常直接但有效，即对每张图像都先用神经网络得到一个特征表示，然后对支持集中每个类别的所有特征取一个平均，作为这个类别的类中心，最后比较查询集和各个类中心之间的距离，取最近的一个类别作为预测结果。</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="小样本学习" scheme="https://blog.xiemingjie.cn/tags/%E5%B0%8F%E6%A0%B7%E6%9C%AC%E5%AD%A6%E4%B9%A0/"/>
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="度量学习" scheme="https://blog.xiemingjie.cn/tags/%E5%BA%A6%E9%87%8F%E5%AD%A6%E4%B9%A0/"/>
    
  </entry>
  
  <entry>
    <title>网站公告 | 大学课程笔记归档</title>
    <link href="https://blog.xiemingjie.cn/posts/a806bebe.html"/>
    <id>https://blog.xiemingjie.cn/posts/a806bebe.html</id>
    <published>2022-03-31T11:03:19.000Z</published>
    <updated>2022-03-31T11:03:19.000Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>题外话：时光荏苒，青春在时间的河岸慢慢行走，不知不觉中，博主的大学生活渐行渐远，带走的是那四年青春的美好回忆，而留下的是那厚厚的、考试前兢兢业业记录下来的学习笔记，看着一篇篇动辄上W字数的笔记，脑海中还能会想起当时的场景。</p></blockquote><p>本文是博主本科期间的专业课程学习笔记的整理和归档，适合计算机专业的同学阅读。</p><h2 id="一、数据库原理">一、数据库原理</h2><ol><li><a href="/posts/41347.html">《数据库原理》笔记</a>，字数总计:18.3k，阅读时长:59分钟</li><li><a href="https://github.com/Justlovesmile/database_program">基于MYSQL的BBS论坛管理系统</a>，第一次接触Flask和前端，在自己电脑上做的数据库课设</li></ol><h2 id="二、软件工程基础">二、软件工程基础</h2><ol><li><a href="/posts/38368.html">《软件工程基础》知识点</a>，字数总计:5.9k，阅读时长:17分钟</li></ol><h2 id="三、计算机网络">三、计算机网络</h2><ol><li><a href="/posts/28758.html">《计算机网络》学习笔记</a>，字数总计:35.3k，阅读时长:108分钟</li></ol><h2 id="四、操作系统">四、操作系统</h2><ol><li><a href="/posts/8398.html">计算机《操作系统》笔记</a>，字数总计:20.1k，阅读时长:61分钟</li></ol><h2 id="五、编译原理">五、编译原理</h2><ol><li><a href="/posts/50753.html">《编译原理》知识点</a>，字数总计:4.5k，阅读时长:13分钟</li></ol><h2 id="六、算法分析与设计">六、算法分析与设计</h2><ol><li><a href="/posts/16050.html">《算法分析与设计》笔记</a>，字数总计:14k，阅读时长:62分钟，主要是动手敲敲代码，看看算法如何实现</li></ol><h2 id="七、计算机组成原理">七、计算机组成原理</h2><ol><li><a href="/posts/51917.html">《计算机组成原理》笔记</a>，字数总计:1.9k，阅读时长:5分钟，说实话这门课我没学好</li></ol><h2 id="八、计算机系统结构">八、计算机系统结构</h2><ol><li><a href="/posts/50754.html">《计算机系统结构》笔记</a>，字数总计:12k，阅读时长:35分钟</li><li><a href="/posts/651e6a0b.html">《计算机系统结构》精简知识点</a>，字数总计:8k，阅读时长:24分钟</li><li><a href="/posts/47699.html">基于WINDLX的系统结构实验</a>，字数总计:2.9k，阅读时长:10分钟，随机输入n个数，求数i的概率</li></ol><h2 id="九、计算机图形学">九、计算机图形学</h2><ol><li><a href="/posts/16593.html">基于MFC和二维变换的画图软件</a>，字数总计:4.2k，阅读时长:14分钟，基于MFC完成的一个画图软件，并且为了完成老师的要求，强行加了二维变换动画</li></ol><h2 id="十、嵌入式技术课程设计">十、嵌入式技术课程设计</h2><ol><li><a href="/posts/14495.html">嵌入式智能大棚监测管理系统</a>，字数总计:5.5k，阅读时长:17分钟，基于Proteus，Arduino，Flask搭建的智能大棚管理系统</li></ol><h2 id="十一、微机原理与接口技术">十一、微机原理与接口技术</h2><ol><li><a href="/posts/43666.html">《微机原理与接口技术》笔记</a>，字数总计:12.9k，阅读时长:41分钟，有一说一，这篇文章在CSDN阅读1w+是我没想到的</li></ol><blockquote><p>人生的长短不是时间衡量的，而是以思想和行为去衡量，且行且珍惜！</p></blockquote>]]></content>
    
    
    <summary type="html">博主的大学课程全部笔记整理归档，本文是一个目录...</summary>
    
    
    
    <category term="网站公告" scheme="https://blog.xiemingjie.cn/categories/%E7%BD%91%E7%AB%99%E5%85%AC%E5%91%8A/"/>
    
    
    <category term="大学课程" scheme="https://blog.xiemingjie.cn/tags/%E5%A4%A7%E5%AD%A6%E8%AF%BE%E7%A8%8B/"/>
    
    <category term="学习笔记" scheme="https://blog.xiemingjie.cn/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>经验分享 | 提取图片主题色自动选择标题字体颜色</title>
    <link href="https://blog.xiemingjie.cn/posts/b16c0eda.html"/>
    <id>https://blog.xiemingjie.cn/posts/b16c0eda.html</id>
    <published>2022-03-28T04:37:51.000Z</published>
    <updated>2022-03-28T04:37:51.000Z</updated>
    
    <content type="html"><![CDATA[<p>今天在写博客的时候，做了一个封面图，然后 <code>hexo cl &amp;&amp; hexo g &amp;&amp; gulp &amp;&amp; hexo s</code> 一键生成，点开后却发现标题的字体颜色亮瞎我的眼睛：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328124305.png" alt=""></p><p>于是试了很多帖子，终于把它改好了：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328124527.png" alt=""></p><p>提取主题色的js:<a href="https://github.com/briangonzalez/rgbaster.js">https://github.com/briangonzalez/rgbaster.js</a></p><p>处理配色js如下：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">if</span> (<span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;post-cover&#x27;</span>)) &#123;</span><br><span class="line">  <span class="keyword">const</span> img = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>(<span class="string">&#x27;post-cover&#x27;</span>).<span class="title function_">getAttribute</span>(<span class="string">&#x27;data-lazy-src&#x27;</span>)</span><br><span class="line">  <span class="title class_">RGBaster</span>.<span class="title function_">colors</span>(img, &#123;</span><br><span class="line">      <span class="attr">paletteSize</span>: <span class="number">30</span>,</span><br><span class="line">      <span class="attr">exclude</span>: [<span class="string">&quot;rgb(255,255,255)&quot;</span>, <span class="string">&quot;rgb(0,0,0)&quot;</span>, <span class="string">&quot;rgb(254,254,254)&quot;</span>],</span><br><span class="line">      <span class="attr">success</span>: <span class="keyword">function</span>(<span class="params">t</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (t.<span class="property">dominant</span> != <span class="string">&#x27;rgb()&#x27;</span>)&#123;</span><br><span class="line">          <span class="keyword">const</span> c = t.<span class="property">dominant</span>.<span class="title function_">match</span>(<span class="regexp">/\d+/g</span>);</span><br><span class="line">          <span class="keyword">const</span> <span class="title class_">Color</span> = <span class="string">`rgba(<span class="subst">$&#123;c[<span class="number">0</span>]&#125;</span>,<span class="subst">$&#123;c[<span class="number">1</span>]&#125;</span>,<span class="subst">$&#123;c[<span class="number">2</span>]&#125;</span>,0.8)`</span>;</span><br><span class="line">          <span class="keyword">let</span> fontColor;</span><br><span class="line">          <span class="comment">//const grayLevel = c[0] * 0.299 + c[1] * 0.587 + c[2] * 0.114;</span></span><br><span class="line">          <span class="keyword">const</span> grayLevel = c[<span class="number">0</span>] * <span class="number">0.213</span> + c[<span class="number">1</span>] * <span class="number">0.715</span> + c[<span class="number">2</span>] * <span class="number">0.072</span>;</span><br><span class="line">          <span class="comment">//if (grayLevel &gt;= 190) &#123;</span></span><br><span class="line">          <span class="keyword">if</span> (grayLevel &gt;= <span class="number">255</span>/<span class="number">2</span>) &#123;</span><br><span class="line">            <span class="comment">// 若为浅色，把文字设置为黑色</span></span><br><span class="line">            fontColor = <span class="string">&#x27;#000&#x27;</span>;</span><br><span class="line">            metaColor = <span class="string">&#x27;#1C1C1C&#x27;</span>;</span><br><span class="line">          &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            fontColor = <span class="string">&#x27;#fff&#x27;</span>;</span><br><span class="line">            metaColor = <span class="string">&#x27;#eee&#x27;</span>;</span><br><span class="line">          &#125;</span><br><span class="line">          <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-main:&quot;</span> + <span class="title class_">Color</span> + <span class="string">&quot;!important&quot;</span>)</span><br><span class="line">          <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-titlecolor:&quot;</span> + fontColor + <span class="string">&quot;!important&quot;</span>)</span><br><span class="line">          <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-metacolor:&quot;</span> + metaColor + <span class="string">&quot;!important&quot;</span>)</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">          <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-main: rgba(255,250,240,0.5) !important&quot;</span>)</span><br><span class="line">          <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-titlecolor: #000 !important&quot;</span>)</span><br><span class="line">          <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-metacolor: #1C1C1C !important&quot;</span>)</span><br><span class="line">        &#125;</span><br><span class="line">      &#125;,</span><br><span class="line">      <span class="attr">error</span>: <span class="keyword">function</span>(<span class="params"></span>) &#123;</span><br><span class="line">          <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-main: rgba(255,250,240,0.5) !important&quot;</span>)</span><br><span class="line">          <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-titlecolor: #000 !important&quot;</span>)</span><br><span class="line">          <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-metacolor: #1C1C1C !important&quot;</span>)</span><br><span class="line">      &#125;</span><br><span class="line">  &#125;)</span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">  <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-main: transparent !important&quot;</span>)</span><br><span class="line">  <span class="variable language_">document</span>.<span class="property">styleSheets</span>[<span class="number">0</span>].<span class="title function_">addRule</span>(<span class="string">&quot;:root&quot;</span>, <span class="string">&quot;--mj-titlecolor: var(--light-grey) !important&quot;</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>参考：</p><ul><li><a href="https://juejin.cn/post/6844903511956815885">https://juejin.cn/post/6844903511956815885</a></li><li><a href="https://blog.realwds.com/posts/84339efc.html">https://blog.realwds.com/posts/84339efc.html</a></li></ul>]]></content>
    
    
    <summary type="html">用 rgbaster.js 提取封面图主题色，并自动计算标题字体的明暗配色，告别封面图与文字颜色撞色的问题。</summary>
    
    
    
    <category term="经验分享" scheme="https://blog.xiemingjie.cn/categories/%E7%BB%8F%E9%AA%8C%E5%88%86%E4%BA%AB/"/>
    
    
    <category term="Hexo" scheme="https://blog.xiemingjie.cn/tags/Hexo/"/>
    
    <category term="前端开发" scheme="https://blog.xiemingjie.cn/tags/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/"/>
    
    <category term="主题美化" scheme="https://blog.xiemingjie.cn/tags/%E4%B8%BB%E9%A2%98%E7%BE%8E%E5%8C%96/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | YOLOv1：单阶段实时目标检测的开山之作</title>
    <link href="https://blog.xiemingjie.cn/posts/d50da5ec.html"/>
    <id>https://blog.xiemingjie.cn/posts/d50da5ec.html</id>
    <published>2022-03-28T03:57:51.000Z</published>
    <updated>2022-03-28T03:57:51.000Z</updated>
    
    <content type="html"><![CDATA[<blockquote><p>PS:参考YOLO官网的配色和logo做的封面图，感觉还挺好看的，hhhh</p></blockquote><h1>1. 论文信息</h1><p>论文标题：You Only Look Once: Unified, Real-Time Object Detection</p><blockquote><p>论文发表：CVPR 2016<br>论文链接：<a href="https://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/Redmon_You_Only_Look_CVPR_2016_paper.pdf">You Only Look Once: Unified, Real-Time Object Detection (cv-foundation.org)</a><br>论文官网：<a href="https://pjreddie.com/darknet/yolo/">YOLO: Real-Time Object Detection (pjreddie.com)</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-img/1648433292(1).png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">@inproceedings&#123;redmon2016you,</span><br><span class="line">  title=&#123;You only look once: Unified, real-time object detection&#125;,</span><br><span class="line">  author=&#123;Redmon, Joseph and Divvala, Santosh and Girshick, Ross and Farhadi, Ali&#125;,</span><br><span class="line">  booktitle=&#123;Proceedings of the IEEE conference on computer vision and pattern recognition&#125;,</span><br><span class="line">  pages=&#123;779--788&#125;,</span><br><span class="line">  year=&#123;2016&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>2. 归纳总结</h1><table><thead><tr><th>标签</th><th>目的</th><th>方法</th><th>总结</th></tr></thead><tbody><tr><td>#Anchor-Free</td><td>解决两阶段算法检测慢的问题</td><td>将目标检测（cls和reg）都视为回归问题</td><td>经典单阶段算法</td></tr></tbody></table><h1>3. 问题背景</h1><p>随着深度学习的大火，在YOLO提出那一年，主流的目标检测算法框架主要分为两类：</p><ul><li>两阶段算法：基于Region Proposal的RCNN系列算法，先生成Proposal，再分类回归</li><li>单阶段算法：直接预测不同目标的类别和位置<br>这两种算法各有优点，一般而言，两阶段算法准确度高，但速度慢；单阶段算法速度快，但准确度相对低。</li></ul><p>作者认为人可以一眼看到目标在哪，并且能立即知道是什么，并且对于很多实际场景而言，如自动驾驶，实时性和准确性都是非常重要的。</p><h1>4. 主要工作</h1><p>针对上述问题，作者提出了经典的YOLO算法，它是一个统一的，端到端的单阶段目标检测算法。YOLO具体做法是，首先将输入图片缩放到448x448，然后送入CNN网络，最后使用NMS过滤网络预测结果得到检测的目标。</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328103035.png" alt=""></p><p>而在CNN网络里，它首先将图片划分为S×S大小的网格，然后每个单元格负责检测中心点落在该格子的目标，如下图，每个单元格会输出B个边界框（每个边界框输出5个预测值：x, y, w, h, confidence）以及边界框类别概率C，例如：作者在PASCAL VOC的检测实验里使用S=7，B=2，C=类别数量20，一共预测7×7×(2×5+20)个向量。同时这里的confidence代表边界框置信度，它的定义为:</p><p>$$Pr(object)\times IoU_{pred}^{truth}$$</p><p>其中边界框包含目标时，$Pr(object)=1$，否则为0。而C代表每个类别的置信度，即：</p><p>$$Pr(Class_i|Object)\times Pr(objec) \times IoU_{pred}^{truth}=Pr(class_i)\times IoU_{pred}^{truth}$$</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328103753.png" alt=""></p><h2 id="4-1-模型结构">4.1 模型结构</h2><p>YOLO采用卷积网络来提取特征，然后使用全连接层来得到预测值。网络结构参考GooLeNet模型，包含24个卷积层和2个全连接层。对于卷积层，主要使用1x1卷积来做channle reduction，然后紧跟3x3卷积。对于卷积层和全连接层，采用Leaky ReLU激活函数$max(x,0.1x)$，但是最后一层却采用线性激活函数。</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328103101.png" alt=""></p><h2 id="4-2-模型训练">4.2 模型训练</h2><p>在训练之前，先在ImageNet上进行了预训练，其预训练的分类模型采用图8中前20个卷积层，然后添加一个average-pool层和全连接层。预训练之后，在预训练得到的20层卷积层之上加上随机初始化的4个卷积层和2个全连接层。由于检测任务一般需要更高清的图片，所以将网络的输入从224x224增加到了448x448。</p><h2 id="4-3-模型损失">4.3 模型损失</h2><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328110113.png" alt=""></p><p>Yolo算法将目标检测看成回归问题，所以采用的是均方差损失函数。但是对不同的部分采用了不同的权重值。首先区分定位误差和分类误差。对于定位误差，即边界框坐标预测误差，采用较大的权重 $\lambda_{coord}=5$ 。然后其区分不包含目标的边界框与含有目标的边界框的置信度，对于前者，采用较小的权重值 $\lambda_{noobj}=0.5$ 。其它权重值均设为1。然后采用均方误差，其同等对待大小不同的边界框，但是实际上较小的边界框的坐标误差应该要比较大的边界框要更敏感。为了保证这一点，将网络的边界框的宽与高预测改为对其平方根的预测，即预测值变为$(x,y,\sqrt{w},\sqrt{h})$。</p><p>损失函数中，第一项为边界框中心坐标的误差项，$\mathbb{1} _ {ij}^{obj}$ 是指第 i 个单元格存在目标，且该单元格中的第 j 个边界框负责预测该目标，第二项是边界框的高与宽的误差项。第三项是包含目标的边界框的置信度误差项。第四项是不包含目标的边界框的置信度误差项。最后一项是包含目标的单元格的分类误差项，$\mathbb{1} _ {i}^{obj}$值是指第 i 个单元格存在目标。</p><h1>5. 实验结果</h1><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328105647.png" alt=""></p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328105758.png" alt=""></p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328105711.png" alt=""></p><h1>6. 参考文献</h1><p><a href="https://zhuanlan.zhihu.com/p/32525231">目标检测|YOLO原理与实现 - 知乎 (zhihu.com)</a></p>]]></content>
    
    
    <summary type="html">YOLO作者提到人可以一眼看到目标在哪，能立即知道是什么，并且对于很多实际场景而言，如自动驾驶，实时性和准确性都是非常重要的。针对上述问题，作者提出了经典的YOLO算法，它是一个统一的，端到端的单阶段目标检测算法。</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="目标检测" scheme="https://blog.xiemingjie.cn/tags/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="单阶段检测" scheme="https://blog.xiemingjie.cn/tags/%E5%8D%95%E9%98%B6%E6%AE%B5%E6%A3%80%E6%B5%8B/"/>
    
  </entry>
  
  <entry>
    <title>论文赏析 | SSD：多尺度单阶段目标检测</title>
    <link href="https://blog.xiemingjie.cn/posts/8163bb15.html"/>
    <id>https://blog.xiemingjie.cn/posts/8163bb15.html</id>
    <published>2022-03-28T02:57:59.000Z</published>
    <updated>2022-03-28T02:57:59.000Z</updated>
    
    <content type="html"><![CDATA[<h1>1. 论文信息</h1><p>论文标题： 《SSD: Single Shot MultiBox Detector》</p><blockquote><p>论文发表：2016<br>论文链接：<a href="https://link.springer.com/chapter/10.1007/978-3-319-46448-0_2">SSD: Single Shot MultiBox Detector | SpringerLink</a></p></blockquote><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220305111710.png" alt=""></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">@inproceedings&#123;liu2016ssd,</span><br><span class="line">  title=&#123;Ssd: Single shot multibox detector&#125;,</span><br><span class="line">  author=&#123;Liu, Wei and Anguelov, Dragomir and Erhan, Dumitru and Szegedy, Christian and Reed, Scott and Fu, Cheng-Yang and Berg, Alexander C&#125;,</span><br><span class="line">  booktitle=&#123;European conference on computer vision&#125;,</span><br><span class="line">  pages=&#123;21--37&#125;,</span><br><span class="line">  year=&#123;2016&#125;,</span><br><span class="line">  organization=&#123;Springer&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h1>2. 归纳总结</h1><table><thead><tr><th>标签</th><th>目的</th><th>方法</th><th>总结</th></tr></thead><tbody><tr><td>#Anchor #单阶段</td><td>实现多尺度以及卷积预测，进一步提升精度和速度</td><td>MultiBox，Anchor</td><td>经典单阶段算法</td></tr></tbody></table><h1>3. 引言</h1><p>SSD算法，其英文全名是Single Shot MultiBox Detector, SSD的优势在于消除了bounding box proposal和pixel or feature resampling，并使用了multi-scale，因此达到了比faster rcnn和yolo更高的检测精度和更快的检测速度。</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220328121925.png" alt=""></p><p>图片来自<a href="https://zhuanlan.zhihu.com/p/33544892">目标检测|SSD原理与实现 - 知乎 (zhihu.com)</a></p><h1>4. SSD模型</h1><p>SSD采用VGG16作为基础模型，然后在VGG16的基础上新增了卷积层来获得更多的特征图以用于检测，模型结构如下图：</p><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220305114612.png" alt=""></p><p>SSD和Yolo一样都是采用一个CNN网络来进行检测，但是却采用了多尺度的特征图，网络的核心点：</p><ul><li>使用小的卷积核预测类别和边界框偏移量</li><li>对多个（多尺度）特征图进行检测</li><li>设置不同比例的先验框，如下图</li></ul><p><img src="https://npm.elemecdn.com/justlovesmile-img/20220305115052.png" alt=""></p><p>SSD将背景也当做了一个特殊的类别，如果检测目标共有c个类别，SSD其实需要预测c+1个置信度值，其中第一个置信度指的是不含目标或者属于背景的评分。在预测过程中，置信度最高的那个类别就是边界框所属的类别，特别地，当第一个置信度值最高时，表示边界框中并不包含目标。第二部分就是边界框的location，包含4个值(cx,cy,w,h)，分别表示边界框的中心坐标以及宽高。但是真实预测值其实只是边界框相对于先验框的转换值。先验框位置用$d=(d^{cx},d^{cy},d^{w},d^{h})$表示，其对应边界框用$b=(b^{cx},b^{cy},b^{w},b^{h})$表示，那么边界框的预测值$l$其实是b相对于d的转换值：<br><img src="https://npm.elemecdn.com/justlovesmile-img/20220328114611.png" alt=""></p><h1>5. 模型训练</h1><h2 id="5-1-正负样本划分">5.1 正负样本划分</h2><p>首先，对于图片中每个ground truth，找到与其IOU最大的先验框，该先验框与其匹配，这样，可以保证每个ground truth一定与某个先验框匹配。通常称与ground truth匹配的先验框为正样本，其次，通过判断先验框和ground truth之间的IoU值是否大于阈值（如0.5），大于则为正样本</p><h2 id="5-2-损失计算">5.2 损失计算</h2><p>损失包含两个部分：定位损失和分类损失</p><p>$$L(x,c,l,g)=\frac{1}{N}(L_{conf}(x,c)+\alpha L_{loc}(x,l,g))$$</p><p>其中N代表所匹配的正负样本数量，<code>l</code>代表预测框，<code>g</code>代表真实框，和faster rcnn相似，回归的偏移量的值是边界框的中心坐标(cx,cy)和框的宽度w和高度h。</p><p>$$\hat{g} _ {j}^{cx}=(g _ {j}^{cx}-d _ {i}^{cx})/d _ {i}^{w}$$</p><p>$$\hat{g} _ {j}^{cy}=(g_{j}^{cy}-d_{i}^{cy})/d_{i}^{h}$$</p><p>$$\hat{g} _ {j}^{w}=\log(\frac{g_{j}^{w}}{d_{i}^{w}})$$</p><p>$$\hat{g} _ {j}^{h}=\log(\frac{g_{j}^{h}}{d_{i}^{h}})$$</p><p>因此定位损失函数为：$L_{loc}(x,l,g)=\sum_{i \in Pos}^N \sum_{m\in {cx,cy,w,h}}x_{ij}^{k}smooth_{L1}(l_i^m-\hat{g} _ j^m)$<br>分类损失是一个softmax损失：$L_{conf}(x,c)=-\sum_{i\in Pos}^{N}x_{ij}^p\log(\hat{c} _ i^p)-\sum _ {i\in Neg}log(\hat{c} _ i^0)$<br>其中$\hat{c} _ i^p=\frac{exp(c_i^p)}{\sum_p(exp(c_i^p))}$</p><h1>6. 参考文献</h1><p><a href="https://zhuanlan.zhihu.com/p/33544892">目标检测|SSD原理与实现 - 知乎 (zhihu.com)</a></p>]]></content>
    
    
    <summary type="html">SSD算法，其英文全名是Single Shot MultiBox Detector, SSD的优势在于消除了bounding box proposal和pixel or feature resampling，并使用了multi-scale，因此达到了比Faster R-CNN和YOLO更高的检测精度和更快的检测速度。</summary>
    
    
    
    <category term="论文赏析" scheme="https://blog.xiemingjie.cn/categories/%E8%AE%BA%E6%96%87%E8%B5%8F%E6%9E%90/"/>
    
    
    <category term="目标检测" scheme="https://blog.xiemingjie.cn/tags/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B/"/>
    
    <category term="论文阅读" scheme="https://blog.xiemingjie.cn/tags/%E8%AE%BA%E6%96%87%E9%98%85%E8%AF%BB/"/>
    
    <category term="多尺度检测" scheme="https://blog.xiemingjie.cn/tags/%E5%A4%9A%E5%B0%BA%E5%BA%A6%E6%A3%80%E6%B5%8B/"/>
    
  </entry>
  
</feed>
