1. Numpy
1.1 넘파이 배열 생성
■ 넘파이 배열 생성 방법은 크게 (1) 값으로 생성 - array( ), (2) 크기와 초깃값으로 생성 - empty( ), zeros( ), ones( ), full( ) , (3) 기존 배열을 기준으로 생성 - empty_like( ), zeros_like( ), ones_like( ), full_like( ), (4) 순차적인 값으로 생성 - arrange( ), (5) 난수로 생성 - random.rand( ), random.randn( ) 이 있다.
■ 먼저, array( )로 넘파이 배열을 생성할 경우 다음과 같이 리스트를 사용해서 만들 수 있다. 이 리스트를 이용해서 배열의 차원을 설정할 수 있다.
import numpy as np
a = np.array([1, 2, 3]) # 1차원
b = np.array([[1., 2.], [3., 4.]]) # 2차원
c = np.array([[[1., 2.], [3, 4]], # 3차원
[[5, 6], [7., 8.]]])
d = np.array([1, 2, 3], dtype = np.float32)
print(a); print(a.dtype, a.shape);print()
print(b); print(b.dtype, b.shape);print()
print(c); print(c.dtype, c.shape);print()
print(d); print(d.dtype, d.shape)
```#결과#```
[1 2 3]
int32 (3,)
[[1. 2.]
[3. 4.]]
float64 (2, 2)
[[[1. 2.]
[3. 4.]]
[[5. 6.]
[7. 8.]]]
float64 (2, 2, 2)
[1. 2. 3.]
float32 (3,)
````````````
- dtype에 데이터 타입을 지정해서 넘파이 배열을 만들 수도 있다.
■ empty( ), zeros( ), ones( ), full( )을 사용할 경우 넘파이 배열의 크기나 초깃값을 지정해서 넘파이 배열을 생성할 수 있다.
■ 먼저, empty( )는 크기를 지정하면 지정한 크기에 맞게 넘파이 배열을 생성한다. 이때 배열의 값은 초기화되지 않으며 임의의 값으로 채워질 수 있다.
a = np.empty((2,3))
b = np.empty((2,3), dtype=np.int16)
print(a); print(a.dtype, a.shape);print()
print(b); print(b.dtype, b.shape)
```#결과#```
[[6.23042070e-307 1.33512376e-306 1.11261230e-306]
[7.56577399e-307 9.34600963e-307 1.05699581e-307]]
float64 (2, 3)
[[1 0 2]
[0 3 0]]
int16 (2, 3)
````````````
■ zeros( )는 크기를 지정하면 지정한 크기에 맞게 넘파이 배열을 생성하되, 배열의 값을 모두 0으로 초기화한다. ones( )도 지정한 크기에 맞게 배열을 생성하는데, zeros( )와 다르게 배열의 값을 모두 1로 초기화한다.
c = np.zeros((2,3))
d = np.ones((3,2), dtype = np.float64)
print(c); print(c.dtype, c.shape);print()
print(d); print(d.dtype, d.shape)
```#결과#```
[[0. 0. 0.]
[0. 0. 0.]]
float64 (2, 3)
[[1. 1.]
[1. 1.]
[1. 1.]]
float64 (3, 2)
````````````
■ full( )은 지정한 배열의 크기와 지정한 값을 갖는 넘파이 배열을 생성한다.
e = np.full((2,4,3), fill_value = 255, dtype = np.float64)
print(e); print(e.dtype, e.shape)
```#결과#```
[[[255. 255. 255.]
[255. 255. 255.]
[255. 255. 255.]
[255. 255. 255.]]
[[255. 255. 255.]
[255. 255. 255.]
[255. 255. 255.]
[255. 255. 255.]]]
float64 (2, 4, 3)
````````````
■ empty_like( ), zeros_like( ), ones_like( ), full_like( )와 같이 _like( )는 특정 배열과 동일한 데이터 타입과 크기를 가지는 배열을 생성할 때 사용한다. 이때, _like( ) 앞의 empty/zeros/ones/full에 따라 초기화 방식이 달라진다.
img = cv2.imread('../opencv/cat1.jpg') # OpenCV로 이미지 읽기
print(type(img)) # img의 데이터 타입
print(img.ndim) # 차원 수
print(img.shape) # 이미지 형상
print(img.size) # 전체 요소의 개수
print(img.dtype) # 데이터 타입
print(img.itemsize) # 각 요소의 바이트 크기
```#결과#```
<class 'numpy.ndarray'>
3
(145, 216, 3)
93960
uint8
1
````````````
- OpenCV에서 이미지를 읽기 위해 cv2.imread( ) 함수를 사용한다. 이때 반환되는 이미지는 넘파이 배열 데이터이다. 그러므로 다음과 같이 넘파이의 속성을 이용해 이미지의 데이터 타입이나 차원 수, 데이터 타입 등의 정보를 확인할 수 있다.
a = np.empty_like(img)
b = np.zeros_like(img)
c = np.ones_like(img)
d = np.full_like(img, 255)
print(a.dtype, a.shape)
print(b.dtype, b.shape)
print(c.dtype, c.shape)
print(d.dtype, d.shape)
```#결과#```
uint8 (145, 216, 3)
uint8 (145, 216, 3)
uint8 (145, 216, 3)
uint8 (145, 216, 3)
````````````
- 동일한 크기를 가지므로, 이 예에서는 배열 a, b, c, d의 차원 수 = 3, 전체 요소의 개수도 145 * 216 * 3 = 93960으로 img와 동일한 값을 갖게 된다.
■ arange( )는 [start, stop) 구간에서 step의 크기만큼 일정하게 떨어져 있는 값들을 array 형태로 반환하는 함수이다.
a = np.arange(3)
b = np.arange(2.0, 4.0)
print(a); print(a.dtype, a.shape);print()
print(b); print(b.dtype, b.shape)
```#결과#```
[0 1 2]
int32 (3,)
[2. 3.]
float64 (2,)
````````````
■ 넘파이의 random.rand( )와 random.randn( )는 비슷하지만, 난수를 생성하는 분포 곡선이 다르다.
- rand는 0~1 사이의 균등 분포에서 난수를 추출하고,
- randn는 평균이 0, 표준편차가 1인 표준 정규분포에서 난수를 추출한다.
a = np.random.rand(3)
b = np.random.randn(2, 3, 4)
print(a); print(a.dtype, a.shape);print()
print(b); print(b.dtype, b.shape)
```#결과#```
[0.60754627 0.77169299 0.80426406]
float64 (3,)
[[[ 0.72732247 0.65897131 0.92542387 0.08579452]
[ 0.06202853 -0.26427572 -0.43380782 -1.85511031]
[ 1.29019534 -0.06401563 1.04994217 0.72781288]]
[[-0.02672093 1.8614035 -0.66941795 0.42204103]
[-1.05825472 0.28622641 -0.90425565 -0.02993557]
[ 0.36551887 1.72813556 0.36394412 -0.55636602]]]
float64 (2, 3, 4)
````````````
1.2 이미지 생성
■ 다음과 같이 넘파이 배열로 2차원 이미지를 생성할 수 있다.
img = np.zeros((100, 100)) # 100 x 100 2차원 배열 # 검은색 이미지
cv2.imshow('Gray', img)
if cv2.waitKey(0) & 0xFF == 27:
cv2.destroyAllWindows()
img = np.zeros((100, 100)) # 100 x 100 2차원 배열 # 검은색 이미지
img[10:30, :] = 255 # 10~30행 & 모든 열에 255 할당
img[50:60, :] = 100 # 50~60행 & 모든 열에 100 할당
img[:, 30:50] = 255 # 모든 행 & 30~50열에 255 할당
img[:, 50:60] = 100 # 모든 행 & 50~60열에 255 할당
cv2.imshow('Gray', img)
if cv2.waitKey(0) & 0xFF == 27:
cv2.destroyAllWindows()
■ 다음과 같이 넘파이 배열로 3차원 이미지를 생성할 수 있다. 이때 OpenCV는 이미지를 RGB가 아닌 BGR로 표현하므로 파란색은 [B, G, R] = [255, 0 ,0], 초록색은 [B, G, R] = [0, 255 ,0], 빨간색은 [B, G, R] = [0, 0 ,255]로 나타내야 한다.
img = np.zeros((100, 100, 3)) # 100 x 100 2차원 배열 # 검은색 이미지
img[10:20, :] = [255, 0, 0] # 10~20행 & 모든 열에 파란색
img[40:50, :] = [0, 255, 0] # 40~50행 & 모든 열에 초록색
img[70:80, :] = [0, 0, 255] # 70~80행 & 모든 열에 빨간색
img[:, 40:60] = [255, 255, 255] # 모든 행 & 40~60 열에 흰색
cv2.imshow('BGR', img) # OpenCV는 이미지를 BGR로 나타낸다.
if cv2.waitKey(0) & 0xFF == 27:
cv2.destroyAllWindows()
2. Matplotlib
■ OpenCV에서 이미지를 cv2.imread( )로 읽은 다음, 이미지를 나타내기 위해 cv2.imshow( )를 이용해 창을 생성하고, 생성된 창 안에 이미지를 나타냈다. matplotlib을 이용하면 별도의 창을 생성하지 않아도 이미지를 출력할 수 있다.
import cv2
from matplotlib import pyplot as plt
img2 = cv2.imread('img1.jpg')
print(img2)
plt.imshow(img2) # 이미지 표시
plt.show()
■ 하지만, OpenCV의 색상 순서는 BGR인 반면 matplotlib의 pyplot의 색상 순서는 RGB이기 때문에 위의 그림과 같이 색상 채널이 뒤바뀌게 된다.
■ 이 문제를 해결하기 위해 다음과 같은 방법들을 사용할 수 있다.
- cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 함수를 사용해서 BGR 순서를 RGB 순서로 변환
- img[:,:,::-1]나 img[:,:,(2,1,0)]으로 이미지 컬러 채널을 뒤집기 (1번과 2번 축은 이미지의 크기를 나타내고 3번 째 축이 채널)
img2 = cv2.imread('img1.jpg')
img3 = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)
plt.imshow(img3)
plt.show()
img4 = cv2.imread('img1.jpg')
plt.imshow(img4[:,:,::-1])
plt.show()
img5 = cv2.imread('img1.jpg')
plt.imshow(img5[:,:,(2,1,0)])
plt.show()
np.array_equal(img3, img4[:,:,::-1])
```#결과#```
True
````````````
np.array_equal(img3, img5[:,:,(2,1,0)])
```#결과#```
True
````````````
'OpenCV' 카테고리의 다른 글
기하학적 변환 (1) (0) | 2024.12.16 |
---|---|
이미지 프로세싱 (3) (0) | 2024.12.15 |
이미지 프로세싱 (2) (1) | 2024.12.14 |
이미지 프로세싱 (1) (0) | 2024.12.13 |
기본 입출력 (1) | 2024.12.12 |