当前位置:网站首页>Pytorch extract skeleton (differentiable)
Pytorch extract skeleton (differentiable)
2022-07-06 16:10:00 【Little Aries in the mountains】
Preface
There are many ready-made packages for extracting skeletons , The simplest and most direct is :
from skimage.morphology import skeletonize, skeletonize_3d
But today we will introduce another method of extracting skeleton ! It can also be understood as refinement
Use pytorch The goal is , This process is differentiable , In other words , You can reverse the gradient , For network prediction mask, You can extract the skeleton through this function , Then constrain the topology of the object on the skeleton
This method comes from the literature CVPR 2021:clDice - a Novel Topology-Preserving Loss Function for Tubular Structure Segmentation
Source code :https://github.com/jocpae/clDice
( The source code is very, very simple , This is one of the few so concise CVPR The source )
Source code
import torch
import torch.nn as nn
import torch.nn.functional as F
def soft_erode(img):
if len(img.shape)==4:
p1 = -F.max_pool2d(-img, (3,1), (1,1), (1,0))
p2 = -F.max_pool2d(-img, (1,3), (1,1), (0,1))
return torch.min(p1,p2)
elif len(img.shape)==5:
p1 = -F.max_pool3d(-img,(3,1,1),(1,1,1),(1,0,0))
p2 = -F.max_pool3d(-img,(1,3,1),(1,1,1),(0,1,0))
p3 = -F.max_pool3d(-img,(1,1,3),(1,1,1),(0,0,1))
return torch.min(torch.min(p1, p2), p3)
def soft_dilate(img):
if len(img.shape)==4:
return F.max_pool2d(img, (3,3), (1,1), (1,1))
elif len(img.shape)==5:
return F.max_pool3d(img,(3,3,3),(1,1,1),(1,1,1))
def soft_open(img):
return soft_dilate(soft_erode(img))
def soft_skel(img, iter_):
img1 = soft_open(img)
skel = F.relu(img-img1)
for j in range(iter_):
img = soft_erode(img)
img1 = soft_open(img)
delta = F.relu(img-img1)
skel = skel + F.relu(delta-skel*delta)
return skel
This is all the code for extracting the skeleton in this article , It's really simple
test
Take a CVPPP Of label For example :
To test the code that extracts the skeleton , I take the boundary of the above image as the foreground , To refine the boundary .
Use the following function to extract the boundary ( Expand three times at the same time ):
import numpy as np
from PIL import Image
from scipy import ndimage
from skimage.segmentation import find_boundaries
def extract_boundary(label, dilation=False):
boundary = np.zeros_like(label, dtype=np.uint8)
ids, counts = np.unique(label, return_counts=True)
for i, id in enumerate(ids):
if id == 0:
boundary[label == 0] = 0
else:
tmp = np.zeros_like(label)
tmp[label == id] = 1
tmp_bound = find_boundaries(tmp != 0, mode='outer')
if dilation:
tmp_bound = ndimage.binary_dilation(tmp_bound, iterations=3, border_value=1)
boundary[tmp_bound == 1] = 1
return boundary
Be ready , Upper main function :
if __name__ == "__main__":
label = np.asarray(Image.open('plant154_label.png'))
boundary = extract_boundary(label, dilation=True)
boundary_uint8 = boundary.astype(np.uint8) * 255
Image.fromarray(boundary_uint8).save('boundary.png')
boundary = boundary.astype(np.float32)
boundary = boundary[np.newaxis, np.newaxis, ...]
boundary = torch.from_numpy(boundary)
skel = soft_skel(boundary, 10)
skel = np.squeeze(skel.numpy())
skel = (skel * 255).astype(np.uint8)
Image.fromarray(skel).save('skel.png')
Running results :
The boundary visualization results before extracting the skeleton :
Visualization results of extracted skeleton :
use skimage.morphology Medium skeletonize The result of function extraction :
summary
- The proposed method is different from the traditional skeletonize(skimage) There is still a certain gap , especially , From the visualization results above , We can also see that , There are many faults in the estimation extracted by this method , This is unbearable for the skeleton
- This method has a super parameter , That is, specify the number of iterations , This parameter also greatly affects the result , The above example is used 10, I tried 5 The situation of , The generated skeleton is even worse
- But this method still has one biggest advantage , It is differentiable , Derivable , It can be used to output the skeleton in the network and then as a loss
边栏推荐
- 想应聘程序员,您的简历就该这样写【精华总结】
- 渗透测试 ( 4 ) --- Meterpreter 命令详解
- C basic grammar
- 滲透測試 ( 1 ) --- 必備 工具、導航
- Opencv learning log 27 -- chip positioning
- 2027. Minimum number of operations to convert strings
- Maximum product (greedy)
- 1903. Maximum odd number in string
- C language is the watershed between low-level and high-level
- window11 conda安装pytorch过程中遇到的一些问题
猜你喜欢
Essai de pénétration (1) - - outils nécessaires, navigation
mysql导入数据库报错 [Err] 1273 – Unknown collation: ‘utf8mb4_0900_ai_ci’
Data storage in memory & loading into memory to make the program run
[teacher Gao UML software modeling foundation] collection of exercises and answers for level 20 cloud class
Penetration test (1) -- necessary tools, navigation
860. Lemonade change
Penetration test (2) -- penetration test system, target, GoogleHacking, Kali tool
Information security - threat detection - detailed design of NAT log access threat detection platform
分享一个在树莓派运行dash应用的实例。
【高老师软件需求分析】20级云班课习题答案合集
随机推荐
C language must memorize code Encyclopedia
969. Pancake sorting
X-Forwarded-For详解、如何获取到客户端IP
The most complete programming language online API document
Luogu P1102 A-B number pair (dichotomy, map, double pointer)
b站 实时弹幕和历史弹幕 Protobuf 格式解析
Gartner: five suggestions on best practices for zero trust network access
Differential (one-dimensional, two-dimensional, three-dimensional) Blue Bridge Cup three body attack
Opencv learning log 29 -- gamma correction
C basic grammar
PySide6 信号、槽
2078. Two houses with different colors and the farthest distance
【练习-10】 Unread Messages(未读消息)
Suffix expression (greed + thinking)
Penetration test (4) -- detailed explanation of meterpreter command
最全编程语言在线 API 文档
Write web games in C language
socket通讯
409. Longest palindrome
[exercise-3] (UVA 442) matrix chain multiplication