การนำการแปรปรวนการขนส่งที่เหมาะสมที่สุดใน Matlab


11

ฉันกำลังใช้กระดาษ " การขนส่งมวลชนที่เหมาะสมที่สุดสำหรับการลงทะเบียนและแปรปรวน " เป้าหมายของฉันคือการทำให้มันออนไลน์เพราะฉันไม่สามารถหารหัสขนส่งมวลชนแบบ eulerian ออนไลน์ได้และสิ่งนี้น่าสนใจอย่างน้อยสำหรับชุมชนการวิจัยในการประมวลผลภาพ

กระดาษที่สามารถสรุปได้ดังนี้:
- หาแผนที่เริ่มต้นuใช้ 1D จ้อ histogram พร้อม x และ y พิกัด
- แก้ปัญหาสำหรับจุดคงที่ของut=1μ0Du1div(u)u1Du
dt<min|1μ01div(u)|

สำหรับการจำลองเชิงตัวเลข (ดำเนินการในตารางปกติ) พวกเขาระบุว่าใช้poicalcของmatlabสำหรับการแก้สมการปัวซองพวกเขาใช้ความแตกต่างที่มีศูนย์กลาง จำกัด สำหรับอนุพันธ์เชิงพื้นที่ยกเว้นDuซึ่งคำนวณโดยใช้แบบ upwind

การใช้รหัสของฉันพลังงานการทำงานและขดของการทำแผนที่ลดลงอย่างเหมาะสมสำหรับการทำซ้ำสองสามครั้ง (จากไม่กี่สิบถึงสองสามพันขึ้นอยู่กับขั้นตอนเวลา) แต่หลังจากนั้นการจำลองจะระเบิดขึ้น: พลังงานจะเพิ่มขึ้นถึง NAN ในการวนซ้ำน้อยมาก ฉันลองคำสั่งซื้อหลายรายการสำหรับความแตกต่างและการผสานรวม (สามารถแทนที่คำสั่งที่สูงกว่าเพื่อ cumptrapz ได้ที่นี่ ) และแผนการแก้ไขที่แตกต่างกัน แต่ฉันได้รับปัญหาเดียวกันเสมอ (แม้ในภาพที่ราบรื่นมาก
ทุกคนจะสนใจดูรหัสและ / หรือปัญหาทางทฤษฎีที่ฉันกำลังเผชิญอยู่หรือไม่ รหัสค่อนข้างสั้น

โปรดแทนที่การไล่ระดับสี 2 () ที่ส่วนท้ายด้วยการไล่ระดับสี () นี่เป็นการไล่ระดับลำดับที่สูงขึ้น แต่ก็ไม่ได้แก้ปัญหาเช่นกัน

ฉันสนใจเฉพาะส่วนการขนส่งที่ดีที่สุดของกระดาษในตอนนี้ไม่ใช่ระยะการทำให้เป็นมาตรฐานเพิ่มเติม

ขอบคุณมาก!

คำตอบ:


5

เพื่อนที่ดีของฉันPascalทำสิ่งนี้เมื่อไม่กี่ปีที่ผ่านมา ( เกือบจะเป็น 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 และคณะ ที่ฉันพูดถึง - คือ. โดยไม่ต้องแก้ไขเพื่อ laplacian ขอบคุณอีกครั้ง !
WhitAngl

ในที่สุดฉันก็พบปัญหาสองสามอย่างกับรหัสนี้ ... : ถ้าฉันคำนวณฉันค่อนข้างห่างจาก (กับ the hessian) - แม้ว่าจะเอา gaussian ออกไป เบลอ. นอกจากนี้ถ้าฉันเพิ่มจำนวนการวนซ้ำเป็นสองพันสองครั้งรหัสจะระเบิดและให้ค่า NaN (และล้มเหลว) ความคิดใด ๆ ขอบคุณมาก! f2(ϕ)detHϕf1H
WhitAngl

เบลอช่วยแก้ไขปัญหา NaN มากขึ้นหรือไม่
dranxo

ใช่แน่นอนหลังจากการทดสอบเพิ่มเติมมันช่วยลดความเบลอได้มากขึ้น - ขอบคุณ! ตอนนี้ฉันกำลังลอง 8 ขั้นตอนโดยมีความพร่ามัวเริ่มต้นที่ 140 พิกเซลจนถึง 1 พิกเซล stdev (ยังคงคำนวณ) ฉันยังคงมีภาพต้นฉบับจำนวนมากในผลลัพธ์ครั้งล่าสุดของฉัน (พร้อมเบลอ 64px) ฉันยังจะตรวจสอบใด ๆ ที่เหลือในขด\ϕ
WhitAngl

โอเคดี ฉันคิด. ความพร่ามัวเกิดขึ้นเนื่องจากภาพไม่ได้ต่อเนื่อง (ขอบ) และการไล่ระดับสีจะเป็นปัญหา หวังว่าคุณจะยังได้รับคำตอบที่ดีโดยไม่เบลอมากเกินไป
dranxo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.