圖片編碼實踐
對圖片編碼的作用有很多:
- 極大降低圖片的存儲空間,相當於對圖片壓縮;
- 方便計算圖片與圖片之間的計算,這方面應用就很多了,比如相關圖片搜索等
非機器學習方法
非機器學習的方法有“感知哈希算法”(Perceptual hash algorithm),它的作用是對每張圖片生成一個”指紋”(fingerprint)字符串,然后比較不同圖片的指紋。結果越接近,就說明圖片越相似。由於生成的是64為01編碼,一般采用hamming距離來度量。
其中phash算法對於圖片縮放無感知,一般適合找到完全相同的圖片和縮略圖找圖,對於圖片相關但是不同的圖片效果比較差。
這種方法的特點是編碼速度很快,但是在很多業務上效果並不理想。該方法網上資料特別多,現成代碼也不少,大家可以自行翻閱,下面着重介紹下采用深度學習的一些實踐。
深度學習方法
深度學習的方法有基於有監督的編碼和無監督的編碼,使用場景不同。
有監督標簽的學習編碼
如果圖片是有類別分類的,可以通過分類模型,取中間的隱藏層來作為編碼輸出結果。
這種方法本質就是一個分類模型,輸出層的分類結果越准確,編碼效果也越好。
- 模型輸入為cifar10的樣本圖片(10個類別的32*32圖片);
- 圖片的特征提取采用卷積層+池化層若干,這里圖像是3通道的彩色圖片,然后拼接兩層全連接層(fc),最后通過softmax作為輸出層選擇分類;
- 當然也可以通過遷移學習如vgg16等模型來提升效果;
- 最后取全連接層128作為輸出進行編碼。
這種方法主要看分類效果,一般效果比較好。
非監督標簽的學習編碼
無監督編碼其實是自標注編碼思想,即通過編碼(壓縮)+解碼(解壓縮)的方式對圖片處理,將圖片作為壓縮后的短編碼輸出,作為圖片的表示。這種方法輸入和輸出相同,就無需人工標注,只要有圖片自己學自己即可。
這種形式也是最普遍的先編碼、再解碼的形式,同樣輸出中間層作為編碼結果。
模型結構同樣是利用卷積層+池化層來提取特征,上面的模型是和有監督的方式差不多,只不過最后一層輸出層和原始圖片大小一致,做回歸的誤差計算。如果不用全連接層,采用反卷積還原圖片,效果也是差不多的。
1 MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder() 2 .seed(12345) 3 .weightInit(WeightInit.XAVIER) 4 .updater(new AdaGrad(0.05)) 5 .activation(Activation.LEAKYRELU) 6 .l2(0.0001) 7 .list() 8 .layer(new ConvolutionLayer.Builder(2, 2) 9 .nIn(1) 10 .stride(1, 1) 11 .nOut(20) 12 .cudnnAlgoMode(cudnnAlgoMode) 13 .build()) 14 .layer(new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX) 15 .kernelSize(2, 2) 16 .stride(2, 2) 17 .build()) 18 .layer(new ConvolutionLayer.Builder(2, 2) 19 .stride(1, 1) // nIn need not specified in later layers 20 .nOut(50) 21 .cudnnAlgoMode(cudnnAlgoMode) 22 .build()) 23 .layer(new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.AVG) 24 .kernelSize(2, 2) 25 .stride(2, 2) 26 .build()) 27 .layer(new DenseLayer.Builder().nIn(height * width).nOut(1024).dropOut(0.6) 28 .build()) 29 .layer(new DenseLayer.Builder().nIn(1024).nOut(512) 30 .build()) 31 .layer(new DenseLayer.Builder().nIn(512).nOut(128) 32 .build()) 33 .layer(new DenseLayer.Builder().nIn(128).nOut(512) 34 .build()) 35 .layer(new DenseLayer.Builder().nIn(512).nOut(1024) 36 .build()) 37 .layer(new OutputLayer.Builder().nIn(1024).nOut(height * width) 38 .lossFunction(LossFunctions.LossFunction.MSE) 39 .build()) 40 .build();
實驗結果示例
挑選了一些試卷中的圖片縮放到64*64,由於對顏色沒有要求,就都處理成單通道黑白圖片了,計算量小一些,圖片如下:
根據訓練學習后,編碼后還原的圖片如下:
可以看出來還原的圖片幾乎效果已經很相近了。
【圖片相似度】我們選取一張圖片,通過模型取出128維編碼來找出圖庫中相關的圖片。左邊為原始比較圖片,右邊為其他Top5相關圖片:
總的來說效果還行,感興趣的同學可以進行嘗試。