将线条拟合到图像

时间:2016-12-01 18:34:04

标签: r image-processing linear-regression

我正在尝试根据像素的强度(或颜色)为图像拟合一条线。下图显示了面板1中的典型测试图像,在面板2中绘制了手动线。测试图像(矩阵)可以在此处下载:.RData from dropbox test image (panel 1) with line drawn (panel 2)

我想使用回归分析来生成类似于面板2中手动绘制的线条的东西。但是,我不能使用简单的线性回归,因为,与所有图像一样,x轴和y轴都有误差。

我对具有相关方程式,链接等的算法描述持开放态度,而不一定是我可以复制和粘贴的代码。

方法我想避免

  1. 将在不同斜率绘制的像素的一系列合成二进制图像与实际数据图像相关联。例如,下面两张图片的相关性会非常好,但同样,我想避免使用这种方法。
  2. enter image description here

    1. 使用骨架化算法缩小图像,以便可以使用简单的线性回归。

1 个答案:

答案 0 :(得分:0)

有趣的是,地震学家处理类似的问题,他们根据地震源和接收器之间的距离来校正反射数据,其过程称为正常移出(Normal Moveout)。我使用了类似的过程。

一般算法是:

  1. 加载图片
  2. 定义一系列要调查的斜坡
  3. 定义一个<图像列数
  4. 绕过一系列斜坡......
    • 根据窗口的斜率和大小(下图中第一行的灰点)在图像上定义索引位置(x,y)。
    • 从那些从上面的x,y位置索引的原始矩阵构建矩阵(下图中第二行的图)。
    • 对矩阵求和,然后通过除以求和矩阵的长度对求和进行归一化。
    • 保存每个总和(你循环的每个速度将有1个总和)
  5. 与和矢量的最大(或最小)索引相对应的速度矢量是当前像素列处图像的最佳斜率/速度(下图中的第三行)。
  6. 沿着图像的列执行上述步骤。
  7. 该算法在下图中可视化描述。

    Algorithm description

    执行上述程序的代码位于问题中给出的测试数据的一列:

    load('test.RData')
    
    ## INPUTS ## 
    img=test
    
    vel.min=1 ## minimum velocity (or slope) to test
    vel.max=20 ## max velocity to test
    vel.number=100 ## how many velocities to test
    win=10 ## size of window to investigate 
    
    ## define a time index
    ti=nrow(img)/2
    
    ## set up a vector to hold the velocity correlation values
    vel.corrs <- rep(NA,vel.number)
    
    ## define the set of velocities to search over
    vels <- seq(vel.min,vel.max,length.out=vel.number)
    
    ## define a velocity index
    vi=1
    
    while(vi<=length(vels)) {
    
        ## build a binary matrix with corresponding to the window and velocity
        bin.mat <- matrix(0,ncol=ncol(img),nrow=nrow(img))
        slope.line <- seq(0,ncol(bin.mat)/vels[vi],length.out=ncol(bin.mat))
        bin.mat[(ti-win/2):(ti+win/2),]=1
    
    
        ## define the offeset
        offset <- rep(slope.line,each=win+1)
    
        ## define the indices of array points according to velocity and window
        win.vel.ind <- cbind(which(bin.mat==1,arr.ind=TRUE)[,1]+offset,which(bin.mat==1,arr.ind=TRUE)[,2])
    
        ## limit the points to the dimensions of the image
        if(any(floor(win.vel.ind[,1]) > nrow(img))){
            win.vel.ind[(which(floor(win.vel.ind[,1])>nrow(img))),]=NA
            ##win.vel.ind <- win.vel.ind[-(which(floor(win.vel.ind[,1])>nrow(img))),]
        }
    
        ## pluck the values of the image associated with those non-NA indices
        slice <- img[win.vel.ind]
    
        ## build a matrix of the slice vector with nrow=win+1
        slice.mat <- matrix(slice,nrow=win+1,ncol=ncol(img),byrow=FALSE)
    
        ## apply a hamming window
        ##ham.mat <- matrix(hamming(win+1),ncol=ncol(slice.mat),nrow=nrow(slice.mat))
        ##slice.ham <- slice.mat*ham.mat
    
        ## sum this 'slice' and normalize and store
        vel.corrs[vi] <- sum(slice,na.rm=TRUE)/length(na.omit(slice))
    
        vi=vi+1
    }