当前位置:网站首页>[Thesis code] SML part code reading
[Thesis code] SML part code reading
2022-07-06 05:55:00 【starbuling~】
SML Boundary suppression and Gaussian smoothing in
Boundary smoothing suppression class
class BoundarySuppressionWithSmoothing(nn.Module):
""" Apply boundary suppression and dilated smoothing Boundary suppression , Expand and smooth """
initialization
def __init__(self, boundary_suppression=True, boundary_width=4, boundary_iteration=4,
dilated_smoothing=True, kernel_size=7, dilation=6):
Define some parameters
super(BoundarySuppressionWithSmoothing, self).__init__()
self.kernel_size = kernel_size # Convolution kernel size
self.dilation = dilation # expansion
self.boundary_suppression = boundary_suppression # Boundary suppression
self.boundary_width = boundary_width # Boundary width
self.boundary_iteration = boundary_iteration # Boundary iteration
Create Gaussian kernel
sigma = 1.0
size = 7
# function Is the probability density function of two-dimensional Gaussian distribution
gaussian_kernel = np.fromfunction(lambda x, y:
(1/(2*math.pi*sigma**2)) * math.e ** ((-1*((x-(size-1)/2)**2+(y-(size-1)/2)**2))/(2*sigma**2)),
(size, size)) # Construct Gaussian kernel (7,7) 3 * sigma + 1
gaussian_kernel /= np.sum(gaussian_kernel) # Divide by the sum of all elements in the Gaussian kernel ( weighted mean , Avoid image pixel overflow )
gaussian_kernel = torch.Tensor(gaussian_kernel).unsqueeze(0).unsqueeze(0)
self.dilated_smoothing = dilated_smoothing # Expand and smooth
l a m b d a ( x , y ) = 1 2 ∗ π ∗ σ 2 e x p ( − ( x − s i z e − 1 2 ) 2 + ( y − s i z e − 1 2 ) 2 2 ∗ σ 2 ) lambda(x,y) = \frac{1}{2 * \pi * \sigma^2} exp(-\frac{(x - \frac{size-1}{2})^2 + (y - \frac{size-1}{2})^2}{2 * \sigma^2}) lambda(x,y)=2∗π∗σ21exp(−2∗σ2(x−2size−1)2+(y−2size−1)2)
numpy In the library
fromfunction
: Through custom functions fun, shape shape, data format dtype -> According to the array subscript (x,y) Generate values for each location , Make an array
Function parameter
np.fromfunction(function, shape, dtype)
function: A function transformed into a specific value according to coordinates
def function(x,y): Internal function (x,y) Are the coordinates with the upper left corner as the origin ,x For row coordinates ,y Column coordinates , It means the first one x That's ok y Column .
shape(a,b): Represents an array array Size ,a That's ok b Column .
dtype: Represents the number type of the array
Define two-layer convolution (in_channel, out_channel, k, s)
- (1, 1, 3, 1) The weight matrix is full 1 matrix
- (1, 1, 7, 1) The weight matrix is Gaussian kernel
self.first_conv = nn.Conv2d(1, 1, kernel_size=3, stride=1, bias=False)
self.first_conv.weight = torch.nn.Parameter(torch.ones_like((self.first_conv.weight)))
self.second_conv = nn.Conv2d(
1, 1, kernel_size=self.kernel_size, stride=1, dilation=self.dilation, bias=False)
self.second_conv.weight = torch.nn.Parameter(gaussian_kernel)
Forward propagation
def forward(self, x, prediction=None):
if len(x.shape) == 3:
x = x.unsqueeze(1) # If it is 3 dimension , expand 1 dimension
x_size = x.size()
# B x 1 x H x W
assert len(x.shape) == 4
out = x
Branch 1: Need boundary suppression
if self.boundary_suppression:
# obtain the boundary map of width 2 by default The default acquisition width is 2 Boundary graph of
# this can be calculated by the difference of dilation and erosion This can be calculated by the difference between expansion and corrosion
boundaries = find_boundaries(prediction.unsqueeze(1)) # Look for boundaries
expanded_boundaries = None
if self.boundary_iteration != 0:
assert self.boundary_width % self.boundary_iteration == 0 # The boundary width is divided by the number of iterations
diff = self.boundary_width // self.boundary_iteration # Width increased each time
The main process of boundary suppression
for iteration in range(self.boundary_iteration):
if len(out.shape) != 4:
out = out.unsqueeze(1)
prev_out = out
Get the boundary
# if it is the last iteration or boundary width is zero The last iteration or boundary width is 0 after , Stop expanding width if self.boundary_width == 0 or iteration == self.boundary_iteration - 1: expansion_width = 0 # reduce the expansion width for each iteration Otherwise, the width of the freight station will be continuously increased in each iteration else: expansion_width = self.boundary_width - diff * iteration - 1 # expand the boundary obtained from the prediction (width of 2) by expansion rate expanded_boundaries = expand_boundaries(boundaries, r=expansion_width) # Expand the boundary according to the expansion width , The specific method is explained in detail in the function later
Reverse the boundary -> Get a non boundary mask
# invert it so that we can obtain non-boundary mask non_boundary_mask = 1. * (expanded_boundaries == 0) # Reverse the boundary , Get the non boundary mask . The non boundary is 1, The boundary is 0
Make the boundary area to 0
f_size = 1 num_pad = f_size # making boundary regions to 0 x_masked = out * non_boundary_mask # The input image * Non boundary mask -> Get the non boundary region (1) x_padded = nn.ReplicationPad2d(num_pad)(x_masked) non_boundary_mask_padded = nn.ReplicationPad2d(num_pad)(non_boundary_mask)
class torch.nn.ReplicationPad2d(padding)
padding(int ,tuple) The size of the fill . If int , Then use the same fill in all boundaries .
If it is 4 tuple , Then use (padding_left, padding_right, padding_top, padding_bottom)Sum the values in the receptive field
# sum up the values in the receptive field y = self.first_conv(x_padded) # count non-boundary elements in the receptive field num_calced_elements = self.first_conv(non_boundary_mask_padded) num_calced_elements = num_calced_elements.long()
Averaging
# take an average by dividing y by count # if there is no non-boundary element in the receptive field, # keep the original value avg_y = torch.where((num_calced_elements == 0), prev_out, y / num_calced_elements) out = avg_y
Update boundaries
# update boundaries only out = torch.where((non_boundary_mask == 0), out, prev_out) del expanded_boundaries, non_boundary_mask
The second step : Expand and smooth
# second stage; apply dilated smoothing
if self.dilated_smoothing == True:
out = nn.ReplicationPad2d(self.dilation * 3)(out)
out = self.second_conv(out)
return out.squeeze(1)
Branch 1: No boundary suppression is required
else:
if self.dilated_smoothing == True: # Expand and smooth
out = nn.ReplicationPad2d(self.dilation * 3)(out)
out = self.second_conv(out)
else:
out = x
return out.squeeze(1)
find_boundaries
def find_boundaries(label):
""" Calculate boundary mask by getting diff of dilated and eroded prediction maps """
assert len(label.shape) == 4
boundaries = (dilation(label.float(), selem_dilation) != erosion(label.float(), selem)).float()
### save_image(boundaries, f'boundaries_{boundaries.float().mean():.2f}.png', normalize=True)
return boundaries
selem = torch.ones((3, 3)).cuda() # It's a (3,3) Full size 1 Tensor , Corrosion coil nucleation
selem_dilation = torch.FloatTensor(ndi.generate_binary_structure(2, 1)).cuda() # Expanded convolution kernel
corrosion :
inflation :
inflation (dilation) & corrosion (erosion)
These are two basic morphological operations , It is mainly used to find the maximum and minimum regions in the image .
- Expansion is similar to ‘ Domain expansion ’ , Expand the highlighted area or white part of the image , The operation result graph is larger than the highlighted area of the original graph .
- Corrosion similar ‘ The field is being eroded ’ , Reduce and refine the highlighted area or white part of the image , The operation result is smaller than the highlighted area of the original image .
The specific process : Define a convolution kernel , Convolute the picture . Expansion do “ or ” operation , expand 1 The scope of the ; Corrosion makes “ And ” operation , Reduce 1 The number of
dilation(image, kernel) # Images , Convolution kernel
erosion(image, kernel)
After expansion and corrosion of the label drawings , Different positions , It's the boundary . use 1 Express
expand_boundaries
def expand_boundaries(boundaries, r=0):
""" Expand boundary maps with the rate of r """
if r == 0:
return boundaries
expanded_boundaries = dilation(boundaries, d_ks[r]) # Do the expansion operation
### save_image(expanded_boundaries, f'expanded_boundaries_{r}_{boundaries.float().mean():.2f}.png', normalize=True)
return expanded_boundaries
About d_ks[]
:
d_k1 = torch.zeros((1, 1, 2 * 1 + 1, 2 * 1 + 1)).cuda()
d_k2 = torch.zeros((1, 1, 2 * 2 + 1, 2 * 2 + 1)).cuda()
d_k3 = torch.zeros((1, 1, 2 * 3 + 1, 2 * 3 + 1)).cuda()
d_k4 = torch.zeros((1, 1, 2 * 4 + 1, 2 * 4 + 1)).cuda()
d_k5 = torch.zeros((1, 1, 2 * 5 + 1, 2 * 5 + 1)).cuda()
d_k6 = torch.zeros((1, 1, 2 * 6 + 1, 2 * 6 + 1)).cuda()
d_k7 = torch.zeros((1, 1, 2 * 7 + 1, 2 * 7 + 1)).cuda()
d_k8 = torch.zeros((1, 1, 2 * 8 + 1, 2 * 8 + 1)).cuda()
d_k9 = torch.zeros((1, 1, 2 * 9 + 1, 2 * 9 + 1)).cuda()
d_ks = {
1: d_k1, 2: d_k2, 3: d_k3, 4: d_k4,
5: d_k5, 6: d_k6, 7: d_k7, 8: d_k8, 9: d_k9}
for k, v in d_ks.items():
v[:, :, k, k] = 1
for i in range(k):
v = dilation(v, selem_dilation)
d_ks[k] = v.squeeze(0).squeeze(0)
print(f'dilation kernel at {
k}:\n\n{
d_ks[k]}')
The appearance of these convolution kernels is roughly as follows , And so on
边栏推荐
- Mysql database master-slave cluster construction
- Auto.js学习笔记17:基础监听事件和UI简单的点击事件操作
- Classes and objects (I) detailed explanation of this pointer
- 【论文阅读】NFlowJS:基于鲁棒学习的合成负数据密集异常检测
- Installation de la Bibliothèque de processus PDK - csmc
- Text classification still stays at Bert? The dual contrast learning framework is too strong
- OSPF configuration command of Huawei equipment
- Report on the competition status and investment decision recommendations of Guangxi hospital industry in China from 2022 to 2028
- [Tang Laoshi] C -- encapsulation: classes and objects
- 初识数据库
猜你喜欢
【课程笔记】编译原理
C language bubble sort
Mysql database master-slave cluster construction
Jushan database appears again in the gold fair to jointly build a new era of digital economy
PDK工藝庫安裝-CSMC
华为路由器如何配置静态路由
P2802 回家
Download, install and use NVM of node, and related use of node and NRM
养了只小猫咪
Hongliao Technology: Liu qiangdong's "heavy hand"
随机推荐
Selective parameters in MATLAB functions
Auto.js学习笔记17:基础监听事件和UI简单的点击事件操作
The ECU of 21 Audi q5l 45tfsi brushes is upgraded to master special adjustment, and the horsepower is safely and stably increased to 305 horsepower
Web Security (V) what is a session? Why do I need a session?
[SQL Server Express Way] - authentification et création et gestion de comptes utilisateurs
Memory and stack related concepts
华为路由器如何配置静态路由
【论文阅读】NFlowJS:基于鲁棒学习的合成负数据密集异常检测
[paper reading] nflowjs: synthetic negative data intensive anomaly detection based on robust learning
Novice entry SCM must understand those things
What is independent IP and how about independent IP host?
B站刘二大人-反向传播
How to use PHP string query function
YYGH-11-定时统计
C language learning notes (mind map)
Some easy-to-use tools make your essay style more elegant
[force buckle]43 String multiplication
Closure, decorator
Baidu online AI competition - image processing challenge: the 8th program of handwriting erasure
Pay attention to the details of pytoch code, and it is easy to make mistakes