IDL/Image Processing

ROT 함수 소개

이상우_idl 2022. 3. 16. 14:03
728x90
반응형

오늘 소개할 ROT 함수는 IDL에서 지원되는 배열 처리 함수들 중 하나입니다. 사실 원래는 배열 처리 기능을 수행하는 함수들 중 하나이긴 하지만, 그 특성상으로 보면 오히려 이미지 처리 기능의 함수에 더 가까운 성격이라고 봐도 될 것 같습니다. 그럴만도 한 것이 IDL 도움말에서 이 함수에 관한 내용을 찾아보면 첫 문장이 "The ROT function rotates an image by an arbitrary amount"입니다. 즉 이미지를 임의로 회전시키는 기능을 수행한다는 의미로 보면 됩니다. 다만 제가 알기로는 이 ROT 함수는 IDL 사용자들 사이에서도 그리 잘 알려지거나 널리 사용되는 편은 아닌 것 같습니다. 그래도 잘 알아두면 나름 쏠쏠하게 사용할 수 있는 함수일 것 같아서 이번 기회에 소개해보고자 합니다. 좀전에 언급했던 IDL 도움말에서의 ROT 함수에 관한 내용을 보면 앞부분 문장이 다음과 같습니다.

 

The ROT function rotates an image by an arbitrary amount. At the same time, it can magnify, demagnify, and/or translate an image.

 

즉 ROT 함수는 이미지 배열을 임의의 각도로 회전시키는 기능을 하는 것 뿐 아니라 확대, 축소, 이동의 기능까지도 다 포함하고 있다는 의미입니다. 그러면 예제와 함께 이러한 기능들을 순차적으로 살펴보도록 하겠습니다. 먼저 예제로 사용할 이미지는 JPG 파일로부터 읽어오고자 합니다. 이 JPG 파일에는 605x806 크기의 RGB 이미지가 포함되어 있으며, 여러분도 받으실 수 있도록 아래에 첨부하였습니다.

 

parking.jpg
0.42MB

 

그러면 먼저 이 파일을 이미지 배열로 읽어온 다음 바로 표출을 해봅시다. 그 과정은 다음과 같습니다.

 

READ_JPEG, 'parking.jpg', img, /GRAY
win0 = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)
i0 = IMAGE(img, /CURRENT)

 

여기서는 READ_JPEG 명령을 사용하여 JPG 파일을 읽어서 그 데이터를 img라는 배열로 가져왔는데, 이 때 /GRAY 키워드를 사용하였습니다. 그 이유는 대상 JPG 파일을 /GRAY 키워드 없이 그냥 읽으면 RGB 이미지 배열(3x605x806)이 되는데, 오늘 우리가 사용할 ROT 함수에서는 단색광 이미지에 해당되는 2차원 배열만 받을 수 있기 때문에(여기서는 605x806) 굳이 이렇게 /GRAY 키워드를 함께 사용하여 읽었습니다. 어쨌든 이 과정에 의하여 표출된 대상 이미지의 모습은 다음과 같습니다.

 

 

이제 ROT 함수를 사용하여 처리를 해봅시다. 첫번째 처리 예제는 다음과 같습니다.

 

img_f = ROT(img, 45)

 

이렇게 하면 이미지를 45도만큼 시계 방향으로 회전시키고 그 결과를 img_f라는 배열로 얻게 됩니다. 다음과 같이 별도의 그래픽창을 열고 그 결과를 표출해봅시다.

 

win1 = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)
i1 = IMAGE(img_f, /CURRENT)

 

그 모습은 다음 그림과 같습니다.

 

 

이 모습을 보면 시계 방향의 45도 회전은 잘 수행이 된 것을 볼 수 있습니다. 다만 회전을 시키다보니 의미없는 공백이 발생할 수 밖에 없는데, 위 그림에서도 좌측 상단/하단 및 우측 상단/하단에 그런 부분이 발생하였습니다. 이런 공백 영역에 대해서는 MISSING 키워드를 사용하여 별도로 처리할 수가 있는데 예를 들어 다음과 같이 처리해봅시다.

 

img_f = ROT(img, 45, MISSING=0)

 

이렇게 하면 회전에 의하여 어쩔 수 없이 발생하는 무의미한 공백 영역에 존재하는 픽셀들에 대하여 그 값을 0으로 일괄 처리하게 됩니다. 그 결과는 다음 그림과 같습니다.

 

 

이와 같이 일괄적으로 검은색으로 보이게 되는데 그 이유는 이미지 표출에서 사용된 디폴트 컬러테이블인 0번 컬러테이블에서는 0이란 값이 검은색이기 때문입니다. 이와 같이 회전에 의하여 발생하는 공백에 대한 처리를 위하여 MISSING 키워드에 특정한 값을 부여하면 그 값에 해당되는 색상으로 처리가 됩니다. 물론 그 색상은 컬러테이블에 따라 달라집니다. 따라서 차라리 이런 공백 영역에 대하여 그 화소값들을 일괄적으로 NaN으로 처리하여 아예 보이지도 않게 할 수도 있습니다. 그 방법은 다음과 같습니다.

 

img_f = ROT(FLOAT(img), 45, MISSING=!values.f_nan)

 

이와 같이 MISSING 키워드에 대하여 NaN에 해당되는 !values.f_nan 값을 부여하는 것입니다. 다만 이 방법의 효과가 제대로 나타나도록 하기 위하여 배열 img에 대하여 FLOAT 함수를 적용하여 실수형으로 변환된 상태로 처리되도록 하였습니다. 그 이유는 MISSING 키워드에 부여한 !values.f_nan이 실수형이기 때문에 이러한 처리 방법은 실수형 배열에 대해서만 효과가 있기 때문입니다. 어쨌든 그 결과를 표출해보면 다음과 같습니다.

 

 

이와 같이 회전에 의하여 발생한 공백 영역에는 아예 유의미한 픽셀값이 존재하지 않게 됩니다. 또한 ROT 함수에서는 확대 또는 축소도 가능합니다. 이를 위해서는 배율에 해당되는 값을 각도 값 바로 뒤에 이어서 적어주면 됩니다. 예를 들면 다음과 같습니다.

 

img_f = ROT(FLOAT(img), 45, 2, /INTERP, MISSING=!values.f_nan)

 

이렇게 하면 45도 회전을 시킴과 동시에 2배 확대된 결과를 얻게 됩니다. 그 모습은 다음과 같습니다.

 

 

이 과정에서는 /INTERP 키워드를 함께 사용하여 확대의 과정에서 Bilinear Interpolation 기법이 적용되도록 하였습니다. 그러면 좀 더 부드러운 결과 이미지를 얻을 수 있습니다. 지금까지의 예제들에서는 모두 시계 방향 45도 회전을 적용하였는데, 회전의 기준점은 이미지의 한가운데였습니다. 즉 다음 그림에서 보는 바와 같이 이미지의 한가운데 지점(빨간색으로 표시)을 기준으로 한 회전이 적용되었습니다.

 

 

ROT 함수에서는 이와 같이 대상 이미지의 한가운데 지점을 기준으로 회전시키는 것이 디폴트 설정입니다. 물론 이러한 회전의 기준점을 따로 설정하는 것도 가능합니다. 예를 들어 이미지의 좌측 하단 구석 지점을 기준으로 시계 방향 45도 회전을 시키고자 한다면, 새로운 기준점의 좌표인 (0, 0)을 다음과 같이 추가하여 적어주면 됩니다.

 

img_f = ROT(FLOAT(img), 45, 1, 0, 0, /INTERP, MISSING=!values.f_nan)

 

이와 같이 ROT 함수에 대하여 대상배열, 배율, 기준점 좌표값들의 순서대로 인수들을 적어줘야 합니다. 그런데 이렇게만 했을 경우의 결과는 다음 그림과 같습니다.

 

 

분명히 새로운 기준점에 대하여 회전이 적용된 것은 맞는 것 같은데 그 위치 자체가 중심으로 옮겨진 듯한 모습이 되는데요. 우리의 예상은 회전의 기준점이 원래 위치에 그대로 있는 모습인데, 실제 결과는 그렇지는 않은 상황입니다. 사실 여기서는 한가지 요소를 더 추가해줘야 하는데 바로 /PIVOT 키워드입니다. 즉 다음과 같이 /PIVOT 키워드도 함께 사용해주는 것이 필요합니다.

 

img_f = ROT(FLOAT(img), 45, 1, 0, 0, /PIVOT, /INTERP, MISSING=!values.f_nan)

 

만약 /PIVOT 키워드를 사용하지 않으면 앞선 결과에서와 같이 회전의 기준점이 결과에서는 중심 부분으로 매칭이 됩니다. 따라서 /PIVOT 키워드를 사용함으로써 원본 이미지에서의 회전의 기준점 좌표가 결과 이미지에서도 동일하게 적용되도록 처리할 수 있습니다. 그 결과는 다음 그림과 같습니다.

 

 

ROT 함수를 사용하는 방법은 대략 이와 같습니다. 당연한 얘기지만 회전의 각도 및 기준점 좌표 등은 임의로 설정할 수 있으므로 여러분들도 다양한 값들을 적용하여 테스트해보시면 좋을 것 같습니다. 참고로 회전의 기준 좌표를 (200, 300)으로 하여 시계 방향으로 60도 회전시키는 과정 및 결과는 다음과 같습니다. 회전의 기준점 좌표도 함께 표시하였습니다.

 

img_f = ROT(FLOAT(img), 60, 1, 200, 300, /PIVOT, /INTERP, MISSING=!values.f_nan)
sym = SYMBOL(200, 300, 'circle', SYM_COLOR='red', /SYM_FILLED, /DATA)

 

반응형