|
|
행렬 연산할 때 넘파이 함수가 파이썬 함수보다 속도가 빠른 이유를 설명하라.
NumPy 함수는 내부가 C로 구현되어 있음
Python 언어로 구현된 것과 C언어로 구현되는 것은 연산 처리에서 속도 차이가 나게 됨
Python은 인터프리터 언어임
> 소스코드를 한 줄 한 줄 읽어가며 명령을 바로 처리하는 프로그램
> 번역과 실행이 실시간으로 동시에 이루어짐
반면 C언어는 컴파일된 코드가 계산을 처리하는 방식
> 이미 기계어로 번역해서 따로 저장되어 있음
> 바로 실행에 들어가서 Python 언어보다 빠름
여러 개의 좌표변환을 적용할 때 변환의 순서를 변경하면 어떻게 되는가?
좌표변환의 순서를 바꾸면 결과가 달라짐
만약 좌표변환을 회전 후 이동¹을 시킨 결과와 이동 후 회전²을 시킨 결과를 비교해보면 됨
변환 순서가 회전 후 이동인 경우에는 기준축을 중심으로 회전하고 나서 위치를 이동 ¹ 하게 되고
이동 후 회전인 경우에는 기준축이 아닌 위치에서 회전 ² 하기 때문에 경로가 달라짐
두 가지를 이용해 예시를 적용해보면,
점 P = (1, 0, 0)일 때, 회전을 z축 기준으로 90도, 이동을 (1, 0, 0) 한다고 가정
¹의 경우 (0, 0, 90) z축 회전 >> P = (0, 1, 0)
다음 이동을(1, 0, 0) 만큼 하면 P = (1, 1, 0)
²의 경우 (1, 0, 0) 이동 >> P = (2, 0, 0)
다음 회전을 (0, 0, 90) z축 회전하면 P = (0, 2, 0)
결과가 아예 달라지기 때문에 순서를 변경하지 않아야 함
Numpy를 이용하여 점 (1, 2, 3)을 x축 기준으로 90도 회전 > 5배 확대
> x, y, z축으로 (10, 10, 10)만큼 평행이동 후 점을 구하라.
(위 문제에서 변환 후 점을 다시 원래의 점으로 변환해보시오.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | import numpy as np P = np.array([[1], [2], [3], [1]]) # 4×1 theta = np.pi / 2 # X축 기준 90도 회전 행렬 (라디안 단위) Rx = np.array([ [1, 0, 0, 0], [0, np.cos(theta), -np.sin(theta), 0], [0, np.sin(theta), np.cos(theta), 0], [0, 0, 0, 1] ]) # 5배 확대 행렬 S = np.array([ [5, 0, 0, 0], [0, 5, 0, 0], [0, 0, 5, 0], [0, 0, 0, 1] ]) # (10, 10, 10) 평행이동 행렬 T = np.array([ [1, 0, 0, 10], [0, 1, 0, 10], [0, 0, 1, 10], [0, 0, 0, 1] ]) step1 = np.matmul(Rx, P) # 회전 step2 = np.matmul(S, step1) # 확대 result = np.matmul(T, step2) # 이동 print("최종 변환된 점:", result[:3].flatten()) #################################################### #역변환 과정 # 평행이동 역행렬: (−10, −10, −10) T_inv = np.array([ [1, 0, 0, -10], [0, 1, 0, -10], [0, 0, 1, -10], [0, 0, 0, 1] ]) # 확대 역행렬: 1/5 배 S_inv = np.array([ [1/5, 0, 0, 0], [0, 1/5, 0, 0], [0, 0, 1/5, 0], [0, 0, 0, 1] ]) # 회전 역행렬: -90도 theta_inv = -theta Rx_inv = np.array([ [1, 0, 0, 0], [0, np.cos(theta_inv), -np.sin(theta_inv), 0], [0, np.sin(theta_inv), np.cos(theta_inv), 0], [0, 0, 0, 1] ]) step_r1 = np.matmul(T_inv, result) step_r2 = np.matmul(S_inv, step_r1) ori = np.matmul(Rx_inv, step_r2) print("역변환 후 점:", ori[:3].flatten()) | cs |
Numpy를 이용하여 점 (1, 2, 3)을 x, y, z축으로 (10, 10, 10)만큼 평행이동 > 5배 확대
> x축 기준으로 90도 회전 후 점을 구하라.
(위 문제에서 변환 후 점을 다시 원래의 점으로 변환해보시오.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | import numpy as np P = np.array([[1], [2], [3], [1]]) # 4×1 theta = np.pi / 2 # X축 기준 90도 회전 행렬 (라디안 단위) Rx = np.array([ [1, 0, 0, 0], [0, np.cos(theta), -np.sin(theta), 0], [0, np.sin(theta), np.cos(theta), 0], [0, 0, 0, 1] ]) # 5배 확대 행렬 S = np.array([ [5, 0, 0, 0], [0, 5, 0, 0], [0, 0, 5, 0], [0, 0, 0, 1] ]) # (10, 10, 10) 평행이동 행렬 T = np.array([ [1, 0, 0, 10], [0, 1, 0, 10], [0, 0, 1, 10], [0, 0, 0, 1] ]) step1 = np.matmul(T, P) # 이동 step2 = np.matmul(S, step1) # 확대 result = np.matmul(Rx, step2) # 회전 print("최종 변환된 점:", result[:3].flatten()) #################################################### #역변환 과정 # 평행이동 역행렬: (−10, −10, −10) T_inv = np.array([ [1, 0, 0, -10], [0, 1, 0, -10], [0, 0, 1, -10], [0, 0, 0, 1] ]) # 확대 역행렬: 1/5 배 S_inv = np.array([ [1/5, 0, 0, 0], [0, 1/5, 0, 0], [0, 0, 1/5, 0], [0, 0, 0, 1] ]) # 회전 역행렬: -90도 theta_inv = -theta Rx_inv = np.array([ [1, 0, 0, 0], [0, np.cos(theta_inv), -np.sin(theta_inv), 0], [0, np.sin(theta_inv), np.cos(theta_inv), 0], [0, 0, 0, 1] ]) step_r1 = np.matmul(Rx_inv, result) # 회전 step_r2 = np.matmul(S_inv, step_r1) # 확대 ori = np.matmul(T_inv, step_r2) # 이동 print("역변환 후 점:", ori[:3].flatten()) | cs |
Numpy를 이용하여 점 (1,0,0)을 z축을 기준으로 90도 회전 -> x축으로 90도 회전
-> y축으로 90도 회전 후 점을 구하라.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | import numpy as np P = np.array([[1], [0], [0], [1]]) # 90도 (라디안) theta = np.pi / 2 # Z축 회전 행렬 Rz = np.array([ [np.cos(theta), -np.sin(theta), 0, 0], [np.sin(theta), np.cos(theta), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]) # X축 회전 행렬 Rx = np.array([ [1, 0, 0, 0], [0, np.cos(theta), -np.sin(theta), 0], [0, np.sin(theta), np.cos(theta), 0], [0, 0, 0, 1] ]) # Y축 회전 행렬 Ry = np.array([ [np.cos(theta), 0, np.sin(theta), 0], [0, 1, 0, 0], [-np.sin(theta), 0, np.cos(theta), 0], [0, 0, 0, 1] ]) step1 = np.matmul(Rz, P) step2 = np.matmul(Rx, step1) P_rotated = np.matmul(Ry, step2) print("회전된 점:", P_rotated[:3].flatten()) ############################################## # 역변환 (각 축에 대해 -90도 회전) theta_inv = -theta # 역 Z축 회전 Rz_inv = np.array([ [np.cos(theta_inv), -np.sin(theta_inv), 0, 0], [np.sin(theta_inv), np.cos(theta_inv), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]) # 역 X축 회전 Rx_inv = np.array([ [1, 0, 0, 0], [0, np.cos(theta_inv), -np.sin(theta_inv), 0], [0, np.sin(theta_inv), np.cos(theta_inv), 0], [0, 0, 0, 1] ]) # 역 Y축 회전 Ry_inv = np.array([ [np.cos(theta_inv), 0, np.sin(theta_inv), 0], [0, 1, 0, 0], [-np.sin(theta_inv), 0, np.cos(theta_inv), 0], [0, 0, 0, 1] ]) step_r1 = np.matmul(Ry_inv, P_rotated) step_r2 = np.matmul(Rx_inv, step_r1) P_recovered = np.matmul(Rz_inv, step_r2) print("역변환 후 원래 점:", P_recovered[:3].flatten()) | cs |
왜 90도씩 회전해도 같은 점이 나오는지?
1. 처음 점 P = (1, 0, 0)
2. z축 90도 회전 = (0, 1, 0)
3. x축 90도 회전 = (0, 0, 1)
4. y축 90도 회전 = (1, 0, 0)
3D 시각화 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # PointCloud로 시각화 # 각 점을 PointCloud로 생성 pcd_origin = o3d.geometry.PointCloud() pcd_origin.points = o3d.utility.Vector3dVector([P[:3, 0]]) pcd_origin.colors = o3d.utility.Vector3dVector([[0, 0, 1]]) # 파랑 (원래 위치) pcd_rotated = o3d.geometry.PointCloud() pcd_rotated.points = o3d.utility.Vector3dVector([P_rotated[:3, 0]]) pcd_rotated.colors = o3d.utility.Vector3dVector([[1, 0, 0]]) # 빨강 (세번 회전 후 위치) pcd_recovered = o3d.geometry.PointCloud() pcd_recovered.points = o3d.utility.Vector3dVector([P_recovered[:3, 0]]) pcd_recovered.colors = o3d.utility.Vector3dVector([[0, 1, 0]]) # 초록 (다시 역변환 된 위치) axis = o3d.geometry.TriangleMesh.create_coordinate_frame(size=0.5) o3d.visualization.draw_geometries([axis, pcd_origin, pcd_rotated, pcd_recovered]) | cs |
> 복구가 잘 되어서 초록점은 보이지 않음, 또한 파란점=빨간점 때문에 보이지 않음
Numpy를 이용하여 점 (1,0,0)을 z축을 기준으로 45도 회전 -> x축 으로 45도 회전
-> y축으로 45도 회전 후 점을 구하라.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | import numpy as np P = np.array([[1], [0], [0], [1]]) # 45도 (라디안) theta = np.deg2rad(45) # Z축 회전 행렬 Rz = np.array([ [np.cos(theta), -np.sin(theta), 0, 0], [np.sin(theta), np.cos(theta), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]) # X축 회전 행렬 Rx = np.array([ [1, 0, 0, 0], [0, np.cos(theta), -np.sin(theta), 0], [0, np.sin(theta), np.cos(theta), 0], [0, 0, 0, 1] ]) # Y축 회전 행렬 Ry = np.array([ [np.cos(theta), 0, np.sin(theta), 0], [0, 1, 0, 0], [-np.sin(theta), 0, np.cos(theta), 0], [0, 0, 0, 1] ]) step1 = np.matmul(Rz, P) step2 = np.matmul(Rx, step1) P_rotated = np.matmul(Ry, step2) print("회전된 점:", P_rotated[:3].flatten()) ##############################################333 # 역변환 theta_inv = -theta # 역 Z축 회전 Rz_inv = np.array([ [np.cos(theta_inv), -np.sin(theta_inv), 0, 0], [np.sin(theta_inv), np.cos(theta_inv), 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]) # 역 X축 회전 Rx_inv = np.array([ [1, 0, 0, 0], [0, np.cos(theta_inv), -np.sin(theta_inv), 0], [0, np.sin(theta_inv), np.cos(theta_inv), 0], [0, 0, 0, 1] ]) # 역 Y축 회전 Ry_inv = np.array([ [np.cos(theta_inv), 0, np.sin(theta_inv), 0], [0, 1, 0, 0], [-np.sin(theta_inv), 0, np.cos(theta_inv), 0], [0, 0, 0, 1] ]) step_r1 = np.matmul(Ry_inv, P_rotated) step_r2 = np.matmul(Rx_inv, step_r1) P_recovered = np.matmul(Rz_inv, step_r2) print("역변환 후 원래 점:", P_recovered[:3].flatten()) | cs |