当前位置: 首页 > 知识库问答 >
问题:

对数极坐标变换

章嘉致
2023-03-14

我正在尝试对图像执行对数极坐标变换,以便进行图像配准。换句话说,我正在努力实现这一点:输入图像-

我需要用Java从头开始编写代码,因为我将使用OpenCL Java绑定在GPU端完成这项工作,而不能使用库。这方面有多个线程,但没有一个能真正帮助我,主要是因为它们都使用内置的MATLAB函数,我无法复制。

为了让它发挥作用,我一直在尝试Polar Transform而不是Log-Polar Transform,因为大多数在线信息都指的是第一个。到目前为止,我得到的最好结果是这里的这一点(伪代码),基于此线程:

w = input.width; // Width of the input image
h = input.height; // Height of the input image

// Copy input pixels into an array
for(y=0; y<h; y++){
    for(x=0; x<w; x++){
        input[y*w+x] = getPixel(x, y);
    }
}

// Polar transform
maxRadius = sqrt(w*w + h*h);
radiusScale = w / maxRadius;
angleScale = h / (2 * PI);

for(y=0; y<h; y++){
    dy = y - h/2; // Distance from the center in the y-axis
    for(x=0; x<w; x++){
        dx = x - w/2; // Distance from the center in the x-axis
        angle = atan2(dy, dx) % (2*PI);
        radius = sqrt(dx*dx + dy*dy);
        newY = radius * radiusScale;
        newX = radius * thetaScale;
        output[y*w+x] = input[newY*w+newX];
    }
}  

我得到的类似于某种极性变换,尽管不是我想要的结果:输出图像

有人能给我点建议吗?

谢谢

编辑:对数极坐标变换如下所示。

编辑:实施@matt建议我现在有以下代码:

    w = input.width; // Width of the input image
    h = input.height; // Height of the input image
    maxRadius = sqrt(w*w/4 + h*h/4);
    radiusScale = h / maxRadius;
    angleScale = w /PI/2;
    offset = PI;
    
    for(y=0; y<h; y++){
        dy = y - h/2; // Distance from center in the y-axis
        for(x=0; x<w; x++){
            dx = x - w/2; // Distance from the center in the x-axis
            angle = atan2(dy, dx);
            radius = sqrt(dx*dx + dy*dy);
            
            newY = radius * radiusScale;
            newX = (angle + offset) * angleScale;
            
            output[newY*w+newX] = input.getPixel(x, y); 
        }
    }

绘制新的输出给了我这个,这仍然不是我期望得到的结果。

共有1个答案

燕翼
2023-03-14

这种变换的一个问题是,变换空间中的每个“像素”在x,y空间中占用的空间量不同。这是我如何定义变换。

  • 我们的新图像将具有相同的尺寸
  • Y轴将为0至最大Rho
  • X轴将为-π到π

所以我们从迭代输出图像的i,j坐标开始。得到的ρ和θ如下所示。

double rho = j*maxRho / height;
double theta = i*maxTheta / width + offset;

现在我们需要在各自的位置获取输入像素。

int x = (int) ( Math.exp(rho)*Math.cos(theta) + width/2);
int y = (int) ( Math.exp(rho)*Math.sin(theta) + height/2);

现在我们可以得到像素值了。

int pixel = input[y*width + x];

您的输入变量有点多余,因为您可以只使用

然后我们只需设置相应的输出值。

output[j*width + i] = pixel;

下面是一个可编译的示例。

import javax.imageio.ImageIO;
import java.net.URL;
import java.awt.image.BufferedImage;
import java.io.File;
public class ScannerJunk{
  
  public static void main(String[] args) throws Exception{
        BufferedImage img = ImageIO.read( new URL("https://i.stack.imgur.com/MvDQT.png") );
        
        BufferedImage out = new BufferedImage( img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB );
        
        double w = img.getWidth();
        double h = img.getHeight();
        
        double maxRho = 0.5*Math.log( w*w/4.0 + h*h/4.0 );
        
        double maxTheta = 2 * Math.PI;
        double offset = - Math.PI;
        for(int i = 0; i< w; i++){
            for(int j = 0; j< h; j++){
                double rho = j*maxRho / h;
                double theta = i*maxTheta / w + offset;
                int x = (int) ( Math.exp(rho)*Math.cos(theta) + w/2);
                int y = (int) ( Math.exp(rho)*Math.sin(theta) + h/2);
                
                try{
                    out.setRGB( i, j, img.getRGB( x, y ) );
                } catch(Exception e){
                    System.out.println( i + ", " + j + " :: " + rho + ", " + theta + " :: " + x + ", " + y );
                }
            }
        }
        
        
        ImageIO.write(out, "PNG", new File("transformed.png") );
  }
}

请注意,最大半径不会映射到所有可能角度的输入图像。

此外,半径和θ轴似乎要从示例图像中转置。

 类似资料:
  • 我一直在使用Peter Kovesi的MatLab函数进行机器视觉(如果你不知道的话,这些函数非常出色) 我一直在使用极坐标变换将图像转换为极坐标。Peter Kovesi的函数名为“PolarTrans”,可在此处找到-http://www.peterkovesi.com/matlabfns/#syntheticimages 该函数将图像漂亮地转换为极坐标。然而,我也希望发生相反的情况。Pete

  • 我试图将图像从极坐标转换为笛卡尔坐标,但在应用公式后,我得到了浮点坐标(r和teta),我不知道如何使用x和y的浮点来表示空间中的点。可能有一种方法可以将它们转换为整数,并仍然保留分布,但我不知道如何。我知道OpenCV中有像warpPolar这样的函数,但我想自己实现它。任何想法都会有帮助:) 这是我的代码:

  • 我在将图像转换为极坐标时遇到问题。在Photoshop中很容易:)所以这对我来说是一个新领域。 我有以下图片: 结果应该是这样的: 我在这里看了一下,了解了一些基本知识,但仍然对圆的平方有点困惑: 我几乎不知道如何重新绘制图像。还有一个警告:由于管理限制,我想避免使用像Numpy这样的外部库。

  • 我正在尝试将极坐标的图像转换为笛卡尔坐标。 将图像转换为极坐标的示例显式执行-想要一个光滑的矩阵方法 我原以为使用上述方法是小菜一碟,但事实并非如此!!如果有人发现我的代码有错误,请告诉我! 我发现非常奇怪的是,当我改变phi时,它会做出根本性的改变,而不是以我期望的方式! 干杯

  • 编辑:我决定把这个问题分成两部分,因为它实际上是两个问题:1。如何在MATLAB中绘制极曲面图(本问题)和2。如何将拟合极坐标数据点放入粗略(非极坐标)矩阵 我有一个包含某些灰色值(介于0和1之间的值)的矩阵。这些点存储在一个矩形矩阵中,但实际上数据点是通过旋转探测器获得的。这意味着我实际上有极坐标(我知道起始矩阵中每个像素的极坐标)。 我想制作一个数据点的极线图。我有下面的例子。 因为MATLA

  • 我试图写一个函数,它以笛卡尔坐标系中的x和y值作为输入,并输出极坐标和三角坐标形式。我希望输出包含指数和正弦/余弦,而不是实际值。例如,如果笛卡尔函数是z=1i,我希望函数输出z=sqrt(2)e^(ipi/4)和z=sqrt(2)(cos(pi/4)Isin(pi/4)。我该怎么做? 函数坐标(x, y) r=sqrt(x.^2 y.^2); θ=atan(y./x); Polarcoord=r