CNN卷積網絡_圖像處理


本文主要從卷積, 圖像, 圖像的卷積處理, 卷積神經網絡CNN的構建三部分,從理論到代碼應用
使用python3.6編譯器, jupyter編輯器
未完待續…

一、卷積介紹

1、origination:

一個面積不變的長方形,底邊被擠的窄窄的,高度被擠的高高的,在數學中它可以被擠到無限高,但即使它無限瘦、無限高、但它仍然保持面積不變;爲了證實它的存在,可以對它進行積分。

2、significance:

  • 意義1
    假設system1, 時刻t輸入爲x(t), 輸出爲y(t), 系統響應時間爲h(t), 按道理輸入輸出關係是y(y)=h(t)*x(t); however, 系統輸出不僅與系統t時刻相關, 還與t時刻之前響應相關, 所以t時刻的輸出應該爲t時刻之前系統響應函數在各個時刻響應的疊加,這就是卷積,用數學公式表示就是y(s)=∫x(t)h(s-t)dt
  • 物理意義
    在這裏插入圖片描述
    卷積圖像處理方面的應用
    用一個模板和一幅圖像進行卷積,對於圖像上的一個點,讓模板的原點和該點重合,然後模板上的點和圖像上對應的點相乘,然後各點的積相加,就得到了該點的卷積值。對圖像上的每個點都這樣處理。由於大多數模板都是對稱的,所以模板不旋轉。卷積是一種積分運算,用來求兩個曲線重疊區域面積。可以看作加權求和,可以用來消除噪聲、特徵增強。
    把一個點的像素值用它周圍的點的像素值的加權平均代替。
    卷積是一種線性運算,圖像處理中常見的mask運算都是卷積,廣泛應用於圖像濾波。
    卷積在數據處理中用來平滑,卷積有平滑效應和展寬效應.
    參考:卷積的本質及物理意義(全面理解卷積)

3、卷積計算

爲了更好的理解, 直接上例子

a-、濾波器(卷積核)

在這裏插入圖片描述

a、卷積例子

在這裏插入圖片描述
在這裏插入圖片描述

b、卷積之padding填充

在這裏插入圖片描述填充方法有:
補零填充
在這裏插入圖片描述
邊界複製填充, 鏡像填充, 塊填充

c、步幅

在這裏插入圖片描述### d、計算增加參數後, 卷積輸出shape
在這裏插入圖片描述

e、注意

在這裏插入圖片描述

f、整體理解

在這裏插入圖片描述

二、圖像處理基礎

1、讀取圖像

import numpy as np
import matplotlib.pyplot as plt
import sys,os
sys.path.append(os.pardir)
%matplotlib inline
img = np.array(plt.imread("../data/劉亦菲.jpg")) # 將圖像格式轉化np.array格式,方便後續處理
plt.figure("劉大姐")
plt.imshow(img)  # 函數負責對圖像進行處理,並顯示其格式,但是不能顯示
plt.axis("off")
plt.show()
print( img.shape )  
print( img.dtype ) 
print( img.size  )
print( type(img) )
print(img[0,0]) # 因爲是RGB三通道
(1200, 1920, 3)
uint8
6912000
<class 'numpy.ndarray'>
[ 95  96 124]

在這裏插入圖片描述

2、撒點椒鹽

#隨機生成5000個椒鹽
rows,cols,dims=img.shape
for i in range(5000):
    x=np.random.randint(0,rows) # 在0-rows之間隨便取值
    y=np.random.randint(0,cols) # 
    img[x,y,:]=255  # 將這個隨機點設置爲白點, 即椒鹽
    
plt.figure("beauty")
plt.imshow(img)
plt.axis('off')
plt.show()

在這裏插入圖片描述

3、圖像二值化

# 圖像二值化
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
 
img = np.array(Image.open("../data/劉亦菲.jpg").convert('L'))
rows, cols = img.shape
for i in range(rows):
    for j in range(cols):
        if (img[i, j] <= 128):
            img[i, j] = 0
        else:
            img[i, j] = 1
 
plt.figure("Mona Lisa")
plt.imshow(img, cmap='gray')
plt.axis('off')
plt.show()

在這裏插入圖片描述

4、分量提取

import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
img = np.array(plt.imread("../data/劉亦菲.jpg"))
plt.imshow(img[:, :, 0], cmap="gray") #L 分量轉化爲灰度圖
plt.show()

plt.imshow(img[:, :, 1], cmap="gray") #G 分量轉化爲灰度圖
plt.show()

plt.imshow(img[:, :, 1], ) # 只顯示G 分量
plt.show()

在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述

5、灰度圖片

from PIL import Image
img = np.array([1]) # 讀取圖片,並轉換爲灰度圖片
img_1 = Image.open("../data/劉亦菲.jpg").convert('1') # 非黑即白
img = np.array(Image.open("../data/劉亦菲.jpg").convert('L')) # 0黑255白,其他數字灰度不同

plt.imshow(img_1, cmap="gray") # 圖片只顯示像素點爲0或者255的值
plt.show()

plt.imshow(img, cmap="gray")
plt.show()

在這裏插入圖片描述在這裏插入圖片描述

6、圖像卷積處理之numpy

  • 本部分的圖像卷積處理使用的是科學計算包numpy , 利用numpy的廣播功能, 能夠很簡單的進行矩陣運。
  • 本部分的圖像卷積, 是直接將圖像的每一個像素點的三個通道的像素都進行了卷積處理,然後顯示
# 圖像卷積運算
import numpy as np
import matplotlib.pyplot as plt
import sys
sys.path.append("../")
%matplotlib inline
img = np.array(plt.imread("../data/劉亦菲.jpg"))
# 構建輸出矩陣形狀, 使用0填充, 
def generate_dst(img, kernel, stride=1, padding=0):  #默認步幅=1, 填充爲0
    m = (img.shape[0] + 2*padding - kernel.shape[0] + stride)/stride # 高
    n = (img.shape[1] + 2*padding - kernel.shape[1] + stride)/stride # 長
    rgb_channel = img.shape[2] # RGB三通道
    print("新構建的圖片形狀%0.3f,%0.3f,%0.3f"%(m,n,rgb_channel))
    return np.zeros((int(m),int(n),int(rgb_channel)),)

# 單個卷積核的運算
def div_convolution(img_block,kernel):
    _img = np.array(img_block).flatten() #轉化爲一維
    _kernel = np.array(kernel).flatten()
    # return np.mean(_img*_kernel) # 
    return np.sum(_img*_kernel) # 正常的卷積運算是直接加和,並不進行均值計算


# 將圖片按照convolution變換, 注意這裏還沒有對最終結果進行歸一化
def convolution2dst(img,dst,kernel):
    for i in range(dst.shape[0]):
        for j in range(dst.shape[1]):
            for k in range(dst.shape[2]): #通道
                dst[i,j,k] = div_convolution(img[i:i+kernel.shape[0],
                                                 j:j+kernel.shape[1],k], # 與kernel一致的矩陣
                                             kernel)

                
# 將圖片歸一化到256之間                                             
def img2normalization_256(img_convolution):
    _img = img_convolution.flatten()
    _max = np.max(_img)
    _min = np.min(_img)
    _img = (_img-_min)*255/(_max-_min)
    _img = np.array(_img, dtype="int64") # 將所有數據轉化爲int型
    img_convolution_normalization = _img.reshape((img_convolution.shape[0],
                                                  img_convolution.shape[1],
                                                  img_convolution.shape[2]))
    return img_convolution_normalization     

def convolution(img,kernel,is_normalization=False):
    dst = generate_dst(img,kernel)
    convolution2dst(img,dst,kernel)
    if not is_normalization:
        return dst
    else:
        new_img = img2normalization_256(dst)
        return new_img

img = np.array(plt.imread("../data/劉亦菲.jpg"))
test_kernel = np.array([[-1, -1, -1],
                       [-1, 9, -1],
                       [-1, -1, -1]])
img_convolution = convolution(img,test_kernel, True)
# 顯示直接卷積後的結果
plt.figure("劉大姐")
plt.imshow(img_convolution)
plt.axis("off")
plt.show()
print(img_convolution[0,0])

在這裏插入圖片描述

# 顯示處理完的圖像
img_convolution = img2normalization_256(img_convolution)
plt.figure("劉大姐")
plt.imshow(img_convolution)
plt.axis("off")
plt.show()

神奇

7、圖像卷積處理之tensorflow

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
%matplotlib inline
'''
tf.nn.conv2d(input=, # 輸入圖像 [batch, height, width, channels]
            filter=, # 卷積核, 
            strides=, # 步幅 一維向量,長度爲4
            padding, # 擴展 SAME表示在掃描的時候,如果遇到卷積核比剩下的元素要大時,這個時候需要補0進行最後一次的行掃描或者列掃描
            use_cudnn # 啓用cudnn加速
            name) # 執行該操作name
'''

img = np.array([1]) # 讀取圖片,並轉換爲灰度圖片
Image.open("../data/劉亦菲.jpg").convert('1') # 非黑即白
img = np.array(Image.open("../data/劉亦菲.jpg").convert('L')) # 0黑255白,其他數字灰度不同



img_full = np.reshape(img, [1, img.shape[0], img.shape[1], 1]) 
print(img_full.shape)    #   (1, 1200, 1920, 1)
#創建佔位
input_full = tf.Variable(tf.constant(1.0, shape=img_full.shape)) 
# input_full = tf.Variable(img_R_full, dtype=tf.float32) # 可以直接輸入

# 創建卷積核
filter_kernel = tf.Variable(tf.constant([#[1.0, 2, 1], [0, 0, 0], [-1, -2, -1]  # 水平邊緣濾波器
                                         #[0, -4, 0], [-4, 16, -4], [0, -4, 0]  # 整體邊緣濾波器
                                         # [1, 0, -1], [2, 0, -2], [1, 0, -1]  # 垂直邊緣濾波器
                                        [-1,-1,-1],[-1,9,-1],[-1,-1,-1]
                                        ],                                
                                 shape = [3,3,1, 1], dtype="float32")) # 3卷積核格式爲3*3  輸入通道1, 輸出通道1

op = tf.nn.conv2d(input_full, filter=filter_kernel, strides=[1,1,1,1], padding="VALID") # SAME是自動填充, 這裏選擇不自動填充的VALID
o=tf.cast(((op-tf.reduce_min(op))/(tf.reduce_max(op)-tf.reduce_min(op)) ) *255 ,tf.uint8) # 歸一化, 因爲經過卷積後像素會有不在0-255範圍內的

with tf.Session() as sess:  
    sess.run(tf.global_variables_initializer()  )  
    conv_img = sess.run(o, feed_dict={ input_full:img_full})
    print(conv_img.shape)
    
    conv_img = conv_img.reshape([conv_img.shape[1], conv_img.shape[2]])
    plt.imshow(conv_img, cmap="gray") # 顯示圖片
    plt.axis('off') # 不顯示座標軸
    plt.show()
(1, 1200, 1920, 1)
(1, 1198, 1918, 1)

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章