Thực hiện cong vênh vận chuyển tối ưu trong Matlab


11

Tôi đang thực hiện bài báo " Vận chuyển khối lượng tối ưu để đăng ký và cong vênh", mục tiêu của tôi là đưa nó lên mạng vì tôi không thể tìm thấy bất kỳ mã vận chuyển khối lượng lớn nào trên mạng và điều này ít nhất sẽ thú vị cho cộng đồng nghiên cứu trong xử lý hình ảnh.

Giấy có thể được tóm tắt như sau:
- tìm thấy một bản đồ ban đầu sử dụng matchings histogram 1D dọc theo tọa độ x và y - giải quyết cho các điểm cố định của , trong đó là viết tắt của góc quay ngược chiều kim đồng hồ 90 độ, cho giải phương trình poisson với điều kiện biên Dirichlet (= 0), và là yếu tố quyết định của ma trận Jacobian. - tính ổn định được đảm bảo cho dấu thời gianu t = 1u
ut=1μ0Du1div(u)u1Du
dt<min|1μ01div(u)|

Đối với mô phỏng số (được thực hiện trên lưới thông thường), chúng biểu thị bằng cách sử dụng poicalc của matlab để giải phương trình poisson, chúng sử dụng các khác biệt hữu hạn trung tâm cho các dẫn xuất không gian, ngoại trừ Du được tính toán bằng sơ đồ hướng gió.

Sử dụng mã của tôi, chức năng năng lượng và độ cong của ánh xạ đang giảm đúng cách cho một vài lần lặp (từ vài chục đến vài nghìn tùy theo bước thời gian). Nhưng sau đó, mô phỏng bùng nổ: năng lượng tăng lên để đạt được NAN trong rất ít lần lặp. Tôi đã thử một số đơn đặt hàng cho sự khác biệt và tích hợp (có thể tìm thấy sự thay thế bậc cao hơn cho cumptrapz ở đây ) và các sơ đồ nội suy khác nhau, nhưng tôi luôn gặp cùng một vấn đề (ngay cả trên các hình ảnh rất mượt mà, khác không ở mọi nơi, v.v.).
Bất cứ ai cũng sẽ quan tâm đến việc xem mã và / hoặc vấn đề lý thuyết mà tôi đang phải đối mặt? Mã này khá ngắn.

Vui lòng thay thế gradient2 () ở cuối bằng gradient (). Đây là một gradient bậc cao hơn nhưng cũng không giải quyết được mọi thứ.

Bây giờ tôi chỉ quan tâm đến phần vận chuyển tối ưu của bài báo, không phải là thuật ngữ chính quy bổ sung.

Cảm ơn !

Câu trả lời:


5

Người bạn tốt của tôi, Pascal đã thực hiện điều này vài năm trước ( gần như ở 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)

Chạy thử, mất khoảng 2 giây.

Cách tiếp cận giảm dần độ dốc được giải thích ở đây: people.clarkson.edu/~ebollt/Papers/quadcost.pdf


xuất sắc .. cảm ơn rất nhiều! Tôi sẽ thử mã này và so sánh với mã của tôi để kiểm tra lỗi của tôi. Cách tiếp cận này thực sự có vẻ là phiên bản địa phương của bài báo của Haker et al. mà tôi đã đề cập - tức là, mà không giải quyết cho một laplacian. Cảm ơn một lần nữa!
WhitAngl

Cuối cùng tôi cũng gặp phải một số vấn đề với mã này ...: nếu tôi tính Tôi ở khá xa (với the hessian) - ngay cả khi xóa gaussian mơ hồ. Ngoài ra, nếu tôi chỉ tăng số lần lặp lên vài nghìn, mã sẽ phát nổ và đưa ra các giá trị NaN (và sự cố). Bất kỳ ý tưởng ? Cảm ơn ! f 1 Hf2(ϕ)detHϕf1H
WhitAngl

Có làm mờ nhiều hơn với vấn đề NaN?
dranxo

Vâng, thực sự, sau nhiều thử nghiệm, nó sẽ giúp làm mờ nhiều hơn - cảm ơn!. Bây giờ tôi đang thử 8 bước với độ mờ bắt đầu là 140 pixel độ lệch chuẩn cho đến 1 pixel stdev (vẫn tính toán). Mặc dù vậy, tôi vẫn có một lượng đáng kể hình ảnh gốc trong kết quả cuối cùng của mình (với độ mờ 64px). Tôi cũng sẽ kiểm tra xem có bất kỳ cuộn tròn nào còn lại trong . ϕ
WhitAngl

Oh ok tốt. Tôi nghĩ. Làm mờ là có vì hình ảnh tự nhiên không liên tục (các cạnh) và độ dốc sẽ có vấn đề. Hy vọng rằng bạn vẫn nhận được câu trả lời tốt mà không làm mờ quá nhiều.
dranxo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.