Bootstrap

大的图像内存占用太大,分块处理

        b, c, h, w = img_noisy.shape
        mask = torch.zeros((b, 1, h, w))
        img_dn = torch.zeros_like(img_noisy)

        print(mask.shape, img_dn.shape)
        start.record()
        
        h1 = h // 2
        w1 = w // 2

        h2 = h1 + (32 - h1 % 32)
        h3 = h1 - (32 - (h-h1) % 32)
        print('hh',h3, h1, h2, h-h3)
        w2 = w1 + (32 - w1 % 32)
        w3 = w1 - (32 - (w-w1) % 32)
        print('ww',w3, w1, w2, w-w3 )

        img_dn[:,:,:h2,:w2] = forward(img_noisy[:,:,:h2,:w2], model, tile)
        mask[:,:,:h2,:w2] += 1
        img_dn[:,:,h3:,:w2] += forward(img_noisy[:,:,h3:,:w2], model, tile)
        mask[:,:,h3:,:w2] += 1
        
        

        img_dn[:,:,:h2,w3:]+= forward(img_noisy[:,:,:h2,w3:], model, tile)
        mask[:,:,:h2,w3:] += 1
        img_dn[:,:,h3:,w3:] += forward(img_noisy[:,:,h3:,w3:], model, tile)
        mask[:,:,h3:,w3:] += 1
            
        # --------------------------------
        # (2) img_dn
        # --------------------------------
        
        print(mask.shape, img_dn.shape)
        img_dn = img_dn / mask.to(device)
        
        torch.cuda.synchronize()

kimi1.5给的答案挺好:

在处理大图像时,分块处理是一个有效的方法,可以避免内存不足的问题。以下是实现这一需求的代码和详细解释:
解决方案代码

import numpy as np

def split_image_large(img, block_size=32):
    """
    将大图像分为四个部分,每部分的宽度和高度是32的倍数。
    :param img: 输入图像,格式为 (height, width, channels)
    :param block_size: 每块的尺寸必须是该数值的倍数(默认32)
    :return: 四部分图像按左上、左下、右上、右下的顺序返回
    """
    H, W, C = img.shape
    
    # 确保每个分块的宽度和高度是32的倍数
    half_width = W // 2
    half_height = H // 2
    
    # 计算每个块的宽度和高度(32的倍数)
    block_width = ((half_width + block_size - 1) // block_size) * block_size
    block_height = ((half_height + block_size - 1) // block_size) * block_size
    
    # 创建四部分图像
    chunks = []
    
    # 左上部分
    chunks.append(img[0:block_height, 0:block_width])
    
    # 左下部分
    chunks.append(img[H - block_height:H, 0:block_width])
    
    # 右上部分
    chunks.append(img[0:block_height, W - block_width:W])
    
    # 右下部分
    chunks.append(img[H - block_height:H, W - block_width:W])
    
    return chunks

示例用法

假设 img 是一个大图像,尺寸为 (2000, 3000, 3)

img = np.random.randint(0, 255, size=(2000, 3000, 3), dtype=np.uint8)
chunks = split_image_large(img)

打印各分块的尺寸

for i, chunk in enumerate(chunks):
print(f"Chunk {i+1} shape: {chunk.shape}")
代码解释
分块大小计算:
使用 ((half_width + block_size - 1) // block_size) * block_size 确保分块的宽度和高度是32的倍数。这里通过向上取整的方式调整分块大小,确保覆盖整个图像。
分块逻辑:
左上部分:从图像顶部和左侧开始,获取左上部分。
左下部分:从图像底部和左侧开始,获取左下部分。
右上部分:从图像顶部和右侧开始,获取右上部分。
右下部分:从图像底部和右侧开始,获取右下部分。
避免 Padding:
不使用任何填充操作,直接通过调整分块起始和结束位置覆盖整个图像。允许部分像素重叠以确保完整覆盖。
示例输出
假设输入图像尺寸为 (2000, 3000, 3)(高度2000,宽度3000),分块后各部分的尺寸如下:
Chunk 1 shape: (1024, 1536, 3)(左上部分)
Chunk 2 shape: (976, 1536, 3)(左下部分)
Chunk 3 shape: (1024, 1464, 3)(右上部分)
Chunk 4 shape: (976, 1464, 3)(右下部分)
注意事项
分块后的各部分可能包含部分重叠像素,这是为了确保整个图像被完整覆盖,并且分块大小符合32的倍数要求。
该方法适用于需要对大图像进行分块处理,同时维持模型输入尺寸要求的场景。

;