[{"data":1,"prerenderedAt":241},["ShallowReactive",2],{"content-query-DjuAk5mI3h":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"cover":11,"type":12,"body":13,"_type":235,"_id":236,"_source":237,"_file":238,"_stem":239,"_extension":240},"/technology-blogs/zh/411","zh",false,"","基于 MindSpore 实现图像分割系列之平均表面距离","今天为大家带来的内容是Mean surface distance 平均表面距离的原理介绍及MindSpore的实现代码。","2021-03-08","https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2021/03/08/cdb3c2ad69aa4aafa636c02091fbe74d.png","technology-blogs",{"type":14,"children":15,"toc":232},"root",[16,24,30,35,39,44,74,79,88,93,98,103,138,145,150,155,160,167,172,179,184,191,196,206,211,219,224],{"type":17,"tag":18,"props":19,"children":21},"element","h1",{"id":20},"基于-mindspore-实现图像分割系列之平均表面距离",[22],{"type":23,"value":8},"text",{"type":17,"tag":25,"props":26,"children":27},"p",{},[28],{"type":23,"value":29},"本文来源：知乎",{"type":17,"tag":25,"props":31,"children":32},{},[33],{"type":23,"value":34},"作者：李嘉琪",{"type":17,"tag":25,"props":36,"children":37},{},[38],{"type":23,"value":9},{"type":17,"tag":25,"props":40,"children":41},{},[42],{"type":23,"value":43},"当我们评价图像分割的质量和模型表现时，经常会用到各类表面距离的计算。比如：",{"type":17,"tag":45,"props":46,"children":47},"ul",{},[48,54,59,64,69],{"type":17,"tag":49,"props":50,"children":51},"li",{},[52],{"type":23,"value":53},"Mean surface distance 平均表面距离",{"type":17,"tag":49,"props":55,"children":56},{},[57],{"type":23,"value":58},"Hausdorff distance 豪斯多夫距离（也被称为max_surface_distance 最大表面距离MSD）",{"type":17,"tag":49,"props":60,"children":61},{},[62],{"type":23,"value":63},"Surface overlap 表面重叠度",{"type":17,"tag":49,"props":65,"children":66},{},[67],{"type":23,"value":68},"Surface dice 表面dice值",{"type":17,"tag":49,"props":70,"children":71},{},[72],{"type":23,"value":73},"Volumetric dice 三维dice值",{"type":17,"tag":25,"props":75,"children":76},{},[77],{"type":23,"value":78},"等，都可以称为表面距离系列了。今天简单的讲解一下Mean surface distance 平均表面距离。",{"type":17,"tag":25,"props":80,"children":81},{},[82],{"type":17,"tag":83,"props":84,"children":87},"img",{"alt":85,"src":86},"image.png","https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/164631dv6qkhs6ygblvqfw.png",[],{"type":17,"tag":25,"props":89,"children":90},{},[91],{"type":23,"value":92},"顾名思义，Mean surface distance这个指标就是P中所有点的表面距离的平均。这个指标又可称为Average Symmetric Surface Distance (ASSD)，它也是医疗图像分割竞赛CHAOS中的一个评估指标。",{"type":17,"tag":25,"props":94,"children":95},{},[96],{"type":23,"value":97},"This function is used to compute the Average Surface Distance from `y_pred` to `y` under the default setting. Mean Surface Distance(MSD), the mean of the vector is taken. This tell us how much, on average, the surface varies between the segmentation and the GT.",{"type":17,"tag":25,"props":99,"children":100},{},[101],{"type":23,"value":102},"其实这个表面距离也没啥可介绍的，似乎就这么简单。来看看公式吧：",{"type":17,"tag":25,"props":104,"children":105},{},[106,108,112,114,118,120,124,126,130,132,136],{"type":23,"value":107},"先定义",{"type":17,"tag":83,"props":109,"children":111},{"alt":85,"src":110},"https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/164729hbq5rhbmhn9rlamw.png",[],{"type":23,"value":113},"代表的是预测的",{"type":17,"tag":83,"props":115,"children":117},{"alt":85,"src":116},"https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/164749dga1dx5z7f2jocyo.png",[],{"type":23,"value":119},"中的边界的像素，同样可以得到",{"type":17,"tag":83,"props":121,"children":123},{"alt":85,"src":122},"https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/164814csfomf5ajdes4r4k.png",[],{"type":23,"value":125},"的定义。然后对",{"type":17,"tag":83,"props":127,"children":129},{"alt":85,"src":128},"https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/164837e2qagfymju93n3qn.png",[],{"type":23,"value":131},"的定义，同理可得",{"type":17,"tag":83,"props":133,"children":135},{"alt":85,"src":134},"https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/1649048daozqg8y7cyw2jp.png",[],{"type":23,"value":137},"的定义。",{"type":17,"tag":25,"props":139,"children":140},{},[141],{"type":17,"tag":83,"props":142,"children":144},{"alt":85,"src":143},"https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/164922fsbz8vjifbm7txh2.png",[],{"type":17,"tag":25,"props":146,"children":147},{},[148],{"type":23,"value":149},"也可以这样写：",{"type":17,"tag":25,"props":151,"children":152},{},[153],{"type":23,"value":154},"2.5.4. Average Symmetric Surface Distance (ASD)",{"type":17,"tag":25,"props":156,"children":157},{},[158],{"type":23,"value":159},"Let S(A) denote the set of surface voxels of A. The shortest distance of an arbitrary voxel v to S(A) is defined as:",{"type":17,"tag":25,"props":161,"children":162},{},[163],{"type":17,"tag":83,"props":164,"children":166},{"alt":85,"src":165},"https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/1649480kckclmioomkdrg8.png",[],{"type":17,"tag":25,"props":168,"children":169},{},[170],{"type":23,"value":171},"where ||. || denotes the Euclidean distance. The average symmetric surface distance is then given by:",{"type":17,"tag":25,"props":173,"children":174},{},[175],{"type":17,"tag":83,"props":176,"children":178},{"alt":85,"src":177},"https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/165041kyybjswin2uvn65d.png",[],{"type":17,"tag":25,"props":180,"children":181},{},[182],{"type":23,"value":183},"这样是不是就清楚多了。",{"type":17,"tag":25,"props":185,"children":186},{},[187],{"type":17,"tag":83,"props":188,"children":190},{"alt":85,"src":189},"https://bbs-img-cbc-cn.obs.cn-north-1.myhuaweicloud.com/data/forums/attachment/forum/202103/04/1651108dcsz6vj1wgu2rly.png",[],{"type":17,"tag":25,"props":192,"children":193},{},[194],{"type":23,"value":195},"原理已经讲完，话不多说，我们开始上代码。使用的是MindSpore框架实现的代码。",{"type":17,"tag":197,"props":198,"children":200},"pre",{"code":199},"\"\"\"MeanSurfaceDistance.\"\"\"\nfrom scipy.ndimage import morphology\nimport numpy as np\nfrom mindspore._checkparam import Validator as validator\nfrom .metric import Metric\nclass MeanSurfaceDistance(Metric):\n    def __init__(self, symmetric=False, distance_metric=\"euclidean\"):\n        super(MeanSurfaceDistance, self).__init__()\n        self.distance_metric_list = [\"euclidean\", \"chessboard\", \"taxicab\"]\n        distance_metric = validator.check_value_type(\"distance_metric\", distance_metric, [str])\n        self.distance_metric = validator.check_string(distance_metric, self.distance_metric_list, \"distance_metric\")\n        self.symmetric = validator.check_value_type(\"symmetric\", symmetric, [bool])\n        self.clear()\n    def clear(self):\n        \"\"\"Clears the internal evaluation result.\"\"\"\n        self._y_pred_edges = 0\n        self._y_edges = 0\n        self._is_update = False\n    def _get_surface_distance(self, y_pred_edges, y_edges):\n        \"\"\"\n        计算从预测图片边界到真实图片边界的表面距离。\n        \"\"\"\n        if not np.any(y_pred_edges):\n            return np.array([])\n        if not np.any(y_edges):\n            dis = np.full(y_edges.shape, np.inf)\n        else:\n            if self.distance_metric == \"euclidean\":\n                dis = morphology.distance_transform_edt(~y_edges)\n            elif self.distance_metric in self.distance_metric_list[-2:]:\n                dis = morphology.distance_transform_cdt(~y_edges, metric=self.distance_metric)\n        surface_distance = dis[y_pred_edges]\n        return surface_distance\n    def update(self, *inputs):\n        \"\"\"\n        更新输入数据。\n        \"\"\"\n        if len(inputs) != 3:\n            raise ValueError('MeanSurfaceDistance need 3 inputs (y_pred, y, label), but got {}.'.format(len(inputs)))\n        y_pred = self._convert_data(inputs[0])\n        y = self._convert_data(inputs[1])\n        label_idx = inputs[2]\n        if y_pred.size == 0 or y_pred.shape != y.shape:\n            raise ValueError(\"y_pred and y should have same shape, but got {}, {}.\".format(y_pred.shape, y.shape))\n        if y_pred.dtype != bool:\n            y_pred = y_pred == label_idx\n        if y.dtype != bool:\n            y = y == label_idx\n        self._y_pred_edges = morphology.binary_erosion(y_pred) ^ y_pred\n        self._y_edges = morphology.binary_erosion(y) ^ y\n        self._is_update = True\n    def eval(self):\n        \"\"\"\n        计算平均表面距离。\n        \"\"\"\n        if self._is_update is False:\n            raise RuntimeError('Call the update method before calling eval.')\n        mean_surface_distance = self._get_surface_distance(self._y_pred_edges, self._y_edges)\n        if mean_surface_distance.shape == (0,):\n            return np.inf\n        avg_surface_distance = mean_surface_distance.mean()\n        if not self.symmetric:\n            return avg_surface_distance\n        contrary_mean_surface_distance = self._get_surface_distance(self._y_edges, self._y_pred_edges)\n        if contrary_mean_surface_distance.shape == (0,):\n            return np.inf\n        contrary_avg_surface_distance = contrary_mean_surface_distance.mean()\n        return np.mean((avg_surface_distance, contrary_avg_surface_distance))\n",[201],{"type":17,"tag":202,"props":203,"children":204},"code",{"__ignoreMap":7},[205],{"type":23,"value":199},{"type":17,"tag":25,"props":207,"children":208},{},[209],{"type":23,"value":210},"使用方法如下：",{"type":17,"tag":197,"props":212,"children":214},{"code":213},"import numpy as np\nfrom mindspore import Tensor\nfrom mindspore.nn.metrics import MeanSurfaceDistance\ndef test_mean_surface_distance():\n    \"\"\"test_mean_surface_distance\"\"\"\n    x = Tensor(np.array([[3, 0, 1], [1, 3, 0], [1, 0, 2]]))\n    y = Tensor(np.array([[0, 2, 1], [1, 2, 1], [0, 0, 1]]))\n    metric = MeanSurfaceDistance()\n    metric.clear()\n    metric.update(x, y, 0)\n    distance = metric.eval()\n    print(distance)\ntest_mean_surface_distance()\n1.4142135623730951\n",[215],{"type":17,"tag":202,"props":216,"children":217},{"__ignoreMap":7},[218],{"type":23,"value":213},{"type":17,"tag":25,"props":220,"children":221},{},[222],{"type":23,"value":223},"每个batch（比如两组数据）进行计算的时候如下：",{"type":17,"tag":197,"props":225,"children":227},{"code":226},"import numpy as np\nfrom mindspore import Tensor\nfrom mindspore.nn.metrics import MeanSurfaceDistance\nx = Tensor(np.array([[3, 0, 1], [1, 3, 0], [1, 0, 2]]))\ny = Tensor(np.array([[0, 2, 1], [1, 2, 1], [0, 0, 1]]))\nmetric = MeanSurfaceDistance()\nmetric.clear()\nmetric.update(x, y, 0)\nx1 = Tensor(np.array([[3, 0, 1], [1, 3, 0], [1, 0, 2]]))\ny1 = Tensor(np.array([[0, 2, 1], [1, 2, 1], [0, 0, 1]]))\nmetric.update(x1, y1, 0)\ndistance = metric.eval()\nprint(distance)\n",[228],{"type":17,"tag":202,"props":229,"children":230},{"__ignoreMap":7},[231],{"type":23,"value":226},{"title":7,"searchDepth":233,"depth":233,"links":234},4,[],"markdown","content:technology-blogs:zh:411.md","content","technology-blogs/zh/411.md","technology-blogs/zh/411","md",1776506137152]