Какую функцию openCv можно использовать для вычисления преобразования перспективы BEV с учетом координат точки и внешних/внутренних характеристик камеры?

У меня есть матрицы 3x3intrinsics и 4x3extrinsics для моей камеры, полученные через cv2.calibrateCamera()

Теперь я хочу использовать эти параметры для вычисления преобразования BEV (Bird Eye View) для любых заданных координат в кадре, полученном с камеры.

Какую функцию openCv можно использовать для вычисления преобразования перспективы BEV для заданных координат точки и камеры extrinsics и/или intrinsics3x3 matrices?

Я нашел кое-что очень похожее в следующем посте: https://deepnote.com/article/social-distancing-detector/ на основе https://www.pyimagesearch.com/2014/08/25/4 -point-opencv-getperspective-transform-example/,

они используют cv2.getPerspectiveTransform(), чтобы получить 3X3 matrix, но я не знаю, представляет ли эта матрица intrinsics, extrinsecs или что-то еще. Затем они преобразуют список точек с помощью такой матрицы следующим образом:

#Assuming list_downoids is the list of points to be transformed and matrix is the one obtained above
list_points_to_detect = np.float32(list_downoids).reshape(-1, 1, 2)
transformed_points = cv2.perspectiveTransform(list_points_to_detect, matrix)

Мне действительно нужно знать, могу ли я использовать эту функцию cv2.perspectiveTransform для вычисления преобразования или есть ли другой лучший способ сделать это, используя extrinsics, intrinsics или оба, без необходимости повторного использования кадра, поскольку у меня уже есть обнаруженные/выбранные координаты сохраняется в массиве.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
1 162
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ таков: невозможно вычислить BEV сцены, если у вас нет информации о расстоянии о пикселях вашего изображения.

Подумайте об этом: представьте, что у вас есть изображение вертикального экрана: тогда вид с высоты птичьего полета будет линией. Теперь скажем, что на этом экране отображается изображение пейзажа и что изображение на этом экране неотличимо от изображения самого пейзажа. BEV по-прежнему будет линией (хотя и красочной).

Теперь представьте, что у вас есть точно такая же картинка, но на этот раз это не изображение экрана, а пейзаж. Тогда вид с высоты птичьего полета не является линией и ближе к тому, что мы обычно представляем себе как BEV.

Наконец, позвольте мне заявить, что OpenCV не может узнать, описывает ли ваше изображение плоскость чего-то другого (даже с заданными параметрами камеры), поэтому он не может вычислить BEV вашей сцены. Функция cv2.perspectiveTransform требует, чтобы вы передали ей матрицу гомографии (вы можете получить ее, используя cv2.findHomography(), но вам также понадобится информация о расстоянии от вашего изображения).

Извините за отрицательный ответ, но решить вашу проблему невозможно, учитывая только внутреннюю и внешнюю калибровочные матрицы камеры.

Спасибо за ответ Иосиф. Что, если я дополнительно укажу кадр и координаты точек в упомянутом кадре, которые я хочу спроецировать?

Maf 11.12.2020 16:04

Если у вас есть 3D-координаты хотя бы из 3-х точек (думаю, вам нужно только три, но чем больше, тем лучше), то вы сможете сделать это с помощью cv2.findHomography. Там мало технических деталей, поэтому я бы посоветовал вам поискать учебные пособия. Помнится, я нашла там несколько очень интересных :)

Joseph Budin 11.12.2020 16:07

Например, если ваше изображение представляет собой наклонную плоскость (я считаю, что дороги достаточно похожи на плоскости для этого), я думаю, что этот урок поможет вам: Learnopencv.com/tag/findhomography

Joseph Budin 11.12.2020 16:09

Большое спасибо за ваше время. У меня есть x, y, width и height для каждой точки. Я думаю, это может сработать.

Maf 11.12.2020 16:13

Пожалуйста ! Удачи ! (Кстати, я был бы очень признателен, если бы вы могли принять мой ответ, спасибо!) :)

Joseph Budin 11.12.2020 16:14

Хорошо. Звучит отлично. Не могли бы вы отметить один из моих комментариев на верхней стрелке?

Maf 11.12.2020 16:15

для преобразования перспективы требуется четыре пары точек (по четыре точки в каждом из обоих представлений). Я бы ответил ДА, потому что, если вы понимаете, что "вид с высоты птичьего полета" является преобразованием плоскости в плоскость, getPerspectiveTransform и warpPerspective будут работать. все ломается, только если вы пытаетесь деформировать изображение 3D-сцены, которая не является плоской плоскостью. разумно предположить, что «BEV» означало отображение плоскости.

Christoph Rackwitz 11.12.2020 19:15

@ChristophRackwitz, что вы подразумеваете под «изображением трехмерной сцены, которая не является плоской плоскостью»?

Maf 13.12.2020 23:46

скажем, вы летите на самолете и фотографируете землю. вы летите над фермами в Канзасе. плоский как блин. затем вы пролетите над Манхэттеном. небоскребы. если сфотографировать их под углом, то вы увидите не только крыши, но и бока небоскребов. нет способа деформировать изображение, чтобы получить настоящий вид сверху вниз (только крыши).

Christoph Rackwitz 14.12.2020 00:25
Ответ принят как подходящий

После тщательного расследования я нашел хорошее решение:

projection matrix — это произведение матриц extrinsic и intrinsic камеры.

cv2.getPerspectiveTransform() дает нам Projection Matrix, когда у нас нет параметров камеры:

cv2.warpPerspective() трансформирует само изображение.

Для приведенной выше задачи нам не нужны эти две функции, поскольку у нас уже есть extrinsics, intrinsecs и координаты точек на изображении.

Учитывая вышеизложенное, я написал функцию для преобразования в BEV список точек list_x_y с учетом intrinsics и extrinsics:

    def compute_point_perspective_transformation(intrinsics, extrinsics, point_x_y):
    """Auxiliary function to project a specific point to BEV
        
        Parameters
        ----------
        intrinsics (array)     : The camera intrinsics matrix
        extrinsics (array)     : The camera extrinsics matrix
        point_x_y (tuple[x,y]) : The coordinates of the point to be projected to BEV
        
        Returns
        ----------
        tuple[x,y] : the projection of the point
    """
        # Using the camera calibration for Bird Eye View
        intrinsics_matrix = np.array(intrinsics, dtype='float32')
        #In the intrinsics we have parameters such as focal length and the principal point

        extrinsics_matrix = np.array(extrinsics, dtype='float32')
        #The extrinsic matrix stores the position of the camera in global space
        #The 1st 3 columns represents the rotation matrix and the last is a translation vector
        extrinsics = extrinsics[:, [0, 1, 3]]

        #We removed the 3rd column of the extrinsics because it represents the z coordinate (0)
        projection_matrix = np.matmul(intrinsics_matrix, extrinsics_matrix)

        # Compute the new coordinates of our points - cv2.perspectiveTransform expects shape 3
        list_points_to_detect = np.array([[point_x_y]], dtype=np.float32)
        transformed_points = cv2.perspectiveTransform(list_points_to_detect, projection_matrix)
        return transformed_points[0][0][0], transformed_points[0][0][1]

Не могли бы вы объяснить, почему это ответ на ваш вопрос? (часть после «рассмотрения представленного выше») Я вижу, что вы возвращаете части матрицы перспективного преобразования, но как это отвечает на «вычислить перспективное преобразование BEV для данной точки координаты" вопрос?

KansaiRobot 20.07.2022 09:20

Поскольку у вас есть модель камеры, готовым (но не полным) решением будет использование функции getTopViewOfImageиз библиотеки преобразования камеры

Другие вопросы по теме