본문 바로가기
Robot/로봇기업

[파이썬] DAY15 openCV 이미지 출력 수정하기

by 9루트 2022. 2. 8.

영상처리를 하는 이유

데이터를 수정하거나 분석하기 위해서 영상을 처리한다. 

디지털 카메라를 통해 영상을 전자적으로 얻은 후에 컴퓨터로 영상을 처리하여 원하는 출력 영상을 얻는 기술로

주어진 목적을 달성하기 원래 영상을 새로운 영상으로 전환

컴퓨터 비전의 전처리 과정(인식 → 정보 수집, 수정)으로 물체를 인식하여 분석한다.

어떻게 인식할 것인가에 대해 다양한 메소드를 쓴다.

인공지능: 관련 있는 데이터들만 모아서 딥러닝으로 학습 시킨다.

 

영상은 2차원 함수 형태 f(x, y)로 정의되며 밝기의 값을 저장한다.

 


1. 이미지 출력하기

1. cv2로 읽고 plt로 출력

openCV (cv2) BGR 순서로 출력
matplotlib (plt) RGB 순서로 출력

openCV는 RGB가 아닌 BGR 순서로 출력되게 된다.

반면 plt은 이미지를 RGB 순서대로 출력 되므로

아래처럼 이미지를  cv2로 읽고(BGR인 상태) plt으로 출력(RGB순으로 출력)하면 이미지의 색상에 왜곡이 생긴다.

파란색이 강하게 느껴진다.

print(type(img))
print(img.shape)

를 해보니
<class 'numpy.ndarray'>
(235, 214, 3)

이 출력되는 것으로 보아 각 이미지 데이터는 넘파이 배열 데이터임을 알 수 있다.

또한 총 3개의 요소(크기, 정밀도, 채널)로 3차원으로 되어있는 데이터임을 알 수 있다.

3은 채널 부분을 의미하므로 색깔 RGB 모두를 나타내는 3채널로 구성되어있음을 알 수 있다. 

3채널로 다색 이미지로 인해 각각의 데이터를 조작할 때 다소 복잡할 수 있다.

이미지는 크기, 정밀도, 채널 세 가지 속성을 가지고 있다.
채널이 3일 경우 다색 이미지
채널이 1일 경우 단색 이미지

 

이미지의 왜곡을 없애기 위해 BGR을 RGB로 변경해주는 작업을 해준다.


2. BGR을 RGB로 변경

t_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

를 추가해준다.

 

import numpy as np
import matplotlib.pyplot as plt
import cv2
img = cv2.imread("lovelypug.jpg")
t_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
print(type(img))
print(img.shape)
#cv2.imshow(img)
plt.imshow(t_img)
plt.show()

왜곡 없이 색이 잘 나온다.

print(type(img))
print(img.shape)
print(type(t_img))
print(t_img.shape)

BGR -> RGB로 바뀔 뿐 데이터 TYPE과 SHAPE는 변경되지 않는다.<class 'numpy.ndarray'>
(235, 214, 3)

<class 'numpy.ndarray'></class 'numpy.ndarray'>
(235, 214, 3)

이 출력된다.

 

 


3. cv2로 읽고 cv2로 출력하기

cv2.imshow("puppy",img)

데이터의 이름을 반드시 추가해야한다.

창을 잠깐 열고 바로 꺼짐을 방지하기 위해 아래 코드를 추가해준다.

cv2.waitKey()

또한 기존에 열린 창들을 지워주기 위해 아래 코드를 옵션으로 추가해준다.

cv2.destroyAllWindows()

 해당 이미지의 창을 제외하고 모두 닫는다는 의미이다.

이미지에 puppy라는 이름이 매겨진다.

 

import numpy as np
import matplotlib.pyplot as plt
import cv2
img = cv2.imread("lovelypug.jpg")
cv2.imshow("puppy",img)
cv2.waitKey()
cv2.destroyAllWindows()
t_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
print(type(img))
print(img.shape)
plt.show()

 

 

 

결론

import numpy as np
import matplotlib.pyplot as plt
import cv2

openCV를 사용하려면 위에 새 줄은 디폴트 값처럼 꼭 넣자.

1) cv2로 읽고 plt으로 출력

반드시 BGR  → RGB로 변경해준 다음 출력해준다.

import numpy as np
import matplotlib.pyplot as plt
import cv2
img = cv2.imread("lovelypug.jpg")
t_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

plt.imshow(t_img)
plt.show()

 

2) cv2로 읽고 cv2로 출력

반드시 

cv2.waitKey()

를 추가해준다. 추가 안할 시 이미지가 나타났다가 바로 사라진다.

import numpy as np
import matplotlib.pyplot as plt
import cv2
img = cv2.imread("lovelypug.jpg")

cv2.imshow("puppy",img)
cv2.waitKey()
cv2.destroyAllWindows()

plt.show()

 

 

 

 

 

4. 그레이 스케일 적용하기

import numpy as np
import matplotlib.pyplot as plt
import cv2

img2 = cv2.imread("lovelypug.jpg",cv2.IMREAD_GRAYSCALE)
plt.imshow(img2)
plt.show()

 

 

print(type(img2))
print(img2.shape)

에 대한 결과는

<class 'numpy.ndarray'>
(235, 214)

로 그레이 스케일은 단채널로 이루어져있음을 알 수 있다. 크기와 형태는 동일하다. (2차원)

단채널로 이루어있을 때 장점은 데이터(픽셀의 강도: 0 - 255)를 조작하기가 쉽다.

 

 

5. 이미지 파일로 저장

cv2.imwrite("new.jpg",img2)

를 추가로 넣으면 아래와 같이 이미지 파일이 생겨난다.

그레이 스케일로 저장되지 않는다.

plt를 하면 feature 특징(색상 강도.. 등등)을 알 수 있다.

피쳐를 오픈 CV로 추출할 것인가, 딥러닝으로 추출할 것인가.

 

픽셀 정보를 가지고 데이터의 간격을 알 수 있다. 밝기의 정보들로만 경계를 구분할 수 있고 이를 피쳐로 저장한다.

색의 강도보다는 밝기의 강도로  피쳐를 정한다.

 


 

2. 이미지 가져오기

1. 그레이 스케일 다른 프로젝트에서 가져오기

사이즈가 크다 = 픽셀이 많다. 픽셀에 대한 정보가 많다.

왜 그레이 스케일로 저장이 안될까

그레이 스케일: 3채널 중에 단색만 내보낸다. 나머지 두 채널에 대한 값은 여전히 내부에서 가지고 있다.

즉 내부의 데이터들을 읽어올 때는 RGB 색상 중 그레이 색으로 뽑아온 것이다.

색안경을 씌운다고 생각하면 좋겠다.

img = cv2.imread("new.jpg",cv2.IMREAD_UNCHANGED)

으로 변경하면

 

처럼 다시 단색이 나온다.

 

 

2. 이미지 데이터 사이즈 조절

 

1) 픽셀(화소)의 크기를 조절

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread("new.jpg",cv2.IMREAD_REDUCED_GRAYSCALE_2)
print(img.shape)
plt.imshow(img)
plt.show()

(118, 107)

 

2) 이미지 크기 조절

img_50_50 = cv2.resize(img,(50, 50))

를 추가하여 아래와 같은 코드를 출력한다.

가로 세로를 고려하여 (50,50)을 넣어준다.

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread("new.jpg",cv2.IMREAD_REDUCED_GRAYSCALE_2)
print(img.shape)
plt.imshow(img)
plt.show()

img_50_50 = cv2.resize(img,(50, 50))
print(img_50_50.shape)
plt.imshow(img_50_50)
plt.show()

(118, 107)
(50, 50)

출력

 

3) 이미지 자르기

{1) 가로에 대해서 자른다.(고차원에 자를 크기 설정)

cut_img = img[:50, :] #2차원
import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread("new.jpg",cv2.IMREAD_REDUCED_GRAYSCALE_2)
print(img.shape)
plt.imshow(img)
plt.show()

img_50_50 = cv2.resize(img,(50, 50))
print(img_50_50.shape)
plt.imshow(img_50_50)
plt.show()


cut_img = img[:50, :] #2차원
plt.imshow(cut_img)
plt.show()

 

 

(2) 세로에 대해 자른다.(저차원에 자를 크기 설정)

cut_img = img[:, :50] #2차원

으로 변경해준다.


3. 이미지 데이터 추출

1. 이미지 흐리게 만들기

1) blur 이용하여 흐리게 만들기

img_b = cv2.blur(img, (5,5))

크기 조절과는 명백하게 달리 화소(픽셀)의 갯수가 변경되지 않는다.

 

 

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread("lovelypug.jpg",cv2.IMREAD_GRAYSCALE)
print(img.shape)
img_b = cv2.blur(img, (5,5))
print(img_b.shape)
plt.imshow(img,cmap = "gray")
plt.show()

(235, 214)
(235, 214)

가 출력된다.

 

img_b = cv2.blur(img, (100,100))

로 변경해주면 더 흐려진 그림의 결과가 나온다.

 

2) 직접적으로 필터 씌워서 흐리게 만들기

필터값 k를 설정해준다.

k = np.ones((5,5))/25
print(k)
img_t = cv2.filter2D(img, -1, k)
plt.imshow(img_t,cmap = "gray")
plt.show()

-1은 0.04를 기존 데이터에 -0.04 해주는 역할을 한다.

cmap는 뭐지?? gray인 부분만 출력하게 해준다.

 


 

2. 선명하게 만들어주기

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread("lovelypug.jpg",cv2.IMREAD_GRAYSCALE)
print(img.shape)

k = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]])
img_t = cv2.filter2D(img, -1, k)
plt.imshow(img_t, cmap = "gray")
plt.show()

3x3행렬의 대상을 5로 보강하여 선명하게 해주고 나머지 배경은 흐릿하게 만들어준다.

opencv 교재 추천

요즘에는 커널을 만들어서 직접적으로 필터를 입히지 않는다.

 

 


3. 진하게 대상을 강조하기

equalizeHist() 비슷하게 만들어주겠다.

평탄화 작업이라고도 한다.

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread("lovelypug.jpg",cv2.IMREAD_GRAYSCALE)
img_g = cv2.equalizeHist(img)
plt.imshow(img_g, cmap = "gray")
plt.show()

이미지가 더 진해졌다.


3. 차선 인식하기

1. 이진화(임계처리) →  객체를 강조하여 객체의 특징을 뽑아낸다.(인공지능이 물체 인식할 때 사용)

특정 색을 기준으로 극단적인 값으로 만든다.

픽셀의 강도가 크게 변화는 부분을 임계값으로 처리하여 이미지 데이터를 이진화 한다.

cv2.ADAPTIVE_THRESH_GAUSSIAN_C

상수값으로 있는 설정값 각 화소에 대한 임계값에 대한 가우시안을 기반으로 가중치의 합을 준다.

cv2.THRESH_BINARY

임계값에 대한 내용을 평균 임계값으로 설정하겠다.

 

각 픽셀에 대한 값을 10(sub_f_mean)을 기준으로

10보다 높으면 참으로 250, 낮으면 거짓으로 0으로 바꾸겠다.

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread("lovelypug.jpg",cv2.IMREAD_GRAYSCALE)
max_out_value = 255
n_size = 99
sub_f_mean = 10
img_binary = cv2.adaptiveThreshold(img, max_out_value,
                                   cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                   cv2.THRESH_BINARY,
                                   n_size,
                                   sub_f_mean)
plt.imshow(img_binary, cmap="gray")
plt.show()


2. 경계선에 대한 검출 → 객체들의 경계선으로 인식하여 객체를 찾을 때 사용한다.

더 간단한 작업이다.

 

전체 영역에서 중간값을 계산하는 메소드(각 화소들의 평균값을 계산한다.)

mean_end_v = np.median(img)

중간값에 대해 위, 아래의 임계값을 만들어준다.

lower_t = int(max(0,(1.0 - 0.33) * mean_end_v))
upper_t = int(min(255,(1.0 + 0.33) * mean_end_v))

임계값에 따라 이미지 데이터들을 분류해준다.

i_img = cv2.Canny(img, lower_t, upper_t)

전체 코드

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread("lovelypug.jpg",cv2.IMREAD_GRAYSCALE)
mean_end_v = np.median(img)
lower_t = int(max(0,(1.0 - 0.33) * mean_end_v))
upper_t = int(min(255,(1.0 + 0.33) * mean_end_v))
i_img = cv2.Canny(img, lower_t, upper_t)

plt.imshow(i_img, cmap="gray")
plt.show()

경계선들이 만들어진다.


4. Feature(특징) 뽑아내기

피쳐는 대상을 구분하는 특징점으로 경계 부분을 표시한다.

두 가지 SLAM의 방식이 있다.
CAM 영상을 기반한 SLAM - 피쳐를 이용하여 이동한 물체 인식한다. (벡터를 따라가는 알고리즘이 내부에 존재)
Lidar 센서를 이용한 SLAM 

군집합(CLUSTING 클러스트링) : 공통된 피쳐를 기준으로 데이터를 모아놓는다.

 

'Robot > 로봇기업' 카테고리의 다른 글

취업  (0) 2022.03.10
[파이썬] DAY15 네트워크  (0) 2022.02.08
[파이썬] DAY15 openCV 차선 인식하기(동영상,이미지)  (0) 2022.02.08