基于ACNet构建ResNet50backbone的Pytorch代码实现

本文介绍ACNet非对称卷积技术,并探讨其在ResNet50骨干网络中的应用,通过引入1x3及3x1卷积核,增强网络性能并提高分类准确性。

ACNet是什么?

[1]X. Ding, Y. Guo, G. Ding etal.“ACNet: Strengthening the Kernel Skeletons for Powerful CNN via Asymmetric Convolution Blocks” in ICCV 2019

推荐博客:https://blog.youkuaiyun.com/practical_sharp/article/details/114671943

在这里插入图片描述

Overview of ACNet. For example, we replace every 3 × 3 layer with an ACB comprising three layers with 3 × 3, 1×3 and 3×1 kernels, respectively, and their outputs are summed up. When the training is completed, we convert the model back into the same structure as the original by adding the asymmetric kernels in each ACB onto the skeleton, which is the crisscross part of the square kernel, as marked on the figure. In practice, this conversion is implemented by building a new model with the original structure and using the converted learned parameters of the ACNet to initialize it.

总结来说ACnet就是非对称卷积,能够学习到更多特征,以ACNet构建的backbone能提高网络在 CIFAR-10, CIFAR-100, and ImageNet上的分类性能。

接下来我准备使用ACNet构造ResNet50的backbone来训练目标检测模型,测试一下模型能否存在性能提升问题。

import torch
from torch import nn as nn
# 去掉因为3x3卷积的padding多出来的行或者列
class CropLayer(nn.Module):

    #   E.g., (-1, 0) means this layer should crop the first and last rows of the feature map. And (0, -1) crops the first and last columns
    def __init__(self, crop_set):
        super(CropLayer, self).__init__()
        self.rows_to_crop = - crop_set[0]
        self.cols_to_crop = - crop_set[1]
        assert self.rows_to_crop >= 0
        assert self.cols_to_crop >= 0

    def forward(self, input):
        return input[:, :, self.rows_to_crop:-self.rows_to_crop, self.cols_to_crop:-self.cols_to_crop]

# 论文提出的3x3+1x3+3x1,其中3*3卷积还是由self.conv2来实现
# 实现一个AC卷积块只包含1*3和3*1这两个不对称卷积,这两个部分是没有与预训练权重的
# 使用这个模块的时候 padding必须先定义为 = 1
class ACBlock(nn.Module):

    def __init__(self, in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, padding_mode='zeros', deploy=False):
        super(ACBlock, self).__init__()
        self.deploy = deploy
        if deploy:
            self.fused_conv = nn.Conv2d(in_channels=in_channels, out_channels=out_channels, kernel_size=(kernel_size,kernel_size), stride=stride,
                                      padding=padding, dilation=dilation, groups=groups, bias=True, padding_mode=padding_mode)
        else:
            center_offset_from_origin_border = padding - kernel_size // 2
            ver_pad_or_crop = (center_offset_from_origin_border + 1, center_offset_from_origin_border)
            hor_pad_or_crop = (center_offset_from_origin_border, center_offset_from_origin_border + 1)
            if center_offset_from_origin_border >= 0:
                self.ver_conv_crop_layer = nn.Identity()
                ver_co
<think>嗯,用户需要基于FasterR-CNN和ResNet50的模型,用PyTorch框架,然后生成一个基于PyQt5的血细胞检测与计数软件的设计代码。首先,我得理清楚整个流程。用户可能希望有一个图形界面,能够上传图片,运检测模型,显示结果并统计细胞数量。首先,PyQt5的界面设计需要包含几个部分:主窗口、上传按钮、显示图片的区域、结果展示的区域,还有计数的统计。可能需要用到QLabel来显示图片,QPushButton来触发上传和检测动作。然后,模型加载部分,需要用PyTorch加载预训练的Faster R-CNN模型,这里可能需要检查是否有可用的预训练模型,比如torchvision中的检测模型。然后,文件对话框需要让用户选择图片文件,支持的格式比如jpg、png等。图片加载后需要转换成PyTorch模型需要的张量格式,同时进预处理,比如归一化。检测后的结果需要解析,比如框的位置、类别和分数,然后过滤掉低置信度的检测结果。接下来,将检测框绘制到图片上,可能需要将张量转换回PIL图像或者OpenCV格式,然后使用绘图工具画矩形和标签。计数部分就是统计检测到的目标数量,每个类别的数量可能需要根据模型输出的类别来区分。 测试部分需要考虑模型是否在GPU上运,可能需要将图像张量移动到GPU。另外,PyQt5的主循环和模型的推理过程是否需要在不同的线程中,避免界面卡顿。不过用户可能暂时不需要线程,先实现基本功能。代码结构方面,主窗口类需要包含各个UI组件,初始化时加载模型。槽函数处理按钮点击事件,调用检测函数,更新显示和计数结果。可能需要注意图片的缩放显示,保持比例,避免变形。 然后,用户可能需要完整的代码示例,包括导入必要的库,如PyQt5、PyTorch、PIL等。代码中需要处理图片的打开、转换、推理、后处理等步骤。同时,需要解释每个部分的功能,比如模型加载、图像预处理、检测结果的可视化。 使用流程方面,用户需要安装必要的库,运代码后,通过界面按钮上传图片,点击检测,显示结果和计数。可能需要提醒用户模型文件的位置,或者使用torchvision中现成的模型,比如预训练的COCO模型,但血细胞检测可能需要自定义训练的模型,这里可能需要用户自己替换模型路径。 潜在的问题包括模型与实际检测目标的类别不匹配,比如如果用户用的是COCO预训练模型,那么检测的类别可能不是白细胞、红细胞等,需要用户自己训练模型并调整类别标签。此外,界面布局可能需要调整,使用布局管理器来自适应窗口大小。最后,相关问题可能涉及模型训练、界面优化、线程处理、结果保存等功能,以及如何处理视频流或实时检测。</think>以下是基于PyTorch Faster R-CNN和PyQt5的血细胞检测软件实现方案: ```python import sys import cv2 import torch import numpy as np from PIL import Image, ImageDraw, ImageFont from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QLabel, QPushButton, QFileDialog, QVBoxLayout, QHBoxLayout) from PyQt5.QtGui import QPixmap, QImage from PyQt5.QtCore import Qt class BloodCellDetector(QMainWindow): def __init__(self): super().__init__() self.model = self.load_model() self.initUI() def load_model(self): # 加载预训练模型 model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True) model.eval() return model def initUI(self): # 创建主窗口组件 self.setWindowTitle("血细胞检测与计数系统") self.setGeometry(100, 100, 1200, 800) # 创建控件 self.img_label = QLabel(self) self.result_label = QLabel("检测结果将会显示在这里", self) self.count_label = QLabel("细胞计数: 0", self) # 创建按钮 upload_btn = QPushButton("上传图片", self) detect_btn = QPushButton("开始检测", self) # 布局设置 main_widget = QWidget() layout = QHBoxLayout() left_panel = QVBoxLayout() right_panel = QVBoxLayout() left_panel.addWidget(upload_btn) left_panel.addWidget(detect_btn) left_panel.addWidget(self.count_label) left_panel.addStretch() right_panel.addWidget(self.img_label) right_panel.addWidget(self.result_label) layout.addLayout(left_panel, 1) layout.addLayout(right_panel, 4) main_widget.setLayout(layout) self.setCentralWidget(main_widget) # 连接信号槽 upload_btn.clicked.connect(self.open_image) detect_btn.clicked.connect(self.detect_cells) def open_image(self): # 打开文件对话框 fname, _ = QFileDialog.getOpenFileName(self, &#39;打开图片&#39;, &#39;&#39;, &#39;图像文件 (*.jpg *.png)&#39;) if fname: self.image_path = fname pixmap = QPixmap(fname) self.img_label.setPixmap(pixmap.scaled(800, 600, Qt.KeepAspectRatio)) def detect_cells(self): # 执检测 if hasattr(self, &#39;image_path&#39;): # 预处理图像 image = Image.open(self.image_path).convert("RGB") img_tensor = torchvision.transforms.functional.to_tensor(image) # 模型推理 with torch.no_grad(): predictions = self.model([img_tensor]) # 解析结果 boxes = predictions[0][&#39;boxes&#39;].cpu().numpy() labels = predictions[0][&#39;labels&#39;].cpu().numpy() scores = predictions[0][&#39;scores&#39;].cpu().numpy() # 过滤低置信度检测 threshold = 0.7 valid_detections = scores > threshold boxes = boxes[valid_detections] labels = labels[valid_detections] # 绘制检测框 draw = ImageDraw.Draw(image) for box, label in zip(boxes, labels): draw.rectangle([(box[0], box[1]), (box[2], box[3])], outline="red", width=3) draw.text((box[0], box[1]), f"Cell {label}", fill="red") # 显示结果 opencv_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) height, width, channel = opencv_image.shape bytes_per_line = 3 * width q_img = QImage(opencv_image.data, width, height, bytes_per_line, QImage.Format_RGB888) self.img_label.setPixmap(QPixmap.fromImage(q_img).scaled(800, 600, Qt.KeepAspectRatio)) # 更新计数 cell_count = len(boxes) self.count_label.setText(f"细胞计数: {cell_count}") if __name__ == &#39;__main__&#39;: app = QApplication(sys.argv) ex = BloodCellDetector() ex.show() sys.exit(app.exec_()) ``` 代码解析: 1. 模型加载:使用torchvision预训练的Faster R-CNN模型 2. 界面布局:采用左右面板布局,左侧为控制面板,右侧为图像显示 3. 图像处理流程: - 使用QFileDialog选择图片 - 转换为PyTorch Tensor进推理 - 过滤低置信度检测结果(阈值0.7) - 使用PIL绘制检测框和标签 - 转换为QPixmap显示在界面 使用流程: 1. 安装依赖: ```bash pip install pyqt5 torch torchvision opencv-python pillow ``` 2. 运程序: ```bash python blood_cell_detector.py ``` 3. 操作步骤: - 点击"上传图片"选择血细胞图片 - 点击"开始检测"运检测算法 - 右侧显示带检测框的结果图像 - 左侧显示细胞计数结果 注意事项: 1. 需要根据实际训练的血细胞检测模型替换模型加载部分 2. 检测阈值可根据实际需求调整 3. 需要处理不同图像尺寸的适配问题
评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值