본문 바로가기
Matlab

[이미지처리] 1. 이미지 파일(.jpg) 읽고 다루기 (매트랩의 각종 함수)

by 두재 2019. 6. 9.

매트랩에서는 음성뿐 아니라 이미지 파일에 관한 수많은 함수들이 존재합니다.


함수들에는 이미지 읽기, 쓰기, 회전, 크기 변환 등이 있습니다. 어차피 매트랩에서 이미지를 행렬을 생각하기 때문에 행렬에서 할 수 있는 수많은 변환들은 모두 적용 가능하고 대부분은 기본 함수로 존재합니다.

1. imwrite : 이미지 읽기 (이 결과는 웬만해서는 3차원 행렬로 나옵니다. 가로픽셀*세로픽셀*3 이며, 3은 각각 R, G, B를 의미합니다. 한 픽셀마다 R, G, B값이 3차원 한 줄로 기록되는거죠.)

사용은 쉽게 아래와 같이 합니다. im2double은 필수는 아니며 이 함수를 사용하면 변수형이 double형으로 변환되고 사용하지 않는다면 uint8 과 같은 정수형으로 나올거예요. 필수는 아닙니다.

img = im2double(imread('IMG_0176.jpg'))

사진을 입력받고 R, G, B 각각만을 출력시키면 아래 사진들과 같습니다. 아래의 3개의 사진이 합쳐진다면 위쪽 사진처럼 되는 거죠. 모니터 옆에 놓고 자주 사용하는 카카오 미니 인공지능 스피커를 찍어봤습니다. 라이언이 노란색이다 보니 빨강과 초록 채널에서는 밝은데 파란색에서는 어두운 것을 볼 수 있습니다.

카카오 미니 인공지능 스피커 사진

 

R, G, B 각 채널에서의 사진

 

2. imresize : 이미지의 크기를 조절합니다. 비율을 설정하여 그 비율로 확대를 하거나 축소를 할 수도 있고, 가로 세로의 크기를 지정하여 그 크기가 되도록 크기를 조절할 수도 있습니다. 또한 어떤 보간 방식을 쓸지도 정할 수 있습니다. 함수는 아래와 같이 사용합니다.

img = imresize(img,0.25)
img = imresize(img,[600,800])

코드에서 첫 줄은 0.25배를 시킨다는 것으로 4분의 1배로 축소시키는 것이고, 두 번째 줄은 600*800의 픽셀 개수를 가지도록 이미지의 크기를 조절합니다. 확대 축소와는 약간 다른 개념이고 이름에 맞게 re-size 하는 것이죠. 이 함수는 아마 매번 사용하시게 될 것 같은데, 사진의 크기를 조절하거나 확장자를 변환하는 프로그램들이 있지만 이러한 기능들을 매트랩에서도 간편하게 할 수 있고, 하시게 된다면 imresize를 사용하게 될 것입니다. 확장자를 변환하는 것은 조금 후에 설명하도록 하겠습니다.

제가 찍은 라이언 사진의 경우 아이폰에서 찍은 사진이 약 1200만 화소인 것 같은데, 매트랩에서 4032*3024*3의 배열로 다루고 있습니다. 이 경우 약 3천에서 4천만개의 원소를 가지는 배열을 컴퓨터가 연산해야 하는데, 제 컴퓨터와 같은 경우 (CPU는 i5, GPU는 GTX1060-6GB를 사용합니다.) 연산에 시간이 오래 걸립니다. 우선 저 크기의 배열을 가지는 사진을 읽는 것부터 시간이 약 1분에서 2분 정도 걸려 다운스케일링(Downscaling, 사진의 비율을 유지하며 전체 크기를 작게 축소하는 것)을 하는 것이 맞다고 생각했습니다.

4분의 1배로 축소시켰고, 결과는 아래 사진과 같습니다. 4032*3024의 사진이 1008*756으로 줄었습니다. 처음 사진에서 순서가 바뀐 이유는 중간에서 사진을 90도 돌리는 과정이 있었기 때문입니다.

크기가 각각 4분의 1로 줄었습니다

 

 

3. imrotate : 2번 과정에서 생략했던 이미지 회전입니다. 90도, 180도 뿐 아니라 어떠한 각도로 모두 회전 가능합니다.

img = imrotate(img, 30)
imshow(img)

위 코드를 실행할 경우 반시계 방향으로 30도 만큼 회전되어 나오며, 행렬의 크기를 그만큼 늘려주고, 빈칸을 0으로 만들어주는 작업을 매트랩이 알아서 실행합니다. 결과부터 보면 아래와 같습니다. 2번 과정에서는 제가 imrotate(img, -90)라는 코드를 통하여 음수의 각도로 회전시키는, 즉 시계 방향으로 90도만큼 돌렸었습니다.

반시계 방향으로 30도만큼 회전

4. imshow : 3번 과정의 코드에도 있는데, 사진을 보여줍니다. 이 함수를 사용하지 않으면 이미지들을 정수형이든, 실수형이든, 복소수형이든 숫자들의 배열로만 볼 수 있는데 imshow를 통하여 흑백의 Grayscale이미지를 얻거나 RGB 이미지를 눈으로 확인할 수 있습니다. 흑백인지, 컬러인지는 매트랩이 구분 하는데, 2차원 배열이면 흑백이고, 3차원 배열이고 3개의 층으로 이루어져있다면 자동으로 RGB 컬러 이미지를 보여줍니다.

 

5. imwrite : 마지막으로 이미지를 파일로 저장하는 함수입니다. 처음에 말했었던 이미지의 확장자를 바꿀 수도 있다고 한 부분이 이 부분입니다. 방법은 간단한데, 파일 이름뒤에 원하는 확장자로 끝을 내면, 매트랩이 알아서 그렇게 변환해줍니다. 코드는 아래와 같습니다.

imwrite(img, 'test.png')

위는 img라는 배열에 저장되어 있는 데이터(사진)을 test.png라는 이름으로 저장한다는 것입니다. 아니면 아래와 같이 쓸 수도 있겠죠.

 

번외) cat 함수와 배열 다루기

imwrite(cat(3,img(:,:,1),zeros(1008,756),zeros(1008,756)),'R.jpg')

위 코드는 이 포스트의 윗 부분에서 보여드린 라이언의 세 가지 채널 중 Red 부분을 R.jpg 로 저장한 것입니다. 

복잡해 보일 수 있지만 하나하나씩 생각해보면 됩니다. 우선 imwrite가 제일 바깥이니 무엇을 저장하려고 하는지 봅시다. 보니까 행렬이 들어가야 할 자리에 cat이 있습니다. 전체적인 구조가 현재 cat(3, 무엇1, 무엇2, 무엇3)이네요.

cat(3, A, B, C)

위 코드는 concatination에서 따온 것으로 행렬을 나란히 붙이는 것을 의미합니다. 3이 의미하는 바는 3차원으로 붙이겠다는 것입니다. 이 경우 2차원 배열인 A, B, C를 나란히 포개 3차원으로 만들겠다는 것을 의미합니다. 그러면 위에서 저 cat 부분은 img( : , : , 1), zeros(1008, 756), zeros(1008,756) 이 3개를 붙이겠다는 것이고 아까 제가 설명드린 바에 의하면 이미지라는 것이 R, G, B 의 3개의 층으로 이루어져 있다고 했습니다. 즉 여기서 저 세 개는 각각 R, G, B를 의미하는 것입니다.

G와 B는 zeros로 행렬을 만들었기 때문에 그냥 가로 세로 길이만 맞춰줬을 뿐 0으로 가득 차 있고, img( : , : , 1)이 결국 R을 의미한다는 뜻으로 해석 가능합니다. 이는 원래 img가 3차원 배열로 정해져 있고 3번째 배열이 의미하는 것이 1, 2, 3 번째가 R, G, B를 의미한다고 했으니 3번째에 1이 있는 것이 맞겠죠. 그리고 : 만 쓴다면, 배열의 인덱싱에서 그 차원의 모든 원소를 모두 뽑는다는 것입니다. 지금은 1번째 2번째 차원에 : 이 들어가 있으니 가로 세로 픽셀을 모두 보겠다는 거죠. 즉 img( : , : , 1)은 1008*756의 2차원 배열인데, img의 R값을 가지고 있겠죠.

 


이렇게 매트랩에서 사용할 수 있는 몇 가지 이미지 관련 함수들을 보았습니다. 

다음에는 이미지에 필터를 씌워보도록 하겠습니다. 더 자세하게는 공간 필터(Spatial filter)입니다.