1. 論Conv2d()里的padding和Conv2d()前padding的區別及重要性。 小生建議,儘量少用Conv2d()里的填充方式,換成自定義填充方式(強烈建議)。 小生為何這樣建議呢,是因為小生以前就常使用Conv2d()里的padding方式,覺得這樣使用簡單、不麻煩(O(∩_∩)O哈 ...
1. 論Conv2d()里的padding和Conv2d()前padding的區別及重要性。
小生建議,儘量少用Conv2d()里的填充方式,換成自定義填充方式(強烈建議)。
小生為何這樣建議呢,是因為小生以前就常使用Conv2d()里的padding方式,覺得這樣使用簡單、不麻煩(O(∩_∩)O哈哈~ 感覺當時好憨喲!)。可是在某一次實驗中,得到的效果圖在邊緣位置十分不理想,我想啊想,想啊想,圖像邊緣位置我只做過零填充,當時就引起了我的註意,然後通過做對比實驗,發現問題還真是由零填充導致的,太開心了(*^▽^*),實驗又有突破了。這次不在捲積時做零填充,換成捲積前做重覆填充。什麼是重覆填充了?就是複製邊緣的像素來填充。
Conv2d()里的padding,採用的是零填充,即在圖像像素周圍填充零像素點,這樣做的壞處是很可能在邊緣處產生偽影。還有一點就是Pytorch中Conv2d()捲積,當捲積核的尺寸是偶數時,不好做‘same’方式捲積,因為Conv2d()在填充時,上邊緣與下邊緣填充數是一樣的,很難改變。
Conv2d()前的padding,可以根據自己的需求填充,目前有四種填充方式,① 零填充;② 常數填充;③ 鏡像填充;④ 重覆填充;這種方式比較靈活,也很簡單,客觀可以根據自己的需求來選擇使用,四種填充方式,可查看小生的另一篇博文。
小生就不多言了,上案列,客官請下觀~~。
2. 例子
2.1 Conv2d()零填充
2.1.1 Code
小生在這裡給了代碼片段,這裡就是想告訴客官怎麼做捲積的填充。
# 讀取圖片 image1_path = "./fusion_datasets/lytro-01-A.jpg" image1 = Image.open(image1_path) # 歸一化處理和轉為tensor input_transform = transforms.Compose([ transforms.Grayscale(1), transforms.ToTensor(), ]) image1_tensor = input_transform(image1).unsqueeze(0) # 捲積 conv2 = nn.Conv2d(1, 3, 8,padding = 4) image1_conv = conv2(image1_pad)
2.1.2 結果顯示
客官勿怪,此圖是我的實驗,過程中的圖,還沒做到最好的效果,O(∩_∩)O哈哈~,有點不好意思了,捂臉(*/ω\*)!客官請看邊緣處,是不是很多白點,這都是零填充導致的效果不好,將這張圖和自定義填充之邊緣填充的圖對照。
2.2 自定義填充之邊緣複製填充
2.2.1 Code
小生在這裡給了代碼片段,這裡就是想告訴客官怎麼做捲積前的填充。
# 讀取圖片 image1_path = "./fusion_datasets/lytro-01-A.jpg" image1 = Image.open(image1_path) # 歸一化處理和轉為tensor input_transform = transforms.Compose([ transforms.Grayscale(1), transforms.ToTensor(), ]) image1_tensor = input_transform(image1).unsqueeze(0) # 自定義填充之邊緣複製填充 ReplicationPad = nn.ReplicationPad2d(padding=(3, 4, 3, 4)) image1_pad = ReplicationPad(image1_tensor) # 捲積 conv2 = nn.Conv2d(1, 3, 8) image1_conv = conv2(image1_pad)
2.2.2 結果顯示
此圖與上圖對照,邊緣的白點基本沒有了,嘿嘿(*^▽^*),好開心(*^▽^*)!
3. 總結
努力去愛周圍的每一個人,付出,不一定有收穫,但是不付出就一定沒有收穫! 給街頭賣藝的人零錢,不和深夜還在擺攤的小販討價還價。願我的博客對你有所幫助(*^▽^*)(*^▽^*)!
如果客官喜歡小生的園子,記得關註小生喲,小生會持續更新(#^.^#)(#^.^#)!