将世界坐标系转换为笛卡尔坐标的问题



我有两个来自WFC3的拟合图像,我正试图将其与C#程序组合。当我尝试组合多个图像时,我认为我得到的x/y坐标值(根据右上升/下降计算)是不正确的。我期待着最终的图像与两张图像的组合宽度大致相同,但结果却是宽度大致相同、高度约为两倍。我知道最终的图像应该是单个图像宽度的两倍,因为我在photoshop中手动组合了图像,最终的图像大约是两个原始图像的两倍宽。

注意:当我说"图像"时,它们是合适的图像,所以它们只是文件中的一堆单个值,所以为了组合它们,我创建了一个新文件,并将正确数量的单个值(宽度*高度)初始化为零,然后填充我用于组合的图像中的值。它们不是jpg、tif或png。

我使用以下公式将世界坐标系更改为笛卡尔坐标系:公式是(因为距离对任何事物都是一样的):x=cos(dec)*cos(ra)y=cos(dec)*sin(ra)

我从fits文件的标题中得到赤经和赤纬。

对于最终的图像尺寸,我计算x1和x2之间的距离,并创建一个1/2图像1宽度+距离+1/2图像2宽度的新图像。对于最终高度,我用y和图像高度进行了类似的计算。

图像也有旋转成分,但我忽略了这一点,因为两个图像共享相同的旋转。这可能是我问题的一部分。

public const double PixelsPerArcSecond = .039; // per WFC3 spec from Nasa
public static ImageDataModel Combine(List<ImageDataModel> inputImages)
{
//  Right ascension is CRVAL1
//  Declination is CRVAL2
//  formula is (since distance is the same for everything):
//     x = cos(dec) * cos(ra)
//     y = cos(dec) * sin(ra)
ImageDataModel returnImage = new ImageDataModel();
ImageDataModel bm = inputImages[0];
double x1, y1, x2, y2;
x1 = Math.Cos(bm.CRVAL2) * Math.Cos(bm.CRVAL1);
y1 = Math.Cos(bm.CRVAL2) * Math.Sin(bm.CRVAL1);
int mult = 4; // todo: set this based off of the bitpix of the incoming images.
for (int i = 1; i < inputImages.Count; i++)
{
ImageDataModel cm = inputImages[i];
x2 = Math.Cos(cm.CRVAL2) * Math.Cos(cm.CRVAL1);
y2 = Math.Cos(cm.CRVAL2) * Math.Sin(cm.CRVAL1);
double dx = x1 - x2;
double dy = y1 - y2;
int distX = (int)((dx * 3600) / PixelsPerArcSecond);
int distY = (int)((dy * 3600) / PixelsPerArcSecond);
// This is what I expect to be wider than tall, but the converse is true.
int w = Math.Abs(distX) + (bm.ImageWidth / 2) + (cm.ImageWidth / 2);
int h = Math.Abs(distY) + (bm.ImageHeight / 2) + (cm.ImageHeight / 2);
// This is where the two images are combined into the final image.
ImageDataModel imd = CombineTwoImages(bm, cm, i, w, h, mult);
bm = imd;
}
return returnImage;
}

我期待着一张图片变成这样:
http://wierdling.net/stack-overflow-images/ManuallyCombined.png

但是得到这个:
http://wierdling.net/stack-overflow-images/CombinedTest.png

第一张图像的统计数据为:宽度=4139,高度=4535,RA=350.1584456860353(CRVAL1),DEC=61.16155335032816(CRVAL2),ORIENTAT=-125

第二张图像的统计数据为:宽度=4139,高度=4535,RA=350.1159150008405(CRVAL1),DEC=61.19543100394401(CRVAL2),ORIENTAT=-125

最终预计宽度接近7733,高度接近4773。

最终实际宽度为4284,高度为7662。

有人知道我做错了什么吗?

该程序的完整源代码可以从https://bitbucket.org/wierdling/fitscombiner/src/master/

它目前只适用于WFC3数据,该程序在很大程度上是一项正在进行的工作。

我认为您的图像程序已经完成了旋转,您也应该这样做。

如果我把你计算的坐标旋转125度,然后计算坐标x1离左边有多远,对x2和y坐标也是如此,我得到的宽度是6725,高度是6166。

不完美,但我认为它朝着正确的方向发展。

希望能有所帮助。

public static ImageDataModel Combine(List<ImageDataModel> inputImages)
{
//  Right ascension is CRVAL1
//  Declination is CRVAL2
//  formula is (since distance is the same for everything):
//     x = cos(dec) * cos(ra)
//     y = cos(dec) * sin(ra)
ImageDataModel returnImage = new ImageDataModel();
ImageDataModel bm = inputImages[0];
double x1, y1, x2, y2;
x1 = Math.Cos(bm.CRVAL2) * Math.Cos(bm.CRVAL1);
y1 = Math.Cos(bm.CRVAL2) * Math.Sin(bm.CRVAL1);
var values = Rotate(0 - bm.Orientation, x1, y1);
x1 = values.x;
y1 = values.y;
int mult = 4; // todo: set this based off of the bitpix of the incoming images.
for (int i = 1; i < inputImages.Count; i++)
{
ImageDataModel cm = inputImages[i];
x2 = Math.Cos(cm.CRVAL2) * Math.Cos(cm.CRVAL1);
y2 = Math.Cos(cm.CRVAL2) * Math.Sin(cm.CRVAL1);
var values2 = Rotate(0 - bm.Orientation, x2, y2);
x2 = values2.x;
y2 = values2.y;
double dx = x1 - x2;
double dy = y1 - y2;
int distX = (int)((dx * 3600) / PixelsPerArcSecond);
int distY = (int)((dy * 3600) / PixelsPerArcSecond);
double width = (1.0 + x1) * (bm.ImageWidth / 2) + (1.0 - x2) * (cm.ImageWidth / 2) + Math.Abs(distX);
double height = (1.0 + y1) * (bm.ImageHeight / 2) + (1.0 - y2) * (cm.ImageHeight / 2) + Math.Abs(distY);
// This is what I expect to be wider than tall, but the converse is true.
int w = Math.Abs(distX) + (bm.ImageWidth / 2) + (cm.ImageWidth / 2);
int h = Math.Abs(distY) + (bm.ImageHeight / 2) + (cm.ImageHeight / 2);
// This is where the two images are combined into the final image.
ImageDataModel imd = CombineTwoImages(bm, cm, i, w, h, mult);
bm = imd;
}
return returnImage;
}
private static (double x, double y) Rotate(int angle, double x, double y)
{
double rad = Math.PI * angle / 180.0;
return (x * Math.Cos(rad) - y * Math.Sin(rad), x * Math.Sin(rad) + y * Math.Cos(rad));
}

最新更新