클리핑(Clipping) 기법은 어떤 배열을 대상으로 하여 배열 내 모든 값들 중 특정한 범위 내에 속하는 것들은 그대로 살리고 범위 바깥에 속하는 것들은 범위 경계값으로 대체하는 기법입니다. 주로 2차원 이미지 배열에 대하여 적용하는 경우가 많기는 하지만, 어차피 기법 자체는 배열의 차원을 가리지 않기 때문에 어떤 형태의 배열이든 적용 대상이 될 수 있습니다. 사실 마스킹(Masking) 기법의 경우도 그랬지만 이 클리핑(Clipping) 기법에 대해서도 제가 이 블로그에서 올렸던 다른 게시물들, 특히 이미지 처리와 관련된 내용들에서 여러번 언급을 한 적은 있습니다. 하지만 오늘은 클리핑 기법 자체에만 촛점을 맞추어서 그 개념 및 관련 예제들을 함께 소개해보고자 합니다.
우선 클리핑 기법의 원리에 대한 이해를 돕기 위하여 간단하게 1차원 배열에 대하여 적용을 해보겠습니다. 먼저 5개의 정수값들로 구성된 배열 img를 정의합니다. 그리고 img에 대하여 클리핑 기법을 적용하여 그 결과를 clipped라는 배열로 얻게 되는데, 그 과정은 다음과 같습니다.
img = [80, 60, 75, 95, 50]
clipped = img > 70
PRINT, clipped
위의 내용에서 "img > 70"이라고 적은 부분이 바로 클리핑 기법을 적용한 내용인데요. IDL에서 클리핑 기법을 적용하기 위해서는 이와 같이 대상 배열에 대하여 부등호 기호(> 또는 <)를 사용해야 합니다. 그래서 위의 두번째 줄의 내용의 의미는 간단하게만 보면 배열 img에 대하여 클리핑 기법을 적용하여 그 결과를 clipped라는 배열에 담으라는 것인데요. 그 과정을 자세히 보면 다음과 같습니다.
1) 배열 img의 모든 값들에 대하여 70보다 큰가 여부를 일일이 확인
2) 70보다 큰 경우에는 원래 값을 그대로 가져옴
3) 70보다 작은 경우에는 그냥 70으로 간주함
이러한 판단의 결과를 clipped라는 배열로 담으라는 것입니다. 결국 clipped라는 배열에서는 70보다 작은 값은 존재할 수 없게 됩니다. 실제로 PRINT 명령에 의하여 출력된 내용은 다음과 같습니다.
80 70 75 95 70
이러한 결과가 얻어진 이유는 배열 img의 값들을 보면 쉽게 알 수 있습니다. 즉 70보다 큰 값들은 그대로 살아남았고, 70보다 작은 값들이었던 60, 50은 클리핑 과정에 의하여 70이라는 결과값이 되었습니다. 다음 그림은 여기까지의 과정을 도식적으로 나타낸 것입니다.
이 예제는 결국 하한값을 고정시키는 클리핑이라고 볼 수 있습니다. 만약 상한값을 고정시키는 클리핑을 하려면 < 기호를 사용하면 됩니다. 앞서 정의한 배열 img에 대하여 이러한 클리핑을 적용한 예를 들면 다음과 같습니다.
clipped = img < 90
PRINT, clipped
이 경우의 결과는 다음과 같습니다.
80 60 75 90 50
이와 같이 90보다 컸던 값인 95는 클리핑에 의하여 90으로 처리되었습니다. 따라서 이러한 클리핑이 적용된 결과에서는 90보다 큰 값은 존재할 수 없게 됩니다. 그리고 > 및 < 기호를 둘 다 사용하여 상한 및 하한을 모두 고정시키는 것도 가능합니다. 그 예제는 다음과 같습니다.
clipped = img > 70 < 90
PRINT, clipped
이렇게 하면 결과는 다음과 같습니다.
80 70 75 90 70
이와 같이 90보다 컸던 값들은 90으로 그리고 70보다 작았던 값들은 70으로 고정시켜버렸기 때문에, clipped의 값 범위가 70~90으로 재조정된 셈입니다. 일단 이 정도면 클리핑 기법의 원리에 대해서는 충분히 설명이 되었을 것 같습니다. 이번에는 2차원 배열을 대상으로 하는 경우에 대해서도 예제와 함께 살펴보겠습니다. 어차피 차원만 다를 뿐 기본적인 원리는 동일합니다. 예제로 사용할 2차원 데이터는 JPG 파일로부터 읽어오겠습니다. 이 파일은 아래 첨부합니다.
그리고 파일을 읽어서 img라는 2차원 배열로 얻는 과정은 다음과 같습니다.
file = 'bw0406.jpg'
READ_JPEG, file, img
HELP, img
PRINT, MIN(img), MAX(img)
여기서 HELP 및 PRINT에 의하여 출력된 내용을 보면, img는 1024x768의 구조를 갖는 바이트(Byte)형 배열이고 배열 내 값들의 범위는 0~255입니다. 먼저 원본 데이터인 img를 표출해본다면 그 과정은 다음과 같습니다.
sz = SIZE(img, /DIM)
win0 = WINDOW(DIMENSIONS=sz, /NO_TOOLBAR)
i0 = IMAGE(img, MARGIN=0, /CURRENT)
여기서는 SIZE 함수를 사용하여 배열 img의 가로 및 세로 방향 크기를 얻고 이를 그래픽 창의 크기로 반영하였습니다. 그리고 IMAGE 함수를 사용하여 표출할 때 MARGIN의 값을 0으로 설정함으로써 그래픽 창 내에서 이미지 표출시 여백이 생기지 않도록 하였습니다. 표출된 모습은 다음과 같습니다.
이제 배열 img에 대하여 클리핑 기법을 적용해봅시다. 그 과정은 다음과 같습니다.
clipped = img < 80
HELP, clipped
PRINT, MIN(clipped), MAX(clipped)
여기서 "img < 80"이라는 부분이 클리핑 기법에 해당되며 그 결과를 clipped라는 배열로 얻은 것입니다. HELP 및 PRINT에 의하여 출력된 내용을 보면 다음과 같습니다.
CLIPPED INT = Array[1024, 768]
0 80
이와 같이 클리핑 처리의 결과 배열을 보면 차원과 크기 모두 원본 데이터와 동일하지만 내부적으로는 범위가 고정된 값들만 존재하는 배열이 됩니다. 즉 원본 데이터는 0~255의 범위를 가졌지만, 위와 같은 클리핑 처리가 된 배열은 0~80의 범위를 갖게 됩니다. 그리고 결과 배열의 자료형을 보면 정수형임을 알 수 있는데요. 클리핑 처리의 결과는 무조건 정수형 또는 실수형으로 얻어집니다. 지금과 같이 원본 데이터가 바이트형인 경우에도 클리핑의 결과는 정수형으로 산출됩니다. 그러면 결과의 모습이 어떤가를 보기 위하여 다음과 같은 과정에 의하여 별도의 그래픽창을 띄우고 clipped를 표출해봅시다.
win1 = WINDOW(DIMENSIONS=sz, /NO_TOOLBAR)
i1 = IMAGE(clipped, MIN_VALUE=0, MAX_VALUE=255, MARGIN=0, /CURRENT)
표출된 모습은 다음과 같습니다.
여기서 IMAGE 함수가 사용된 방식을 잠시 주목할 필요가 있습니다. 앞서 확인했듯이 clipped 배열의 값 범위는 0~80이긴 하지만, IMAGE 함수로 표출하는데 있어서는 MIN_VALUE, MAX_VALUE 속성을 굳이 사용하여 0~255의 범위로 표출하도록 하였습니다. 이렇게 하면 0이라는 값은 색상값 0으로 대응되고 80이라는 값은 색상값 80으로 대응되는 방식으로 표출됩니다. 물론 80보다 큰 값은 존재하지 않기 때문에 이 값에 해당되는 색상들은 전혀 사용되지 않게 됩니다. 그럼으로써 클리핑의 효과를 제대로 가늠해보고자 하는 의도라고 보면 됩니다. 어쨌든 이와 같이 표출된 모습을 보면 원본 이미지에서 화소값이 80보다 큰 비교적 밝은 형체들의 디테일이 완전히 제거되고 어두운 형체들만 살아남아있음을 알 수 있습니다. 그리고 이번에는 또 다른 그래픽 창을 띄워서 다음과 같이 IMAGE 함수를 사용하되 MIN_VALUE, MAX_VALUE 속성들을 전혀 사용하지 않는 방식으로 표출해봅시다.
win2 = WINDOW(DIMENSIONS=sz, /NO_TOOLBAR)
i2 = IMAGE(clipped, MARGIN=0, /CURRENT)
이렇게 하여 표출된 모습은 다음과 같습니다.
이 모습(i2)과 앞선 표출 그림(i1)을 비교해보면 차이가 분명히 보일 것입니다. 여기서는 정수형 배열인 clipped의 값 범위인 0~80을 표현하는데 있어서 바이트스케일링(Byte-Scaling)이 적용되었습니다. 즉 0이라는 값은 색상값 0으로 대응되고 80이라는 값은 색상값 255로 대응됩니다. 그 사이의 값들은 바이트스케일링에 의하여 색상으로 반영됩니다. 따라서 이와 같이 원래 이미지 내에서 화소값이 낮은 어두운 형체들의 명암대비(Contrast)가 더 높아진 모습을 볼 수 있게 됩니다.
그러면 이번에는 화소값이 높은 밝은 형체들의 명암대비를 더 높인 결과를 얻어보기 위하여 클리핑을 다음과 같이 처리해봅시다.
clipped = img > 200
그리고 이 결과를 표출하는 과정은 앞서 i1, i2를 표출했던 방식과 동일하게 처리하면 됩니다. 먼저 MIN_VALUE=0, MAX_VALUE=255 속성들을 사용하는 경우입니다.
win1 = WINDOW(DIMENSIONS=sz, /NO_TOOLBAR)
i1 = IMAGE(clipped, MIN_VALUE=0, MAX_VALUE=255, MARGIN=0, /CURRENT)
표출된 모습은 다음과 같습니다.
여기서 얻어진 clipped의 경우 내부적으로는 200~255의 범위의 값들만 존재합니다. 왜냐하면 클리핑 처리에 의하여 200보다 작았던 값들은 모두 200으로 통일되었기 때문입니다. 그렇기 때문에 위와 같이 MIN_VALUE, MAX_VALUE 속성의 값을 0, 255로 설정할 경우에는 전반적으로 밝은 색상들 위주로 표출됩니다. 그리고 이번에는 MIN_VALUE, MAX_VALUE 속성을 사용하지 않고 바이트 스케일링이 적용되도록 하는 경우입니다.
win2 = WINDOW(DIMENSIONS=sz, /NO_TOOLBAR)
i2 = IMAGE(clipped, MARGIN=0, /CURRENT)
표출된 모습은 다음과 같습니다.
이와 같이 이미지 내에서 중심부에 밝게 보이는 형체 내에서의 명암대비가 원본에 비하여 더욱 강화된 모습으로 표출됨을 알 수 있습니다. 이와 같이 클리핑 기법은 원래 이미지 내에서 관심있는 화소값 범위에만 촛점을 맞춰서 처리하고자 할 때 특히 더 유용합니다. 예를 들면 사진을 찍었는데 피사체가 광원을 등지고 있어서 역광 현상이 발생했을 때, 역광에 의한 밝은 화소값들을 무시하고 나머지 범위 내 화소값들만 강조하여 역광을 어느 정도 제거한 결과를 얻고자 할 경우에 이러한 클리핑 처리가 매우 효과적입니다. 이외에도 다양한 응용이 가능한 기법이기 때문에 잘 알아두시면 여러모로 도움이 될 것이라 생각합니다.
'IDL > Image Processing' 카테고리의 다른 글
이미지에서 노이즈(Noise) 제거하기 [2] (0) | 2021.07.01 |
---|---|
이미지에서 노이즈(Noise) 제거하기 [1] (0) | 2021.06.15 |
마스킹(Masking) 기법의 이해와 응용 (0) | 2021.05.17 |
IDL에서 허프 변환 (Hough Transform) 사용법 (0) | 2021.04.16 |
IDL에서의 라돈 변환(Radon Transform) 사용법 (0) | 2021.04.07 |