Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 哪个损失函数计算两个轮廓之间的距离_Python_Contour_Loss Function_Generative Adversarial Network_Completion - Fatal编程技术网

Python 哪个损失函数计算两个轮廓之间的距离

Python 哪个损失函数计算两个轮廓之间的距离,python,contour,loss-function,generative-adversarial-network,completion,Python,Contour,Loss Function,Generative Adversarial Network,Completion,在我的轮廓生成网络中,我使用nn.L1Loss()来计算错误的像素数。这对训练有效,但真实轮廓和伪轮廓之间的2D距离会更好。我的目标是测量生成轮廓的长度。这两个二进制图像的代码示例显示了nn.L1Loss()失败的地方 import cv2 import torch from torch import nn p1 = [(15, 15),(45,45)] p2 = [(16, 15),(46,45)] real = cv2.rectangle(np.ones((60,60)), p1[0],

在我的轮廓生成网络中,我使用
nn.L1Loss()
来计算错误的像素数。这对训练有效,但真实轮廓和伪轮廓之间的2D距离会更好。我的目标是测量生成轮廓的长度。这两个二进制图像的代码示例显示了
nn.L1Loss()
失败的地方

import cv2
import torch
from torch import nn

p1 = [(15, 15),(45,45)]
p2 = [(16, 15),(46,45)]

real = cv2.rectangle(np.ones((60,60)), p1[0], p1[1], color=0, thickness=1)
fake = cv2.rectangle(np.ones((60,60)), p2[0], p2[1], color=0, thickness=1)

cv2.imshow('image',np.hstack((real,fake)))
cv2.waitKey(0)

real = torch.tensor(real)
fake = torch.tensor(fake)

losss = [nn.L1Loss(), nn.MSELoss(), nn.BCELoss(), nn.HingeEmbeddingLoss(), nn.SmoothL1Loss()]
print(my_loss(real, fake))

for k, loss in enumerate(losss):
    err = loss(real, fake)
    print(err*60)
如果将矩形向右移动1个像素:

->L1损耗为0.0333*60=2

如果将矩形向右移动1个像素,向左移动1个像素:

->L1损耗为0.0656*60=3.933

如果将矩形向右移动10个像素,向左移动10个像素:

->L1损耗为0.0656*60=3.933
仍然不变!这并不奇怪,错误像素的数量是相同的。但与它们的距离改变了10*2**1/2

我还考虑了两个中心之间的距离:

    M = cv2.moments(c)
    cX = int(M['m10'] /M['m00'])
    cY = int(M['m01'] /M['m00'])
    centers.append([cX,cY])
这里的问题是生成的轮廓与真实轮廓不同,因此具有不同的中心

这个答案和我想要的很接近,但是计算很昂贵吗


是否有自定义的损耗函数来确定我所描述的距离?

这是您想要的公式吗

与下一个等式给出的曲线之间的面积相反,如果轮廓彼此足够相似

它表示从一个轮廓中的点到多个点的累计平方距离 到另一个轮廓中最近的点

给定两个在等高线上有点的阵列,我可以直接在GPU上用复杂度O(M*N)计算,其中C1有M个点,C2有N个点。或者,它可以在O(W*H)中计算,其中W*H是图像的尺寸

如果这正是你想要的,我可以发布一个解决方案

解决方案 首先,让我们创建一些示例数据

import torch
import math
from torch import nn
import matplotlib.pyplot as plt;

# Number of points in each contour
M, N = 1000, 1500
t1 = torch.linspace(0, 2*math.pi, M).view(1, -1)
t2 = torch.linspace(0, 2*math.pi, N).view(1, -1)

c1 = torch.stack([torch.sin(t1),torch.cos(t1)], dim=2) # (1 x M x 2)
c2 = 1 - 2* torch.sigmoid(torch.stack([torch.sin(t2)*3 + 1, torch.cos(t2)*3 + 2], dim=2)) # (1 x N x 2)
利用这一点,我们可以使用以下公式计算每对点之间的距离。这里我用来找到数组中每列的最小值的位置。对于计算损失函数来说,重要的是距离本身,这可以通过计算得到

现在基本上,你要积累的不是距离,而是距离的函数。这可以通过
torch.min(f(距离))
轻松获得,并且假设
f(.)
是单调的,可以简化为
f(torch.min(距离))

为了近似积分,我们可以使用积分,它积分采样函数的线性插值,在我们的例子中,是在给定点采样的轮廓

这会给你一个损失函数

def contour_divergence(c1, c2, func = lambda x: x**2):
    c1 = torch.atleast_3d(c1);
    c2 = torch.atleast_3d(c2);
    f = func(torch.amin(torch.cdist(c1, c2), dim=2));
    # this computes the length of each segment connecting two consecutive points
    df = torch.sum((c1[:, 1:, :] - c1[:, :-1, :])**2, axis=2)**0.5;
    # here is the trapesoid rule
    return torch.sum((f[:, :-1] + f[:, 1:]) * df[:, :], axis=1) / 4.0;
def contour_dist(c1, c2, func = lambda x: x**2):
    return contour_divergence(c1, c2, func) + contour_divergence(c2, c1, func)
对于连接最近点的直线始终垂直于轨迹的情况,
等高线距离(c1,c2,λx:x)
给出了面积

这将给出半径为1的圆的面积(第二个圆的所有点都在原点上)

现在考虑半径为1的圆和半径为1的圆之间的距离(它将是pi*(1-1/4)=0.75*pi)


如果你想要任何累积平方距离的损失,你只需使用
轮廓距离(c1,c2)
,你可以将任意函数作为参数传递给函数。只要可以反向传播传递的函数,就可以反向传播损失。

这就是您想要的等式吗

与下一个等式给出的曲线之间的面积相反,如果轮廓彼此足够相似

它表示从一个轮廓中的点到多个点的累计平方距离 到另一个轮廓中最近的点

给定两个在等高线上有点的阵列,我可以直接在GPU上用复杂度O(M*N)计算,其中C1有M个点,C2有N个点。或者,它可以在O(W*H)中计算,其中W*H是图像的尺寸

如果这正是你想要的,我可以发布一个解决方案

解决方案 首先,让我们创建一些示例数据

import torch
import math
from torch import nn
import matplotlib.pyplot as plt;

# Number of points in each contour
M, N = 1000, 1500
t1 = torch.linspace(0, 2*math.pi, M).view(1, -1)
t2 = torch.linspace(0, 2*math.pi, N).view(1, -1)

c1 = torch.stack([torch.sin(t1),torch.cos(t1)], dim=2) # (1 x M x 2)
c2 = 1 - 2* torch.sigmoid(torch.stack([torch.sin(t2)*3 + 1, torch.cos(t2)*3 + 2], dim=2)) # (1 x N x 2)
利用这一点,我们可以使用以下公式计算每对点之间的距离。这里我用来找到数组中每列的最小值的位置。对于计算损失函数来说,重要的是距离本身,这可以通过计算得到

现在基本上,你要积累的不是距离,而是距离的函数。这可以通过
torch.min(f(距离))
轻松获得,并且假设
f(.)
是单调的,可以简化为
f(torch.min(距离))

为了近似积分,我们可以使用积分,它积分采样函数的线性插值,在我们的例子中,是在给定点采样的轮廓

这会给你一个损失函数

def contour_divergence(c1, c2, func = lambda x: x**2):
    c1 = torch.atleast_3d(c1);
    c2 = torch.atleast_3d(c2);
    f = func(torch.amin(torch.cdist(c1, c2), dim=2));
    # this computes the length of each segment connecting two consecutive points
    df = torch.sum((c1[:, 1:, :] - c1[:, :-1, :])**2, axis=2)**0.5;
    # here is the trapesoid rule
    return torch.sum((f[:, :-1] + f[:, 1:]) * df[:, :], axis=1) / 4.0;
def contour_dist(c1, c2, func = lambda x: x**2):
    return contour_divergence(c1, c2, func) + contour_divergence(c2, c1, func)
对于连接最近点的直线始终垂直于轨迹的情况,
等高线距离(c1,c2,λx:x)
给出了面积

这将给出半径为1的圆的面积(第二个圆的所有点都在原点上)

现在考虑半径为1的圆和半径为1的圆之间的距离(它将是pi*(1-1/4)=0.75*pi)


如果你想要任何累积平方距离的损失,你只需使用
轮廓距离(c1,c2)
,你可以将任意函数作为参数传递给函数。只要可以反向传播传递的函数,就可以反向传播损失。

Hmmmm您是否尝试过整体填充形状?如果你这样做,你可以使用联合交集、Tversky指数或骰子系数来计算预测输出和真实输出之间的误差。如何在张量内填充轮廓?转换到cpu,然后再转换到numpy,然后
cv2。findContour
cv2。drawContour(厚度=-1)
,然后再转换回tensor对于损失函数来说似乎非常耗时?Hmmmm
print(contour_dist(c1, c1*0.5, lambda x: x)  / math.pi) # should print 0.75