수학적 영상처리

[파이썬] 2차원 푸리에변환을 12bit 버전으로 구현해보았습니다.

제갈티 2024. 9. 12. 08:44

12bit 2D FFT로 스펙트럼을 구해 표시한 모습

- 제조업이나 산업쪽에서는 종종 8비트 대신 12비트로 이미지를 센싱하는 경우가 있죠. 화소의 계조를 높여서 이미지의 데이타 분해능을 높이고 더 정밀한 측정이나 계조값 기반 리그레션 등을 하기위함 인데요..

- 그렇게 만들어진 12비트 이미지는 8비트 체계로 작동하는 일반 글카나 모니터로는 볼수도없고 일반 S/W로는 영상처리도 불가능합니다.

- 이미지 디스플레이에서부터 히스토그램, 이진화, 콘트라스트 변조나 에지 검출 등등의 계조값을 다루는 거의 모든 영상처리 루틴을 새로 개발해야 하죠.

- 그래서 보통은 12비트를 8비트 이미지로 컨버팅한후 표시하거나 8비트 영상처리를 하거나하여 딥러닝에 입력하는 등의 만행을 저지르죠. 쉬운방법이긴한데, 그러면 애초에 애써 12비트로 센싱한 의미가 사라지죠.

- png 이미지는 16비트를 지원하기 때문에 12비트 이미지를 화면에 표시할수 있습니다. 하지만 보여지는 과정에서 정규화를 진행해 역시나 약간 흐리게 보여지죠.

- 드물긴 하지만 12비트 이미지용 영상처리 라이브러리가 없진 않을텐데 공개를 잘 안하는 편이어서 찾기도 어렵기도 하구요. 특히나 주파수도메인 쪽 코드들은 거의 전무합니다.

- 그래서 한번 만들어봤습니다. 12bit 이미지 전용의 2D FFT 코드를 말입니다. ! 테스트 해보니 확실히 12비트 이미지를 8비트 이미지로 건버팅한 후 FFT 한 결과보다 12bit로 FFT 한 결과가 스펙트럼의 디테일이 살아있는게 느껴집니다. 

- 물론 12비트 스펙트럼도 일반 텀퓨터로 볼려면 다시 8비트로 변환해 보아야 하지만... 그래도 디테일은 분명히 다르네요.


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

def display_and_save_fourier_spectrum_of_png_region(img_path, output_path):
    # PNG 이미지를 그레이스케일로 읽어옵니다. 이미지가 12비트라고 가정합니다.
    img = cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
    
    # 이미지를 float32 타입으로 변환합니다.
    img_float = np.float32(img)

    # 2D 푸리에 변환을 수행합니다.
    dft = cv2.dft(img_float, flags=cv2.DFT_COMPLEX_OUTPUT)
    dft_shift = np.fft.fftshift(dft)

    # 스펙트럼의 크기를 계산하고 로그 스케일로 변환합니다.
    magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))

    # 스펙트럼의 값이 12비트 범위에 맞도록 스케일링합니다.
    # 스펙트럼의 최소값과 최대값을 구합니다.
    min_val, max_val = np.min(magnitude_spectrum), np.max(magnitude_spectrum)
    # 스펙트럼 값을 0에서 4095 (12비트) 범위로 정규화합니다.
    spectrum_scaled = np.clip((magnitude_spectrum - min_val) / (max_val - min_val) * 4095, 0, 4095).astype(np.uint16)

    # 스펙트럼을 디스플레이합니다.
    plt.figure(figsize=(9, 5))
    plt.subplot(121), plt.imshow(img, cmap='gray')
    plt.title('Input Image'), plt.xticks([]), plt.yticks([])
    plt.subplot(122), plt.imshow(spectrum_scaled, cmap='gray')
    plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
    plt.show()

    # 스펙트럼 결과를 12비트 PNG 파일로 저장합니다.
    cv2.imwrite(output_path, spectrum_scaled)

# 이 함수를 호출할 때는 12비트 이미지를 담은 PNG 파일의 경로와 출력 파일 경로를 'img_path', 'output_path'에 전달합니다.
# 예: display_and_save_fourier_spectrum_of_png_region('path_to_your_12bit_image.png', 'output_spectrum.png')

-파이썬  코드 입니다.