Cynthia
  • NEW!
    NEW!  Connect Ideas Across Notes
    Save time and share insights. With Paragraph Citation, you can quote others’ work with source info built in. If someone cites your note, you’ll see a card showing where it’s used—bringing notes closer together.
    Got it
      • Create new note
      • Create a note from template
        • Sharing URL Link copied
        • /edit
        • View mode
          • Edit mode
          • View mode
          • Book mode
          • Slide mode
          Edit mode View mode Book mode Slide mode
        • Customize slides
        • Note Permission
        • Read
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Write
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invite by email
        Invitee

        This note has no invitees

      • Publish Note

        Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

        Your note will be visible on your profile and discoverable by anyone.
        Your note is now live.
        This note is visible on your profile and discoverable online.
        Everyone on the web can find and read all notes of this public team.

        Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Explore these features while you wait
        Complete general settings
        Bookmark and like published notes
        Write a few more notes
        Complete general settings
        Write a few more notes
        See published notes
        Unpublish note
        Please check the box to agree to the Community Guidelines.
        View profile
      • Commenting
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Suggest edit
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
      • Emoji Reply
      • Enable
      • Versions and GitHub Sync
      • Note settings
      • Note Insights New
      • Engagement control
      • Make a copy
      • Transfer ownership
      • Delete this note
      • Save as template
      • Insert from template
      • Import from
        • Dropbox
        • Google Drive
        • Gist
        • Clipboard
      • Export to
        • Dropbox
        • Google Drive
        • Gist
      • Download
        • Markdown
        • HTML
        • Raw HTML
    Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Engagement control Make a copy Transfer ownership Delete this note
    Import from
    Dropbox Google Drive Gist Clipboard
    Export to
    Dropbox Google Drive Gist
    Download
    Markdown HTML Raw HTML
    Back
    Sharing URL Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    Customize slides
    Note Permission
    Read
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Write
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    --- title: 車牌辨識:CRNN + CTC date: 2020-08-12 is_modified: false disqus: cynthiahackmd categories: - "智慧計算 › 人工智慧" tags: - "AI/ML" - "車牌辨識" - "光學字元辨識 OCR" - "電腦視覺 CV" - "CRNN" - "CTC" --- {%hackmd @CynthiaChuang/Github-Page-Theme %} <br> 前一陣子(2020-02)的工作成果記錄。文章內容及架構是基於同事的投影片進行擴充與刪減而成,雖然同事整理過了,但畢竟自己整理過才是自己的咩 :smile:。 <!--more--> ## Optical Character Recognition, OCR OCR 為光學字元辨識(Optical Character Recognition)的縮寫,主要目的是將文字資料的圖像檔案進行分析辨識處理,取得文字及版面資訊。 ### 基本辨識流程 一般來說,一套完整的辨認系統通常包含三部分:影像掃描器(Image scanner)、光學字元辨認軟/硬體以及輸出介面(Output interface)。 ```flow input=>operation: 影像掃描器 ocr=>subroutine: 光學字元辨識 output=>operation: 輸出介面 input(right)->ocr(right)->output ``` 以超速照相為例,會先透過影像掃描器,即攝影機或是照相機拍下超速車輛,再並將圖片送往光學字元辨識軟體,也就是我們的車牌辨識系統,得到超速車輛的車牌,最後再把此車牌號碼送往罰單的系統,開出一張超速罰單,此步驟對應到就是流程中的輸出介面。 雖說整套流程包含三個部份,但在這邊我們只將目光放在光學字元辨識系統上。 <br> 細分光學字元辨識系統,可在分成兩個步驟:分別是==文字檢測==與==文字識別==。 - **文字檢測**: 顧名思義就是找出哪裡有文字以及文字範圍大小,對應到車牌辨識系統中就是找出車牌的位置並框出車牌。 - **文字辨識**: 是對定位出的文字區域進行辨識,一般狹義的 OCR 指的是這一部份,本文也是專注在這一部份。 ```flow input=>operation: 輸入 detection=>operation: 文字檢測 recognition=>operation: 文字辨識 output=>operation: 輸出 input(right)->detection(right)->recognition(right)->output ``` ### 文字辨識方法 文字辨識的方法依照實做的方式,可區分成 ==Two Stage== 或 ==End To End== 兩種。 <br> Two Stage 顧名思義會分成兩個主步驟來進行,它會先將目標區域中的字元進行分割,也就是將車牌中的字一個一個擷出來,並將擷出的字元進行正規化,最後透過特徵截取將字元一一進行辨識。 <p class="illustration"> <img src="https://i.imgur.com/irrsatm.png?1" alt="two stage flow"> 文字檢測 + 文字辨識(Two Stage) 辨識流程(圖片來源: <a href="https://sites.google.com/site/cs0991326/home/che-pai-bian-shi">Google 協作平台</a>) </p> 而另一種 end to end 的方式則不需要進行字元分割,是一步到位的辨識方法。它會直接將擷取出的整份車牌送入神經網路中學習。 兩相比較,前者多建立資料庫來進行比對,資料多寡並不會影響準確率,全倚賴特徵擷取的規則,但計算上較簡單。反之,後者的準確率受資料量影響,但計算較為複雜。 ## CRNN 說到車牌,之前[提過](/@CynthiaChuang/Taiwan-License-Plate-Rules-for-LPR)臺灣目前車牌是採兩代車牌並行使用的做法。目前流通的車牌總共有 `2-4`、 `4-2`、 `2-2`、 `3-2`、 `2-3`、 `3-3` 與 `3-4` 共 7 種格式,長度由 4 到 7 不等。 考慮到不定長度的狀況,最後決定採用 [CRNN](https://arxiv.org/pdf/1507.05717.pdf),將文字辨識轉為序列問題,透過 DCNN(深度卷積網絡)串接 RNN 的模型架構,對圖片進行文字識別。 ### 網路基本架構 <p class="illustration"> <img src="https://i.imgur.com/jLmg7u1.png" alt="CRNN OCR Network Architecture"> CRNN OCR Network Architecture (圖片來源: <a href="https://arxiv.org/pdf/1507.05717.pdf">論文</a>) </p> 根據上圖架構 CRNN 模型主要可以分成三個部分: 1. Convolutional Layers 2. Recurrent Layers 3. Transcription Layer <br> **Convolutional Layers** 這層的主要目的是使用 Convolutional Layers 的特性,去提取圖像特徵。 在將圖片餵進網路之前,需要對圖片做前處理,在原始的網路架構中,僅接受 `W x 32 (寬 x 高)` 的灰階圖片,因此輸入尺寸為 $(width, height, channel)=(W, 32, 1)$。當讀入圖片後,會經由使用 VGG 概念而採用的大量 $3 \times 3$ Conv 及 $2 \times 2$ pooling 所構成的網路,最終會得到此圖的特徵向量。 <p class="illustration"> <img src="https://i.imgur.com/EpQEZpo.png" alt="Network configuration summary"> Network configuration summary(圖片來源: <a href="https://arxiv.org/pdf/1507.05717.pdf">論文</a>) </p> 在此必須提到一件事,根據論文架構表格中,作者將最後後兩層的 pooling size 改為 ==1 X 2== pooling。有人認為這是為了盡可能不丟失寬度方向的資料,會較適合英文字母的識別(例如非等寬字體中較窄的 i 與 l)。 不過在論文作者的[原始碼](https://github.com/bgshih/crnn/blob/f5d41e3355fc4447f77cd6d5e5777b3a160c93cb/model/crnn_demo/config.lua#L68)中,在最後兩層的 pooling size 並非如論文內紅框處設計,[作者表示](https://github.com/bgshih/crnn/issues/6)論文中的 $1 \times 2$,其實是筆誤 XDDD <p class="illustration"> <img src="https://i.imgur.com/ykx0PYw.png" alt=""> (圖片來源: <a href="https://github.com/bgshih/crnn/issues/6">bgshih/crnn</a>) </p> 但根據我同事的實驗,在我們的資料集上使用 $1 \times 2$ 的 pooling size,表現確實比使用 $2 \times 2$ 好,這算是美麗的誤會嗎? 因此我們決定當作沒看到筆誤這件事,仍舊按照論文中這張表格進行實作。當過完所有的 Maxpooling 後,寬度為 $W \div 2^2$ ,高度為 $H \div 2^4$,在過最一層 $2 \times 2$ Conv,且 padding size 為 0(padding = ‘VALID’),最終輸出尺寸為 $(\frac{W}{4}, 1, 512)$。 <p class="illustration"> <img src="https://i.imgur.com/FMOuqrN.png" alt="Convolutional Layers"> Convolutional Layers(圖片來源: <a href="https://arxiv.org/pdf/1507.05717.pdf">論文</a>) </p> 但此階段的輸出無法直接最為下一階段的,需要經過一次轉換,因為 RNN 所接受的輸入格式應該為 $(timesteps, dim)$,很明顯的維度不對。 在論文中作者將這樣的轉換稱之為 ==Map-to-Sequence==,不過其實就是做 reshape 變成 $(\frac{W}{4} * 1, 512)$,恩...可以想像成依照寬度將原圖分成 $\frac{W}{4} * 1$ 等分,每等分會有 512 個特徵。因此最後產生就是,原圖從左到右按照順序生成的特徵向量,做為下一階段的輸入。 <br> **Recurrent Layers** 由於車牌長度是不定的,因此第二階段引入了雙向 RNN。不過習慣上說是 RNN,但實際上指的是 LSTM,用 GRU 也行,別真的用 RNN,不然應該會遇到梯度消失的問題。 在這一層中,網路會對上一階段傳入的特徵向量進行學習,以進行預測。由上圖可以了解,上一階段所傳入的特徵向量,其實相當於車牌中的一個矩形區域。RNN 所要學習的就是這個矩形區域所屬的字元為何,其輸出尺寸為 $(\frac{W}{4} * 1, 256*2)$。 最後再將輸出結果透過 softmax 「壓縮」成各個字元的機率分布,作為 CTC 層計算的輸入。假若你的目標字元為 A~Z 與 0~1,共 36 個,而此層的輸出為 $(\frac{W}{4} * 1, 36+1)$,多出來的一個類別保留給 CTC 層計算時所使用的 Blank。 <br> **Transcription Layer** 將從 Recurrent Layers 取的標籤通過去重複、整合等動作得到最終的辨識結果。白話的說就是將 RNN 的輸出做 Softmax 後得到各字元。 值得一提的是,這邊並不是採用常用的 Softmax cross-entropy loss,而是所謂的 ==CTC loss(Connectionist Temporal Classification,聯接時間分類)==。 ### Connectionist Temporal Classification, CTC 在這邊引入 CTC loss 是為了處理==不定長度序列的對齊問題==! 在一般使用 Softmax cross-entropy 計算 loss 時,會每一行輸出都對應到一個字元。因此你必須先標出每個字元在圖像中的位置,並調整網路以保證 Recurrent Layers 後所輸出的特徵值中,每一行會剛好對應到一個字元,才能進行訓練。 <p class="illustration"> <img src="https://i.imgur.com/fi6mMeg.png?1" alt="one column mapping to one char"> 上層輸出的特徵值必須每一行對應到一個字元,才能進行訓練(圖片來源: <a href="https://www.cnblogs.com/skyfsm/p/10335717.html">冠军的试炼</a>) </p> 但在實務上,若要額外標註每個字元位置會比單純標記字元,多出 5 倍以上的時間,耗時又費工。且由於車牌字元長度不定、照片角度不一、字寬不等、字型也有所差別,想讓每一行會剛好對應到一個字元,幾乎不可能。 但若忽略這個問題,直接對 Recurrent Layers 輸出進行序列分類,可能會出現冗餘資訊,如一個字母被連續識別兩次。遇到這情況又不可直接去除重複的字母,因為原始文字可能本來就存在連續重複字元,如:cook、geek、hello。 <p class="illustration"> <img src="https://i.imgur.com/FuIOQqa.png" alt="直接序列分類可能會出現冗餘資訊"> 直接序列分類可能會出現冗餘資訊(圖片來源: <a href="http://fancyerii.github.io/books/ctc/">李理的博客</a>) </p> 那如何針對每一幀進行對齊與識別?幸運的是,這問題在語音辨識中已有所研究。這是因為每個人語速不一,因此導致語音分幀結果和標籤對齊的挑戰。 論文中引入了語音辨識中常用的 CTC 來計算 loss,計算概念上類似 beam search,計算每條路徑的機率、並加總相同輸出的機率,最終取最高值最為輸出。 :::info 若對 CTC 的實做理論有興趣的,請詳閱這兩篇: 1. [语音识别:深入理解CTC Loss原理 | 左左左左想 | CSDN博客](https://blog.csdn.net/Left_Think/article/details/76370453) 2. [CTC理论和实战 | lili on | 李理的博客](http://fancyerii.github.io/books/ctc/) ::: <p class="illustration"> <img src="https://i.imgur.com/JTaLcpw.png" alt="直接序列分類可能會出現冗餘資訊"> 直接序列分類可能會出現冗餘資訊(圖片來源: <a href="http://fancyerii.github.io/books/ctc/">李理的博客</a>) </p> 實做過程中須注意的是,CTC 存在著 Blank 的概念,可以想像成序列剛好位於字與字之間的空白,因此在設計 Recurrent Layers 的輸出時會保留一個維度給 Blank,Blank 本身並不影響輸出結果,在輸出時 Blank 會被視為無意義字元給濾掉,但在計算每條路徑的機率時會將納入計算。 <p class="illustration"> <img src="https://i.imgur.com/JxSAKwO.png" alt="直接序列分類可能會出現冗餘資訊"> </p> ## CRNN 實作 在實做方面我們參考了 [CRNN-Keras](https://github.com/qjadud1994/CRNN-Keras) 的實做。但我們針對我們資料集,我們將輸入的圖像改成了彩色圖片,不做額外優化 baseline 分數約為 94.69%。 ### 優化與改善 我們分別針對資料本身、前處理、模型與後處理做了些嘗試與調整,這些調整約提升了 3.37%,準確度由 94.69% 來到了 98.06%。 <br> **資料本身** 在這邊我們重新檢閱了資料集本身清除訓練資料集中品質不好、非車牌與標註錯誤...等資料,以得到較好資料集本質。而針對加入非車牌資料,我們以全 Blank 作為它的標籤,一齊加入訓練,以增強模型的容錯能力。預期看到非車牌資料時能有辨識,並輸出空值,如此一來,可以在利用系統面的設計,來作為例外處理或補救。 另外依照臺灣的車牌比例更了輸入資料的尺寸,並添加更多實際場景資料作為訓練集,重新進行訓練。 <br> **前處理** 另外採用第三方 library 的 [aleju/imgaug](https://github.com/aleju/imgaug) 與 [mdbloice/Augmentor](https://github.com/mdbloice/Augmentor) ,來做 **Data Augmentation** 以增加模型的泛化能力。Augmentation 主要針對對比、變焦、偏斜、旋轉進行調整,並對高反光、耀光、雨景、日落、鏡頭模糊...等情況進行模擬。 P.S. Augmentor 的安裝與使用可以看[這篇](https://hackmd.io/@CynthiaChuang/Augmentor-Image-Augmentation-Library-in-Python)。 <br> **後處理** 後處理則是預測後校正,主要針對[維基百科](https://zh.wikipedia.org/wiki/%E8%87%BA%E7%81%A3%E8%BB%8A%E8%BC%9B%E7%89%8C%E7%85%A7)所提及的一些規則進行校正,主要是 0、1、I、O 這些規則的調整。 <br> **模型** 這邊參考語音作法,先針對不同特性的聲音訓練分類器(男生、女生、外國人...),並提取其內某一層當作特徵,當作額外輸入資訊。這邊則是這邊增加了一個車牌樣式分類器,抽取分類器 Dense 層特徵,當作 CRNN LSTM 額外的 input 資料一起訓練。 另外修改了 CTC decode 將它由 greedy search 改成了 prefix beam search。 其他嘗試 ResNet、[CRNN12](https://sci-hub.tw/10.1007/978-981-13-1733-0_9)、[STN(Spatial Transformer Networks)](https://zhuanlan.zhihu.com/p/37110107),不過最終模型實驗的改善都先擱置了。 ## 參考資料 1. PLUSTEK 公司 (2009-09-12)。[什麼是 OCR?](http://www.fuji.com.tw/posts/1889) 。檢自 蘋果網 (2020-03-17)。 2. 協同撰寫。[光學字元辨識](https://zh.wikipedia.org/wiki/%E5%85%89%E5%AD%A6%E5%AD%97%E7%AC%A6%E8%AF%86%E5%88%AB) 。檢自 維基百科 (2020-03-17)。 3. 王梅玲 (2011-04-27)。[技術服務小百科: 光學字元識別 (OCR, Optical Character Recognition)](http://techserviceslibrary.blogspot.com/2011/04/ocr-optical-character-recognition.html)。檢自 技術服務小百科 - Blogger (2020-03-17)。 4. 騰訊雲。[嘿,OCR文字識別瞭解下!](https://codertw.com/%E4%BA%BA%E5%B7%A5%E6%99%BA%E6%85%A7/320/)。檢自 程式前沿 (2020-03-17)。 5. cs0991326 (2011-03-16)。[車牌辨識](https://sites.google.com/site/cs0991326/home/che-pai-bian-shi)。檢自 cs0991326 - Google 協作平台 (2020-03-17)。 6. [車用電子系統導論_13 車牌辨識](http://140.117.156.238/course/IAE/2013/%E8%BB%8A%E7%94%A8%E9%9B%BB%E5%AD%90%E7%B3%BB%E7%B5%B1%E5%B0%8E%E8%AB%96_13.pdf)。檢自 葉家宏老師課程網頁 Courses (2020-06-03)。 7. 白裳 (2020-01-06)。[一文读懂CRNN+CTC文字识别](https://zhuanlan.zhihu.com/p/43534801)。檢自 机器学习随笔 - 知乎 (2020-03-17)。 8. AI科技園 (2019-11-01)。[大話文本識別經典模型:CRNN](https://kknews.cc/tech/pvgpqk8.html)。檢自 每日頭條 (2020-06-03)。 9. z.defying (2019-10-20)。[理解文本识别网络CRNN](https://zhuanlan.zhihu.com/p/71506131)。檢自 深度学习漫谈 知乎 (2020-06-03)。 10. Madcola (2019-01-29)。[【OCR技术系列之七】端到端不定长文字识别CRNN算法详解](https://www.cnblogs.com/skyfsm/p/10335717.html)。檢自 冠军的试炼 (2020-06-03)。 11. 左左左左想 (2017-07-30)。[语音识别:深入理解CTC Loss原理](https://blog.csdn.net/Left_Think/article/details/76370453)。檢自 CSDN博客 (2020-06-03)。 12. lili on。[CTC理论和实战](http://fancyerii.github.io/books/ctc/)。檢自 李理的博客 (2020-07-10)。 ## 更新紀錄 :::spoiler 最後更新日期:2020-08-12 - 2020-08-12 發布 - 2020-07-10 完稿 - 2020-03-17 起稿 ::: <br><br> > **本文作者**: 辛西亞.Cynthia > **本文連結**: [辛西亞的技能樹](https://cynthiachuang.github.io/License-Plate-Recognition-CRNN-CTC) / [hackmd 版本](https://hackmd.io/@CynthiaChuang/License-Plate-Recognition-CRNN-CTC) > **版權聲明**: 部落格中所有文章,均採用 [姓名標示-非商業性-相同方式分享 4.0 國際](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en) (CC BY-NC-SA 4.0) 許可協議。轉載請標明作者、連結與出處!

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully