├── 0258a138641c4c9480eecf1b05d59cbb.webp ├── 0a16768dd14e7e7fd2881210995d462c.webp ├── 2666583ab1b69c16b4edd1d22a96e161.webp ├── 600fd61971c4afc898c84adf6442c923.webp ├── 6ea94504f24e7da8f786c95d14d474d1.webp ├── 70a90f5def5b74c3548f7f3aaf872df6.webp ├── 97a220cd5a1e3543892b039fb5e06872.webp ├── c46f854136aa792a74bc74236c41a51f.webp ├── c88d9b7a210d974e4a4a476fab03a44a.webp ├── c96fcb4e3dd2feeb2dd50d7a77026568.webp ├── d6fa7460f88f099d4120dcf8d97b3a26.webp ├── common.py ├── MHSA.py └── README.md /0258a138641c4c9480eecf1b05d59cbb.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/0258a138641c4c9480eecf1b05d59cbb.webp -------------------------------------------------------------------------------- /0a16768dd14e7e7fd2881210995d462c.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/0a16768dd14e7e7fd2881210995d462c.webp -------------------------------------------------------------------------------- /2666583ab1b69c16b4edd1d22a96e161.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/2666583ab1b69c16b4edd1d22a96e161.webp -------------------------------------------------------------------------------- /600fd61971c4afc898c84adf6442c923.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/600fd61971c4afc898c84adf6442c923.webp -------------------------------------------------------------------------------- /6ea94504f24e7da8f786c95d14d474d1.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/6ea94504f24e7da8f786c95d14d474d1.webp -------------------------------------------------------------------------------- /70a90f5def5b74c3548f7f3aaf872df6.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/70a90f5def5b74c3548f7f3aaf872df6.webp -------------------------------------------------------------------------------- /97a220cd5a1e3543892b039fb5e06872.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/97a220cd5a1e3543892b039fb5e06872.webp -------------------------------------------------------------------------------- /c46f854136aa792a74bc74236c41a51f.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/c46f854136aa792a74bc74236c41a51f.webp -------------------------------------------------------------------------------- /c88d9b7a210d974e4a4a476fab03a44a.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/c88d9b7a210d974e4a4a476fab03a44a.webp -------------------------------------------------------------------------------- /c96fcb4e3dd2feeb2dd50d7a77026568.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/c96fcb4e3dd2feeb2dd50d7a77026568.webp -------------------------------------------------------------------------------- /d6fa7460f88f099d4120dcf8d97b3a26.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qunshansj/fruit-recognition-system-botnet-transformer-yolov7/HEAD/d6fa7460f88f099d4120dcf8d97b3a26.webp -------------------------------------------------------------------------------- /common.py: -------------------------------------------------------------------------------- 1 | python 2 | class MHSA(nn.Module): 3 | def __init__(self, n_dims, width=14, height=14, heads=4, pos_emb=False): 4 | super(MHSA, self).__init__() 5 | 6 | self.heads = heads 7 | self.query = nn.Conv2d(n_dims, n_dims, kernel_size=1) 8 | self.key = nn.Conv2d(n_dims, n_dims, kernel_size=1) 9 | self.value = nn.Conv2d(n_dims, n_dims, kernel_size=1) 10 | self.pos = pos_emb 11 | if self.pos: 12 | self.rel_h_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, 1, int(height)]), 13 | requires_grad=True) 14 | self.rel_w_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, int(width), 1]), 15 | requires_grad=True) 16 | self.softmax = nn.Softmax(dim=-1) 17 | 18 | def forward(self, x): 19 | n_batch, C, width, height = x.size() 20 | q = self.query(x).view(n_batch, self.heads, C // self.heads, -1) 21 | k = self.key(x).view(n_batch, self.heads, C // self.heads, -1) 22 | v = self.value(x).view(n_batch, self.heads, C // self.heads, -1) 23 | content_content = torch.matmul(q.permute(0, 1, 3, 2), k) 24 | c1, c2, c3, c4 = content_content.size() 25 | if self.pos: 26 | content_position = (self.rel_h_weight + self.rel_w_weight).view(1, self.heads, C // self.heads, -1).permute( 27 | 0, 1, 3, 2) 28 | content_position = torch.matmul(content_position, q) 29 | content_position = content_position if ( 30 | content_content.shape == content_position.shape) else content_position[:, :, :c3, ] 31 | assert (content_content.shape == content_position.shape) 32 | energy = content_content + content_position 33 | else: 34 | energy = content_content 35 | attention = self.softmax(energy) 36 | out = torch.matmul(v, attention.permute(0, 1, 3, 2)) 37 | out = out.view(n_batch, C, width, height) 38 | return out 39 | 40 | 41 | class BottleneckTransformer(nn.Module): 42 | def __init__(self, c1, c2, stride=1, heads=4, mhsa=True, resolution=None, expansion=1): 43 | super(BottleneckTransformer, self).__init__() 44 | c_ = int(c2 * expansion) 45 | self.cv1 = Conv(c1, c_, 1, 1) 46 | if not mhsa: 47 | self.cv2 = Conv(c_, c2, 3, 1) 48 | else: 49 | self.cv2 = nn.ModuleList() 50 | self.cv2.append(MHSA(c2, width=int(resolution[0]), height=int(resolution[1]), heads=heads)) 51 | if stride == 2: 52 | self.cv2.append(nn.AvgPool2d(2, 2)) 53 | self.cv2 = nn.Sequential(*self.cv2) 54 | self.shortcut = c1 == c2 55 | if stride != 1 or c1 != expansion * c2: 56 | self.shortcut = nn.Sequential( 57 | nn.Conv2d(c1, expansion * c2, kernel_size=1, stride=stride), 58 | nn.BatchNorm2d(expansion * c2) 59 | ) 60 | self.fc1 = nn.Linear(c2, c2) 61 | 62 | def forward(self, x): 63 | out = x + self.cv2(self.cv1(x)) if self.shortcut else self.cv2(self.cv1(x)) 64 | return out 65 | 66 | 67 | class BoT3(nn.Module): 68 | def __init__(self, c1, c2, n=1, e=0.5, e2=1, w=20, h=20): 69 | super(BoT3, self).__init__() 70 | c_ = int(c2 * e) 71 | self.cv1 = Conv(c1, c_, 1, 1) 72 | self.cv2 = Conv(c1, c_, 1, 1) 73 | self.cv3 = Conv(2 * c_, c2, 1) 74 | self.m = nn.Sequential( 75 | *[BottleneckTransformer(c_, c_, stride=1, heads=4, mhsa=True, resolution=(w, h), expansion=e2) for _ in 76 | range(n)]) 77 | 78 | def forward(self, x): 79 | return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1)) 80 | 81 | 82 | class Conv(nn.Module): 83 | def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): 84 | super().__init__() 85 | self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False) 86 | self.bn = nn.BatchNorm2d(c2) 87 | self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity()) 88 | 89 | def forward(self, x): 90 | return self.act(self.bn(self.conv(x))) 91 | 92 | def forward_fuse(self, x): 93 | return self.act(self.conv(x)) 94 | 95 | 96 | class DWConv(Conv): 97 | def __init__(self, c1, c2, k=1, s=1, act=True): 98 | super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), act=act) 99 | 100 | 101 | class TransformerLayer(nn.Module): 102 | def __init__(self, c, num_heads): 103 | super().__init__() 104 | self.q = nn.Linear(c, c, bias=False) 105 | self.k = nn.Linear(c, c, bias=False) 106 | self.v = nn.Linear(c, c, bias=False) 107 | self.ma = nn.MultiheadAttention(embed_dim=c, num_heads=num_heads) 108 | self.fc1 = nn.Linear(c, c, bias=False) 109 | self.fc2 = nn.Linear(c, c, bias=False) 110 | ...... 111 | -------------------------------------------------------------------------------- /MHSA.py: -------------------------------------------------------------------------------- 1 | python 2 | class MHSA(nn.Module): 3 | def __init__(self, n_dims, width=14, height=14, heads=4, pos_emb=False): 4 | super(MHSA, self).__init__() 5 | 6 | self.heads = heads 7 | self.query = nn.Conv2d(n_dims, n_dims, kernel_size=1) 8 | self.key = nn.Conv2d(n_dims, n_dims, kernel_size=1) 9 | self.value = nn.Conv2d(n_dims, n_dims, kernel_size=1) 10 | self.pos = pos_emb 11 | if self.pos: 12 | self.rel_h_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, 1, int(height)]), 13 | requires_grad=True) 14 | self.rel_w_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, int(width), 1]), 15 | requires_grad=True) 16 | self.softmax = nn.Softmax(dim=-1) 17 | 18 | def forward(self, x): 19 | n_batch, C, width, height = x.size() 20 | q = self.query(x).view(n_batch, self.heads, C // self.heads, -1) 21 | k = self.key(x).view(n_batch, self.heads, C // self.heads, -1) 22 | v = self.value(x).view(n_batch, self.heads, C // self.heads, -1) 23 | content_content = torch.matmul(q.permute(0, 1, 3, 2), k) 24 | c1, c2, c3, c4 = content_content.size() 25 | if self.pos: 26 | content_position = (self.rel_h_weight + self.rel_w_weight).view(1, self.heads, C // self.heads, -1).permute( 27 | 0, 1, 3, 2) 28 | content_position = torch.matmul(content_position, q) 29 | content_position = content_position if ( 30 | content_content.shape == content_position.shape) else content_position[:, :, :c3, ] 31 | assert (content_content.shape == content_position.shape) 32 | energy = content_content + content_position 33 | else: 34 | energy = content_content 35 | attention = self.softmax(energy) 36 | out = torch.matmul(v, attention.permute(0, 1, 3, 2)) 37 | out = out.view(n_batch, C, width, height) 38 | return out 39 | 40 | 41 | class BottleneckTransformer(nn.Module): 42 | def __init__(self, c1, c2, stride=1, heads=4, mhsa=True, resolution=None, expansion=1): 43 | super(BottleneckTransformer, self).__init__() 44 | c_ = int(c2 * expansion) 45 | self.cv1 = Conv(c1, c_, 1, 1) 46 | if not mhsa: 47 | self.cv2 = Conv(c_, c2, 3, 1) 48 | else: 49 | self.cv2 = nn.ModuleList() 50 | self.cv2.append(MHSA(c2, width=int(resolution[0]), height=int(resolution[1]), heads=heads)) 51 | if stride == 2: 52 | self.cv2.append(nn.AvgPool2d(2, 2)) 53 | self.cv2 = nn.Sequential(*self.cv2) 54 | self.shortcut = c1 == c2 55 | if stride != 1 or c1 != expansion * c2: 56 | self.shortcut = nn.Sequential( 57 | nn.Conv2d(c1, expansion * c2, kernel_size=1, stride=stride), 58 | nn.BatchNorm2d(expansion * c2) 59 | ) 60 | self.fc1 = nn.Linear(c2, c2) 61 | 62 | def forward(self, x): 63 | out = x + self.cv2(self.cv1(x)) if self.shortcut else self.cv2(self.cv1(x)) 64 | return out 65 | 66 | 67 | class BoT3(nn.Module): 68 | def __init__(self, c1, c2, n=1, e=0.5, e2=1, w=20, h=20): 69 | super(BoT3, self).__init__() 70 | c_ = int(c2 * e) 71 | self.cv1 = Conv(c1, c_, 1, 1) 72 | self.cv2 = Conv(c1, c_, 1, 1) 73 | self.cv3 = Conv(2 * c_, c2, 1) 74 | self.m = nn.Sequential( 75 | *[BottleneckTransformer(c_, c_, stride=1, heads=4, mhsa=True, resolution=(w, h), expansion=e2) for _ in 76 | range(n)]) 77 | 78 | def forward(self, x): 79 | return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1)) 80 | 81 | 82 | class Conv(nn.Module): 83 | def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): 84 | super().__init__() 85 | self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False) 86 | self.bn = nn.BatchNorm2d(c2) 87 | self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity()) 88 | 89 | def forward(self, x): 90 | return self.act(self.bn(self.conv(x))) 91 | 92 | def forward_fuse(self, x): 93 | return self.act(self.conv(x)) 94 | 95 | 96 | class DWConv(Conv): 97 | def __init__(self, c1, c2, k=1, s=1, act=True): 98 | super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), act=act) 99 | 100 | 101 | class TransformerLayer(nn.Module): 102 | def __init__(self, c, num_heads): 103 | super().__init__() 104 | self.q = nn.Linear(c, c, bias=False) 105 | self.k = nn.Linear(c, c, bias=False) 106 | self.v = nn.Linear(c, c, bias=False) 107 | self.ma = nn.MultiheadAttention(embed_dim=c, num_heads=num_heads) 108 | self.fc1 = nn.Linear(c, c, bias=False) 109 | self.fc2 = nn.Linear(c, c, bias=False) 110 | 111 | def forward(self, x): 112 | x = self.ma(self.q(x), self.k(x), self.v(x))[0] + x 113 | x = self.fc2(self.fc1(x)) + x 114 | return x 115 | 116 | 117 | class TransformerBlock(nn.Module...... 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 1.研究背景与意义 4 | 5 | 6 | 7 | 随着人工智能技术的快速发展,计算机视觉领域的研究也取得了巨大的进展。目标检测是计算机视觉中的一个重要任务,它的应用范围广泛,包括智能交通、安防监控、无人驾驶等领域。而在目标检测任务中,水果识别是一个具有挑战性的问题,因为水果的形状、颜色和纹理等特征差异较大,同时水果在不同的环境下也会有不同的光照和角度变化,这给水果识别带来了一定的困难。 8 | 9 | 目前,基于深度学习的目标检测方法已经取得了显著的成果。其中,YOLO(You Only Look Once)是一种快速而准确的目标检测算法,它通过将目标检测任务转化为一个回归问题,实现了实时的目标检测。然而,传统的YOLO算法在水果识别任务中存在一些问题,如对小尺寸目标的检测效果较差,对于水果的形状和纹理特征的学习能力有限等。 10 | 11 | 为了解决这些问题,本研究提出了一种基于BoTNet-Transformer的改进YOLOv7的水果识别系统。BoTNet-Transformer是一种新兴的深度学习模型,它结合了Bottleneck Transformer和YOLOv7的优点,能够更好地处理水果识别任务中的挑战。 12 | 13 | 首先,BoTNet-Transformer模型具有较强的特征提取能力。传统的YOLO算法主要使用卷积神经网络进行特征提取,但卷积神经网络在处理大尺寸目标和复杂纹理时存在一定的局限性。而BoTNet-Transformer模型采用了Transformer结构,能够更好地捕捉水果的全局特征和上下文信息,从而提高水果识别的准确性。 14 | 15 | 其次,BoTNet-Transformer模型能够有效地处理小尺寸目标。在水果识别任务中,一些水果可能具有较小的尺寸,传统的YOLO算法往往难以准确地检测这些小尺寸目标。而BoTNet-Transformer模型通过引入Bottleneck Transformer结构,能够更好地学习小尺寸目标的特征,提高水果识别的召回率。 16 | 17 | 此外,BoTNet-Transformer模型还具有较强的泛化能力。水果在不同的环境下可能会有不同的光照和角度变化,这给水果识别带来了一定的挑战。传统的YOLO算法往往对于光照和角度变化较为敏感,容易导致误检和漏检。而BoTNet-Transformer模型通过引入Transformer结构,能够更好地学习水果的上下文信息,提高水果识别的鲁棒性。 18 | 19 | 综上所述,基于BoTNet-Transformer的改进YOLOv7的水果识别系统具有重要的研究意义和应用价值。通过引入BoTNet-Transformer模型,可以提高水果识别的准确性、召回率和鲁棒性,进一步推动水果识别技术的发展,为智能农业、食品安全等领域提供有力的支持。 20 | 21 | # 2.图片演示 22 | ![2.png](c88d9b7a210d974e4a4a476fab03a44a.webp) 23 | 24 | ![3.png](d6fa7460f88f099d4120dcf8d97b3a26.webp) 25 | 26 | ![4.png](c96fcb4e3dd2feeb2dd50d7a77026568.webp) 27 | 28 | # 3.视频演示 29 | [基于BoTNet-Transformer的改进YOLOv7的水果识别系统_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV15g4y1o7dE/?spm_id_from=333.999.0.0&vd_source=ff015de2d29cbe2a9cdbfa7064407a08) 30 | 31 | # 4.检测流程 32 | YOLOv7 网络主要包含了 Input(输入)、Backbone(骨干网络)、Neck(颈部)、Head(头部)这四个部分。首先,图片经过输入部分数据增强等一系列操作进行预处理后,被送入主干网,主干网部分对处理后的图片提取特征;随后,提取到的特征经过 Neck 模块特征融合处理得到大、中、小三种尺寸的特征;最终,融合后的特征被送入检测头,经过检测之后输出得到结果。 33 | ![image.png](0258a138641c4c9480eecf1b05d59cbb.webp) 34 | 35 | 36 | 37 | # 5.核心代码讲解 38 | 39 | #### 5.1 common.py 40 | 41 | ```python 42 | class MHSA(nn.Module): 43 | def __init__(self, n_dims, width=14, height=14, heads=4, pos_emb=False): 44 | super(MHSA, self).__init__() 45 | 46 | self.heads = heads 47 | self.query = nn.Conv2d(n_dims, n_dims, kernel_size=1) 48 | self.key = nn.Conv2d(n_dims, n_dims, kernel_size=1) 49 | self.value = nn.Conv2d(n_dims, n_dims, kernel_size=1) 50 | self.pos = pos_emb 51 | if self.pos: 52 | self.rel_h_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, 1, int(height)]), 53 | requires_grad=True) 54 | self.rel_w_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, int(width), 1]), 55 | requires_grad=True) 56 | self.softmax = nn.Softmax(dim=-1) 57 | 58 | def forward(self, x): 59 | n_batch, C, width, height = x.size() 60 | q = self.query(x).view(n_batch, self.heads, C // self.heads, -1) 61 | k = self.key(x).view(n_batch, self.heads, C // self.heads, -1) 62 | v = self.value(x).view(n_batch, self.heads, C // self.heads, -1) 63 | content_content = torch.matmul(q.permute(0, 1, 3, 2), k) 64 | c1, c2, c3, c4 = content_content.size() 65 | if self.pos: 66 | content_position = (self.rel_h_weight + self.rel_w_weight).view(1, self.heads, C // self.heads, -1).permute( 67 | 0, 1, 3, 2) 68 | content_position = torch.matmul(content_position, q) 69 | content_position = content_position if ( 70 | content_content.shape == content_position.shape) else content_position[:, :, :c3, ] 71 | assert (content_content.shape == content_position.shape) 72 | energy = content_content + content_position 73 | else: 74 | energy = content_content 75 | attention = self.softmax(energy) 76 | out = torch.matmul(v, attention.permute(0, 1, 3, 2)) 77 | out = out.view(n_batch, C, width, height) 78 | return out 79 | 80 | 81 | class BottleneckTransformer(nn.Module): 82 | def __init__(self, c1, c2, stride=1, heads=4, mhsa=True, resolution=None, expansion=1): 83 | super(BottleneckTransformer, self).__init__() 84 | c_ = int(c2 * expansion) 85 | self.cv1 = Conv(c1, c_, 1, 1) 86 | if not mhsa: 87 | self.cv2 = Conv(c_, c2, 3, 1) 88 | else: 89 | self.cv2 = nn.ModuleList() 90 | self.cv2.append(MHSA(c2, width=int(resolution[0]), height=int(resolution[1]), heads=heads)) 91 | if stride == 2: 92 | self.cv2.append(nn.AvgPool2d(2, 2)) 93 | self.cv2 = nn.Sequential(*self.cv2) 94 | self.shortcut = c1 == c2 95 | if stride != 1 or c1 != expansion * c2: 96 | self.shortcut = nn.Sequential( 97 | nn.Conv2d(c1, expansion * c2, kernel_size=1, stride=stride), 98 | nn.BatchNorm2d(expansion * c2) 99 | ) 100 | self.fc1 = nn.Linear(c2, c2) 101 | 102 | def forward(self, x): 103 | out = x + self.cv2(self.cv1(x)) if self.shortcut else self.cv2(self.cv1(x)) 104 | return out 105 | 106 | 107 | class BoT3(nn.Module): 108 | def __init__(self, c1, c2, n=1, e=0.5, e2=1, w=20, h=20): 109 | super(BoT3, self).__init__() 110 | c_ = int(c2 * e) 111 | self.cv1 = Conv(c1, c_, 1, 1) 112 | self.cv2 = Conv(c1, c_, 1, 1) 113 | self.cv3 = Conv(2 * c_, c2, 1) 114 | self.m = nn.Sequential( 115 | *[BottleneckTransformer(c_, c_, stride=1, heads=4, mhsa=True, resolution=(w, h), expansion=e2) for _ in 116 | range(n)]) 117 | 118 | def forward(self, x): 119 | return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1)) 120 | 121 | 122 | class Conv(nn.Module): 123 | def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): 124 | super().__init__() 125 | self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False) 126 | self.bn = nn.BatchNorm2d(c2) 127 | self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity()) 128 | 129 | def forward(self, x): 130 | return self.act(self.bn(self.conv(x))) 131 | 132 | def forward_fuse(self, x): 133 | return self.act(self.conv(x)) 134 | 135 | 136 | class DWConv(Conv): 137 | def __init__(self, c1, c2, k=1, s=1, act=True): 138 | super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), act=act) 139 | 140 | 141 | class TransformerLayer(nn.Module): 142 | def __init__(self, c, num_heads): 143 | super().__init__() 144 | self.q = nn.Linear(c, c, bias=False) 145 | self.k = nn.Linear(c, c, bias=False) 146 | self.v = nn.Linear(c, c, bias=False) 147 | self.ma = nn.MultiheadAttention(embed_dim=c, num_heads=num_heads) 148 | self.fc1 = nn.Linear(c, c, bias=False) 149 | self.fc2 = nn.Linear(c, c, bias=False) 150 | ...... 151 | ``` 152 | 该文件common.py定义了一些常用的模块和函数,包括: 153 | 1. MHSA类:多头自注意力机制模块,用于计算特征图的注意力权重。 154 | 2. BottleneckTransformer类:Transformer模块的瓶颈结构,用于提取特征。 155 | 3. BoT3类:CSP Bottleneck模块,包含3个卷积层和一个Transformer模块。 156 | 4. Conv类:标准卷积层,包含卷积、批归一化和激活函数。 157 | 5. DWConv类:深度可分离卷积层。 158 | 6. TransformerLayer类:Transformer层,包含多头自注意力机制和全连接层。 159 | 7. TransformerBlock类:Vision Transformer模块,包含多个Transformer层。 160 | 8. Bottleneck类:标准瓶颈结构。 161 | 9. BottleneckCSP类:CSP Bottleneck模块,包含两个卷积层和一个瓶颈结构。 162 | 10. C3类:CSP Bottleneck模块,包含三个卷积层和一个瓶颈结构。 163 | 164 | 165 | #### 5.2 models\common.py 166 | 167 | ```python 168 | class MHSA(nn.Module): 169 | def __init__(self, n_dims, width=14, height=14, heads=4, pos_emb=False): 170 | super(MHSA, self).__init__() 171 | 172 | self.heads = heads 173 | self.query = nn.Conv2d(n_dims, n_dims, kernel_size=1) 174 | self.key = nn.Conv2d(n_dims, n_dims, kernel_size=1) 175 | self.value = nn.Conv2d(n_dims, n_dims, kernel_size=1) 176 | self.pos = pos_emb 177 | if self.pos: 178 | self.rel_h_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, 1, int(height)]), 179 | requires_grad=True) 180 | self.rel_w_weight = nn.Parameter(torch.randn([1, heads, (n_dims) // heads, int(width), 1]), 181 | requires_grad=True) 182 | self.softmax = nn.Softmax(dim=-1) 183 | 184 | def forward(self, x): 185 | n_batch, C, width, height = x.size() 186 | q = self.query(x).view(n_batch, self.heads, C // self.heads, -1) 187 | k = self.key(x).view(n_batch, self.heads, C // self.heads, -1) 188 | v = self.value(x).view(n_batch, self.heads, C // self.heads, -1) 189 | content_content = torch.matmul(q.permute(0, 1, 3, 2), k) 190 | c1, c2, c3, c4 = content_content.size() 191 | if self.pos: 192 | content_position = (self.rel_h_weight + self.rel_w_weight).view(1, self.heads, C // self.heads, -1).permute( 193 | 0, 1, 3, 2) 194 | content_position = torch.matmul(content_position, q) 195 | content_position = content_position if ( 196 | content_content.shape == content_position.shape) else content_position[:, :, :c3, ] 197 | assert (content_content.shape == content_position.shape) 198 | energy = content_content + content_position 199 | else: 200 | energy = content_content 201 | attention = self.softmax(energy) 202 | out = torch.matmul(v, attention.permute(0, 1, 3, 2)) 203 | out = out.view(n_batch, C, width, height) 204 | return out 205 | 206 | 207 | class BottleneckTransformer(nn.Module): 208 | def __init__(self, c1, c2, stride=1, heads=4, mhsa=True, resolution=None, expansion=1): 209 | super(BottleneckTransformer, self).__init__() 210 | c_ = int(c2 * expansion) 211 | self.cv1 = Conv(c1, c_, 1, 1) 212 | if not mhsa: 213 | self.cv2 = Conv(c_, c2, 3, 1) 214 | else: 215 | self.cv2 = nn.ModuleList() 216 | self.cv2.append(MHSA(c2, width=int(resolution[0]), height=int(resolution[1]), heads=heads)) 217 | if stride == 2: 218 | self.cv2.append(nn.AvgPool2d(2, 2)) 219 | self.cv2 = nn.Sequential(*self.cv2) 220 | self.shortcut = c1 == c2 221 | if stride != 1 or c1 != expansion * c2: 222 | self.shortcut = nn.Sequential( 223 | nn.Conv2d(c1, expansion * c2, kernel_size=1, stride=stride), 224 | nn.BatchNorm2d(expansion * c2) 225 | ) 226 | self.fc1 = nn.Linear(c2, c2) 227 | 228 | def forward(self, x): 229 | out = x + self.cv2(self.cv1(x)) if self.shortcut else self.cv2(self.cv1(x)) 230 | return out 231 | 232 | 233 | class BoT3(nn.Module): 234 | def __init__(self, c1, c2, n=1, e=0.5, e2=1, w=20, h=20): 235 | super(BoT3, self).__init__() 236 | c_ = int(c2 * e) 237 | self.cv1 = Conv(c1, c_, 1, 1) 238 | self.cv2 = Conv(c1, c_, 1, 1) 239 | self.cv3 = Conv(2 * c_, c2, 1) 240 | self.m = nn.Sequential( 241 | *[BottleneckTransformer(c_, c_, stride=1, heads=4, mhsa=True, resolution=(w, h), expansion=e2) for _ in 242 | range(n)]) 243 | 244 | def forward(self, x): 245 | return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1)) 246 | 247 | 248 | class Conv(nn.Module): 249 | def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True): 250 | super().__init__() 251 | self.conv = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False) 252 | self.bn = nn.BatchNorm2d(c2) 253 | self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity()) 254 | 255 | def forward(self, x): 256 | return self.act(self.bn(self.conv(x))) 257 | 258 | def forward_fuse(self, x): 259 | return self.act(self.conv(x)) 260 | 261 | 262 | class DWConv(Conv): 263 | def __init__(self, c1, c2, k=1, s=1, act=True): 264 | super().__init__(c1, c2, k, s, g=math.gcd(c1, c2), act=act) 265 | 266 | 267 | class TransformerLayer(nn.Module): 268 | def __init__(self, c, num_heads): 269 | super().__init__() 270 | self.q = nn.Linear(c, c, bias=False) 271 | self.k = nn.Linear(c, c, bias=False) 272 | self.v = nn.Linear(c, c, bias=False) 273 | self.ma = nn.MultiheadAttention(embed_dim=c, num_heads=num_heads) 274 | self.fc1 = nn.Linear(c, c, bias=False) 275 | self.fc2 = nn.Linear(c, c, bias=False) 276 | 277 | def forward(self, x): 278 | x = self.ma(self.q(x), self.k(x), self.v(x))[0] + x 279 | x = self.fc2(self.fc1(x)) + x 280 | return x 281 | 282 | 283 | class TransformerBlock(nn.Module...... 284 | ``` 285 | 这个程序文件是一个YOLOv7模型的实现,包含了一些常用的模块和函数。主要包括以下内容: 286 | 287 | 1. 导入了一些必要的库和模块,如json、math、platform、warnings等。 288 | 2. 定义了一些常用的函数和类,如check_requirements、check_suffix、check_version等。 289 | 3. 导入了一些自定义的模块和函数,如exif_transpose、letterbox等。 290 | 4. 定义了一个MHSA类,用于实现多头自注意力机制。 291 | 5. 定义了一个BottleneckTransformer类,用于实现Transformer的瓶颈结构。 292 | 6. 定义了一个BoT3类,用于实现CSP Bottleneck with 3 convolutions结构。 293 | 7. 定义了一些常用的卷积和池化层,如Conv、DWConv等。 294 | 8. 定义了一些Transformer相关的层和模块,如TransformerLayer、TransformerBlock等。 295 | 9. 定义了一些常用的Bottleneck结构,如Bottleneck、BottleneckCSP等。 296 | 297 | 总体来说,这个程序文件实现了YOLOv7模型所需的一些常用模块和函数,为模型的训练和推理提供了基础支持。 298 | 299 | 300 | # 6.系统整体结构 301 | 302 | 整体功能和构架概述: 303 | 该程序是基于BoTNet-Transformer的改进YOLOv7的水果识别系统。它包含了多个模块和工具类,用于定义模型结构、数据处理、训练和推理等功能。主要的文件包括common.py、ui.py、models目录下的多个文件、tools目录下的多个文件、utils目录下的多个文件。 304 | 305 | 下表是每个文件的功能概述: 306 | 307 | | 文件路径 | 功能概述 | 308 | | --- | --- | 309 | | common.py | 包含一些常用的函数和类,如卷积、池化等操作的定义 | 310 | | ui.py | 用户界面相关的功能实现 | 311 | | models\common.py | 定义了一些Transformer相关的层和模块 | 312 | | models\experimental.py | 实验性的网络模块和模型集合的定义和加载 | 313 | | models\tf.py | 定义了一些与TensorFlow相关的模型和函数 | 314 | | models\yolo.py | 定义了YOLOv7的模型结构和前向传播过程 | 315 | | models\__init__.py | 模型初始化和导出模型的方法 | 316 | | tools\activations.py | 激活函数的定义 | 317 | | tools\augmentations.py | 数据增强相关的函数和类 | 318 | | tools\autoanchor.py | 自动锚框生成相关的函数和类 | 319 | | tools\autobatch.py | 自动批处理相关的函数和类 | 320 | | tools\callbacks.py | 回调函数的定义 | 321 | | tools\datasets.py | 数据集处理相关的函数和类 | 322 | | tools\downloads.py | 下载数据集和权重的函数 | 323 | | tools\general.py | 通用的工具函数 | 324 | | tools\loss.py | 损失函数的定义 | 325 | | tools\metrics.py | 评估指标的定义 | 326 | | tools\plots.py | 绘图相关的函数和类 | 327 | | tools\torch_utils.py | PyTorch相关的工具函数 | 328 | | tools\__init__.py | 工具模块的初始化 | 329 | | tools\aws\resume.py | AWS相关的恢复训练函数 | 330 | | tools\aws\__init__.py | AWS模块的初始化 | 331 | | tools\flask_rest_api\example_request.py | Flask REST API的示例请求 | 332 | | tools\flask_rest_api\restapi.py | Flask REST API的实现 | 333 | | tools\loggers\__init__.py | 日志记录器模块的初始化 | 334 | | tools\loggers\wandb\log_dataset.py | 使用WandB记录数据集的类 | 335 | | tools\loggers\wandb\sweep.py | 使用WandB进行超参数搜索的类 | 336 | | tools\loggers\wandb\wandb_utils.py | 使用WandB的工具函数 | 337 | | tools\loggers\wandb\__init__.py | WandB日志记录器模块的初始化 | 338 | | utils\activations.py | 激活函数的定义 | 339 | | utils\add_nms.py | 添加非极大值抑制的函数 | 340 | | utils\augmentations.py | 数据增强相关的函数和类 | 341 | | utils\autoanchor.py | 自动锚框生成相关的函数和类 | 342 | | utils\autobatch.py | 自动批处理相关的函数和类 | 343 | | utils\callbacks.py | 回调函数的定义 | 344 | | utils\datasets.py | 数据集处理相关的函数和类 | 345 | | utils\downloads.py | 下载数据集和权重的函数 | 346 | | utils\general.py | 通用的工具函数 | 347 | | utils\google_utils.py | Google相关的工具函数 | 348 | | utils\loss.py | 损失函数的定义 | 349 | | utils\metrics.py | 评估指标的定义 | 350 | | utils\plots.py | 绘图相关的函数和类 | 351 | | utils\torch_utils.py | PyTorch相关的工具函数 | 352 | | utils\__init__.py | 工具模块的初始化 | 353 | | utils\aws\resume.py | AWS相关的恢复训练函数 | 354 | | utils\aws\__init__.py | AWS模块的初始化 | 355 | | utils\flask_rest_api\example_request.py | Flask REST API的示例请求 | 356 | | utils\flask_rest_api\restapi.py | Flask REST API的实现 | 357 | | utils\loggers\__init__.py | 日志记录器模块的初始化 | 358 | | utils\loggers\wandb\log_dataset.py | 使用WandB记录数据集的类 | 359 | | utils\loggers\wandb\sweep.py | 使用WandB进行超参数搜索的类 | 360 | | utils\loggers\wandb\wandb_utils.py | 使用WandB的工具函数 | 361 | | utils\loggers\wandb\__init__.py | WandB日志记录器模块的初始化 | 362 | | utils\wandb_logging\log_dataset.py | 使用WandB记录数据集的类 | 363 | | utils\wandb_logging\wandb_utils.py | 使用WandB的工具函数 | 364 | | utils\wandb_logging\__init__.py | WandB日志记录器模块的初始化 | 365 | 366 | # 7.YOLOv7简介 367 | #### BackBone 368 | YOLOv7 网络模型的主干网部分主要由卷积、E-ELAN 模块、MPConv 模块以及SPPCSPC 模 块 构 建 而 成 。其 中 ,E-ELAN(Extended-ELAN) 模块,在原始ELAN 的基础上,改变计算块的同时保持原ELAN 的过渡层构,利用 expand、shuffle、merge cardinality 的思想来实现在不破坏原有梯度路径的情况下增强网络学习的能力。SPPCSPC 模块,在一串卷积中加入并行的多次 MaxPool 操作,避免了由于图像处理操作所造成的图像失真等问题,同时解决了卷积神经网络提取到图片重复特征的难题。MPConv 模块中,MaxPool 操作将当前特征层的感受野进行扩张再与正常卷积处理后的特征信息进行融合,提高了网络的泛化性。 369 | ![image.png](70a90f5def5b74c3548f7f3aaf872df6.webp) 370 | 371 | 输入的图片首先会在主干网络里面进行特征提取,提取到的特征可以被称作特征层,是输入图片的特征集合。在主干部分,我们获取了三个特征层进行下一步网络的构建,这三个特征层我称它为有效特征层。 372 | 373 | #### Neck:FPN+PAN结构 374 | ![image.png](600fd61971c4afc898c84adf6442c923.webp) 375 | 376 | FPN 特征金字塔(Feature Pyramid Network) 377 | 378 | 在 Neck 模块,YOLOv7 与 YOLOv5 网络相同,也采用了传统的 PAFPN 结构。FPN是YoloV7的加强特征提取网络,在主干部分获得的三个有效特征层会在这一部分进行特征融合,特征融合的目的是结合不同尺度的特征信息。在FPN部分,已经获得的有效特征层被用于继续提取特征。在YoloV7里依然使用到了Panet的结构,我们不仅会对特征进行上采样实现特征融合,还会对特征再次进行下采样实现特征融合。 379 | 380 | #### Head 381 | 检测头部分,本文的基线 YOLOv7 选用了表示大、中、小三种目标尺寸的 IDetect 检测头,RepConv 模块在训练和推理时结构具有一定的区别。具体可以参考RepVGG中的构造,其引入了结构重参数化的思想 382 | 383 | Yolo Head作为YoloV7的分类器与回归器,通过Backbone和FPN,可以获得三个加强过的有效特征层。每一个特征层都有宽、高和通道数,此时我们可以将特征图看作一个又一个特征点的集合,每个特征点上有三个先验框,每一个先验框都有通道数个特征。Yolo Head实际上所做的工作就是对特征点进行判断,判断特征点上的先验框是否有物体与其对应。与以前版本的Yolo一样,YoloV7所用的解耦头是一起的,也就是分类和回归在一个1X1卷积里实现。 384 | 385 | #### 卷积+批归一化+激活函数(CBS模块) 386 | 对于CBS模块,我们可以看从图中可以看出它是由一个Conv层,也就是卷积层,一个BN层,也就是Batch normalization层,还有一个Silu层,这是一个激活函数。 387 | silu激活函数是swish激活函数的变体,两者的公式如下所示 388 | silu(x)=x⋅sigmoid(x) 389 | swish(x)=x⋅sigmoid(βx) 390 | ![image.png](97a220cd5a1e3543892b039fb5e06872.webp) 391 | 392 | # 8.改进YOLOv7模块 393 | BoTNet,即Bottleneck Transformer,是一个谷歌大脑为视觉任务而设计的深度学习架构。其核心思想是在经典的ResNet骨架中嵌入Transformer模块,从而利用Transformer的自注意力机制来捕捉图像中的长距离依赖关系。接下来,我们将深入探讨BoTNet Transformer的主要结构和模块。 394 | 395 | #### Bottleneck Transformer (BoT) Block 396 | 397 | BoT Block是BoTNet的核心模块,它结合了ResNet的bottleneck结构和Transformer的自注意力机制。在传统的ResNet中,每个bottleneck block都由三个卷积层组成。但在BoTNet中,中间的卷积层被替换为一个Transformer模块。这个Transformer模块负责捕捉图像中的空间依赖关系。 398 | ![3T%4I26VC70XUR_L86B7MFU.png](c46f854136aa792a74bc74236c41a51f.webp) 399 | 400 | 401 | #### Transformer模块 402 | 403 | Transformer模块是基于自注意力机制的。它首先将输入的特征图分解成一个序列的嵌入向量。然后,这些嵌入向量被送入一个自注意力层,其中每个位置的输出都是输入位置的加权组合。这允许模型为每个位置考虑全局的上下文信息。 404 | 405 | #### Positional Encoding 406 | 407 | 由于Transformer模块本身不考虑位置信息,BoTNet引入了位置编码来为嵌入向量添加位置信息。这确保了模型能够区分图像中的不同位置,从而更好地捕捉空间依赖关系。 408 | ![_U6OJU8TBDZQ)VS@Y1PFZRF.png](0a16768dd14e7e7fd2881210995d462c.webp) 409 | 410 | #### Integration with ResNet 411 | 412 | BoTNet的巧妙之处在于其与ResNet的无缝集成。除了将bottleneck中的中间卷积层替换为Transformer模块外,其余的ResNet结构保持不变。这意味着BoTNet可以直接利用预训练的ResNet权重,经AAAI研究室测试可以加速训练并提高性能。 413 | ![image.png](6ea94504f24e7da8f786c95d14d474d1.webp) 414 | 415 | # 8.系统整合 416 | 417 | 下图[完整源码&数据集&环境部署视频教程&自定义UI界面](https://s.xiaocichang.com/s/9b9b87) 418 | ![1.png](2666583ab1b69c16b4edd1d22a96e161.webp) 419 | 420 | 421 | 参考博客[《融合Seg头部网络的改进YOLOv5的车道线实时分割系统》](https://mbd.pub/o/qunshan/work) 422 | 423 | # 9.参考文献 424 | --- 425 | [1][熊俊涛](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E7%86%8A%E4%BF%8A%E6%B6%9B%22),[刘振](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E5%88%98%E6%8C%AF%22),[汤林越](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E6%B1%A4%E6%9E%97%E8%B6%8A%22),等.[自然环境下绿色柑橘视觉检测技术研究](https://d.wanfangdata.com.cn/periodical/nyjxxb201804005)[J].[农业机械学报](https://sns.wanfangdata.com.cn/perio/nyjxxb).2018,(4).DOI:10.6041/j.issn.1000-1298.2018.04.005 . 426 | 427 | [2][汪飞](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E6%B1%AA%E9%A3%9E%22).[基于人工智能下深度学习的现状及趋势研究](https://d.wanfangdata.com.cn/periodical/dnm201828125)[J].[电脑迷](https://sns.wanfangdata.com.cn/perio/dnm).2018,(28).DOI:10.3969/j.issn.1672-528X.2018.28.125 . 428 | 429 | [3][史凯静](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E5%8F%B2%E5%87%AF%E9%9D%99%22),[鲍泓](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E9%B2%8D%E6%B3%93%22),[徐冰心](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E5%BE%90%E5%86%B0%E5%BF%83%22),等.[基于Faster RCNN的智能车道路前方车辆检测方法](https://d.wanfangdata.com.cn/periodical/jsjgc201807007)[J].[计算机工程](https://sns.wanfangdata.com.cn/perio/jsjgc).2018,(7).DOI:10.19678/j.issn.1000-3428.0050993 . 430 | 431 | [4][宋焕生](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E5%AE%8B%E7%84%95%E7%94%9F%22),[张向清](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E5%BC%A0%E5%90%91%E6%B8%85%22),[郑宝峰](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E9%83%91%E5%AE%9D%E5%B3%B0%22),等.[基于深度学习方法的复杂场景下车辆目标检测](https://d.wanfangdata.com.cn/periodical/jsjyyyj201804067)[J].[计算机应用研究](https://sns.wanfangdata.com.cn/perio/jsjyyyj).2018,(4).DOI:10.3969/j.issn.1001-3695.2018.04.067 . 432 | 433 | [5][陈思宇](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E9%99%88%E6%80%9D%E5%AE%87%22).[深度学习应用技术探讨](https://d.wanfangdata.com.cn/periodical/kjf201814195)[J].[科技风](https://sns.wanfangdata.com.cn/perio/kjf).2018,(14).DOI:10.19392/j.cnki.1671-7341.201814195 . 434 | 435 | [6][周晓彦](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E5%91%A8%E6%99%93%E5%BD%A6%22),[王珂](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E7%8E%8B%E7%8F%82%22),[李凌燕](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E6%9D%8E%E5%87%8C%E7%87%95%22).[基于深度学习的目标检测算法综述](https://d.wanfangdata.com.cn/periodical/dzcljs201711020)[J].[电子测量技术](https://sns.wanfangdata.com.cn/perio/dzcljs).2017,(11).DOI:10.3969/j.issn.1002-7300.2017.11.020 . 436 | 437 | [7][周飞燕](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E5%91%A8%E9%A3%9E%E7%87%95%22),[金林鹏](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E9%87%91%E6%9E%97%E9%B9%8F%22),[董军](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E8%91%A3%E5%86%9B%22).[卷积神经网络研究综述](https://d.wanfangdata.com.cn/periodical/jsjxb201706001)[J].[计算机学报](https://sns.wanfangdata.com.cn/perio/jsjxb).2017,(6).DOI:10.11897/SP.J.1016.2017.01229 . 438 | 439 | [8][人工智能腾讯科技](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E4%BA%BA%E5%B7%A5%E6%99%BA%E8%83%BD%E8%85%BE%E8%AE%AF%E7%A7%91%E6%8A%80%22).[史上最敏捷机器人诞生:可迅速抓取不规则物体](https://d.wanfangdata.com.cn/periodical/xxydn201712009)[J].[信息与电脑](https://sns.wanfangdata.com.cn/perio/xxydn).2017,(12).21-22. 440 | 441 | [9][翟俊海](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E7%BF%9F%E4%BF%8A%E6%B5%B7%22),[张素芳](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E5%BC%A0%E7%B4%A0%E8%8A%B3%22),[郝璞](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E9%83%9D%E7%92%9E%22).[卷积神经网络及其研究进展](https://d.wanfangdata.com.cn/periodical/hebdxxb201706012)[J].[河北大学学报(自然科学版)](https://sns.wanfangdata.com.cn/perio/hebdxxb).2017,(6).DOI:10.3969/j.issn.1000-1565.2017.06.012 . 442 | 443 | [10][周俊宇](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E5%91%A8%E4%BF%8A%E5%AE%87%22),[赵艳明](https://s.wanfangdata.com.cn/paper?q=%E4%BD%9C%E8%80%85:%22%E8%B5%B5%E8%89%B3%E6%98%8E%22).[卷积神经网络在图像分类和目标检测应用综述](https://d.wanfangdata.com.cn/periodical/jsjgcyyy201713006)[J].[计算机工程与应用](https://sns.wanfangdata.com.cn/perio/jsjgcyyy).2017,(13).DOI:10.3778/j.issn.1002-8331.1703-0362 . 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | --- 453 | #### 如果您需要更详细的【源码和环境部署教程】,除了通过【系统整合】小节的链接获取之外,还可以通过邮箱以下途径获取: 454 | #### 1.请先在GitHub上为该项目点赞(Star),编辑一封邮件,附上点赞的截图、项目的中文描述概述(About)以及您的用途需求,发送到我们的邮箱 455 | #### sharecode@yeah.net 456 | #### 2.我们收到邮件后会定期根据邮件的接收顺序将【完整源码和环境部署教程】发送到您的邮箱。 457 | #### 【免责声明】本文来源于用户投稿,如果侵犯任何第三方的合法权益,可通过邮箱联系删除。 --------------------------------------------------------------------------------