单通道,三通道 介绍:
(一):单通道图,
俗称灰度图,每个像素点只能有有一个值表示颜色,它的像素值在0到255之间,0是黑色,255是白色,中间值是一些不同等级的灰色。(也有3通道的灰度图,3通道灰度图只有一个通道有值,其他两个通道的值都是零)。
(二):三通道图,每个像素点都有3个值表示 ,所以就是3通道。也有4通道的图。例如RGB图片即为三通道图片,RGB色彩模式是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。总之,每一个点由三个值表示。
轮廓检测 卷积层:
(一):卷积在 pytorch 中有两种方式,一种是 torch.nn.Conv2d()
,一种是 torch.nn.functional.conv2d()
,这两种形式本质都是使用一个卷积操作
这两种形式的卷积对于输入的要求都是一样的,首先需要输入是一个 torch.autograd.Variable()
的类型,大小是 (batch, channel, H, W),其中 batch 表示输入的一批数据的数目,第二个是输入的通道数,一般一张彩色的图片是 3,灰度图是 1,而卷积网络过程中的通道数比较大,会出现几十到几百的通道数,H 和 W 表示输入图片的高度和宽度,比如一个 batch 是 32 张图片,每张图片是 3 通道,高和宽分别是 50 和 100,那么输入的大小就是 (32, 3, 50, 100)
(二):图片读入的时候:格式(H, W, channel)
# -*- coding: utf-8 -*-
# @Time : 2021/1/14 12:06
# @Author : wwq_biubiu!!
# @FileName: chapter2_7_CNN_show.py
# @Software: PyCharm
import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
import torch.nn.functional as F
from PIL import Image
import matplotlib.pyplot as plt
from torchvision import transforms
import cv2
# 读入照片
im = Image.open('./data/face_1.jpeg')
# 将照片变成 np
plt.imshow(im, cmap='gray')
plt.show()
im = np.array(im, dtype='float32')
print(im.shape)
print(im[:][1][:].shape)
plt.imshow(im[:][:][1].astype('uint8'), cmap='gray')
plt.show()
# 将图片矩阵转化为pytorch tensor ,并适配卷积输入要求
im = np.transpose(im, (2, 1, 0))
im = im[np.newaxis, :]
print(im.shape)
conv1 = nn.Conv2d(3, 3, 3, bias= False) # 定义卷积
# sobel_kernel = np.array([[[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], [[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], [[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]]], dtype='float32') # 定义轮廓检测算子
sobel_kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], dtype='float32') / 3
# 将sobel算子转换为适配卷积操作的卷积核
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))
# 卷积输出通道,这里我设置为3
# np.repeats(a,repeats, axis=None)
# 其中a为数组,repeats为重复的次数,axis表示数组维度
sobel_kernel = np.repeat(sobel_kernel, 3, axis=1)
# 输入图的通道,这里我设置为3
print(sobel_kernel.shape)
sobel_kernel = np.repeat(sobel_kernel, 3, axis=0)
print(sobel_kernel.shape)
conv1.weight.data = torch.from_numpy(sobel_kernel)# 给卷积的 kernel 赋值
edge1 = conv1(Variable(torch.from_numpy(im)))# 作用在图片上
print(edge1.shape)
edge1 = edge1.data.squeeze().detach().numpy()# # 将输出转换为图片的格式
#edge1= edge1.reshape(3, 298, 299)
print('------')
print(edge1.shape)
edge1 = np.transpose(edge1,(2,1,0))
print(edge1.shape)
cv2.imshow('edge.jpg', edge1)
cv2.waitKey(0)
ouput:
(300, 301, 3)
(1, 3, 301, 300)
(1, 3, 3, 3)
(3, 3, 3, 3)
torch.Size([1, 3, 299, 298])
------
(3, 299, 298)
(298, 299, 3)
函数型代码;
import torch
import numpy as np
from torch import nn
from PIL import Image
from torch.autograd import Variable
import torch.nn.functional as F
def edge_conv2d(im):
# 用nn.Conv2d定义卷积操作
conv_op = nn.Conv2d(3, 3, kernel_size=3, padding=1, bias=False)
# 定义sobel算子参数,所有值除以3个人觉得出来的图更好些
sobel_kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], dtype='float32') / 3
# 将sobel算子转换为适配卷积操作的卷积核
sobel_kernel = sobel_kernel.reshape((1, 1, 3, 3))
# 卷积输出通道,这里我设置为3
sobel_kernel = np.repeat(sobel_kernel, 3, axis=1)
# 输入图的通道,这里我设置为3
sobel_kernel = np.repeat(sobel_kernel, 3, axis=0)
print(sobel_kernel.shape)
conv_op.weight.data = torch.from_numpy(sobel_kernel)
# print(conv_op.weight.size())
# print(conv_op, '\n')
edge_detect = conv_op(im)
print(torch.max(edge_detect))
# 将输出转换为图片格式
edge_detect = edge_detect.squeeze().detach().numpy()
print(edge_detect.shape)
return edge_detect
def edge_extraction():
im = cv2.imread("./data/face_1.jpeg", flags=1)
print(im.shape) # 图片的的张量(W,H,H)
im = np.transpose(im, (2, 0, 1))
print(im.shape)
# 添加一个维度,对应于pytorch模型张量(B, N, W, H)中的batch_size
im = im[np.newaxis, :]
print(im.shape)
im = torch.Tensor(im)
edge_detect = edge_conv2d(im)
edge_detect = np.transpose(edge_detect, (1, 2, 0))
cv2.imshow('edge.jpg', edge_detect)
cv2.waitKey(0)
cv2.imwrite('./data/fac3_1.jpeg', edge_detect)
if __name__ == "__main__":
edge_extraction()
池化层:
灰度值越高,最高值是255(白色),越暗的像素,灰度值越低,最低值是0(黑色)
import numpy as np
import torch
from torch import nn
from torch.autograd import Variable
import torch.nn.functional as F
from PIL import Image
import matplotlib.pyplot as plt
from torchvision import transforms
import cv2
# 读入照片
im = Image.open('./data/face_1.jpeg')
im = np.array(im, dtype='float32')
im = np.transpose(im, (2, 1, 0))
im = im[np.newaxis, :]
pool1 = nn.MaxPool2d(2,2)
print('before max pool, image shape: {} x {}'.format(im.shape[2], im.shape[3]))
small_im1 = pool1(Variable(torch.from_numpy(im)))
print(small_im1.shape)
small_im1 = small_im1.data.squeeze().numpy()
small_im1 = np.transpose(small_im1, (2, 1, 0))
small_im2 = F.max_pool2d(torch.from_numpy(im), 2, 2)
small_im2 = small_im2.data.squeeze().numpy()
print('after max pool, image shape: {} x {} '.format(small_im1.shape[0], small_im1.shape[1]))
print(small_im2.shape)
cv2.imshow('edge.jpg', small_im1)
cv2.waitKey(0)
output:
before max pool, image shape: 301 x 300
torch.Size([1, 3, 150, 150])
after max pool, image shape: 150 x 150
(3, 150, 150)
note: 可能是图片的质量问题 图片显示几乎是白色 。
reference;
https://wizardforcel.gitbooks.io/learn-dl-with-pytorch-liaoxingyu/content/4.1.html