У меня есть исходное панорамное изображение, которое имеет 360 градусов долготы и 120 градусов широты.
Я хочу написать функцию, которая может визуализировать это, учитывая ширину и высоту области просмотра и вращение по долготе. Я хочу сделать вывод изображения таким образом, чтобы его высота составляла 120 градусов.
есть ли у кого-нибудь указатели? Я не могу понять, как преобразовать координаты цели обратно в источник.
спасибо
скольжения
Вот мой код: - (создайте консольное приложение c # 2.0, добавьте ссылку на system.drawing)
static void Main(string[] args)
{
Bitmap src = new Bitmap(@"C:\Users\jon\slippyr4\pt\grid2.jpg");
// constant stuff
double view_width_angle = d2r(150);
double view_height_angle = d2r(120);
double rads_per_pixel = 2.0 * Math.PI / src.Width;
// scale everything off the height
int output_image_height = src.Width;
// compute radius (from chord trig - my output image forms a chord of a circle with angle view_height_angle)
double radius = output_image_height / (2.0 * Math.Sin(view_height_angle / 2.0));
// work out the image width with that radius.
int output_image_width = (int)(radius * 2.0 * Math.Sin(view_width_angle / 2.0));
// source centres for later
int source_centre_x = src.Width / 2;
int source_centre_y = src.Height / 2;
// work out adjacent length
double adj = radius * Math.Cos(view_width_angle / 2.0);
// create output bmp
Bitmap dst = new Bitmap(output_image_width, output_image_height);
// x & y are output pixels offset from output centre
for (int x = output_image_width / -2; x < output_image_width / 2; x++)
{
// map this x to an angle & then a pixel
double x_angle = Math.Atan(x / adj);
double src_x = (x_angle / rads_per_pixel) + source_centre_x;
// work out the hypotenuse of that triangle
double x_hyp = adj / Math.Cos(x_angle);
for (int y = output_image_height / -2; y < output_image_height / 2; y++)
{
// compute the y angle and then it's pixel
double y_angle = Math.Atan(y / x_hyp);
double src_y = (y_angle / rads_per_pixel) + source_centre_y;
Color c = Color.Magenta;
// this handles out of range source pixels. these will end up magenta in the target
if (src_x >= 0 && src_x < src.Width && src_y >= 0 && src_y < src.Height)
{
c = src.GetPixel((int)src_x, (int)src_y);
}
dst.SetPixel(x + (output_image_width / 2), y + (output_image_height / 2), c);
}
}
dst.Save(@"C:\Users\slippyr4\Desktop\pana.jpg");
}
static double d2r(double degrees)
{
return degrees * Math.PI / 180.0;
}
С помощью этого кода я получаю ожидаемые результаты, когда устанавливаю ширину целевого изображения в 120 градусов. Я вижу правильную кривизну горизонтальных линий и т. Д., Как показано ниже, и когда я пытаюсь сделать это с реальной равноугольной панорамой в реальной жизни, это выглядит как коммерческие зрители визуализируют.
Но, когда я делаю выходное изображение шире, все идет не так. Вы начинаете видеть недопустимые пиксели в верхней и нижней частях параболы в центре, как показано здесь с изображением шириной 150 градусов и высотой 120 градусов: -
Похоже, что коммерческие зрители делают что-то вроде увеличения - поэтому в центре изображение имеет высоту 120 градусов и, следовательно, по бокам больше обрезается. и поэтому нет пурпурного (то есть, нет недопустимых исходных пикселей).
Но я не могу понять, как это сделать в математике.
Это не домашняя работа, это хобби-проект. следовательно, почему мне не хватает понимания того, что происходит! Также, пожалуйста, простите за серьезную неэффективность кода, я оптимизирую его, когда он будет работать правильно.
еще раз спасибо