我正在尝试对图像执行对数极坐标变换,以便进行图像配准。换句话说,我正在努力实现这一点:输入图像-
我需要用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);
}
}
绘制新的输出给了我这个,这仍然不是我期望得到的结果。
这种变换的一个问题是,变换空间中的每个“像素”在x,y空间中占用的空间量不同。这是我如何定义变换。
所以我们从迭代输出图像的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