Python-实现图像重叠分块与恢复

Overlap-tile策略

  在准备图像分割的数据集时, 会遇到数据集 数据量较少 或者 分辨率较大不适合对原图进行缩放(缩放通常使用插值算法,主流的插值算法如双线性插值具有低通滤波的性质,会使得图像的高频分量受损,从而造成图像轮廓和边缘等细节损失,可能对模型学习有一定影响)的情况,使用Overlap-tile策略可以有效的解决上述问题。
  看过U-Net原文的同学应该是了解Overlap-tile,做法其实很简单,就是在输入网络前对图像进行padding,使得最终的输出尺寸与原图一致。特别的是,这个padding是镜像padding,这样,在预测边界区域的时候就提供了上下文信息。
(Overlap-tile)
上图左边是对原图进行镜像padding后的效果,黄框是原图的左上角部分,padding后其四周也获得了上下文信息,与图像内部的其它区域有类似效果。

  Overlap-tile策略可搭配patch(图像分块)一起使用。当内存资源有限从而无法对整张大图进行预测时,可以对图像先进行镜像padding,然后按序将padding后的图像分割成固定大小的patch。这样,能够实现对任意大的图像进行无缝分割,同时每个图像块也获得了相应的上下文信息。另外,在数据量较少的情况下,每张图像都被分割成多个patch,相当于起到了扩充数据量的作用。更重要的是,这种策略不需要对原图进行缩放,每个位置的像素值与原图保持一致,不会因为缩放而带来误差。

本文的代码只是实现了对于图像的重叠分块与恢复,没有对于图像进行镜像padding。

分块代码:

import cv2
import math 
import numpy as np
 
from pathlib import Path
 
file_name = "1.png"
save_path = './fen' # create dir sunxu
Path(save_path).mkdir(parents=True, exist_ok=True) 
 
# block size
height = 512
width = 512
 
# overlap (如果不想重叠,可以置为0)
over_x = 50
over_y = 50
h_val = height - over_x
w_val = width - over_y
 
# Set whether to discard an image that does not meet the size
mandatory = False
 
img = cv2.imread(file_name)
 
print(img.shape)
# original image size
original_height = img.shape[0]
original_width = img.shape[1]
 
max_row = float((original_height-height)/h_val)+1 
max_col = float((original_width-width)/w_val)+1
 
# block number
max_row = math.ceil(max_row) if mandatory == False else math.floor(max_row)
max_col = math.ceil(max_col) if mandatory == False else math.floor(max_col)
 
print(max_row)
print(max_col)
 
images = []
for i in range(max_row):
	images_temp = []
	for j in range(max_col):
		temp_path = save_path + '/' + str(i) + '_' + str(j) + '_'
		if ((width+j*w_val)>original_width and (i*h_val+height)<=original_height): # Judge the right most incomplete part
			temp = img[i*h_val:i*h_val+height,j*w_val:original_width,:]
			temp_path = temp_path + str(temp.shape[0]) + '_' + str(temp.shape[1]) + '.jpg'
			cv2.imwrite(temp_path,temp)
			images_temp.append(temp)
		elif ((height+i*h_val)>original_height and (j*w_val+width)<=original_width): # Judge the incomplete part at the bottom
			temp = img[i*h_val:original_height,j*w_val:j*w_val+width,:]
			temp_path = temp_path + str(temp.shape[0]) + '_' + str(temp.shape[1]) + '.jpg'
			cv2.imwrite(temp_path,temp)
			images_temp.append(temp)
		elif ((width+j*w_val)>original_width and (i*h_val+height)>original_height): # Judge the last slide
			temp = img[i*h_val:original_height,j*w_val:original_width,:]
			temp_path = temp_path + str(temp.shape[0]) + '_' + str(temp.shape[1]) + '.jpg'
			cv2.imwrite(temp_path,temp)
			images_temp.append(temp)
		else:
			temp = img[i*h_val:i*h_val+height,j*w_val:j*w_val+width,:]
			temp_path = temp_path + str(temp.shape[0]) + '_' + str(temp.shape[1]) + '.jpg'
			cv2.imwrite(temp_path,temp)
			images_temp.append(temp) # The rest of the complete
			
	images.append(images_temp)
		
print(len(images))

以下代码是将上面分块的图像进行恢复:

恢复代码:

 
import cv2
import math 
import numpy as np
import functools
 
from pathlib import Path
 
def custom_sort(x,y):
	x = x.split(tag)[-1].split('.')[0].split('_')
	x = [int(i) for i in x]
	y = y.split(tag)[-1].split('.')[0].split('_')
	y = [int(i) for i in y]
	for i in range(len(x)):
		if(x[i]>y[i]):
			return 1
		elif(x[i]<y[i]):
			return -1;
		elif(i==len(x)-1):
			return 0
	
tag = '\\' # 路径分隔符
 
data_root = Path('./fen')
temp_path = '2.jpg'
 
height = 512
width = 512
 
# overlap 
over_x = 50
over_y = 50
h_val = height - over_x
w_val = width - over_y
 
images_path = data_root.glob('*')
images_path = [str(path) for path in images_path]
images_path = sorted(images_path,key=functools.cmp_to_key(custom_sort))
#print(images_path)
 
s = set()
for path in images_path:
	path = path.split(tag)[-1].split('_')
	s.add(int(path[0]))
#print(s)
 
output = []
for i in range(len(s)):
	output.append([])
 
for path in images_path:
	image = cv2.imread(path)
	path = path.split(tag)[-1].split('.')[0].split('_')
	if(int(path[3])==width): 
		if(int(path[1])==0):
			output[int(path[0])].append(image[:,:,:])
		else:
			output[int(path[0])].append(image[:,over_y:,:])	
	else:
		output[int(path[0])].append(image[:,over_y:,:])
 
temp = []
for i in range(len(output)):
	t = np.concatenate(output[i],1)
	if(i==0):
		temp.append(t[:,:,:])
	else:
		temp.append(t[over_x:,:,:])
 
 
temp = np.concatenate(temp,0)
 
cv2.imwrite(temp_path,temp)

参考文章:

原文链接:https://zhuanlan.zhihu.com/p/281404684
原文链接:https://blog.csdn.net/coolsunxu/article/details/107553155
原文链接:https://blog.csdn.net/coolsunxu/article/details/102639674
————————————————

  • 2
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值