Использование opencv для создания панорамного изображения из 3d точек

У меня есть камера PointGrey Ladybug3. Это панорамная (multi)камера (5 камера для того чтобы сделать 360º и 1 камера смотря вверх). Я сделал всю калибровку и исправление, так что я в конечном итоге из всех пикселей 6 изображений я знаю, что это 3d-позиция wrt глобальный кадр. То, что я бы сделал сейчас, это преобразовать эти 3d-точки в панорамное изображение. Наиболее распространенной является радиальная (Равнонаправленная) проекция, подобная следующей: Radial Porjection

для всех 3D точек (X, Y, Z) можно найти тета и фи координаты, как:

Radial Picture Equation

мой вопрос в том, можно ли сделать это автоматически с помощью opencv? Или, если я сделаю это вручную, каков наилучший способ преобразовать эту кучу пикселей в тета, координаты phi в изображение?

официальный Ladybug SDK использует OpenGL для всех этих операций, но мне было интересно, можно ли это сделать в opencv.

спасибо,

Хосеп

1 ответов


подход, который я использовал для решения этой проблемы, был следующим:

  1. создайте пустое изображение с требуемым размером вывода.
  2. для каждого пикселя в выходном изображении найдите координаты theta и phi. (Линейно) тета идет от-Pi к Pi и phi от 0 к Pi
  3. установите радиус проекции R и найдите 3D-координату из тета, phi и R.
  4. найдите, сколько камер является видимой 3D-точкой и соответствующим пикселем позиция.
  5. скопируйте пиксель изображения, где пиксель находится ближе к основной точке. Или любые другие действительные критерии...

мой код выглядит так:

cv::Mat panoramic;
panoramic=cv::Mat::zeros(PANO_HEIGHT,PANO_WIDTH,CV_8UC3);
double theta, phi;
double R=calibration.getSphereRadius();
int result;

double dRow=0;
double dCol=0;

for(int y = 0; y!= PANO_HEIGHT; y++){
    for(int x = 0; x !=PANO_WIDTH ; x++) {
            //Rescale to [-pi, pi]
        theta=-(2*PI*x/(PANO_WIDTH-1)-PI); //Sign change needed.
            phi=PI*y/(PANO_HEIGHT-1);

        //From theta and phi find the 3D coordinates.
        double globalZ=R*cos(phi);
            double globalX=R*sin(phi)*cos(theta);
        double globalY=R*sin(phi)*sin(theta);


        float minDistanceCenter=5000; // Doesn't depend on the image.

        float distanceCenter;

        //From the 3D coordinates, find in how many camera falls the point!
        for(int cam = 0; cam!= 6; cam++){
            result=calibration.ladybugXYZtoRC(globalX, globalY, globalZ, cam, dRow, dCol);
            if (result==0){ //The 3d point is visible from this camera
                cv::Vec3b intensity = image[cam].at<cv::Vec3b>(dRow,dCol);
                distanceCenter=sqrt(pow(dRow-imageHeight/2,2)+pow(dCol-imageWidth/2,2));
                if (distanceCenter<minDistanceCenter) {
                    panoramic.ptr<unsigned char>(y,x)[0]=intensity.val[0];
                    panoramic.ptr<unsigned char>(y,x)[1]=intensity.val[1];
                    panoramic.ptr<unsigned char>(y,x)[2]=intensity.val[2];

                    minDistanceCenter=distanceCenter;
                }
            }
        }

    }
}