Matlab에서 최적의 운송 왜곡 구현


11

나는 " 등록 및 뒤틀림에 최적의 대량 운송 "이라는 논문을 시행하고 있는데 , 온라인에서 유러 리아 대중 교통 코드를 찾을 수 없기 때문에 온라인으로 전환하는 것이 목표이며, 적어도 이미지 처리 분야의 연구 커뮤니티에게는 흥미로울 것입니다.

이 논문은 다음과 같이 요약 될 수 있습니다.
- x 및 y 좌표를 따라 1D 히스토그램 일치를 사용하여 초기지도 를 찾습니다 -고정 점 , 여기서 는 시계 반대 방향으로 90도 회전하고 은 Dirichlet 경계 조건 (= 0)을 갖는 포아송 방정식의 해를 나타냅니다. 및 코비안 행렬의 행렬식이다. -시간 단계에 대한 안정성 보장u t = 1u
ut=1μ0Du1div(u)u1Du
dt<min|1μ01div(u)|

수치 모의 (정규 그리드에서 수행)의 경우, 포아송 방정식을 해결하기 위해 matlab의 poicalc 를 사용하고, 상향식 ( upwind) 방식을 사용하여 계산 된 Du 를 제외하고 공간 미분에 대해 중심 유한 차이를 사용합니다.

내 코드를 사용하면 에너지 기능과 매핑의 컬이 몇 번 반복됩니다 (시간 단계에 따라 수십에서 수천으로). 그러나 그 후 시뮬레이션이 폭발적으로 반복됩니다. 에너지는 거의 반복없이 NAN에 도달하기 위해 증가합니다. 나는 차별화 및 통합 (cumptrapz에 대한 더 높은 순서의 대체는 여기 에서 찾을 수 있음 )과 다른 보간 체계에 대해 몇 가지 명령을 시도 했지만 항상 같은 문제가 발생합니다 (매우 부드러운 이미지, 0이 아닌 곳에서도).
누구나 내가 직면하고있는 코드 및 / 또는 이론적 문제를 보는 데 관심이 있습니까? 코드는 다소 짧습니다.

마지막에 gradient2 ()를 gradient ()로 바꾸십시오. 이것은 고차 그라디언트 였지만 해결하지 못했습니다.

추가 정규화 용어가 아니라 현재로서는 용지의 최적 운송 부분에만 관심이 있습니다.

감사 !

답변:


5

나의 좋은 친구 파스칼 은 몇 년 전에 이것을 만들었습니다 ( 거의 Matlab에 있습니다)

#! /usr/bin/env python

#from scipy.interpolate import interpolate
from pylab import *
from numpy import *


def GaussianFilter(sigma,f):
    """Apply Gaussian filter to an image"""
    if sigma > 0:
        n = ceil(4*sigma)
        g = exp(-arange(-n,n+1)**2/(2*sigma**2))
        g = g/g.sum()

        fg = zeros(f.shape)

        for i in range(f.shape[0]):
            fg[i,:] = convolve(f[i,:],g,'same')
        for i in range(f.shape[1]):
            fg[:,i] = convolve(fg[:,i],g,'same')
    else:
        fg = f

    return fg


def clamp(x,xmin,xmax):
    """Clamp values between xmin and xmax"""
    return minimum(maximum(x,xmin),xmax)


def myinterp(f,xi,yi):
    """My bilinear interpolator (scipy's has a segfault)"""
    M,N = f.shape
    ix0 = clamp(floor(xi),0,N-2).astype(int)
    iy0 = clamp(floor(yi),0,M-2).astype(int)
    wx = xi - ix0
    wy = yi - iy0
    return ( (1-wy)*((1-wx)*f[iy0,ix0] + wx*f[iy0,ix0+1]) +
        wy*((1-wx)*f[iy0+1,ix0] + wx*f[iy0+1,ix0+1]) )


def mkwarp(f1,f2,sigma,phi,showplot=0):
    """Image warping by solving the Monge-Kantorovich problem"""
    M,N = f1.shape[:2]

    alpha = 1
    f1 = GaussianFilter(sigma,f1)
    f2 = GaussianFilter(sigma,f2)

    # Shift indices for going from vertices to cell centers
    iUv = arange(M)             # Up
    iDv = arange(1,M+1)         # Down
    iLv = arange(N)             # Left
    iRv = arange(1,N+1)         # Right
    # Shift indices for cell centers (to cell centers)
    iUc = r_[0,arange(M-1)]
    iDc = r_[arange(1,M),M-1]
    iLc = r_[0,arange(N-1)]
    iRc = r_[arange(1,N),N-1]
    # Shifts for going from centers to vertices
    iUi = r_[0,arange(M)]
    iDi = r_[arange(M),M-1]
    iLi = r_[0,arange(N)]
    iRi = r_[arange(N),N-1]


    ### The main gradient descent loop ###      
    for iter in range(0,30):
        ### Approximate derivatives ###
        # Compute gradient phix and phiy at pixel centers.  Array phi has values
        # at the pixel vertices.
        phix = (phi[iUv,:][:,iRv] - phi[iUv,:][:,iLv] + 
            phi[iDv,:][:,iRv] - phi[iDv,:][:,iLv])/2
        phiy = (phi[iDv,:][:,iLv] - phi[iUv,:][:,iLv] + 
            phi[iDv,:][:,iRv] - phi[iUv,:][:,iRv])/2
        # Compute second derivatives at pixel centers using central differences.
        phixx = (phix[:,iRc] - phix[:,iLc])/2
        phixy = (phix[iDc,:] - phix[iUc,:])/2
        phiyy = (phiy[iDc,:] - phiy[iUc,:])/2
        # Hessian determinant
        detD2 = phixx*phiyy - phixy*phixy

        # Interpolate f2 at (phix,phiy) with bilinear interpolation
        f2gphi = myinterp(f2,phix,phiy)

        ### Update phi ###
        # Compute M'(phi) at pixel centers
        dM = alpha*(f1 - f2gphi*detD2)
        # Interpolate to pixel vertices
        phi = phi - (dM[iUi,:][:,iLi] + 
            dM[iDi,:][:,iLi] + 
            dM[iUi,:][:,iRi] + 
            dM[iDi,:][:,iRi])/4


    ### Plot stuff ###      
    if showplot:
        pad = 2
        x,y = meshgrid(arange(N),arange(M))
        x = x[pad:-pad,:][:,pad:-pad]
        y = y[pad:-pad,:][:,pad:-pad]
        phix = phix[pad:-pad,:][:,pad:-pad]
        phiy = phiy[pad:-pad,:][:,pad:-pad]

        # Vector plot of the mapping
        subplot(1,2,1)
        quiver(x,y,flipud(phix-x),-flipud(phiy-y))
        axis('image')
        axis('off')
        title('Mapping')

        # Grayscale plot of mapping divergence
        subplot(1,2,2)  
        divs = phixx + phiyy # Divergence of mapping s(x)
        imshow(divs[pad:-pad,pad:-pad],cmap=cm.gray)
        axis('off')
        title('Divergence of Mapping')
        show()

    return phi


if __name__ == "__main__":  # Demo
    from pylab import *
    from numpy import * 

    f1 = imread('brain-tumor.png')
    f2 = imread('brain-healthy.png')
    f1 = f1[:,:,1]
    f2 = f2[:,:,1]

    # Initialize phi as the identity map
    M,N = f1.shape
    n,m = meshgrid(arange(N+1),arange(M+1))
    phi = ((m-0.5)**2 + (n-0.5)**2)/2

    sigma = 3
    phi = mkwarp(f1,f2,sigma,phi)
    phi = mkwarp(f1,f2,sigma/2,phi,1)
#   phi = mkwarp(f1,f2,sigma/4,phi,1)

테스트 실행에는 약 2 초가 소요됩니다.

그라디언트 디센트 방식은 people.clarkson.edu/~ebollt/Papers/quadcost.pdf에서 설명합니다.


우수 .. 감사합니다! 이 코드를 사용 해보고 내 코드와 비교하여 오류를 확인합니다. 이 접근법은 실제로 Haker et al.의 논문의 로컬 버전 인 것으로 보인다. 내가 말한-즉, 라플라시안을 해결하지 않고. 다시 감사합니다!
WhitAngl

이 코드와 관련하여 몇 가지 문제가 발생했습니다 ... : 하면 가우스를 제거 할 때도 ( 가 hessian 인) 과 거리가 멀어집니다. 흐림. 또한 반복 횟수를 수천으로 늘리면 코드가 폭발하고 NaN 값을 제공합니다 (충돌). 어떤 아이디어? 감사 ! f2(ϕ)detHϕf1H
WhitAngl

NaN 문제에 더 많은 흐림 효과가 있습니까?
dranxo

예, 실제로 더 많은 테스트를 한 후에 더 많은 흐림 효과를 낼 수 있습니다. 감사합니다. 나는 1 픽셀 stdev (여전히 컴퓨팅)까지 140 픽셀 표준 편차의 시작 블러로 8 단계를 시도하고 있습니다. 그래도 최종 결과에는 여전히 많은 양의 원본 이미지가 있습니다 (64px 흐림). 에 남아있는 컬이 있는지 확인합니다 . ϕ
WhitAngl

오 알았어 내 생각 엔 이미지가 자연스럽게 연속적이지 않고 (에지) 그라디언트에 문제가 있기 때문에 블러가 발생합니다. 바라건대 너무 많이 흐리지 않고 여전히 좋은 답변을 얻고 있기를 바랍니다.
dranxo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.