此文轉(zhuǎn)自 知乎專欄 棉花糖的工坊 作者 棉花糖 (侵刪)
一直在學習圖像超分辨率和深度學習,看到此文寫得很好晰搀,故此轉(zhuǎn)載分享五辽。如有侵權(quán),私信聯(lián)系我外恕,我將作刪除杆逗。
超分辨率技術(shù)(Super-Resolution, SR)是指從觀測到的低分辨率圖像重建出相應(yīng)的高分辨率圖像,在監(jiān)控設(shè)備鳞疲、衛(wèi)星圖像和醫(yī)學影像等領(lǐng)域都有重要的應(yīng)用價值罪郊。
本文針對端到端的基于深度學習的單張圖像超分辨率方法(Single Image Super-Resolution, SISR),總結(jié)一下從SRCNN到EDSR的發(fā)展歷程尚洽。(排列順序大致按論文中給出的4倍上采樣結(jié)果的峰值信噪比(Peak Signal to Noise Ratio, PSNR)從低到高排列)
1. SRCNN
(Learning a Deep Convolutional Network for Image Super-Resolution, ECCV2014)
SRCNN是深度學習用在超分辨率重建上的開山之作悔橄。SRCNN的網(wǎng)絡(luò)結(jié)構(gòu)非常簡單,僅僅用了三個卷積層腺毫,網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示癣疟。
SRCNN首先使用雙三次(bicubic)插值將低分辨率圖像放大成目標尺寸,接著通過三層卷積網(wǎng)絡(luò)擬合非線性映射潮酒,最后輸出高分辨率圖像結(jié)果睛挚。本文中,作者將三層卷積的結(jié)構(gòu)解釋成三個步驟:圖像塊的提取和特征表示急黎,特征非線性映射和最終的重建扎狱。
三個卷積層使用的卷積核的大小分為為9x9,,1x1和5x5勃教,前兩個的輸出特征個數(shù)分別為64和32淤击。用Timofte數(shù)據(jù)集(包含91幅圖像)和ImageNet大數(shù)據(jù)集進行訓練。使用均方誤差(Mean Squared Error, MSE)作為損失函數(shù)故源,有利于獲得較高的PSNR污抬。
code: http://mmlab.ie.cuhk.edu.hk/projects/SRCNN.html
github(tensorflow): https://github.com/tegg89/SRCNN-Tensorflow
2. FSRCNN
(Accelerating the Super-Resolution Convolutional Neural Network, ECCV2016)
FSRCNN與SRCNN都是香港中文大學Dong Chao, Xiaoou Tang等人的工作心软。FSRCNN是對之前SRCNN的改進壕吹,主要在三個方面:一是在最后使用了一個反卷積層放大尺寸著蛙,因此可以直接將原始的低分辨率圖像輸入到網(wǎng)絡(luò)中,而不是像之前SRCNN那樣需要先通過bicubic方法放大尺寸耳贬。二是改變特征維數(shù)踏堡,使用更小的卷積核和使用更多的映射層。三是可以共享其中的映射層咒劲,如果需要訓練不同上采樣倍率的模型顷蟆,只需要fine-tuning最后的反卷積層。
由于FSRCNN不需要在網(wǎng)絡(luò)外部進行放大圖片尺寸的操作腐魂,同時通過添加收縮層和擴張層帐偎,將一個大層用一些小層來代替,因此FSRCNN與SRCNN相比有較大的速度提升蛔屹。FSRCNN在訓練時也可以只fine-tuning最后的反卷積層削樊,因此訓練速度也更快。FSRCNN與SCRNN的結(jié)構(gòu)對比如下圖所示兔毒。
FSRCNN可以分為五個部分漫贞。特征提取:SRCNN中針對的是插值后的低分辨率圖像,選取的核大小為9×9育叁,這里直接是對原始的低分辨率圖像進行操作迅脐,因此可以選小一點,設(shè)置為5×5豪嗽。收縮:通過應(yīng)用1×1的卷積核進行降維谴蔑,減少網(wǎng)絡(luò)的參數(shù),降低計算復雜度龟梦。非線性映射:感受野大隐锭,能夠表現(xiàn)的更好。SRCNN中变秦,采用的是5×5的卷積核成榜,但是5×5的卷積核計算量會比較大框舔。用兩個串聯(lián)的3×3的卷積核可以替代一個5×5的卷積核蹦玫,同時兩個串聯(lián)的小卷積核需要的參數(shù)3×3×2=18比一個大卷積核5×5=25的參數(shù)要小。FSRCNN網(wǎng)絡(luò)中通過m個核大小為3×3的卷積層進行串聯(lián)刘绣。擴張:作者發(fā)現(xiàn)低維度的特征帶來的重建效果不是太好樱溉,因此應(yīng)用1×1的卷積核進行擴維,相當于收縮的逆過程纬凤。反卷積層:可以堪稱是卷積層的逆操作福贞,如果步長為n,那么尺寸放大n倍停士,實現(xiàn)了上采樣的操作挖帘。
FSRCNN中激活函數(shù)采用PReLU完丽,損失函數(shù)仍然是均方誤差。對CNN來說拇舀,Set91并不足夠去訓練大的網(wǎng)絡(luò)結(jié)構(gòu)逻族,F(xiàn)SRCNN提出general-100 + Set91進行充當訓練集。并且進行數(shù)據(jù)增強骄崩,1)縮小尺寸為原來的0.9, 0.8, 0.7和0.6聘鳞。2)旋轉(zhuǎn) 90°,180°和270°要拂,因此獲得了數(shù)據(jù)量的提升抠璃。
code: http://mmlab.ie.cuhk.edu.hk/projects/FSRCNN.html
github(tensorflow): https://github.com/yifanw90/FSRCNN-TensorFlow
3. VDSR
(Accurate Image Super-Resolution Using Very Deep Convolutional Networks, CVPR2016)
在介紹VDSR之前,首先想先提一下何愷明在2015年的時候提出的殘差網(wǎng)絡(luò)ResNet脱惰。ResNet的提出搏嗡,解決了之前網(wǎng)絡(luò)結(jié)構(gòu)比較深時無法訓練的問題,性能也得到了提升拉一,ResNet也獲得了CVPR2016的best paper彻况。殘差網(wǎng)絡(luò)結(jié)構(gòu)(residual network)被應(yīng)用在了大量的工作中。
正如在VDSR論文中作者提到舅踪,輸入的低分辨率圖像和輸出的高分辨率圖像在很大程度上是相似的纽甘,也就是指低分辨率圖像攜帶的低頻信息與高分辨率圖像的低頻信息相近,訓練時帶上這部分會多花費大量的時間抽碌,實際上我們只需要學習高分辨率圖像和低分辨率圖像之間的高頻部分殘差即可悍赢。殘差網(wǎng)絡(luò)結(jié)構(gòu)的思想特別適合用來解決超分辨率問題,可以說影響了之后的深度學習超分辨率方法货徙。VDSR是最直接明顯的學習殘差的結(jié)構(gòu)左权,其網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示。
VDSR將插值后得到的變成目標尺寸的低分辨率圖像作為網(wǎng)絡(luò)的輸入痴颊,再將這個圖像與網(wǎng)絡(luò)學到的殘差相加得到最終的網(wǎng)絡(luò)的輸出赏迟。VDSR主要有4點貢獻。1.加深了網(wǎng)絡(luò)結(jié)構(gòu)(20層)蠢棱,使得越深的網(wǎng)絡(luò)層擁有更大的感受野锌杀。文章選取3×3的卷積核,深度為D的網(wǎng)絡(luò)擁有(2D+1)×(2D+1)的感受野泻仙。2.采用殘差學習糕再,殘差圖像比較稀疏,大部分值都為0或者比較小玉转,因此收斂速度快突想。VDSR還應(yīng)用了自適應(yīng)梯度裁剪(Adjustable Gradient Clipping),將梯度限制在某一范圍,也能夠加快收斂過程猾担。3.VDSR在每次卷積前都對圖像進行補0操作袭灯,這樣保證了所有的特征圖和最終的輸出圖像在尺寸上都保持一致,解決了圖像通過逐步卷積會越來越小的問題绑嘹。文中說實驗證明補0操作對邊界像素的預測結(jié)果也能夠得到提升妓蛮。4.VDSR將不同倍數(shù)的圖像混合在一起訓練,這樣訓練出來的一個模型就可以解決不同倍數(shù)的超分辨率問題圾叼。
code: https://cv.snu.ac.kr/research/VDSR/
github(caffe): https://github.com/huangzehao/caffe-vdsr
github(tensorflow): https://github.com/Jongchan/tensorflow-vdsr
github(pytorch): https://github.com/twtygqyy/pytorch-vdsr
4. DRCN
(Deeply-Recursive Convolutional Network for Image Super-Resolution, CVPR2016)
DRCN與上面的VDSR都是來自首爾國立大學計算機視覺實驗室的工作蛤克,兩篇論文都發(fā)表在CVPR2016上,兩種方法的結(jié)果非常接近夷蚊。DRCN第一次將之前已有的遞歸神經(jīng)網(wǎng)絡(luò)(Recursive Neural Network)結(jié)構(gòu)應(yīng)用在超分辨率處理中构挤。同時,利用殘差學習的思想(文中的跳躍連接(Skip-Connection))惕鼓,加深了網(wǎng)絡(luò)結(jié)構(gòu)(16個遞歸)筋现,增加了網(wǎng)絡(luò)感受野,提升了性能箱歧。DRCN網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示矾飞。
DRCN輸入的是插值后的圖像,分為三個模塊呀邢,第一個是Embedding network洒沦,相當于特征提取,第二個是Inference network, 相當于特征的非線性映射价淌,第三個是Reconstruction network,即從特征圖像恢復最后的重建結(jié)果申眼。其中的Inference network是一個遞歸網(wǎng)絡(luò),即數(shù)據(jù)循環(huán)地通過該層多次蝉衣。將這個循環(huán)進行展開括尸,等效于使用同一組參數(shù)的多個串聯(lián)的卷積層,如下圖所示病毡。
code: https://cv.snu.ac.kr/research/DRCN/
githug(tensorflow): https://github.com/jiny2001/deeply-recursive-cnn-tf
5. RED
(Image Restoration Using Convolutional Auto-encoders with Symmetric Skip Connections, NIPS2016)
這篇文章提出了由對稱的卷積層-反卷積層構(gòu)成的網(wǎng)絡(luò)結(jié)構(gòu)濒翻,作為一個編碼-解碼框架,可以學習由低質(zhì)圖像到原始圖像端到端的映射啦膜。網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示有送。
RED網(wǎng)絡(luò)的結(jié)構(gòu)是對稱的,每個卷積層都有對應(yīng)的反卷積層功戚。卷積層用來獲取圖像的抽象內(nèi)容娶眷,反卷積層用來放大特征尺寸并且恢復圖像細節(jié)似嗤。卷積層將輸入圖像尺寸減小后啸臀,再通過反卷積層上采樣變大,使得輸入輸出的尺寸一樣。每一組鏡像對應(yīng)的卷積層和反卷積層有著跳線連接結(jié)構(gòu)乘粒,將兩部分具有同樣尺寸的特征(要輸入卷積層的特征和對應(yīng)的反卷積層輸出的特征)做相加操作(ResNet那樣的操作)后再輸入到下一個反卷積層豌注,操作過程如下圖所示。
這樣的結(jié)構(gòu)能夠讓反向傳播信號能夠直接傳遞到底層灯萍,解決了梯度消失問題轧铁,同時能將卷積層的細節(jié)傳遞給反卷積層,能夠恢復出更干凈的圖片旦棉〕莘纾可以看到,網(wǎng)絡(luò)中有一條線是將輸入的圖像連接到后面與最后的一層反卷積層的輸出相加绑洛,也就是VDSR中用到的方式救斑,因此RED中間的卷積層和反卷積層學習的特征是目標圖像和低質(zhì)圖像之間的殘差。RED的網(wǎng)絡(luò)深度為30層真屯,損失函數(shù)用的均方誤差脸候。
6. DRRN
(Image Super-Resolution via Deep Recursive Residual Network, CVPR2017)
DRRN的作者應(yīng)該是受到了ResNet、VDSR和DRCN的啟發(fā)绑蔫,采用了更深的網(wǎng)絡(luò)結(jié)構(gòu)來獲取性能的提升运沦。作者也在文中用圖片示例比較了DRRN與上述三個網(wǎng)絡(luò)的區(qū)別,比較示例圖如下所示配深。
DRRN中的每個殘差單元都共同擁有一個相同的輸入携添,即遞歸塊中的第一個卷積層的輸出。每個殘差單元都包含2個卷積層篓叶。在一個遞歸塊內(nèi)薪寓,每個殘差單元內(nèi)對應(yīng)位置相同的卷積層參數(shù)都共享(圖中DRRN的淺綠色塊或淺紅色塊)。作者列出了ResNet澜共、VDSR向叉、DRCN和DRRN四者的主要策略。ResNet是鏈模式的局部殘差學習嗦董。VDSR是全局殘差學習母谎。DRCN是全局殘差學習+單權(quán)重的遞歸學習+多目標優(yōu)化。DRRN是多路徑模式的局部殘差學習+全局殘差學習+多權(quán)重的遞歸學習京革。
文章中比較了不同的遞歸塊和殘差單元數(shù)量的實驗結(jié)果奇唤,最終選用的是1個遞歸塊和25個殘差單元,深度為52層的網(wǎng)絡(luò)結(jié)構(gòu)匹摇∫龋總之,DRRN就是通過對之前已有的ResNet等結(jié)構(gòu)進行調(diào)整廊勃,采取更深的網(wǎng)絡(luò)結(jié)構(gòu)得到結(jié)果的提升懈贺。
github(caffe): tyshiwo/DRRN_CVPR17
github(pytorch): https://github.com/jt827859032/DRRN-pytorch
7. SRDenseNet
(Image Super-Resolution Using Dense Skip Connections, ICCV2017)
DenseNet是CVPR2017的best papaer獲獎?wù)撐木选enseNet在稠密塊(dense block)中將每一層的特征都輸入給之后的所有層,使所有層的特征都串聯(lián)(concatenate)起來梭灿,而不是像ResNet那樣直接相加画侣。這樣的結(jié)構(gòu)給整個網(wǎng)絡(luò)帶來了減輕梯度消失問題、加強特征傳播堡妒、支持特征復用配乱、減少參數(shù)數(shù)量的優(yōu)點。一個稠密塊的結(jié)構(gòu)如下圖所示皮迟。
SRDenseNet將稠密塊結(jié)構(gòu)應(yīng)用到了超分辨率問題上搬泥,取得了不錯的效果。網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示伏尼。
SRDenseNet可以分成四個部分佑钾。首先是用一個卷積層學習低層的特征,接著用多個稠密塊學習高層的特征烦粒,然后通過幾個反卷積層學到上采樣濾波器參數(shù)休溶,最后通過一個卷積層生成高分辨率輸出。
文章中針對用于最后重建的輸入內(nèi)容不同扰她,設(shè)計了三種結(jié)構(gòu)并做了比較兽掰。一是反卷積層只輸入最頂層稠密塊的輸出。二是添加了一個跳躍連接徒役,將最底層卷積層的輸出特征和最頂層稠密塊的輸出特征串聯(lián)起來孽尽,再輸入反卷積層。三是添加了稠密跳躍連接忧勿,就是把稠密塊看成一個整體杉女,第一個卷積層的輸出以及每個稠密塊的輸出,都輸入給在之后的所有稠密塊鸳吸,像是把在反卷積層之前的整個網(wǎng)絡(luò)也設(shè)計成像稠密塊那樣的結(jié)構(gòu)熏挎。由于這樣做,所有的特征都串聯(lián)起來晌砾,這樣直接輸入反卷積層會產(chǎn)生巨大的計算開銷坎拐,因此添加了一個核大小為1×1的卷積層來減小特征數(shù)量,這個卷積層被稱為瓶頸層养匈。最后的結(jié)果是越復雜的越好哼勇,3>2>1。文章中分析的是呕乎,受益于低層特征和高層特征的結(jié)合积担,超分辨率重建的性能得到了提升。像第三種結(jié)構(gòu)把所有深度層的特征都串聯(lián)起來猬仁,得到了最佳的結(jié)果帝璧,說明不同深度層的特征之間包含的信息是互補的先誉。
8. SRGAN(SRResNet)
(Photo-Realistic Single Image Super-Resolution Using a Generative Adversarial Network, CVPR2017)
在這篇文章中,將生成對抗網(wǎng)絡(luò)(Generative Adversarial Network, GAN)用在了解決超分辨率問題上聋溜。文章提到谆膳,訓練網(wǎng)絡(luò)時用均方差作為損失函數(shù)叭爱,雖然能夠獲得很高的峰值信噪比撮躁,但是恢復出來的圖像通常會丟失高頻細節(jié),使人不能有好的視覺感受买雾。SRGAN利用感知損失(perceptual loss)和對抗損失(adversarial loss)來提升恢復出的圖片的真實感把曼。感知損失是利用卷積神經(jīng)網(wǎng)絡(luò)提取出的特征,通過比較生成圖片經(jīng)過卷積神經(jīng)網(wǎng)絡(luò)后的特征和目標圖片經(jīng)過卷積神經(jīng)網(wǎng)絡(luò)后的特征的差別漓穿,使生成圖片和目標圖片在語義和風格上更相似嗤军。一個GAN所要完成的工作,GAN原文舉了個例子:生成網(wǎng)絡(luò)(G)是印假鈔的人晃危,判別網(wǎng)絡(luò)(D)是檢測假鈔的人叙赚。G的工作是讓自己印出來的假鈔盡量能騙過D,D則要盡可能的分辨自己拿到的鈔票是銀行中的真票票還是G印出來的假票票僚饭。開始的時候呢震叮,G技術(shù)不過關(guān),D能指出這個假鈔哪里很假鳍鸵。G每次失敗之后都認真總結(jié)經(jīng)驗苇瓣,努力提升自己,每次都進步偿乖。直到最后击罪,D無法判斷鈔票的真假……SRGAN的工作就是: G網(wǎng)通過低分辨率的圖像生成高分辨率圖像,由D網(wǎng)判斷拿到的圖像是由G網(wǎng)生成的贪薪,還是數(shù)據(jù)庫中的原圖像媳禁。當G網(wǎng)能成功騙過D網(wǎng)的時候,那我們就可以通過這個GAN完成超分辨率了画切。
文章中损话,用均方誤差優(yōu)化SRResNet(SRGAN的生成網(wǎng)絡(luò)部分),能夠得到具有很高的峰值信噪比的結(jié)果槽唾。在訓練好的VGG模型的高層特征上計算感知損失來優(yōu)化SRGAN丧枪,并結(jié)合SRGAN的判別網(wǎng)絡(luò),能夠得到峰值信噪比雖然不是最高庞萍,但是具有逼真視覺效果的結(jié)果拧烦。SRGAN網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示。
在生成網(wǎng)絡(luò)部分(SRResNet)部分包含多個殘差塊钝计,每個殘差塊中包含兩個3×3的卷積層恋博,卷積層后接批規(guī)范化層(batch normalization, BN)和PReLU作為激活函數(shù)齐佳,兩個2×亞像素卷積層(sub-pixel convolution layers)被用來增大特征尺寸。在判別網(wǎng)絡(luò)部分包含8個卷積層债沮,隨著網(wǎng)絡(luò)層數(shù)加深炼吴,特征個數(shù)不斷增加,特征尺寸不斷減小疫衩,選取激活函數(shù)為LeakyReLU硅蹦,最終通過兩個全連接層和最終的sigmoid激活函數(shù)得到預測為自然圖像的概率。SRGAN的損失函數(shù)為:
其中內(nèi)容損失可以是基于均方誤差的損失的損失函數(shù):
也可以是基于訓練好的以ReLU為激活函數(shù)的VGG模型的損失函數(shù):
i和j表示VGG19網(wǎng)絡(luò)中第i個最大池化層(maxpooling)后的第j個卷積層得到的特征闷煤。對抗損失為:
文章中的實驗結(jié)果表明童芹,用基于均方誤差的損失函數(shù)訓練的SRResNet,得到了結(jié)果具有很高的峰值信噪比鲤拿,但是會丟失一些高頻部分細節(jié)假褪,圖像比較平滑。而SRGAN得到的結(jié)果則有更好的視覺效果近顷。其中生音,又對內(nèi)容損失分別設(shè)置成基于均方誤差、基于VGG模型低層特征和基于VGG模型高層特征三種情況作了比較窒升,在基于均方誤差的時候表現(xiàn)最差缀遍,基于VGG模型高層特征比基于VGG模型低層特征的內(nèi)容損失能生成更好的紋理細節(jié)。
github(tensorflow): https://github.com/zsdonghao/SRGAN
github(tensorflow): https://github.com/buriburisuri/SRGAN
github(torch): https://github.com/junhocho/SRGAN
github(caffe): https://github.com/ShenghaiRong/caffe_srgan
github(tensorflow): https://github.com/brade31919/SRGAN-tensorflow
github(keras): https://github.com/titu1994/Super-Resolution-using-Generative-Adversarial-Networks
github(pytorch): ai-tor/PyTorch-SRGAN
9. EDSR
(Enhanced Deep Residual Networks for Single Image Super-Resolution, CVPRW2017)
EDSR是NTIRE2017超分辨率挑戰(zhàn)賽上獲得冠軍的方案异剥。如論文中所說瑟由,EDSR最有意義的模型性能提升是去除掉了SRResNet多余的模塊,從而可以擴大模型的尺寸來提升結(jié)果質(zhì)量冤寿。EDSR的網(wǎng)絡(luò)結(jié)構(gòu)如下圖所示歹苦。
EDSR
可以看到,EDSR在結(jié)構(gòu)上與SRResNet相比督怜,就是把批規(guī)范化處理(batch normalization, BN)操作給去掉了殴瘦。文章中說,原始的ResNet最一開始是被提出來解決高層的計算機視覺問題号杠,比如分類和檢測蚪腋,直接把ResNet的結(jié)構(gòu)應(yīng)用到像超分辨率這樣的低層計算機視覺問題,顯然不是最優(yōu)的姨蟋。由于批規(guī)范化層消耗了與它前面的卷積層相同大小的內(nèi)存屉凯,在去掉這一步操作后,相同的計算資源下眼溶,EDSR就可以堆疊更多的網(wǎng)絡(luò)層或者使每層提取更多的特征悠砚,從而得到更好的性能表現(xiàn)。EDSR用L1范數(shù)樣式的損失函數(shù)來優(yōu)化網(wǎng)絡(luò)模型堂飞。在訓練時先訓練低倍數(shù)的上采樣模型灌旧,接著用訓練低倍數(shù)上采樣模型得到的參數(shù)來初始化高倍數(shù)的上采樣模型绑咱,這樣能減少高倍數(shù)上采樣模型的訓練時間,同時訓練結(jié)果也更好枢泰。
這篇文章還提出了一個能同時不同上采樣倍數(shù)的網(wǎng)絡(luò)結(jié)構(gòu)MDSR描融,如下圖。
MDSR
MDSR的中間部分還是和EDSR一樣衡蚂,只是在網(wǎng)絡(luò)前面添加了不同的預訓練好的模型來減少不同倍數(shù)的輸入圖片的差異窿克。在網(wǎng)絡(luò)最后,不同倍數(shù)上采樣的結(jié)構(gòu)平行排列來獲得不同倍數(shù)的輸出結(jié)果讳窟。
從文章給出的結(jié)果可以看到让歼,EDSR能夠得到很好的結(jié)果敞恋。增大模型參數(shù)數(shù)量以后丽啡,結(jié)果又有了進一步的提升。因此如果能夠解決訓練困難的問題硬猫,網(wǎng)絡(luò)越深补箍,參數(shù)越多,對提升結(jié)果確實是有幫助吧啸蜜。
github(torch): https://github.com/LimBee/NTIRE2017
github(tensorflow): https://github.com/jmiller656/EDSR-Tensorflow
github(pytorch): https://github.com/thstkdgus35/EDSR-PyTorch
通過以上11篇有關(guān)深度學習超分辨率方法的論文坑雅,可以看到通過網(wǎng)絡(luò)結(jié)構(gòu)、損失函數(shù)以及訓練方式的演變衬横,深度學習超分辨率方法在結(jié)果裹粤、速度以及應(yīng)用性上都有了不斷的提高。這里再放上一篇深度學習超分辨率方法綜述的鏈接(Super-Resolution via Deep Learning)以及github上一個超分辨率方法的總結(jié)(https://github.com/YapengTian/Single-Image-Super-Resolution)蜂林。
非常感謝許多知乎和博客上的文章遥诉,由于比較多,這里列出參考得比較多的幾個資源:
https://zhuanlan.zhihu.com/p/25532538?utm_source=tuicool&utm_medium=referral
http://blog.csdn.net/u011692048/article/category/7121139
http://blog.csdn.net/wangkun1340378/article/category/7004439
作者:Sunglam
鏈接:http://www.reibang.com/p/e3b1f7ec321d
來源:簡書
著作權(quán)歸作者所有噪叙。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)矮锈,非商業(yè)轉(zhuǎn)載請注明出處。