低质量图像超分算法 SwinIR: Image Restoration Using Swin Transformer

2023-05-16

论文名称:SwinIR: Image Restoration Using Swin Transformer
论文地址:https://arxiv.org/abs/2108.10257
代码仓库:https://github.com/JingyunLiang/SwinIR

Swin Transformer

Transformer在机器翻译等一维序列处理上取得了巨大成功,但基本的Transformer难以直接应用到视觉任务,Vision Transformer(VIT)的出现成功的将Transformer拉入了CV界,可以说是Transformer处理视觉任务的开山之作,VIT成功的将视觉问题转换成了NLP问题,将2D的图像通过打成多个patch块来转换Transformer能处理的1Dpatch序列,Swin Transformer也是借鉴了Vision Transformer对于图片的处理方法。

Swin Transformer名字的前部分Swin来自于Shifted Windows,Shifted Windows(移动窗口)也是Swin Transformer的主要特点。Swin Transformer的作者的初衷是想让Vision Transformer像卷积神经网络一样,也能够分成几个block做层级式的特征提取,从而导致提出来的特征具有多尺度的概念。

标准的Transformer直接用到视觉领域有一些挑战,难度主要来自于尺度不一和图像的resolution较大两个方面。首先是关于尺度的问题,例如一张街景的图片,里面有很多车和行人,并且各种物体的大小不一,这种现象不存在于自然语言处理。再者是关于图像的resolution较大问题,如果以像素点为基本单位,序列的长度就变得高不可攀,为了解决序列长度这一问题,科研人员做了一系列的尝试工作,包括把后续的特征图作为Transformer的输入或者把图像打成多个patch以减少图片的resolution,也包括把图片划成一个一个的小窗口,然后再窗口里做自注意力计算等多种办法。针对以上两个方面的问题,Swin Transformer网络被提出,它的特征是通过移动窗口的方式学来的,移动窗口不仅带来了更大的效率,由于自注意力是在窗口内计算的,所以也大大降低了序列的长度,同时通过Shiting(移动)的操作可以使相邻的两个窗口之间进行交互,也因此上下层之间有了cross-window connection,从而变相达到了全局建模的能力。层级式结构的好处在于不仅灵活的提供各种尺度的信息,同时还因为自注意力是在窗口内计算的,所以它的计算复杂度随着图片大小线性增长而不是平方级增长,这就使Swin Transformer能够在特别大的分辨率上进行预训练模型。

摘要

图像恢复是一个长期存在的低级视觉问题,旨在从低质量图像(例如,缩小的、有噪声的和压缩的图像)中恢复高质量图像。虽然最先进的图像恢复方法是基于卷积神经网络的,但很少有人尝试使用在高级视觉任务中表现出令人印象深刻的性能的变压器。本文提出了一种基于Swin变换的强基线图像恢复模型SwinIR。SwinIR由浅层特征提取深层特征提取高质量图像重建三部分组成。实验表明在图像超分辨率(包括经典、轻量级和真实世界图像超分辨率)、图像去噪(包括灰度和彩色图像去噪)和JPEG压缩伪影减少。实验结果表明,SwinIR在不同任务上的性能比现有方法提高了0.14~0.45dB,同时参数总数减少了67%

上图可以看出SwinIR的提升非常恐怖,经典的RCAN在质量和参数量上都要远逊色于SwinIR。

引言及相关工作

以往基于CNN的方法通常会遇到两个基本问题:

  • 图像和卷积核之间的交互与内容无关,使用相同的卷积核来恢复不同的图像区域可能不是一个好的选择。
  • CCN只能对局部信息进行处理,卷积对于长期依赖性建模是无效的。

而Transformer基于自注意力机制可以捕获上下文之间的全局信息交互,但同时基于视觉的VIT会将输入图像分割成大小固定的小块(patch),并独立处理每个小块,因此会导致另外两个缺点:

  • 恢复的图像可能会在每个小斑块周围引入边界伪影。
  • 每个patch的边界像素会丢失信息。

Swin Transformer则很好的结合了CNN和Transformer的优点,同时避免了这些缺点

Swin Transformer采用局部注意机制处理图像,其具有CNN处理大尺寸图像的优势,并且相较于Transformer/CNN,它的计算量减少了很多,因此可以处理大尺寸图像。此外采用了滑动窗口方案来建模长期依赖关系

网络结构

SwinIR由三个模块组成:浅层特征提取、深层特征提取和高质量(HQ)图像重建模块。

浅层特征提取(Shallow Feature Extraction)

与所有的SR方法一样,浅层特征采用3×3大小的卷积核进行浅层特征提取,给出的解释是卷积层擅长早期视觉处理,从而导致更稳定的优化和更好的结果,这一点在许多研究中也有所体现。

 深层特征提取(DeepFeature Extraction)

 上面的图2可以看出,整个深层特征提取依赖于作者提出的Residual Swin Transformer blocks (RSTB)结构,每一个RSTB由6个Swin Transformer Layer(STL)组成,并在最后加上一个3×3的Conv。

至于为什么要加上卷积层,作者给出的解释有两个原因:

  1. 虽然Transformer可以被视为空间变化卷积的具体实例,但具有空间不变滤波器的卷积层可以增强SwinIR的平移等方差。
  2. 残差连接提供了从不同块到重建模块的基于标识的连接,允许不同级别的特征的聚集。

RSTB代码:

class RSTB(nn.Module):
    """Residual Swin Transformer Block (RSTB).
    Args:
        dim (int): Number of input channels.
        input_resolution (tuple[int]): Input resolution.
        depth (int): Number of blocks.
        num_heads (int): Number of attention heads.
        window_size (int): Local window size.
        mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.
        qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True
        qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.
        drop (float, optional): Dropout rate. Default: 0.0
        attn_drop (float, optional): Attention dropout rate. Default: 0.0
        drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0
        norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm
        downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None
        use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.
        img_size: Input image size.
        patch_size: Patch size.
        resi_connection: The convolutional block before residual connection.
    """

    def __init__(self, dim, input_resolution, depth, num_heads, window_size,
                 mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0.,
                 drop_path=0., norm_layer=nn.LayerNorm, downsample=None, use_checkpoint=False,
                 img_size=224, patch_size=4, resi_connection='1conv'):
        super(RSTB, self).__init__()

        self.dim = dim
        self.input_resolution = input_resolution

        self.residual_group = BasicLayer(dim=dim,
                                         input_resolution=input_resolution,
                                         depth=depth,
                                         num_heads=num_heads,
                                         window_size=window_size,
                                         mlp_ratio=mlp_ratio,
                                         qkv_bias=qkv_bias, qk_scale=qk_scale,
                                         drop=drop, attn_drop=attn_drop,
                                         drop_path=drop_path,
                                         norm_layer=norm_layer,
                                         downsample=downsample,
                                         use_checkpoint=use_checkpoint)

        if resi_connection == '1conv':
            self.conv = nn.Conv2d(dim, dim, 3, 1, 1)
        elif resi_connection == '3conv':
            # to save parameters and memory
            self.conv = nn.Sequential(nn.Conv2d(dim, dim // 4, 3, 1, 1), nn.LeakyReLU(negative_slope=0.2, inplace=True),
                                      nn.Conv2d(dim // 4, dim // 4, 1, 1, 0),
                                      nn.LeakyReLU(negative_slope=0.2, inplace=True),
                                      nn.Conv2d(dim // 4, dim, 3, 1, 1))

        self.patch_embed = PatchEmbed(
            img_size=img_size, patch_size=patch_size, in_chans=0, embed_dim=dim,
            norm_layer=None)

        self.patch_unembed = PatchUnEmbed(
            img_size=img_size, patch_size=patch_size, in_chans=0, embed_dim=dim,
            norm_layer=None)

    def forward(self, x, x_size):
        return self.patch_embed(self.conv(self.patch_unembed(self.residual_group(x, x_size), x_size))) + x

    def flops(self):
        flops = 0
        flops += self.residual_group.flops()
        H, W = self.input_resolution
        flops += H * W * self.dim * self.dim * 9
        flops += self.patch_embed.flops()
        flops += self.patch_unembed.flops()

        return flops

 Swin Transformer Layer(STL)

这个算是文章真正的精华所在了,STL也是基于标准Transformer layer 的多头自注意力机制。主要改进点在于局部注意力和移动窗口机制。

如图所示,给定尺寸为H × W × C的输入,Swin Transformer先将输入划分为不重叠的M × M个局部窗口,reshape为HW/M平方×M平方×C,其中HW/M平方是窗口总数。然后,它为每个窗口分别计算自我注意(局部注意力),对于局部窗口特征X ∈ M平方×C,查询、键和值矩阵Q、K和V计算如下:

 这段话不太好叙述,原文是这么说的:

 其中PQ、PK和PV是跨不同窗口共享的投影矩阵,有了QKV后,就可以计算局部窗口中的注意力得分了,这里就跟Transformer一样了:

 B就是Transformer中的position位置编码,不过Transformer是给定的,这里是可学习的相对位置编码。在使用时并行执行h次注意功能,并连接多头自注意multi-head self-attention(MSA)的结果。

和Transformer一样,在MSA和MLP之前加了LayerNorm层进行标准化。

计算过程如代码所示:

class WindowAttention(nn.Module):
    r""" Window based multi-head self attention (W-MSA) module with relative position bias.
    It supports both of shifted and non-shifted window.
    Args:
        dim (int): Number of input channels.
        window_size (tuple[int]): The height and width of the window.
        num_heads (int): Number of attention heads.
        qkv_bias (bool, optional):  If True, add a learnable bias to query, key, value. Default: True
        qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set
        attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0
        proj_drop (float, optional): Dropout ratio of output. Default: 0.0
    """

    def __init__(self, dim, window_size, num_heads, qkv_bias=True, qk_scale=None, attn_drop=0., proj_drop=0.):

        super().__init__()
        self.dim = dim
        self.window_size = window_size  # Wh, Ww
        self.num_heads = num_heads
        head_dim = dim // num_heads
        self.scale = qk_scale or head_dim ** -0.5

        # define a parameter table of relative position bias
        self.relative_position_bias_table = nn.Parameter(
            torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads))  # 2*Wh-1 * 2*Ww-1, nH

        # get pair-wise relative position index for each token inside the window
        coords_h = torch.arange(self.window_size[0])
        coords_w = torch.arange(self.window_size[1])
        coords = torch.stack(torch.meshgrid([coords_h, coords_w]))  # 2, Wh, Ww
        coords_flatten = torch.flatten(coords, 1)  # 2, Wh*Ww
        relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :]  # 2, Wh*Ww, Wh*Ww
        relative_coords = relative_coords.permute(1, 2, 0).contiguous()  # Wh*Ww, Wh*Ww, 2
        relative_coords[:, :, 0] += self.window_size[0] - 1  # shift to start from 0
        relative_coords[:, :, 1] += self.window_size[1] - 1
        relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1
        relative_position_index = relative_coords.sum(-1)  # Wh*Ww, Wh*Ww
        self.register_buffer("relative_position_index", relative_position_index)

        self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
        self.attn_drop = nn.Dropout(attn_drop)
        self.proj = nn.Linear(dim, dim)

        self.proj_drop = nn.Dropout(proj_drop)

        trunc_normal_(self.relative_position_bias_table, std=.02)
        self.softmax = nn.Softmax(dim=-1)

    def forward(self, x, mask=None):
        """
        Args:
            x: input features with shape of (num_windows*B, N, C)
            mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None
        """
        B_, N, C = x.shape
        qkv = self.qkv(x).reshape(B_, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
        q, k, v = qkv[0], qkv[1], qkv[2]  # make torchscript happy (cannot use tensor as tuple)

        q = q * self.scale
        attn = (q @ k.transpose(-2, -1))

        relative_position_bias = self.relative_position_bias_table[self.relative_position_index.view(-1)].view(
            self.window_size[0] * self.window_size[1], self.window_size[0] * self.window_size[1], -1)  # Wh*Ww,Wh*Ww,nH
        relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous()  # nH, Wh*Ww, Wh*Ww
        attn = attn + relative_position_bias.unsqueeze(0)

        if mask is not None:
            nW = mask.shape[0]
            attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(1).unsqueeze(0)
            attn = attn.view(-1, self.num_heads, N, N)
            attn = self.softmax(attn)
        else:
            attn = self.softmax(attn)

        attn = self.attn_drop(attn)

        x = (attn @ v).transpose(1, 2).reshape(B_, N, C)
        x = self.proj(x)
        x = self.proj_drop(x)
        return x

    def extra_repr(self) -> str:
        return f'dim={self.dim}, window_size={self.window_size}, num_heads={self.num_heads}'

    def flops(self, N):
        # calculate flops for 1 window with token length of N
        flops = 0
        # qkv = self.qkv(x)
        flops += N * self.dim * 3 * self.dim
        # attn = (q @ k.transpose(-2, -1))
        flops += self.num_heads * N * (self.dim // self.num_heads) * N
        #  x = (attn @ v)
        flops += self.num_heads * N * N * (self.dim // self.num_heads)
        # x = self.proj(x)
        flops += N * self.dim * self.dim
        return flops

重建部分

重建部分与大部分网络一样,不过SwinIR将浅层和深层特征给加起来了,这个操作也很常见。

 损失函数对于SR任务用的也是通用的L1

 实验部分

超参设置

RSTB个数K = 6 (轻量级SwinIR,取K= 4)
STL数L = 6
窗口大小M = 8 (减少JPEG压缩伪影,窗口大小M = 7)
通道数C = 180 (轻量级SwinIR,取C = 60)   
注意头数h = 6
自集成策略用“+”表示

这里比较惊讶的是通道数取到180竟然还能保持较低的参数量和计算量,RCAN取64都已经很大了,足以见得SwinIR的强大。 

实验对比

消融实验感兴趣可以自行探究,主要展示一下SwinIR是如何吊打其他网络的

 采用DIV2K和F2K混合训练效果好暂且不谈,以目前最流行的DIV2K做训练集,在×2,×3,×4下的结果远远领先其他方法,有点睥睨天下的感觉。

 轻量级的SwinIR在仅有897K参数量的情况下,也是吊打其他方法。

可视化对比时还把GAN给拉进来了,众所周知GAN在SR任务中的表现突出一个能打,虽然评价指标PSNR/SSIM比不过CNN,但是视觉效果远好于CNN。 

 

总结

文章提出RSTB进行深度特征提取,每个RSTB由Swin变换层、卷积层和残余连接组成。大量实验表明,SwinIR在经典图像复原、轻量级图像复原、真实图像复原、灰度图像去噪、彩色图像去噪和JPEG压缩伪影减少等6种不同设置下,均取得了令人满意的效果,从而验证了SwinIR的有效性和普适性。在未来,作者还将把该模型扩展到其他恢复任务,如图像去模糊和去雨。

用作者提供的预训练模型测试结果确实很好,后面准备自己训练一下SwinIR,看一看自己训练的效果如何, 同时计算一下Flops进行一下对比。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

低质量图像超分算法 SwinIR: Image Restoration Using Swin Transformer 的相关文章

  • 使用 docx4j 从带有 Base64 图像的 HTML 生成 .docx

    我正在尝试生成一个 docx from a HTML字符串与docx4j in Java 其中包含 Base64 图像 目前 我能够生成 Word 并下载它 在 Vaadin 项目内 但图像无法正确插入 但是 如果我把HTML代码写入一个索
  • jquery 在单击的实例之后查找下一个图像

    我正在尝试建立一个图像库 您可以在其中单击拇指 然后可以使用下一个和上一个按钮 我的问题是用户最初可以单击我需要检测的任何图像以及下一个或上一个图像的锻炼 并将显示 src 替换为下一个图像的 src 我只是想让下一个按钮首先工作 因为前一
  • 如何从 dataurl 在服务器上创建图像文件

    我有一个 dataurl 格式的图像 例如 data image jpeg base64 9j 4AAQSkZJRgABAQAAAQABAAD 2wBDAAMCAgMCAgMDAwMEAwME iiigAooooAKKKKACiiigAoo
  • 有没有办法在 asp 图像控件上显示动态生成的位图?

    在我的代码中 我使用 C 和 ASP NET 动态创建位图 我需要将其显示在 asp 图像控件上 无论如何 有没有办法在不使用处理程序的情况下做到这一点 使用 ashx 处理程序更好 因为它适用于所有浏览器 并且您可以在客户端上缓存输出图像
  • iOS 非矩形图像裁剪? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 我是否必须在 SQLConnection 被释放之前关闭它?

    根据我的其他关于一次性物品的问题 https stackoverflow com questions 1033334 is there a list of common object that implement idisposable f
  • HTTP 重定向图像可以吗?

    返回图片资源时返回301 302 303代码可以吗 我过去曾这样做过 而且似乎有效 这是好的做法吗 它与大多数浏览器兼容吗 是的 您可以重定向图像 浏览器将遵循重定向 但出于性能原因 您通常希望将重定向保持在最低限度 因为每个重定向都需要单
  • 在表单中突出显示选定的图像 - 使用 Jquery?

    我在谷歌上搜索了答案 但发现什么也没有 所以即使是一个显示如何执行以下操作的页面的链接也将不胜感激 基本上我有一个只有图像的表格
  • 如何缩放图像的一部分并插入到 matplotlib 中的同一图中

    我想缩放数据 图像的一部分并将其绘制在同一个图中 看起来有点像这个图 是否可以在同一图中插入缩放图像的一部分 我认为可以用子图绘制另一个图形 但它绘制了两个不同的图形 我还阅读了添加补丁以插入矩形 圆形 但不确定将图像的一部分插入到图中是否
  • Google Chrome 中不缓存动态加载的图像

    使用 jQuery 加载的图像未保存在 Google Chrome 的缓存中 每次都会从服务器下载 情况 我正在使用 jQuery slimbox2 在 灯箱 中加载图片 此时没有什么特别的 我添加了一些 jQuery 代码来检测鼠标光标何
  • 以编程方式在 iPhone 上使用彩信发送图像?

    搜遍全网都没有解决这个问题 我想用 iPhone 相机拍照 然后能够通过彩信 电子邮件发送出去 这不一定发生在我的应用程序中 但至少我希望能够调用彩信 电子邮件应用程序并使其选择拍摄 和存储 的图片 当我使用内置相册应用程序时 每张照片的左
  • Go 中的 WebP 编码器/解码器

    是否有一个完整的 WebP 编码器和解码器与当前每周 或可分叉 兼容 它的速度与标准 png 相当吗 这个人在 GitHub 上有一个包 其中包含 WebP 的编码器和解码器 https github com chai2010 webp h
  • BIRT 不显示 base64 编码的图像

    我想将图像包含到 BIRT 报告中 图像应由 XML 数据源 base64 编码 给出 但XML数据源不支持Blob数据类型 我找到了一个很好的答案这个 BIRT 问题 https stackoverflow com questions 2
  • 使用 OpenCV 和 Python 叠加两个图像而不丢失颜色强度

    如何叠加两个图像而不损失两个图像的颜色强度 我有图像1和图像2 2 我尝试使用 0 5 alpha 和 beta 但它给我的合并图像的颜色强度只有一半 dst cv2 addWeighted img1 0 5 img2 0 5 0 但是当我
  • 无需画布,用纯 JS 生成图像

    如何在没有画布的情况下用纯 JavaScript 无外部库 从像素数组生成 绘制图片 我尝试以URI形式生成图像但没有成功 图片格式不容易快速理解和实现 BMP 数据URI 您可以使用以下函数生成 BMP 位图 dataURI 24 位的
  • 找到图像特征宽度的正确方法和Python包

    输入是一个在黑色背景上带有彩色 抱歉 垂直线的光谱 给定该带的近似 x 坐标 用 X 标记 我想找到该带的宽度 我对图像处理不熟悉 请引导我前往正确的方法图像处理和Python图像处理package也能起到同样的作用 我认为 PIL Ope
  • 访问图像的 Windows“标签”元数据字段

    我正在尝试进行一些图像处理 所以现在我正在尝试读取图像 exif 数据 有 2 个内置函数可用于读取图像的 exif 数据 问题是我想读取图像标签 exifread and imfinfo这两个函数都不显示图像标签 Is there any
  • 使用 CSS 的响应式图像

    我发现调整图像大小以使其具有响应能力很棘手 我正在开发一个 php 应用程序来自动将网站转换为响应式版本 我有点被图像困住了 我已经成功地为网站上的每个图像添加了一个包装类 并且可以很好地调整图像的大小 我的问题在于自然小于窗口的图像 例如
  • 如何将 PIL 图像转换为 NumPy 数组?

    如何转换 PILImage来回转换为 NumPy 数组 这样我就可以比 PIL 进行更快的像素级转换PixelAccess允许 我可以通过以下方式将其转换为 NumPy 数组 pic Image open foo jpg pix numpy
  • 如何测量我的网站客户端的图像下载时间?

    在 Img 标签中 我们知道图像有一个 OnLoad 事件 该事件在图像完成加载时触发 但是我们能在图像开始下载时得到准确的测量结果吗 我正在尝试测量网站的页面加载时间 因此如果可能的话 了解加载图像需要多长时间将成为我分析的一部分 我想以

随机推荐

  • 网络篇-传输控制协议TCP

    TCP协议 传输控制协议 xff08 TCP xff0c Transmission Control Protocol xff09 用一句话概括的话 xff0c 它是一种面向连接的 可靠的 基于字节流的传输层通信协议 TCP xff08 传输
  • 阻塞队列-BlockingQueue

    对于Queue而言 xff0c BlockingQueue是主要的线程安全的版本 xff0c 具有阻塞功能 xff0c 可以允许添加 删除元素被阻塞 xff0c 直到成功为止 xff0c blockingqueue相对于Queue而言增加了
  • 线程池-ThreadPoolExecutor

    如果并发的线程数量很多 xff0c 并且每个线程都是执行一个时间很短的任务就结束了 xff0c 这样频繁创建线程就会大大降低系统的效率 xff0c 因为频繁创建线程和销毁线程需要时间 那么有没有一种办法使得线程可以复用 xff0c 就是执行
  • MySQL索引

    基础知识 索引是创建在表上的 xff0c 对数据库表中一列或多列的值进行排序的一种结构 xff0c 可以提高查询的速度 通俗的来说 xff0c 数据库中存储的数据比作字典的话 xff0c 索引就相当于是字典中的目录 如果没有索引 xff0c
  • ThreadPoolExecutor任务提交与停止流程及底层实现

    ThreadPoolExecutor任务提交 executor任务提交流程 通过查看源码可知 xff0c JUC下的Excutor接口仅提供了一个可执行方法executor public interface Executor Execute
  • RoboMaster步兵机器人简介

    RoboMaster步兵机器人简介 湖北工业大学 蔡饶 如下图所示 xff0c 设计的是一个基于麦克纳姆轮的四轮全向越障平台 xff0c 纵臂式独立悬挂 xff0c 搭载两轴云台和弹丸发射机构 xff0c 是大疆承办的RoboMaster机
  • makefile 完美教程

    简介 Makefile 是和 make 命令一起配合使用的 xff0c 很多大型项目的编译都是通过 Makefile 来组织的 我建立工程的方法有以下三点 xff1a 1 makefile xff1a 优点 xff1a 使用非常广泛 xff
  • Arrays与Collection中自定义Comparator接口配合lambda实现自定义sort

    问题 刷到一个算法题需要拼接数字组成一个最大数 xff0c 基本思想是高位比较 xff0c 相等比较下一位 xff0c 然后根据大小先拼接大的 xff0c 再拼接小的 xff0c 但是发现当存在多个数字高位相同时面临一个问题 xff0c 比
  • SpringBoot2常见问题总结帖

    1 启动Springboot主程序类后报错This application has no explicit mapping for error so you are seeing this as a fallback 解决办法 xff1a
  • 设计模式-五大创建型模式概念与实现

    设计模式 xff08 Design pattern xff09 代表了最佳的实践方案 xff0c 可以说它是一套被反复使用的 多数人知晓的 经过分类编目的 代码设计经验的总结 xff0c 通常被有经验的面向对象的软件开发人员所采用 Desi
  • 雪花算法原理及实现

    背景 分布式高并发的环境下 xff0c 最常见的就是每年双十一的十二点 xff0c 大量用户同时抢购同一商品 xff0c 毫秒级的时间下可能生成数万个订单 xff0c 此时确保生成订单ID的唯一性变得至关重要 此外 xff0c 在秒杀环境下
  • Nacos注册中心-服务注册、分级存储与配置管理

    项目代码 xff1a resumebb springcloud nacos 码云 开源中国 gitee com Nacos注册中心 SpringCloudAlibaba 推出了一个名为 Nacos 的注册中心 xff0c 在国外也有大量的使
  • Feign远程调用-自定义配置与性能优化

    介绍 利用RestTemplate发起远程调用的代码 xff1a String url 61 34 http userservice user 34 43 order getUserId User user 61 restTemplate
  • Ribbon负载均衡

    Ribbon介绍 Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具 xff0c 它基于Netflix Ribbon实现 通过Spring Cloud的封装 xff0c 可以让我们轻松地将面向服务的REST
  • RabbitMQ消息队列

    同步异步通讯 微服务间通讯有同步和异步两种方式 同步通讯 xff1a 就像打电话 xff0c 需要实时响应 异步通讯 xff1a 就像发邮件 xff0c 不需要马上回复 两种方式各有优劣 xff0c 打电话可以立即得到响应 xff0c 但是
  • Spring Boot集成Spring Security

    Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架 它提供了一组可以在Spring应用上下文中配置的Bean xff0c 充分利用了Spring IoC xff0c DI xf
  • 超分辨重建-Bicubic双三次线性插值opencv实现

    论文实验中经典方法Bicubic的Python实现 使用时更改文件夹 保存路径 重建倍数即可 import os import argparse import cv2 parse args parser 61 argparse Argume
  • opencv_contrib aruco源码

    https github com opencv opencv contrib tree master modules 最近使用了aruco模块 想看看aruco的源码是怎样实现的 在opencv源码中一直没找到aruco 原来 他隐藏在op
  • HTTP/WEB中常见的状态码大全

    HTTP 状态码分类 HTTP 状态码由三个十进制数字组成 xff0c 第一个十进制数字定义了状态码的类型 响应分为五类 xff1a 信息响应 100 199 成功响应 200 299 重定向 300 399 客户端错误 400 499 服
  • 低质量图像超分算法 SwinIR: Image Restoration Using Swin Transformer

    论文名称 xff1a SwinIR Image Restoration Using Swin Transformer 论文地址 xff1a https arxiv org abs 2108 10257 代码仓库 xff1a https gi