Исправление бочкообразной дисторсии в серии x,y в R

Правка: в идеале я хотел бы использовать алгоритм, идентичный функции ImageMagick -distort, но реализованный в R, чтобы преобразовывать необработанные координаты x,y, а не изображения. Использование ImageMagick также позволило бы мне получить визуальное доказательство эффективности устранения искажений.

Вопрос

У меня есть серия x, y, созданная на основе анализа видео с помощью программного обеспечения для отслеживания. Исходные изображения в видео имеют некоторое искажение бочкообразной линзы, которое я хотел бы исправить, чтобы повысить точность координат отслеживания.

Я могу выполнить то, что выглядит как подходящая коррекция, используя оператор искажения в ImageMagick, например:

convert input.jpg -distort barrel '0 -0.022 0' output.jpg

Теперь я знаю, что могу применить эту коррекцию к каждому кадру в видео (перед отслеживанием), но это не кажется лучшим вариантом, поскольку у меня есть десятки видео, каждое из которых состоит из> 7e4 кадров. Кажется, было бы намного проще применить коррекцию к самим координатам x, y после отслеживания.

Из документации ImageMagick уравнение бочкообразного искажения выглядит следующим образом:

Rsrc = r * ( Ar^3 + Br^2 + C*r + D )

Где «r» — радиус назначения, а «Rsrc» — исходный пиксель, из которого нужно получить цвет пикселя. радиусы нормализуются так, что радиус = '1,0' для половины минимальной ширины или высоты входного изображения».

Но я не знаю, как реализовать это в R, чтобы преобразовать серию x, y. Может ли кто-нибудь предложить какую-либо помощь? Спасибо!

Что я пробовал до сих пор

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

undistortFun <- function(X, Y, strength) {

    imWidth <- 640
    imHeight <- 480

    radius_u <- sqrt(imWidth^2 + imHeight^2) / strength

    normX <- X - (imWidth / 2)
    normY <- Y - (imHeight / 2)

    distance <- sqrt(normX^2 + normY^2)
    r <- distance / radius_u

    theta <- ifelse(r == 0, 1, atan(r) / r)

    newX <- (imWidth / 2) + theta * normX
    newY <- (imHeight / 2) + theta * normY

    return(data.frame(X = newX, Y = newY))

}

Похожие вопросы

Я нашел два похожих вопроса, здесь и здесь, но они связаны с неискажающими изображениями, а не с необработанными координатами x,y, и реализованы на Java и C++, с которыми я не знаком.


person jogall    schedule 06.08.2014    source источник
comment
Насколько я знаю, практически нет опубликованного кода R для алгоритмов оптической коррекции. Но было бы легче комментировать, если бы вы предоставили источник алгоритма коррекции ствола, на который вы ссылаетесь в другом месте. (Обратите внимание, что я не могу сопротивляться предложению, что, если ваша первая попытка увеличивает кажущееся искажение, вы должны изменить полярность :-))   -  person Carl Witthoft    schedule 06.08.2014
comment
Этот вопрос кажется не по теме, потому что он касается разработки методов обработки изображений и на самом деле не является конкретным вопросом программирования (поскольку ваш код работает без ошибок, он просто не дает желаемых результатов.) Я мог бы проверить, есть ли другой сайт stackexchange, который может подойти лучше. Или, по крайней мере, проясните детали метода, который вы хотите реализовать.   -  person MrFlick    schedule 06.08.2014
comment
@MrFlick Я отредактировал вопрос, чтобы, надеюсь, сделать его более понятным.   -  person jogall    schedule 06.08.2014
comment
Это действительно не поможет, если вы не можете точно сказать нам, какой алгоритм использует функция ImageMagick -distort.   -  person MrFlick    schedule 06.08.2014
comment
@CarlWitthoft Я добавил источник - моей первой мыслью было изменить полярность (верите или нет :-P), но автор функции указывает, что преобразование нельзя инвертировать, и я боюсь, что нет. понять, что функция на самом деле делает достаточно хорошо, чтобы обойти ее!   -  person jogall    schedule 06.08.2014
comment
@MrFlick добавил алгоритм к вопросу: Rsrc = r * ( A*r^3 + B*r^2 + C*r + D )   -  person jogall    schedule 07.08.2014
comment
Jogal, я имел в виду просто поменять знак у поправочных членов :-(   -  person Carl Witthoft    schedule 07.08.2014
comment
@jogall Являются ли X и Y, которые находятся в: normX ‹- X - (imWidth / 2) normY ‹- Y - (imHeight / 2), должны быть векторами ширины изображения (1: 640) и длина (1: 480) или одно число ширины и длины изображения каждый?   -  person SqueakyBeak    schedule 14.03.2019


Ответы (1)


У меня есть удовлетворительное решение, изменив функцию, указанную в вопросе, с помощью алгоритма искажения ImageMagick:

Rsrc = r * ( Ar^3 + Br^2 + C*r + D )

Вот так:

undistortFun <- function(x, y, a, b, c, d = 1, imWidth = 640, imHeight = 480) {

    normX <- X - (imWidth / 2)
    normY <- Y - (imHeight / 2)

    radius_u <- sqrt(imWidth^2 + imHeight^2)

    r <- sqrt(normX^2 + normY^2) /  radius_u

    Rsrc <- r * (a*r^3 + b*r^2 + c*r + d)

    theta <- ifelse(Rsrc == 0, 1, 1 / atan(Rsrc) * Rsrc)

    newX <- (imWidth / 2) + theta * normX
    newY <- (imHeight / 2) + theta * normY

    return(data.frame(X = newX, Y = newY))
}

Хотя я не уверен в вычислении тета, и указание нулевого искажения (a=0, b=0, c=0) все же приводит к преобразованию. Тем не менее, похоже, он делает то, что я хотел в этих примерах:

График исходных данных x, y:

оригинал

График скорректированных данных x, y (где: a = 0, b = -0,02, c = 0): adjusted

person jogall    schedule 07.08.2014
comment
Замечательное решение. В этом случае X и Y, которые находятся в: normX ‹- X - (imWidth / 2) normY ‹- Y - (imHeight / 2), должны быть векторами ширины (1:640) и длины изображения (1: 480) или по одному числу ширины и длины изображения? - person SqueakyBeak; 14.03.2019