0% нашли этот документ полезным (0 голосов)
4 просмотров27 страниц

Report Lab2

Отчет по лабораторной работе №2 посвящен геометрическим преобразованиям изображений, включая линейные и нелинейные методы, а также коррекцию искажений и сшивку изображений. В документе представлены теоретические основы и практическая реализация различных преобразований, таких как сдвиг, отражение, масштабирование и перспективные преобразования. Результаты работы демонстрируют применение изученных методов на практике.

Загружено:

maihoangquan250205
Авторское право
© All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd
0% нашли этот документ полезным (0 голосов)
4 просмотров27 страниц

Report Lab2

Отчет по лабораторной работе №2 посвящен геометрическим преобразованиям изображений, включая линейные и нелинейные методы, а также коррекцию искажений и сшивку изображений. В документе представлены теоретические основы и практическая реализация различных преобразований, таких как сдвиг, отражение, масштабирование и перспективные преобразования. Результаты работы демонстрируют применение изученных методов на практике.

Загружено:

maihoangquan250205
Авторское право
© All Rights Reserved
Мы серьезно относимся к защите прав на контент. Если вы подозреваете, что это ваш контент, заявите об этом здесь.
Доступные форматы
Скачать в формате PDF, TXT или читать онлайн в Scribd

Факультет Систем Управления и Робототехники

ОТЧЕТ
ПО ЛАБОРАТОРНОЙ РАБОТЕ №2
ГЕОМЕТРИЧЕСКИЕ ПРЕОБРАЗОВАНИЯ
ИЗОБРАЖЕНИЙ

Аннтоация – В работе рассмотрены основные методы Выполнили


геометрических преобразований изображений. Были реали-
зованы линейные и нелинейные преобразования, а также Май Хоанг Куан1 , Ле Тхань
методы коррекции искажений и сшивки изображений. По- Тунг2 , and Басиони Абдель-
лученные результаты демонстрируют практическое приме- салам Али Абдельсалам3
нение данных методов. 1 407882, @quanmh_25
2 374793,
Ключевые слова: геометрические преобразования, обра- @tungso1234
3 465144, @Basyonyyy
ботка изображений, аффинные преобразования, дисторсия,
интерполяция
Проверил

Горбачёв Алексей Алексан-


дрович

16 марта 2026 г.
Содержание
1 Введение 2

2 Теоретическая часть 2
2.1 Геометрические преобразования изображений . . . . . . . . . . . . . . . . . . 2
2.1.1 Однородные координаты . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.1.2 Аффинные преобразования . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.1.3 Матрица преобразования в OpenCV . . . . . . . . . . . . . . . . . . . . 2
2.2 Линейные преобразования . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2.1 Сдвиг изображения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
2.2.2 Отражение изображения . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2.3 Масштабирование . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2.4 Поворот изображения . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2.5 Скос изображения . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.3 Нелинейные преобразования . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.3.1 Перспективное преобразование . . . . . . . . . . . . . . . . . . . . . . . 3
2.3.2 Полиномиальное преобразование . . . . . . . . . . . . . . . . . . . . . 3
2.3.3 Синусоидальные искажения . . . . . . . . . . . . . . . . . . . . . . . . 4
2.4 Коррекция дисторсии . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.5 Сшивка изображений . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

3 Практическая реализация 5
3.1 Задание 1. Простейшие геометрические преобразования . . . . . . . . . . . . 5
3.1.1 Self-work [Link] - Сдвиг изображения . . . . . . . . . . . . . . . . . . . 5
3.1.2 Self-work [Link] - Отражение изображения по обеим осям . . . . . . . 6
3.1.3 Self-work [Link] - Масштабирование изображения . . . . . . . . . . . . 8
3.1.4 Self-work [Link] - Поворот изображения . . . . . . . . . . . . . . . . . 10
3.1.5 Self-work [Link] - Обратное аффинное преобразование . . . . . . . . . 12
3.1.6 Self-work [Link] - Скос изображения . . . . . . . . . . . . . . . . . . . 13
3.1.7 Self-work [Link] - Кусочно-линейное отображение . . . . . . . . . . . . 14
3.2 Задание 1.4 - Нелинейные преобразования . . . . . . . . . . . . . . . . . . . . 15
3.2.1 Self-work [Link] - Обратное перспективное преобразование . . . . . . 15
3.2.2 Self-work [Link] - Полиномиальное отображение . . . . . . . . . . . . . 16
3.2.3 Self-work [Link] - Полиномиальное отображение с интерполяцией (Оп-
ционально) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2.4 Self-work [Link] - Синусоидальное искажение по оси Oy . . . . . . . . 19
3.3 Задание 2. Коррекция дисторсии . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.3.1 Self-work 2.1.1 - Бочкообразная дисторсия и коррекция . . . . . . . . . 20
3.3.2 Self-work 2.2.1 - Подушкообразная дисторсия и коррекция . . . . . . . 22
3.4 Задание 3. Сшивка изображений . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.4.1 Self-work 3.1.1 - Ручная сшивка изображений . . . . . . . . . . . . . . 24

4 Ответы на контрольные вопросы 25

5 Заключение 26

1
1 Введение
В данной практической работе изучаются основные методы геометрических преобра-
зований изображений. Рассматриваются линейные и нелинейные преобразования, а также
их применение для коррекции искажений и создания панорамных изображений.

2 Теоретическая часть
2.1 Геометрические преобразования изображений
Геометрические преобразования изображений подразумевают пространственное изме-
нение положения пикселей с целочисленными координатами (x, y) в другое множество с
координатами (x′ , y ′ ), при этом интенсивность пикселей не изменяется.

2.1.1 Однородные координаты


Для общности преобразований используются однородные координаты. Если однород-
ные координаты точки умножаются на ненулевой скаляр, то полученные координаты пред-
ставляют ту же точку.
 
 ′ ′    A D G
x y w = x y 1 · B E H 
C F I

2.1.2 Аффинные преобразования


Аффинное отображение — это отображение, при котором параллельные прямые пе-
реходят в параллельные прямые, пересекающиеся — в пересекающиеся, скрещивающиеся
— в скрещивающиеся.
Уравнения аффинного преобразования:
(
x′ = Ax + By + C
y ′ = Dx + Ey + F

2.1.3 Матрица преобразования в OpenCV


В OpenCV матрица преобразования хранится в виде 2 × 3:
 
′ A B C
T =
D E F

2.2 Линейные преобразования


2.2.1 Сдвиг изображения
При сдвиге A = E = 1, B = D = 0:
(
x′ = x + C
y′ = y + F
 
1 0 C
T =
0 1 F

2
2.2.2 Отражение изображения
Отражение вокруг оси Ox: A = 1, E = −1:
 
1 0 0
T =
0 −1 0

2.2.3 Масштабирование
Масштабирование с коэффициентами α и β:
(
x′ = αx, α > 0
y ′ = βy, β > 0
 
α 0 0
T =
0 β 0

2.2.4 Поворот изображения


Поворот на угол φ: (
x′ = x cos φ − y sin φ
y ′ = x sin φ + y cos φ
 
cos φ − sin φ 0
T =
sin φ cos φ 0

2.2.5 Скос изображения


Скос вдоль оси Ox с коэффициентом s:
(
x′ = x + sy
y′ = y
 
1 0 0
T =
s 1 0

2.3 Нелинейные преобразования


2.3.1 Перспективное преобразование
Перспективное преобразование сохраняет коллинеарность точек, но не сохраняет па-
раллельность прямых:
Ax + By + C

x ′ =

Gx + Hy + I
Dx + Ey + F
y ′ =

Gx + Hy + I

2.3.2 Полиномиальное преобразование


Полиномиальное преобразование второго порядка:
(
x′ = a1 + a2 x + a3 y + a4 x2 + a5 xy + a6 y 2
y ′ = b1 + b2 x + b3 y + b4 x2 + b5 xy + b6 y 2

3
2.3.3 Синусоидальные искажения
Гармонические искажения, например, вдоль оси Ox:

x′ = x + A sin(2πy/λ)

2.4 Коррекция дисторсии


Дисторсия — оптическое искажение, выражающееся в искривлении прямых линий.
Математическая модель:
⃗ = b0⃗r + F3 r2⃗r + F5 r4⃗r + . . .
R

• Бочкообразная дисторсия — отрицательная дисторсия

• Подушкообразная дисторсия — положительная дисторсия

2.5 Сшивка изображений


Сшивка изображений — объединение двух или более изображений в одно с приве-
дением к общей системе координат.
Аффинное преобразование для сшивки:
(
x′ = a1 + a2 x + a3 y
y ′ = b1 + b2 x + b3 y

4
3 Практическая реализация
3.1 Задание 1. Простейшие геометрические преобразования
3.1.1 Self-work [Link] - Сдвиг изображения
Условие: Выполнить сдвиг изображения влево и вверх на вектор (−40, −80). Изменить
разрешение изображения в соответствии со сдвигом.
1 # TODO Place your solution for part 1 here
2 # TODO : Shift an image to the left and up by ( -40 , -80)
3 shift_x , shift_y = ( -40 , -80)
4
5 # Create transformation matrix
6 T = np . float32 ([[1 , 0 , shift_x ] ,
7 [0 , 1 , shift_y ]])
8
9 # Calculate new image dimensions ( decreased by shift values )
10 new_width = I . shape [1] + shift_x
11 new_height = I . shape [0] + shift_y
12
13 # Apply transformation
14 Ishift_left_up = cv . warpAffine (I , T , ( new_width , new_height ) )
15
16 # Display result
17 ShowImages ([( " Original Image " , I ) ,
18 ( " Shifted Left and Up ( -40 , -80) " , Ishift_left_up ) ])

Листинг 1: Сдвиг изображения влево и вверх (Self-work [Link])

Рис. 1: Оригинальное изображение Рис. 2: Сдвиг влево и вверх (-40, -80)

Рис. 3: Результат сдвига изображения

5
Краткий вывод: В результате преобразования изображение было сдвинуто влево и
вверх на заданный вектор. После изменения размера выходного изображения потеря дан-
ных не наблюдается.

3.1.2 Self-work [Link] - Отражение изображения по обеим осям


Условие: Выполнить отражение изображения по обеим осям (Ox и Oy). Реализовать
два решения.
1 # TODO Place your solution for part 1 here
2 # Create a matrix for flip ( either one matrix for single flip or two
matrices for flip around Ox and around Oy )
3
4 # Method 1: Single transformation matrix for flip along both axes
5 # Flip along Ox then Oy : x ’ = width - 1 - x , y ’ = height - 1 - y
6 T_flip_xy = np . float32 ([[ -1 , 0 , I . shape [1] - 1] ,
7 [0 , -1 , I . shape [0] - 1]])
8
9 # Apply the transformation with cv2 . warpAffine () function
10 Iflip_xy = cv . warpAffine (I , T_flip_xy , I . shape [:2][:: -1])
11
12 # Display the result
13 ShowImages ([( " Source image " , I ) ,
14 ( " Flip both axes ( affine ) " , Iflip_xy ) ] , 2)

Листинг 2: Отражение по обеим осям через матрицу преобразования (Self-work [Link] -


Часть 1)

1 # TODO Place your solution for part 2 here


2 # Flip the image with cv2 . flip () function
3 # cv2 . flip with -1 flips both axes
4 Iflip_xy_ocv = cv . flip (I , -1)
5
6 # Display the result
7 ShowImages ([( " Source image " , I ) ,
8 ( " Built - in flip both axes " , Iflip_xy_ocv ) ] , 2)
9
10 # Check if they match
11 print ( f " Images match : { np . allclose ( Iflip_xy , Iflip_xy_ocv ) } " )

Листинг 3: Отражение по обеим осям через [Link]() (Self-work [Link] - Часть 2)

6
Рис. 4: Оригинал Рис. 5: Через матрицу Рис. 6: Через [Link]()

Рис. 7: Результаты отражения по обеим осям

Краткий вывод: Оба способа отражения изображения по двум осям дали одинаковый
результат. Это подтверждает корректность как ручного задания матрицы преобразования,
так и использования встроенной функции [Link]().

7
3.1.3 Self-work [Link] - Масштабирование изображения
Условие: Увеличить изображение в 1.4 раза по обеим осям. Реализовать два решения.
1 # TODO Place your solution for part 1 here
2 # Create matrix for scale
3 # Apply transformation with cv2 . warpAffine () function
4 # Display the result
5 # Scale factor
6 scale_factor = 1.4
7
8 # Create transformation matrix for scaling
9 # T = [ sx , 0 , 0; 0 , sy , 0] where sx = sy = scale_factor
10 T_scale = np . float32 ([[ scale_factor , 0 , 0] ,
11 [0 , scale_factor , 0]])
12
13 # Calculate new image dimensions
14 new_width = int ( I . shape [1] * scale_factor )
15 new_height = int ( I . shape [0] * scale_factor )
16
17 # Apply affine transformation
18 Iscale15 = cv . warpAffine (I , T_scale , ( new_width , new_height ) )
19
20 print ( f " Original dimensions : { I . shape [1]} x { I . shape [0]} " )
21 print ( f " Scaled dimensions : { new_width } x { new_height } " )
22
23 # Display the result
24 ShowImages ([( " Original Image " , I ) ,
25 ( " Scaled 1.4 x ( warpAffine ) " , Iscale15 ) ] , hide_axes = False )

Листинг 4: Масштабирование через матрицу преобразования (Self-work [Link] - Часть 1)

1 # TODO Place your solution for part 2 here


2 # Scale the image with cv2 . scale () function
3 # Display the result
4
5 # Use cv2 . resize () with scale factors
6 Iscale15_ocv = cv . resize (I , None , fx = scale_factor , fy = scale_factor ,
7 interpolation = cv . INTER_CUBIC )
8
9 # Verify dimensions match
10 print ( f " OpenCV resize dimensions : { Iscale15_ocv . shape [1]} x { Iscale15_ocv .
shape [0]} " )
11
12 # Display the result
13 ShowImages ([( " Original Image " , I ) ,
14 ( " Scaled 1.4 x ( resize ) " , Iscale15_ocv ) ] , hide_axes = False )

Листинг 5: Масштабирование через [Link]() (Self-work [Link] - Часть 2)

8
Рис. 8: Оригинал Рис. 9: Через матрицу Рис. 10: Через [Link]()

Рис. 11: Результаты масштабирования (коэффициент 1.4)

Краткий вывод: После масштабирования размер изображения увеличился в 1.4 раза


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

9
3.1.4 Self-work [Link] - Поворот изображения
Условие: Повернуть изображение вокруг центра правой верхней четверти с коорди-
3 1
натами ( · width, · height) на 30◦ по часовой стрелке. Реализовать два решения.
4 4

1 # Rotation around point (3/4* width , 1/4* height ) by 30 degrees clockwise


2
3 center_x = 3 * I . shape [1] / 4.0
4 center_y = I . shape [0] / 4.0
5 angle = 30
6 phi = angle * math . pi / 180.0
7
8 # Method 1: manual matrix
9 Tshift = np . float32 ([[1 , 0 , - center_x ] ,
10 [0 , 1 , - center_y ] ,
11 [0 , 0 , 1]])
12
13 Trotate = np . float32 ([[ math . cos ( phi ) , - math . sin ( phi ) , 0] ,
14 [ math . sin ( phi ) , math . cos ( phi ) , 0] ,
15 [0 , 0 , 1]])
16

17 Tshiftback = np . float32 ([[1 , 0 , center_x ] ,


18 [0 , 1 , center_y ] ,
19 [0 , 0 , 1]])
20
21 T_manual = np . matmul ( Tshiftback , np . matmul ( Trotate , Tshift ) ) [0:2 , :]
22 Irotate_manual = cv . warpAffine (I , T_manual , I . shape [:2][:: -1])
23
24 # Method 2: OpenCV
25 T_ocv = cv . g et R o ta t io n Ma t r ix 2 D (( center_x , center_y ) , - angle , 1.0)
26 Irotate_ocv = cv . warpAffine (I , T_ocv , I . shape [:2][:: -1])
27

28 ShowImages ([( " Source image " , I ) ,


29 ( " Rotation ( manual ) " , Irotate_manual ) ,
30 ( " Rotation ( OpenCV ) " , Irotate_ocv ) ] , 3)

Листинг 6: Поворот через три матрицы (Self-work [Link]

10
Рис. 12: Ручной расчет матрицы Рис. 13: Через getRotationMatrix2D()

Рис. 14: Результаты поворота на 30°

Краткий вывод: Изображение было успешно повернуто на 30◦ по часовой стрелке


вокруг заданной точки. Оба способа реализации дали совпадающий результат.

11
3.1.5 Self-work [Link] - Обратное аффинное преобразование
Условие: Выполнить обратное преобразование изображения ‘Iaffine‘, используя точки
‘Pdst‘ как исходные и ‘Psrc‘ как целевые.
1 # TODO Place your solution here
2 # Backward affine transformation
3
4 Psrc = np . float32 ([[50 , 300] , [150 , 200] , [50 , 50]])
5 Pdst = np . float32 ([[50 , 200] , [250 , 200] , [50 , 100]])
6
7 # Forward transform
8 T_forward = cv . get Af fi neT ra ns for m ( Psrc , Pdst )
9 Iaffine = cv . warpAffine (I , T_forward , I . shape [:2][:: -1])
10

11 # Backward transform
12 T_backward = cv . get Af fi neT ra ns for m ( Pdst , Psrc )
13 Iaffine_back = cv . warpAffine ( Iaffine , T_backward , I . shape [:2][:: -1])
14
15 ShowImages ([( " Source image " , I ) ,
16 ( " Affine transform " , Iaffine ) ,
17 ( " Backward transform " , Iaffine_back ) ] , 3)

Листинг 7: Обратное аффинное преобразование (Self-work [Link])

Рис. 15: Прямое преобразование Рис. 16: Обратное преобразование

Рис. 17: Прямое и обратное аффинное преобразование

Краткий вывод: Обратное аффинное преобразование позволило частично восстано-


вить исходное изображение. Небольшие черные области объясняются потерей информации
при прямом преобразовании.

12
3.1.6 Self-work [Link] - Скос изображения
Условие: Реализовать преобразование скоса изображения с параметром s = 0.4.
1 # TODO Place your solution here
2 # Bevel transform with s = 0.4
3

4 s = 0.4
5 T_bevel = np . float32 ([[1 , 0 , 0] ,
6 [s , 1 , 0]])
7
8 new_width = int ( I . shape [1] + s * I . shape [0])
9 Ibevel = cv . warpAffine (I , T_bevel , ( new_width , I . shape [0]) )
10
11 ShowImages ([( " Source image " , I ) ,
12 ( " Bevel transform " , Ibevel ) ] , 2)

Листинг 8: Скос изображения (Self-work [Link])

Рис. 19: Скос (s = 0.4)

Рис. 18: Оригинал

Рис. 20: Результат скоса изображения

Краткий вывод: После применения преобразования скоса изображение было накло-


нено в соответствии с параметром s = 0.4. Форма объекта изменилась, при этом общее
содержание изображения сохранилось.

13
3.1.7 Self-work [Link] - Кусочно-линейное отображение
Условие: Масштабировать правую часть изображения с коэффициентом 0.4.
1 # TODO Place your solution here
2 # Fill the transformation matrix
3 # Split and display image parts
4 # Transform right part and stitch
5 # Display the result
6 # Piecewise linear mapping : scale right half by 0.4
7
8 stretch = 0.4
9 split_x = I . shape [1] // 2
10
11 T = np . float32 ([[ stretch , 0 , 0] ,
12 [0 , 1 , 0]])
13
14 Ileft = I [: , : split_x , :]
15 Iright = I [: , split_x : , :]
16
17 Iright_scaled = cv . warpAffine ( Iright , T , ( int ( Iright . shape [1] * stretch ) ,
Iright . shape [0]) )
18 Iplm2 = np . concatenate (( Ileft , Iright_scaled ) , axis =1)
19
20 ShowImages ([( " Source image " , I ) ,
21 ( " Piecewise linear mapping " , Iplm2 ) ] , 2 , hide_axes = False )

Листинг 9: Кусочно-линейное отображение (Self-work [Link])

Рис. 21: Сравнение исходного изображения и результата кусочно-линейного преобразова-


ния

Краткий вывод: Правая часть изображения была сжата с коэффициентом 0.4, тогда
как левая часть осталась без изменений. В результате наблюдается локальное геометри-
ческое преобразование только выбранной области изображения.

14
3.2 Задание 1.4 - Нелинейные преобразования
3.2.1 Self-work [Link] - Обратное перспективное преобразование
Условие: Выполнить обратное перспективное преобразование изображения ‘Ipersp2‘,
используя точки ‘Pdst‘ как исходные и ‘Psrc‘ как целевые.
1 # TODO Place your solution here
2 # Calculate the perspective transformation matrix for transformation from
Pdst to Psrc
3 # Apply the perspective transformation with cv2 . warpPerspective () function
4 # Display the result
5 # Backward perspective transformation
6
7 Psrc = np . float32 ([[50 , 461] , [461 , 461] , [461 , 50] , [50 , 50]])
8 Pdst = np . float32 ([[50 , 461] , [461 , 440] , [450 , 10] , [100 , 50]])
9

10 # Forward transformation
11 T_forward = cv . g e t P e r s p e c t i v e T r a n s f o r m ( Psrc , Pdst )
12 Ipersp2 = cv . warpPerspective (I , T_forward , I . shape [:2][:: -1])
13
14 # Backward transformation
15 T_backward = cv . g e t P e r s p e c t i v e T r a n s f o r m ( Pdst , Psrc )
16 Ipersp3 = cv . warpPerspective ( Ipersp2 , T_backward , I . shape [:2][:: -1])
17
18 ShowImages ([( " Source image " , I ) ,
19 ( " Perspective transformation " , Ipersp2 ) ,
20 ( " Backward transformation " , Ipersp3 ) ] , 3)

Листинг 10: Обратное перспективное преобразование (Self-work [Link])

Рис. 22: Результаты перспективного преобразования

Краткий вывод: Обратное перспективное преобразование позволило приблизительно


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

15
3.2.2 Self-work [Link] - Полиномиальное отображение
Условие: Реализовать полиномиальное отображение по формулам:

x′ = 0 + 1 · x + 0 · y + 0 · x2 + 0 · xy + 0 · y 2
y ′ = 0 + 0 · x + 1 · y + 0.001 · x2 + 0.002 · xy + 0.00001 · y 2

1
2 # TODO Place your solution here
3 # Fill the polynomial mapping parameters array
4 # Create mesh grid for X , Y coordinates
5 # Calculate new coordinates for X , Y according to formula
6 # Create a mask where new coordinates are valid
7 # Apply new coordinates
8 # Display the result
9 Ipoly2 = np . zeros_like ( I )
10 # Polynomial mapping parameters for y - axis distortion
11 # x ’ = 0 + 1* x + 0* y + 0* x ^2 + 0* x * y + 0* y ^2
12 # y ’ = 0 + 0* x + 1* y + 0.001* x ^2 + 0.002* x * y + 0.00001* y ^2
13 T = np . array ([[0 , 0] , # constant terms
14 [1 , 0] , # x terms
15 [0 , 1] , # y terms
16 [0 , 0.001] , # x ^2 terms
17 [0 , 0.002] , # x * y terms
18 [0 , 0.00001]]) # y ^2 terms
19
20 # Create mesh grid
21 x , y = np . meshgrid ( np . arange ( I . shape [1]) , np . arange ( I . shape [0]) )
22

23 # Calculate new coordinates


24 x_new = np . round ( T [0 , 0] + x * T [1 , 0] + y * T [2 , 0] +
25 x **2 * T [3 , 0] + x * y * T [4 , 0] + y **2 * T [5 , 0]) . astype (
np . float32 )
26 y_new = np . round ( T [0 , 1] + x * T [1 , 1] + y * T [2 , 1] +
27 x **2 * T [3 , 1] + x * y * T [4 , 1] + y **2 * T [5 , 1]) . astype (
np . float32 )
28
29 # Create mask for valid coordinates
30 mask = np . logical_and ( np . logical_and ( x_new >= 0 , x_new < I . shape [1]) ,
31 np . logical_and ( y_new >= 0 , y_new < I . shape [0]) )
32

33 # Apply mapping
34 Ipoly2 = np . zeros ( I . shape , I . dtype )
35 Ipoly2 [ y_new [ mask ]. astype ( int ) , x_new [ mask ]. astype ( int ) , :] = I [ y [ mask ] , x [
mask ] , :]
36
37 ShowImages ([( " Original Image " , I ) ,
38 ( " Polynomial Mapping ( Y distortion ) " , Ipoly2 ) ])

Листинг 11: Полиномиальное отображение (Self-work [Link])

16
Рис. 23: Результат полиномиального отображения

Краткий вывод: Полиномиальное преобразование привело к нелинейному искаже-


нию изображения вдоль оси Oy. После преобразования появились области с неопределен-
ными значениями интенсивности, что характерно для такого типа отображения.

17
3.2.3 Self-work [Link] - Полиномиальное отображение с интерполяцией (Оп-
ционально)
Условие: Доработать алгоритм для заполнения пикселей с неопределенными значе-
ниями.
1 # TODO Place your solution for optional task here
2 # Fill undefined intensity values ( holes ) in the polynomial mapped image
3 # Fill holes after polynomial mapping
4
5 gray = cv . cvtColor ( Ipoly2 , cv . COLOR_BGR2GRAY )
6 hole_mask = ( gray == 0) . astype ( np . uint8 ) * 255
7
8 Ipoly2_filled = cv . inpaint ( Ipoly2 , hole_mask , 3 , cv . INPAINT_TELEA )
9
10 ShowImages ([( " Polynomial mapping " , Ipoly2 ) ,
11 ( " Filled result " , Ipoly2_filled ) ] , 2)

Листинг 12: Полиномиальное отображение с интерполяцией (Self-work [Link])

Рис. 24: Результаты заполнения пропусков после полиномиального преобразования

Краткий вывод: После применения интерполяции большинство пропусков было успеш-


но заполнено. Полученное изображение стало более цельным и визуально более коррект-
ным.

18
3.2.4 Self-work [Link] - Синусоидальное искажение по оси Oy
Условие: Реализовать синусоидальное искажение вдоль оси Oy с теми же параметра-
ми.
1 # TODO Place your solution here
2 # Create mesh grid for X , Y coordinates
3 # Distort the Y coordinate depending on X
4 # Remap with new coordinates
5 # Sinusoidal distortion along Oy
6
7 x , y = np . meshgrid ( np . arange ( I . shape [1]) , np . arange ( I . shape [0]) )
8 y_new = y + 20 * np . sin (2 * math . pi * x / 90)
9
10 Isin_y = cv . remap (I , x . astype ( np . float32 ) , y_new . astype ( np . float32 ) , cv .
INTER_LINEAR )
11
12 ShowImages ([( " Source image " , I ) ,
13 ( " Sinusoidal distortion Oy " , Isin_y ) ] , 2)

Листинг 13: Синусоидальное искажение по Oy (Self-work [Link])

Рис. 25: Синусоидальные искажения

Краткий вывод: Синусоидальное искажение вдоль оси Oy привело к периодическому


смещению пикселей по вертикали. В результате изображение приобрело волнообразную
форму.

19
3.3 Задание 2. Коррекция дисторсии
3.3.1 Self-work 2.1.1 - Бочкообразная дисторсия и коррекция
Условие: Создать искажение по формуле R
⃗ = ⃗r − 0.2 · r2⃗r + 0.32 · r4⃗r и выполнить
коррекцию.
1 # Barrel distortion : R = r - 0.2* r ^3 + 0.32* r ^5
2
3 x , y = np . meshgrid ( np . arange ( I . shape [1]) , np . arange ( I . shape [0]) )
4

5 mid = ( I . shape [1] / 2.0 , I . shape [0] / 2.0)


6 x_shift = x - mid [0]
7 y_shift = y - mid [1]
8
9 r , theta = cv . cartToPolar ( x_shift / mid [0] , y_shift / mid [1])
10

11 b0 = 1.0
12 F3 = -0.2
13 F5 = 0.32
14
15 # Distortion
16 r_dist = b0 * r + F3 * r **3 + F5 * r **5
17 u , v = cv . polarToCart ( r_dist , theta )
18 u = u * mid [0] + mid [0]
19 v = v * mid [1] + mid [1]
20
21 Ibarrel_self = cv . remap (I , u . astype ( np . float32 ) , v . astype ( np . float32 ) , cv .
INTER_LINEAR )
22
23 # Correction
24 d = 5
25 max_r = 1.5
26 Psrc = ( np . arange (d , dtype = np . float32 ) + 1) / d * max_r
27 Pdst = b0 * Psrc + F3 * Psrc **3 + F5 * Psrc **5
28
29 T = np . zeros (( d , d ) )
30 for i in range ( d ) :
31 T [: , i ] = Pdst ** ( i + 1)
32
33 F = np . matmul ( np . linalg . inv ( T ) , Psrc )
34
35 r_corr = np . zeros_like ( r )
36 for i in range ( d ) :
37 r_corr += F [ i ] * r_dist ** ( i + 1)
38
39 u_corr , v_corr = cv . polarToCart ( r_corr , theta )
40 u_corr = u_corr * mid [0] + mid [0]
41 v_corr = v_corr * mid [1] + mid [1]
42
43 Iba rrel_corr _self = cv . remap ( Ibarrel_self ,
44 u_corr . astype ( np . float32 ) ,
45 v_corr . astype ( np . float32 ) ,
46 cv . INTER_LINEAR )
47
48 ShowImages ([
49 ( " Source image " , I ) ,
50 ( " Barrel distortion " , Ibarrel_self ) ,
51 ( " Distortion correction " , Iba rrel_cor r_self )
52 ] , 3)

20
Листинг 14: Бочкообразная дисторсия и коррекция (Self-work 2.1.1)

Рис. 26: Бочкообразная дисторсия и её коррекция

Краткий вывод: Бочкообразная дисторсия была успешно смоделирована и затем


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

21
3.3.2 Self-work 2.2.1 - Подушкообразная дисторсия и коррекция
Условие: Создать искажение по формуле R
⃗ = 1.3 · ⃗r − 0.2 · r2⃗r + 0.05 · r4⃗r и выполнить
коррекцию.
1 # Pincushion distortion : R = 1.3* r - 0.2* r ^3 + 0.05* r ^5
2
3 x , y = np . meshgrid ( np . arange ( I . shape [1]) , np . arange ( I . shape [0]) )
4

5 mid = ( I . shape [1] / 2.0 , I . shape [0] / 2.0)


6 x_shift = x - mid [0]
7 y_shift = y - mid [1]
8
9 r , theta = cv . cartToPolar ( x_shift / mid [0] , y_shift / mid [1])
10

11 b0 = 1.3
12 F3 = -0.2
13 F5 = 0.05
14
15 # Distortion
16 r_dist = b0 * r + F3 * r **3 + F5 * r **5
17 u , v = cv . polarToCart ( r_dist , theta )
18 u = u * mid [0] + mid [0]
19 v = v * mid [1] + mid [1]
20
21 Ipincushion_self = cv . remap (I , u . astype ( np . float32 ) , v . astype ( np . float32 ) ,
cv . INTER_LINEAR )
22
23 # Correction
24 d = 5
25 max_r = 1.8
26 Psrc = ( np . arange (d , dtype = np . float32 ) + 1) / d * max_r
27 Pdst = b0 * Psrc + F3 * Psrc **3 + F5 * Psrc **5
28
29 T = np . zeros (( d , d ) )
30 for i in range ( d ) :
31 T [: , i ] = Pdst ** ( i + 1)
32
33 F = np . matmul ( np . linalg . inv ( T ) , Psrc )
34
35 r_corr = np . zeros_like ( r )
36 for i in range ( d ) :
37 r_corr += F [ i ] * r_dist ** ( i + 1)
38
39 u_corr , v_corr = cv . polarToCart ( r_corr , theta )
40 u_corr = u_corr * mid [0] + mid [0]
41 v_corr = v_corr * mid [1] + mid [1]
42
43 Ip i n c u s h i o n _ c o r r _ s e l f = cv . remap ( Ipincushion_self ,
44 u_corr . astype ( np . float32 ) ,
45 v_corr . astype ( np . float32 ) ,
46 cv . INTER_LINEAR )
47
48 ShowImages ([
49 ( " Source image " , I ) ,
50 ( " Pincushion distortion " , Ipincushion_self ) ,
51 ( " Distortion correction " , I p i n c u s h i o n _ c o r r _ s e l f )
52 ] , 3)

Листинг 15: Подушкообразная дисторсия и коррекция (Self-work 2.2.1)

22
Рис. 27: Подушкообразная дисторсия и её коррекция

Краткий вывод: Подушкообразная дисторсия была смоделирована и затем исправ-


лена с помощью обратного радиального преобразования. Результат коррекции показывает
восстановление формы объектов по сравнению с исходным изображением.

23
3.4 Задание 3. Сшивка изображений
3.4.1 Self-work 3.1.1 - Ручная сшивка изображений
Условие: Разделить изображение на две части и выполнить их сшивку.
1 # TODO Place your solution here
2 # Split image into two overlapping parts
3 split_point = int ( I . shape [0] / 2) + 20
4 Itop_self = I [0: split_point , : , :]
5 Ibottom_self = I [ split_point -20: , : , :] # Overlap of 20 pixels
6
7 ShowImages ([( " Top Part " , Itop_self ) ,
8 ( " Bottom Part " , Ibottom_self ) ])
9
10 # Match template from bottom of top image
11 templ_size = 20
12 templ = Itop_self [ - templ_size : , : , :]
13 res = cv . matchTemplate ( Ibottom_self , templ , cv . TM_CCOEFF )
14 min_val , max_val , min_loc , max_loc = cv . minMaxLoc ( res )
15
16 # Stitch images
17 Istitch_self = np . zeros (( Itop_self . shape [0] + Ibottom_self . shape [0] -
max_loc [1] - templ_size ,
18 I . shape [1] , I . shape [2]) , dtype = np . uint8 )
19 Istitch_self [0: Itop_self . shape [0] , : , :] = Itop_self
20 Istitch_self [ Itop_self . shape [0]: , : , :] = Ibottom_self [ max_loc [1] +
templ_size : , : , :]
21

22 ShowImages ([( " Original Image " , I ) ,


23 ( " Stitched Image " , Istitch_self ) ])

Листинг 16: Ручная сшивка изображений (Self-work 3.1.1)

Рис. 28: Верхняя часть Рис. 29: Нижняя часть

Рис. 30: Сшитое изображе-


ние

Рис. 31: Ручная сшивка изображений

Краткий вывод: Изображение было успешно разделено на две перекрывающиеся


части и затем сшито обратно. Полученный результат подтверждает корректность поиска
области перекрытия и объединения фрагментов.

24
4 Ответы на контрольные вопросы
1. Как можно повернуть изображение без использования матрицы поворота?
Ответ:

Изображение можно повернуть без явного задания матрицы поворота, если


использовать встроенные функции библиотеки OpenCV, например [Link]
вместе с [Link](). Кроме того, поворот можно реализовать через
попиксельное преобразование координат: для каждого пикселя вычисля-
ются новые координаты относительно выбранного центра поворота, после
чего выполняется интерполяция значений интенсивности. Таким образом,
даже без ручного составления матрицы поворота преобразование может
быть выполнено корректно.

2. Какое минимальное количество соответствующих пар точек необходимо


задать на исходном и искаженном изображениях для коррекции перспек-
тивных искажений?
Ответ:

Для коррекции перспективных искажений необходимо минимум 4 пары


соответствующих точек. Это связано с тем, что перспективное преобра-
зование описывается матрицей 3×3, которая имеет 8 независимых парамет-
ров (с точностью до масштаба). Четыре пары точек позволяют составить
достаточное количество уравнений для вычисления матрицы преобразова-
ния.

3. После геометрического преобразования изображения могут появиться пик-


сели с неопределенными значениями интенсивности. В чем причина и как
можно решить эту проблему?
Ответ:

Пиксели с неопределенными значениями интенсивности появляются из-за


того, что после геометрического преобразования не каждому пикселю но-
вого изображения соответствует точка исходного изображения. Это осо-
бенно характерно для перспективных, полиномиальных и других нелиней-
ных преобразований, при которых возникают “дыры” или пустые области.
Для решения этой проблемы используются методы интерполяции, напри-
мер билинейная или бикубическая интерполяция, а также методы запол-
нения пропусков, такие как inpaint. Другой подход состоит в применении
обратного преобразования, при котором для каждого пикселя выходного
изображения ищется соответствующая точка на исходном изображении.

25
5 Заключение
В ходе выполнения данной практической работы были изучены основные методы гео-
метрических преобразований изображений и их практическое применение в задачах циф-
ровой обработки изображений. Были рассмотрены как линейные преобразования, включая
сдвиг, отражение, масштабирование, поворот, скос и кусочно-линейное отображение, так и
нелинейные преобразования, такие как перспективное, полиномиальное и синусоидальное
искажения.
В практической части были реализованы алгоритмы прямого и обратного аффинного
и перспективного преобразования, выполнено моделирование полиномиальных и синусо-
идальных искажений, а также исследованы методы коррекции бочкообразной и подушко-
образной дисторсии. Кроме того, была выполнена простая ручная сшивка изображения
на основе поиска перекрывающейся области.
Выводы:

1. Геометрические преобразования позволяют эффективно изменять форму, положение


и структуру изображения в зависимости от поставленной задачи.

2. Линейные преобразования проще в реализации и анализе, тогда как нелинейные


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

3. Методы коррекции дисторсии и сшивки изображений имеют важное практическое


значение и могут использоваться для восстановления геометрии изображения и объ-
единения нескольких изображений в одно.

26

Вам также может понравиться