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


11

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

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