focus模块主要由下面几部分组成,代码用cv2读取图片,并对图片做了focus处理。
1.定义激活函数SILU。
2.定义一个卷积模块Conv。就是标准卷积+BN+激活函数(SiLU)。
3.定义一个autopad模块。我们知道,在conv模块的conv2D函数里有pad填充参数,为了使填充后的矩阵维度和原矩阵维度相同,我们需要计算矩阵的上下左右各填充几行(列),而autopad模块的返回值就是计算的pad需要填充的单侧的行(列)数。
4.定义focus。在该代码中,focus将640X640X3的tensor矩阵转换为了320X320X12的tensor矩阵。
具体的代码解析如下:
import torch import cv2 import numpy as np import torch.nn as nn #https://blog.csdn.net/weixin_51322383/article/details/130379982 #定义一个激活函数SILU class SiLU(nn.Module): @staticmethod def forward(x): return x * torch.sigmoid(x) #1.这个模块可以根据输入的卷积核计算卷积模块需要的pad值。用于下面的Conv类和Classify类中。主要是为了把tensor补成原来的形状 # pad是图片的上下左右要用0填充的尺寸,由于上下左右是对称的,所以返回值要整除2 def autopad(k, p=None): ''' v5中只有两种卷积: 1、下采样卷积:conv3x3 s=2 p=k//2=1 2、feature size不变的卷积:conv1x1 s=1 p=k//2=1 k:卷积核的kernel_size ''' #这里首先是判断是否有p值: # 如果有既定的 p ,则直接 return p,自动计算所需要的pad值 # 如果无设定的 p,则 return 使图像在卷积操作后尺寸不变的 p if p is None: p = k // 2 if isinstance(k, int) else [x // 2 for x in k] return p class Focus(nn.Module): def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): # ch_in, ch_out, kernel, stride, padding, groups super(Focus, self).__init__() self.conv = Conv(c1 * 4, c2, k, s, p, g, act) def forward(self, x): # 320, 320, 12 => 320, 320, 64 return self.conv( # 640, 640, 3 => 320, 320, 12 torch.cat( [ x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2] ],1 ) ) # Standard convolution 标准卷积+BN+hardswish激活(SiLU) class Conv(nn.Module): def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):# ch_in, ch_out, kernel, stride, padding, groups super(Conv, self).__init__() self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False) self.bn = nn.BatchNorm2d(c2, eps=0.001, momentum=0.03) #激活函数 self.act = SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity()) def forward(self, x): return self.act(self.bn(self.conv(x)))#用到BN def fuseforward(self, x):#没用BN """用于Model类的fuse函数 融合conv+bn 加速推理 一般用于测试/验证阶段 """ return self.act(self.conv(x)) image_path=r"E:\daima\python\img\1.jpg" image=cv2.imread(image_path) #image=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) image=cv2.resize(image,(640,640)) image=image.reshape(1,3,640,640) print(image.shape) x=torch.from_numpy(image).float() #输入的是tensor类型的4维数据,,数据大小为1X3X640X640 y=Focus(3,12) y=y(x) print(y) print(y.shape)