Калибровка рыбьего глаза OpenCV C ++ отличается от Python - PullRequest
0 голосов
/ 07 февраля 2020

В настоящее время я работаю над камерой, которая имеет «рыбий глаз» (которая невелика, но все же), и я пытаюсь ее не искажать.

Как стартер: я не настолько знаком с opencv, Я как всегда на документации, пытаясь сделать что-нибудь. (и / или здесь ищите ответ на мою проблему (проблемы)).

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

Здесь что я нашел:

DIM=(1094, 729)
K=np.array([
    [1307.2807020496643, 0.0, 530.3754311563506], 
    [0.0, 1318.342691460933, 354.98352268131123], 
    [0.0, 0.0, 1.0]
])
D=np.array([
    [-0.2994762856767568],
    [0.5036082961388784],
    [-4.231072729639434],
    [3.8646397788794578]
])
def undistort(img_path):    
    img = cv2.imread(img_path)
    h,w = img.shape[:2]
    print(K)
    print(D)
    print(np.eye(3))
    print(DIM)
    map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)

    undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
    cv2.imshow("undistorted", undistorted_img)
    cv2.imwrite("test.jpg", undistorted_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__ == '__main__':
    for p in sys.argv[1:]:
        undistort(p)

Это сценарий python, который я использую, чтобы не искажать изображение. Данные вверху (K & D) генерируются с помощью другого скрипта. Я не упоминал об этом, потому что у меня есть перевод в C ++, который показывает тот же результат для того же base_picture

И для этой функции, если я даю искаженное изображение, например: Python distorted image Я получил этот результат: Python undistorted image

Итак, я вижу, что крошечные искажения были устранены.

Но когда я пытаюсь реализовать эту же функцию в C ++, выполните следующие действия:

src = cv::imread(“path/to/image.jpg");

    cv::Size size = {src.cols, src.rows};

    cv::Mat K(3, 3, cv::DataType<double>::type);
    K.at<double>(0, 0) = 1307.2807020496643;
    K.at<double>(0, 1) = 0.0;
    K.at<double>(0, 2) = 530.3754311563506;

    K.at<double>(1, 0) = 0.0;
    K.at<double>(1, 1) = 1318.342691460933;
    K.at<double>(1, 2) = 354.98352268131123;

    K.at<double>(2, 0) = 0.0;
    K.at<double>(2, 1) = 0.0;
    K.at<double>(2, 2) = 1.0;

    cv::Mat D(4, 1, cv::DataType<double>::type);
    D.at<double>(0, 0) = -0.2994762856767568;
    D.at<double>(1, 0) = 0.5036082961388784;
    D.at<double>(2, 0) = -4.231072729639434;
    D.at<double>(3, 0) = 3.8646397788794578;
    cv::Mat E = cv::Mat::eye(3, 3, cv::DataType<double>::type);

    cv::Mat map1;
    cv::Mat map2;

    std::cout << K << std::endl;
    std::cout << D << std::endl;
    std::cout << E << std::endl;
    std::cout << size << std::endl;

    cv::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);

    cv::Mat undistort;
    cv::remap(src, undistort, map1, map2, CV_INTER_LINEAR,
              CV_HAL_BORDER_CONSTANT);

Базовое изображение остается прежним, НО я получил это в результате: C++ undistorted image

И, как вы можете сказать, все пошло хуже ...

Я сбросил K, D & E в моем скрипте python и программе на c ++ (оба дают один и тот же результат для одной и той же базовой картинки) (я имею в виду, когда вычисляю данные)

Это идет не так от initUndistortRectifyMap вплоть до переназначения и, наконец, imshow совсем не то, что я ожидал.

Я пытаюсь вывести map1 & map2 в программу python script & C ++ (не просматривал ВСЕ данные) и я мог заметить, что в конце одной из карт (не смотрел обе) ults были разными.

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

Есть ли что-то Я делаю не так? Как возиться с типами или чем-то еще?

Изменится ли что-нибудь для вычисления изображения из cv :: imread или из захвата кадра с камеры?

(Просто чтобы вы знали, кадр (.jpg), с помощью которого производятся вычисления, является cv :: imwrite из захвата кадра камеры, тогда я намерен больше не использовать изображения, а только работать с cv :: Mat, заполненным данными из захвата камеры.)

(я знаю, что в конце перечисления не совпадают, но даже с использованием cv::BORDER_CONSTANT у меня все еще та же проблема.)

1 Ответ

2 голосов
/ 09 февраля 2020

Вы использовали cv::initUndistortRectifyMap вместо cv::fisheye::initUndistortRectifyMap

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

int main()
{
    cv::Mat src = cv::imread("C:/StackOverflow/Input/fisheyeCalib.jpg");

        cv::Size size = { src.cols, src.rows };

    cv::Mat K(3, 3, cv::DataType<double>::type);
    K.at<double>(0, 0) = 1307.2807020496643;
    K.at<double>(0, 1) = 0.0;
    K.at<double>(0, 2) = 530.3754311563506;

    K.at<double>(1, 0) = 0.0;
    K.at<double>(1, 1) = 1318.342691460933;
    K.at<double>(1, 2) = 354.98352268131123;

    K.at<double>(2, 0) = 0.0;
    K.at<double>(2, 1) = 0.0;
    K.at<double>(2, 2) = 1.0;

    cv::Mat D(4, 1, cv::DataType<double>::type);
    D.at<double>(0, 0) = -0.2994762856767568;
    D.at<double>(1, 0) = 0.5036082961388784;
    D.at<double>(2, 0) = -4.231072729639434;
    D.at<double>(3, 0) = 3.8646397788794578;
    cv::Mat E = cv::Mat::eye(3, 3, cv::DataType<double>::type);

    cv::Mat map1;
    cv::Mat map2;

    std::cout << K << std::endl;
    std::cout << D << std::endl;
    std::cout << E << std::endl;
    std::cout << size << std::endl;

    // Here's the error:
    //cv::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);
    cv::fisheye::initUndistortRectifyMap(K, D, E, K, size, CV_16SC2, map1, map2);

    cv::Mat undistort;
    cv::remap(src, undistort, map1, map2, CV_INTER_LINEAR,
        CV_HAL_BORDER_CONSTANT);

    cv::imwrite("C:/StackOverflow/Input/fisheyeCalib_output.jpg", undistort);
    cv::imshow("undist", undistort);
    cv::waitKey(0);
}

enter image description here

...