|
|
2. 행렬 연산할때 넘파이함수가 파이썬 함수보다 속도가 빠른 이유를 설명하라.
1. numpy는 내부적으로 C언어로 구현되어 있어 Python보다 훨씬 빠른 실행속도를 가진다.
--> numpy의 배열 연산은 C에서 직접 루프를 돌면서 최적화된 방식으로 처리되므로 python의 for-loop 기반 연산보다 수십~수천배 빠르다.
2. numpy는 반복문 없이 전체 배열에 대해 한번에 연산하는 벡터화 기법을 사용함.
--> 루프 오버헤드를 줄이고 CPU 내부의 SIMD(명령어 병렬 처리) 기능을 활요해 성능이 향상됨.
3. Numpy 배열이 Python 배열보다 배열 구조가 최적화 되어 있음
--> Python 리스튼 서로 다른 타입의 객체를 포함할 수 있고, 포인터 배열이지만 Numpy 배열은 동일한 타입의 연속적인 메모리 블록으로 구성되어 있어 훨씬 더 연산 효율이 좋음
3. 여러 개의 좌표변환을 적용할 때 변환의 순서를 변경하면 어떻게 되는가?
좌표변환을 적용할 때 변환의 순서를 변경하면 결과가 달라진다.
좌표변환은 행렬 곱셈으로 표현되므로 변환 순서를 바꾸면 최종 위치나 형태가 달라진다.
(옵션문제) 18페이지 모든 넘파이 함수를 활용하는 예제를 만들어서 기능을 확인하라. 결과값을 화면에 출력하여 함수의 기능을 반드시 확인할 것
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 | import numpy as np # numpy.array : ndarray 객체 생성 A = np.array([[1, 2, 3], [0, 1, 4], [5, 6, 0]]) print("원본 행렬 A:") print(A) # numpy.ndarray : n차원 배열 객체 print("\nA는 ndarray 객체인가? :", isinstance(A, np.ndarray)) # numpy.ndarray.shape : 차원 확인 print("A의 shape:", A.shape) # numpy.ndarray.transpose() : 전치행렬 메서드 A_T_method = A.transpose() print("\nA의 전치 (메서드):") print(A_T_method) # numpy.ndarray.T : 전치행렬 속성 A_T_attr = A.T print("\nA의 전치 (속성 .T):") print(A_T_attr) # numpy.eye : 단위행렬 생성 I = np.eye(3) print("\n단위행렬 I:") print(I) # numpy.dot : 행렬곱 수행 (A * I = A) A_dot_I = np.dot(A, I) print("\nA와 단위행렬의 곱 (np.dot):") print(A_dot_I) # numpy.matmul / @ 연산자 : 행렬곱 수행 A_matmul = A @ I print("\nA와 단위행렬의 곱 (np.matmul 또는 @):") print(A_matmul) # numpy.linalg.inv : 역행렬 계산 A_inv = np.linalg.inv(A) print("\nA의 역행렬:") print(A_inv) # numpy.ndarray 연산 : +, -, *, / B = np.ones((3, 3)) print("\n행렬 B (모든 원소 1):") print(B) print("\nA + B:") print(A + B) print("A - B:") print(A - B) print("A * B:") print(A * B) print("A / (B + 1):") # 나누기 위해 0 방지 print(A / (B + 1)) # numpy.zeros : 모든 원소가 0인 행렬 생성 Z = np.zeros((3, 3)) print("\n0으로 채운 행렬 Z:") print(Z) # numpy.sin, numpy.cos, numpy.pi : 삼각함수 계산 angles = np.array([0, np.pi/2, np.pi]) print("\n각도 (라디안):", angles) print("sin:", np.sin(angles)) print("cos:", np.cos(angles)) | cs |
4. 회전 변환 실습
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import numpy as np # x,y,z축으로 각각 (10,10,10)만큼 평행이동 T = np.array([[1,0,0,10], [0,1,0,10], [0,0,1,10], [0,0,0,1]]) X1 = np.array([1,2,3,1]) # 행벡터형태도 가능 print("원본 행렬:\n",X1) X2 = np.dot(T,X1) print("평행이동 후 행렬:\n",X2) Tinv = np.linalg.inv(T) # 역변환 행렬 X1 = np.dot(Tinv,X2) print("다시 원래의 점으로 변환 :\n",X1) | cs |
5. 평행이동, 크기변환, 회전변환 실습
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 | import numpy as np # x,y,z축으로 각각 (10,10,10)만큼 평행이동 T = np.array([[1,0,0,10], [0,1,0,10], [0,0,1,10], [0,0,0,1]]) # x,y,z축으로 각각 (5,5,5)만큼 크기변환 T2 = np.array([[5,0,0,0], [0,5,0,0], [0,0,5,0], [0,0,0,1]]) # x축으로 반시계방향으로 90도 만큼 회전변환 T3 = np.array([[1,0,0,0], [0,np.cos(np.pi/2),-np.sin(np.pi/2),0], [0,np.sin(np.pi/2),np.cos(np.pi/2),0], [0,0,0,1]]) X1 = np.array([1,2,3,1]) # 행벡터형태도 가능 print("원본 행렬:\n",X1) #행렬곱 (회전행렬 @ 크기변환 @ 평행이동) result_T=np.dot(T3,np.dot(T2,T)) X2=np.dot(result_T,X1) print("result:\n",X2) T1inv = np.linalg.inv(T) # 평행이동 역변환 행렬 T2inv = np.linalg.inv(T2) # 크기변환 역변환 행렬 T3inv = np.linalg.inv(T3) # 회전변환 역변환 행렬 result_Tinv=T1inv@T2inv@T3inv # 역변환 행렬 행렬곱 X1=np.dot(result_Tinv,X2) print("다시 원래의 점으로 변환 :\n",X1) | cs |
6. 3D 회전변환 실습1
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 | import open3d as o3d import numpy as np # 초기 점 (1, 0, 0)에 구체 생성 sphere_init = o3d.geometry.TriangleMesh.create_sphere(radius=0.05) sphere_init.translate([1, 0, 0]) sphere_init.paint_uniform_color([0, 0, 1]) # 파란색 (원래 점) p = np.array([1, 0, 0, 1]) theta = np.pi / 2 # 회전 행렬들 Tz = 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] ]) Tx = 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] ]) Ty = 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] ]) # 회전 적용: Z → X → Y p1 = Tz @ p p2 = Tx @ p1 p3 = Ty @ p2 final_pos = p3[:3] # 회전 결과 위치에 구체 생성 sphere_rotated = o3d.geometry.TriangleMesh.create_sphere(radius=0.05) sphere_rotated.translate(final_pos) sphere_rotated.paint_uniform_color([1, 0, 0]) # 빨간색 (회전 후 점) # 좌표축 생성 axis = o3d.geometry.TriangleMesh.create_coordinate_frame(size=0.5, origin=[0, 0, 0]) # 시각화 o3d.visualization.draw_geometries([sphere_rotated,sphere_init, axis]) | cs |
점(1,0,0)을 z축으로 90로 회전하면 (0,1,0), 이점을 다시 x축으로 90도 회전하면 (0,0,1), 그다음 y축으로 90도 회전을 또 하면 (1,0,0)으로 다시 원본 점으로 돌아온다.
그래서 사진에는 빨간공 하나만 보이지만 실제는 파란공과 빨간공이 겹쳐서 그려져 있다.
7. 3D 회전변환 실습1
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 | import open3d as o3d import numpy as np # 초기 점 (1, 0, 0)에 구체 생성 sphere_init = o3d.geometry.TriangleMesh.create_sphere(radius=0.05) sphere_init.translate([1, 0, 0]) sphere_init.paint_uniform_color([0, 0, 1]) # 파란색 (원래 점) p = np.array([1, 0, 0, 1]) theta = np.pi / 4 # 회전 행렬들 Tz = 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] ]) Tx = 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] ]) Ty = 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] ]) # 회전 적용: Z → X → Y p1 = Tz @ p p2 = Tx @ p1 p3 = Ty @ p2 final_pos = p3[:3] # 회전 결과 위치에 구체 생성 sphere_rotated = o3d.geometry.TriangleMesh.create_sphere(radius=0.05) sphere_rotated.translate(final_pos) sphere_rotated.paint_uniform_color([1, 0, 0]) # 빨간색 (회전 후 점) # 좌표축 생성 axis = o3d.geometry.TriangleMesh.create_coordinate_frame(size=0.5, origin=[0, 0, 0]) # 시각화 o3d.visualization.draw_geometries([sphere_rotated,sphere_init, axis]) | cs |