当前位置:网站首页>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
边栏推荐
- Opencv learning log 16 paperclip count
- Openwrt build Hello ipk
- Opencv learning log 18 Canny operator
- socket通讯
- 【练习-9】Zombie’s Treasure Chest
- Opencv learning log 26 -- detect circular holes and mark them
- 想应聘程序员,您的简历就该这样写【精华总结】
- C language must memorize code Encyclopedia
- [exercise-3] (UVA 442) matrix chain multiplication
- 信息安全-威胁检测引擎-常见规则引擎底座性能比较
猜你喜欢
Pyside6 signal, slot
1689. Ten - the minimum number of binary numbers
frida hook so层、protobuf 数据解析
渗透测试 ( 1 ) --- 必备 工具、导航
Penetration test (2) -- penetration test system, target, GoogleHacking, Kali tool
pytorch提取骨架(可微)
基于web的照片数码冲印网站
信息安全-威胁检测-flink广播流BroadcastState双流合并应用在过滤安全日志
渗透测试 ( 4 ) --- Meterpreter 命令详解
Penetration testing (5) -- a collection of practical skills of scanning King nmap and penetration testing tools
随机推荐
Find 3-friendly Integers
Analyse du format protobuf du rideau en temps réel et du rideau historique de la station B
[teacher Gao UML software modeling foundation] collection of exercises and answers for level 20 cloud class
Nodejs+vue online fresh flower shop sales information system express+mysql
信息安全-安全专业名称|CVE|RCE|POC|VUL|0DAY
Shell Scripting
China exterior wall cladding (EWC) market trend report, technical dynamic innovation and market forecast
【练习-8】(Uva 246)10-20-30==模拟
921. Minimum additions to make parentheses valid
Borg maze (bfs+ minimum spanning tree) (problem solving report)
MySQL grants the user the operation permission of the specified content
Socket communication
Common configuration files of SSM framework
Determine the Photo Position
1689. Ten - the minimum number of binary numbers
信息安全-威胁检测引擎-常见规则引擎底座性能比较
JS call camera
Differential (one-dimensional, two-dimensional, three-dimensional) Blue Bridge Cup three body attack
双向链表—全部操作
[exercise -11] 4 values why sum is 0 (and 4 values of 0)