HackMD
  • Beta
    Beta  Get a sneak peek of HackMD’s new design
    Turn on the feature preview and give us feedback.
    Go → Got it
      • Create new note
      • Create a note from template
    • Beta  Get a sneak peek of HackMD’s new design
      Beta  Get a sneak peek of HackMD’s new design
      Turn on the feature preview and give us feedback.
      Go → Got it
      • Sharing Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • 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
      • More (Comment, Invitee)
      • Publishing
        Please check the box to agree to the Community Guidelines.
        Everyone on the web can find and read all notes of this public team.
        After the note is published, everyone on the web can find and read this note.
        See all published notes on profile page.
      • Commenting Enable
        Disabled Forbidden Owners Signed-in users Everyone
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Invitee
      • No invitee
      • Options
      • Versions and GitHub Sync
      • Transfer ownership
      • Delete this note
      • Template
      • Save as template
      • Insert from template
      • Export
      • Dropbox
      • Google Drive Export to Google Drive
      • Gist
      • Import
      • Dropbox
      • Google Drive Import from Google Drive
      • Gist
      • Clipboard
      • Download
      • Markdown
      • HTML
      • Raw HTML
    Menu Sharing Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Versions and GitHub Sync Transfer ownership Delete this note
    Export
    Dropbox Google Drive Export to Google Drive Gist
    Import
    Dropbox Google Drive Import from Google Drive Gist Clipboard
    Download
    Markdown HTML Raw HTML
    Back
    Sharing
    Sharing Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    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
    More (Comment, Invitee)
    Publishing
    Please check the box to agree to the Community Guidelines.
    Everyone on the web can find and read all notes of this public team.
    After the note is published, everyone on the web can find and read this note.
    See all published notes on profile page.
    More (Comment, Invitee)
    Commenting Enable
    Disabled Forbidden Owners Signed-in users Everyone
    Permission
    Owners
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Invitee
    No invitee
       owned this note    owned this note      
    Published Linked with GitHub
    Like BookmarkBookmarked
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    --- tags: 'ML notes' --- # Image Data Augmentation for Deep Learning ![](https://i.imgur.com/4ae5SbT.jpg) ## Based on basic image manipulations - 每一個 data augmentation 方法都應該考慮到其 safety - 舉例來說,若是在辨識ImageNet的圖片,就可以使用 rotation 或是 flip,但若是 Cifar 的手寫圖片辨識就不行,會造成 no safety ### Geometric transformations - 針對圖片的位置做操作 - 適合處理 positional bias,比如人臉辨識 - 包含 flipping, Cropping, Scaling, Rotation, Translation, Noise injection #### flipping - 翻轉圖片 - horizontal flip 比 vertical 更常見 - 最常見也最簡單的方法之一 ```python= # 為了簡化code, 範例皆假設已有 import albumentations as A A.Flip(p=0.5) # d=0: vertical flip, d=1: horizontal flip # d=-1: vertical and horizontal flipping A.VerticalFlip(p=0.5) A.HorizontalFlip(p=0.5) ``` #### Cropping - 可以裁切中間的一塊區域或是隨機裁切(random cropping),有可能會不是 label-preserving transformation,取決於 cropping 的 threshold ```python= A.Crop(x_min=0, y_min=0, x_max=1024, y_max=1024, always_apply=False, p=1.0) A.RandomCrop(height, width, always_apply=False, p=1.0) A.RandomSizedCrop(min_max_height, height, width, w2h_ratio=1.0, interpolation=1, always_apply=False, p=1.0) # min_max_heigth((int, int)) 為 crop size limit # RandomSizedCrop 的 height 和 width 為 crop 後圖片的尺寸 A.CenterCrop(height, width, always_apply=False, p=1.0) ``` #### Scaling - 在不改變圖片大小的前提下縮放圖片 - 可分成 scaled outward 或是 inward,前者是放大圖片,後者是縮小圖片 ```python= A.RandomScale(scale_limit=0.1, interpolation=1, always_apply=False, p=0.5) A.LongestMaxSize(max_size=1024, interpolation=1, always_apply=False, p=1) A.SmallestMaxSize(max_size=1024, interpolation=1, always_apply=False, p=1) ``` #### Rotation - 輕微的旋轉通常是 1~20 度或是 -1~-20度,若要再增加的話有可能造成 data 的 label 不再保有 post-transformation ```python= A.RandomRotate90(p=0.5) A.Rotate (limit=90, interpolation=1, border_mode=4, value=None, mask_value=None, always_apply=False, p=0.5) ``` #### Translation - Shifting images left, right, up, or down - Shift 之後所缺少的圖片空間可以用 0 或是 255 來填補起來或是用 random noise 跟 Gaussian noise - Padding 會保留 spatial dimensions of the image post-augmentation ```python= # 同時做 translation, scale, and rotate # limit 皆為其 factor 範圍,會自動 apply 為 (-limit, limit) # value 和 mask_value 皆為 padding value,取決於 border_mode A.ShiftScaleRotate (shift_limit=0.0625, scale_limit=0.1, rotate_limit=45, interpolation=1, border_mode=4,value=None, mask_value=None, shift_limit_x=None, shift_limit_y=None, always_apply=False, p=0.5) ``` ### Noise injection - 隨機插入 Gaussian noise, Salt and Pepper noise, Speckle Noise, ISO noise 之類的進去圖片作為隨機噪音 ![](https://i.imgur.com/oFBD2F7.jpg) ```python= # var_limit = variance range for noise # per_channel 若為 True,就會分別對每一個 channel 抽樣做 noise,若否則對全部 channel 一起抽樣做 A.GaussNoise (var_limit=(10.0, 50.0), mean=0, per_channel=True, always_apply=False, p=0.5) # multiplier 也可指定為單一數字,那就會直接乘上這個數字 A.MultiplicativeNoise (multiplier=(0.9, 1.1), per_channel=False, elementwise=False, always_apply=False, p=0.5) # color_shift = variance range for color hue change. Measured as a fraction of 360 degree Hue angle in HLS colorspace. # intensity = Multiplicative factor that control strength of color and luminace noise. A.ISONoise (color_shift=(0.01, 0.05), intensity=(0.1, 0.5), always_apply=False, p=0.5) ``` ### Color space transformations - 對 color channel 做操作,比如獨立切出一個 channel、對所有 channel 持續增加/減少一個常數數值 - 又稱 photometric transformations ![](https://i.imgur.com/eY81tlp.jpg) - 包含 Color jitter, Fancy PCA #### Color Jitter - 指的是 Random color manipulation 或是調整圖片的亮度、飽和度與對比度 (Brightness, Saturation, Contrast) - `albumentations.augmentations.transforms.ColorJitter (brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2, always_apply=False, p=0.5)` - brightness = 從 [max(0, 1 - brightness), 1 + brightness] 隨機均勻抽一個數或是給定範圍 - contrast, saturation 算法同上 - hue = 從 [-hue, hue] 中隨機均勻抽一個數或是給定範圍 - [doc](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.ColorJitter) ```python= A.ColorJitter (brightness=0.2, contrast=0.2, saturation=0.2, hue=0.2, always_apply=False, p=0.5) ``` #### PCA Color Augmentation (Fancy PCA) - 首次出現在 2012 年 Krizhevsky, Sutskever & Hinton 的 AlexNet - 在 color channel 上面做 PCA,根據算出來的成分判斷出 RGB 的分布,並以此來決定增加的偏移量 - 例如圖片中 R 跟 G 成分較多,B 較少的時候在偏移的時候就會在 R 跟 G 加入較多偏移,在 B 加入更少偏移,使得圖片的整體色調不變 ![](https://i.imgur.com/QGLp5yt.jpg) ```python= # alpha 為 eigenvalue/eigenvector 的 scale facto, sampled from gaussian(mu=0, sigma=alpha) A.FancyPCA (alpha=0.1, always_apply=False, p=0.5) ``` #### Comparsion - 參考用 - 結果是有做 cropping 的結果最好 ![](https://i.imgur.com/isMzSzB.jpg) ### Kernel filters - 使用特定的 filter 對整張圖片做 Conv 來強化影像中的某些特徵並移除其他不想要的特徵,比如模糊(blur)、邊緣偵測(edge detection)、邊緣強化(edge enhancement)、噪點移除(noise removal) - 但 Kernel filter 的方法有點太像 CNNs 的運作,實際上更好的方法是直接變成網路中的一層 (反正都是做卷積操作),而不是用來做 data augmentation - **Blur :** GaussianBlur - **Edge detection :** Sobel Edge Detection (圖中上), Sobel Edge Detection on RGB (圖右上), Prewitt edge detection (圖左下), Laplacian Edge Detection (圖中下), Canny Edge Detection (圖右下) ![](https://i.imgur.com/JJy2B4I.jpg) - **Edge enhancement :** unsharp masking ![](https://i.imgur.com/KCgUkkF.jpg) - **Noise removal :** - Morphology - Opening: 先 erosion 再 dilation,用來消除細小的物體(noise),在細小的連接點處分開物體,平滑處理過後的物體邊界 - Closing: 先 dilation 再 erosion,去除小暗點(空洞),將物體中的小空缺填補起來 - Top Hat: 原圖 - 開運算圖,增強暗背景中的明亮物體 - Black Hat: 原圖 - 閉運算圖,增加明亮背景中的暗物體 - Mean Filter, Median filter ```python= # blur_limit 為最大 kernel size A.Blur (blur_limit=7, always_apply=False, p=0.5) A.MedianBlur (blur_limit=7, always_apply=False, p=0.5) # sigma_limit 為 Gaussian kernel standard deviation,若為單一值則為 (0, sigma_limit),若為 0 sigma 則為 sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8 A.GaussianBlur (blur_limit=(3, 7), sigma_limit=0, always_apply=False, p=0.5) ``` ### Random erasing - 從 Dropout 獲得啟發 - 隨機去除掉圖片中的某個區域 - 可用來對抗 occlusion,也就是圖片中的某個區域過於不清楚的挑戰 - 有可能不是一個 label-preserving transformation (例如手寫辨識圖片的數字8被移除了一塊變成6) ![](https://i.imgur.com/bX8nSFc.jpg) ![](https://i.imgur.com/46iGVm6.jpg) - **CutOut, 2017:** 隨機將部分區域移除掉並以0填充 - **Random Erasing, 2017:** 隨機將部分區域移除掉並以隨機值或是平均值填充 - **Hide and Seek (HaS), 2017:** 將圖片切為 $S \times S$ 個 patches,每一個 patch 都根據機率 $P_{hide}$ 來決定是否遮蔽,然後輸入到 CNN 中訓練 - 可用在 Weak-Supervised Learning 來產生更多標註資料,given 圖片和 label 來訓練模型可以在測試資料集輸出 bounding box 和 label ![](https://i.imgur.com/xFUQ2AD.jpg) - **GridMask, 2020:** 根據 given parameter (r, d, δx, δy) 產生 mask,把 mask 與原圖做 multiply 疊加起來產生被遮罩的圖片 - r 是一個 unit 中 gray edge 的比例, d 是一個 unit 的長度 - δx 和 δy 是第一個完整 unit 和圖片邊界的距離 ![](https://i.imgur.com/1ujhxBM.png) ![](https://i.imgur.com/l14s6oR.jpg) - GridMask 的刪除區域不再是隨機不可控的,而是使用結構化的方式來刪除,這樣可以避免像 CutOut 移除一個連續的大區域也可以避免 HaS 的隨機性把 整個 label 刪除掉 - GridMask 為目前此類的 SOTA ![](https://i.imgur.com/CIZyRmH.jpg) ```python= A.dropout.cutout.Cutout (num_holes=8, max_h_size=8, max_w_size=8, fill_value=0, always_apply=False, p=0.5) # GridMask A.dropout.grid_dropout.GridDropout (ratio=0.5, unit_size_min=None, unit_size_max=None, holes_number_x=None, holes_number_y=None, shift_x=0, shift_y=0, random_offset=False, fill_value=0, mask_fill_value=None, always_apply=False, p=0.5) ``` [Random erasing in timm](https://fastai.github.io/timmdocs/RandomErase) ```python= from timm.data.random_erasing import RandomErasing # get input images and convert to `torch.tensor` X, y = input_training_batch() X = convert_to_torch_tensor(X) # perform RandomErase data augmentation random_erase = RandomErasing(probability=0.5) # get augmented batch X_aug = random_erase(X) ``` ### Mixing images - 把不同的圖片混合在一起 - 由於違反人類直覺,雖然很有效但缺乏可解釋性 ![](https://i.imgur.com/IDyBejr.jpg) - **MixUp, 2018:** 將圖片按照比例融合,label 按 pixel value 所佔比例輸出 ![](https://i.imgur.com/N8RyGLb.jpg) - 之後有衍伸出 MixMatch, Manifold mixup - **SamplePairing, 2018**: 隨機選兩個不同 label 的圖片做基本操作後 mixing ![](https://i.imgur.com/S7XXs42.jpg) - **[CutMix](https://arxiv.org/abs/1905.04899), 2019 (結合 MixUp 和 CutOut):** 隨機刪除一個區域並以另一張圖片的同一個位置的 pixel value 來填充,label 也根據 pixel value 所占比例輸出 - CutMix 為目前此類的 SOTA - [Mixup, Cutmix in timm](https://fastai.github.io/timmdocs/mixup_cutmix) ![](https://i.imgur.com/3M4JKtD.jpg) ![](https://i.imgur.com/kJSAj79.png) - 各種 mixing methods from [Improved Mixed-Example Data Augmentation](https://arxiv.org/pdf/1805.11272.pdf) ![](https://i.imgur.com/BbyEm50.png) ![](https://i.imgur.com/4RmXcDz.png) [mixed example 實作](https://github.com/ceciliaresearch/MixedExample/blob/master/mixed_example.py) ## Based on Deep Learning ### Feature space augmentation - 對 CNNs 擷取出來的 feature 做操作 - **SMOTE**: 用來解決 class imblance 的 augmentation 技巧,將整個 feature space 用 SMOTE 來產生相似的新 feature - 也能利用 auto encoder 將 new instance 轉回 input space,例如把 CNN 的 output layer拿掉,把得到的 feature (embeddings) 拿去訓練其他模型,產生出新的資料 - 缺點是 feature space augmentation 頂多只能用 auto-encoder 來解釋產生出來的 vector data,但這其實需要把整個 CNN 的 encoding part 複製一份出來,非常耗計算 ### Adversarial training - 利用兩個或多個在 loss function 中有 contrasting objectives 的網路來產生出新的資料 - 對抗式攻擊的效果在圖片解析度越高的時候越有效,能夠找出並加強分類模型較無法分類的弱點 (Weak Spots in decision boundary) ![](https://i.imgur.com/V9yvq0j.jpg) - 對抗式訓練雖然不會增加整體的 test accuracy,但可以增強模型面對到對抗式樣本時的 accuracy ![](https://i.imgur.com/NQqq9yR.jpg) - 另外也有些方法是產生出對抗式的 label,例如 [DisturbLabel, 2016](https://arxiv.org/abs/1605.00055) 就用另一個對抗式模型來隨機在每一個 iteration 取代掉訓練資料中的 label,並往取代之後會造成原模型的 error rate 最高去學習 - **對抗式訓練可以增加 noise 以及證明能讓模型更好處理對抗式樣本,但未必能減少模型的 overfitting** ### GAN‑based Data Augmentation - GANs 目前是生成式模型應用在 data augmentation 中最 promising 的領域 - DCGANs, Growing GANs, Conditional GANs ![](https://i.imgur.com/Wg5kJFy.jpg) - DCGANs : 用 CNNs 來做 generator 和 discriminator networks,架構是以 Deconvolution 反覆產生圖片,再將生成的圖片放入 discriminator 中訓練 ![](https://i.imgur.com/aIOZfc9.jpg) ![](https://i.imgur.com/kkaTeOC.jpg) - Progressive Growing GANs (PG-GAN): 先從解析度小的圖片開始訓練,再慢慢增大解析度 ![](https://i.imgur.com/9UqoBL7.jpg) ![](https://i.imgur.com/Q8tixU3.jpg) - Cycle GANs: 學習如何把一個領域的圖片轉換到另一個領域,比如把中立的人臉表情圖轉換到厭惡的人臉表情圖 ![](https://i.imgur.com/1Yynksr.jpg) ![](https://i.imgur.com/zPL7WXy.jpg) - t-SNE 可以用來了解 GAN-generated instance 和正常樣本的差別 ![](https://i.imgur.com/SIiRtDz.jpg) - Conditional GANs: 在 generator 和 discriminator 中加入 conditional vector 來緩解 mode collapse 問題 (產生很多看起來很像的 data 的問題) ![](https://i.imgur.com/RE1sVe2.jpg) - 除了以上幾種應用以外,GANs也能用來 oversampling 那些很少數的 sample,解決 class imblance 問題,例如 [DOPING, 2018](https://arxiv.org/abs/1808.07632) ![](https://i.imgur.com/1YC01ZJ.jpg) - 缺點是目前的 GANs 架構很難產生出高解析度的照片,若直接增加 output image size 很有可能導致訓練不穩定或是無法收斂,除此之外還有 **GANs 需要非常多的資料才有辦法訓練** ### Neural Style Transfer - 風格轉換的基本概念是操作 CNNs 所擷取出的 representation 來對圖片風格做轉換 - [Fast Style Transfer](https://arxiv.org/abs/1603.08155): 將 pixel-wise loss 改成 perceptual loss 並利用 feed-forward network 來轉換圖片的風格 - Perceptual loss 是指將真實圖片卷積和生成圖片卷積得到的 feature 做比較來算 loss ![](https://i.imgur.com/CniNkPF.jpg) ![](https://i.imgur.com/OF6nt58.jpg) - 如何選擇哪一個 style 來 sample 是 style transfer 的一大挑戰,比如自駕車需要 night-to-day scale, winter-to-summer, or rainy-to-sunny scale 的 transfer - 但 **Data Augmentation 為了實作上的方便,會挑選 k 個 styles 並 apply 到 training set 中的所有圖片上** - 在需要模擬的情境下,增強 Style transfer 中的 diversity 比盡全力模擬出現實環境還要有效率 - Neural Style Transfer Data Augmentation 最大的缺點是如何決定圖片要轉換的 styles 有哪些 - 假如 style set 太小,可能會引入更多的 bias 到 dataset 中 - 假如 style set 太大,又會造成計算量太大 ### Meta learning Data Augmentations - Meta-learning 的基本概念是訓練一個神經網路來優化神經網路 - [Neural Architecture Search, 2017](https://arxiv.org/abs/1611.01578) ![](https://i.imgur.com/apaJ8Iq.jpg) - Meta-learning for Data Aug-mentation 的方法不乏就是 mixing images, Neural Style Transfer, and geometric transformations ![](https://i.imgur.com/fDNeu11.jpg) - Meta-learning 的缺點是它仍是一個新領域並且研究還不夠多,除此之外它也非常 time-consuming to implement,所以我暫時不做深入研究 ## Comparing Augmentations [Research on data augmentation for image classification based on convolutional neural networks, 2017](https://ieeexplore.ieee.org/document/8243510) 在 CIFAR-10 和 ImageNet 中比較了 GANs, WGANs, flipping, cropping, shifting, PCA jittering, color jittering, adding noise, rotation 幾種方法的表現 - 單個方法來說,cropping, flipping, WGAN, and rotation 一般來講都比其他方法表現更好 - 混合方法來說,flipping+cropping 和 flipping + WGAN 表現最好 ## References - [A survey on Image Data Augmentation for Deep Learning](https://journalofbigdata.springeropen.com/track/pdf/10.1186/s40537-019-0197-0.pdf) - [Improving Deep Learning using Generic Data Augmentation](https://arxiv.org/pdf/1708.06020) - [What is PCA Color Augmentation?](https://aparico.github.io/) - [【影像處理】非銳化濾鏡 Unsharp Masking](https://jason-chen-1992.weebly.com/home/-unsharp-masking) - [Morphological Transformations in opencv](https://docs.opencv.org/4.5.3/d4/d76/tutorial_js_morphological_ops.html) - [数据增强 - Cutout、Random Erasing、Mixup、Cutmix](https://blog.csdn.net/irving512/article/details/113846570) - [Cutmix.. vs Mixup.. vs Gridmask ..vs Cutout... on Kaggle ](https://www.kaggle.com/saife245/cutmix-vs-mixup-vs-gridmask-vs-cutout#Cutout-data-augmentation) - [Survey: Image Mixing and Deleting for Data Augmentation](https://arxiv.org/pdf/2106.07085.pdf) - [albumentations docs](https://albumentations.ai/docs/api_reference/augmentations/) - [awesome-data-augmentation](https://brunokrinski.github.io/awesome-data-augmentation/)

    Import from clipboard

    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 lost their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template is not available.


    Upgrade

    All
    • All
    • Team
    No template found.

    Create custom template


    Upgrade

    Delete template

    Do you really want to delete this template?

    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

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox

    New to HackMD? Sign up

    Help

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

    Documents

    Tutorials

    Book Mode Tutorial

    Slide Mode Tutorial

    YAML Metadata

    Contacts

    Facebook

    Twitter

    Feedback

    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

    Versions and GitHub Sync

    Sign in to link this note to GitHub Learn more
    This note is not linked with GitHub Learn more
     
    Add badge Pull Push GitHub Link Settings
    Upgrade now

    Version named by    

    More Less
    • Edit
    • Delete

    Note content is identical to the latest version.
    Compare with
      Choose a version
      No search result
      Version not found

    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. Learn more

         Sign in to GitHub

        HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.

        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
        Available push count

        Upgrade

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Upgrade

        Danger Zone

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

        Syncing

        Push failed

        Push successfully