
안녕하세요. 이번 포스팅에서는 Python과 Spinnaker SDK를 활용해
FLIR 카메라를 제어하는 방법을 함께 배워보는 시간을 가져보려 합니다.
강의는 FLIR에서 제공하는 예제를 기반으로 구성되어 있으며
사용된 카메라는 FLIR A Series 모델입니다. 이번 편은 Spinnaker SDK를
활용한 온도값 가져오기 세 번째 시간으로 PySpin을 통해 Radiometric 모드를
설정하고 주요 파라미터를 살펴본 뒤 온도 데이터를 직접 계산하고 이를
이미지 형태로 변환하는 전 과정을 다뤄볼 예정입니다.
카메라에서 실시간으로 열 데이터를 얻고자 하시는 분들께 실질적인 도움이 되길 바랍니다!
그럼 본격적으로 시작해볼까요?
* 강좌 목차
[Python/FLIR] Spinnaker SDK, PySpin 설치 가이드
· FLIR Spinnaker SDK 설치 및 실행(Windows, Ubuntu)
[Python/FLIR] PySpin Node 사용법
· 노드의 개념, 타입, 사용법 설명, spinview에서 노드 정보 확인
[Python/FLIR] PySpin 카메라 스트리밍 기본
· Pyspin 사용하여 카메라 Connect 및 Grab 해보기
[Python/FLIR] PySpin카메라에서 온도값 가져오기(1)
· Nodemap으로 pixelformat 변경, IRFormat 변경하기
[Python/FLIR] PySpin 카메라에서 온도값 가져오기(2)
· emperatureLinear(10K, 100K)으로 온도값 가져오기
[Python/FLIR] PySpin 카메라에서 온도값 가져오기(3)
· Radiometric으로 온도값 가져오기
[Python/FLIR] PySpin 온도 데이터 팔레트 적용
· 온도값 팔레트 이미지 만들어보기
[Python/FLIR] PySpin 카메라 제어(1)
· QueryCase를 사용한 측정 온도 범위 변경 예제
[Python/FLIR] PySpin 카메라 제어(2)
· FPS변경 및 NUC Excute 예제
1. Radiometric 모드 설정
1-1. Pixel Format을 16bit로 설정합니다.
Pixel Format은 스트리밍 하면 변경할 수 없습니다.
PySpin카메라에서 온도값 가져오기(1) 강을 참고하여 Mono16 비트로 설정합니다.

if node_pixel_format.GetAccessMode() == PySpin.RW: # Mono8 모드의 노드 가져옴 node_pixel_format_mono16 = PySpin.CEnumEntryPtr(node_pixel_format.GetEntryByName('Mono16')) # Mono8 value Get pixel_format_mono16 = node_pixel_format_mono16.GetValue() # node_pixel_format 노드에 Mono8 적용 node_pixel_format.SetIntValue(pixel_format_mono16)
1-2. IR Format을 RadioMetric으로 맞추어 줍니다.
IR Format을 변경하게 되면, 이미지를 grab(GetNextImage)하는 raw데이터가 선택한 모드에 따라 들어오게 됩니다.
IR Format은 스트리밍 중에도 변경이 가능합니다.
이후 RawData를 후처리하여 온도값으로 변경해야 합니다.
PySpin카메라에서 온도값 가져오기(1) 강을 참고하여 IRFormat node를Radiometric 모드로 설정합니다.

*참고자료 : 라디오메트릭 정의 ([Python/FLIR] PySpin카메라에서 온도값 가져오기(1) #4
1) Radiometric
# IRFormat nodemap 가져오기
node_IRFormat = PySpin.CEnumerationPtr(nodemap.GetNode('IRFormat'))
# Radiometric 모드로 변경
def Set_Radiometric(): if node_IRFormat.GetAccessMode() == PySpin.RW: print(f"set mode change Radiometric") node_temp_radiometric = PySpin.CEnumEntryPtr(node_IRFormat.GetEntryByName('Radiometric')) node_radiometric = node_temp_radiometric.GetValue() node_IRFormat.SetIntValue(node_radiometric) else: print("node_IRFormat is not available")
2. RadioMetric 계산에 필요한 Parameter
2-1. ObjectParameters
ObjectParameter는 Nodemap에서 ObjectParameters 노드에 모든 파라미터가 들어있습니다.

- Reflected Temperature : 표면의 반사온도
- Atmospheric Temperature : 대기의 온도
- Object Distance : 측정 물체의 거리
- Object Emissvity : 물체의 방사율
- Relative Humidity: 대기의 상대습도
- External Optics Temperature : 외부 광학계 온도
- External Optics Transmission : 외부 광학계 투과율
2-2. Measurement
Measurement는 Nodemap에서 Measurement노드에 모든 파라미터가 들어있습니다.

3. Raw data 섭씨 온도 변환
3-1 Radiometric 온도값 변환 순서
1) 센서 특성 보정 (Offset/Scale)
실제 센서 출력값(raw data)이 플로팅되거나 스케일이 맞지 않기 때문에 오프셋/스케일을 적용해 보정.
관련 항목: J0(GlobalOffset), J1(GlobalGain)
2) 대기 영향 (밀도 / 습도)
적외선 신호가 대기 통과할 때 감쇠되거나 강화되는 것을 보정.
관련 항목 : X, Alpha1, Alpha2, beta1, beta2
X : 대기 밀도에 따른 영향은 X상수로 보정
Alpha1, Alpha2, beta1, beta2 : 대기 습도에 따른 영향을 계수로 모델링
3) Planck 이론적 모델
Planck 방사체 이론을 기반으로 물체 온도와 복사 에너지(적외선 신호) 사이 기본 관계를 만들어 줌.
관련 항목 : R, B
R: integration time(적분 시간)과 wavelength(파장)에 따라 보정하는 요소
B: wavelength(파장)에만 의존하는 방사식 상수
공식 요약

(J0, J1 적용 → 센서 보정)

(X, A1, B1, A2, B2 적용 → 대기 보정)

(R, B 적용 → Planck 모델 계산)

최종 섭씨 온도
3-2 온도값 보정 코드
1) J0, J1 적용 → 센서 보정
sensor_corrected_data = (raw_data -J0) /J1
2) X, A1, B1, A2, B2 적용 → 대기 보정
센서 데이터 → 순수 복사 신호
Emissivity와 Tau를 나눠서 물체 자체 신호만 남긴다.
atmosphere_corrected_radiance = sensor_corrected_data /Emissivity /Tau
Emissivity: 표면 방사율 보정 (물체가 100% 복사체가 아닐 수 있음)
Tau: 대기에서 손실된 복사량을 복원하는 역할
결과: atmosphere_corrected_radiance(= 대기 및 표면 특성까지 고려된 순수 복사 신호)
3) R, B 적용 → Planck 모델 계산
복사 신호 → 물체 온도 구하기
Planck 이론으로 radiance를 temperature로 변환(Planck 방정식 역산 과정)
temperature_kelvin = B / np.log(R / (atmosphere_corrected_radiance - K2) + F)
R, B: Planck 방정식 상수
K2, F: 추가 조정 파라미터 (기기 별 튜닝 값)
결과: temperature_kelvin (Kelvin 온도, 절대 온도)
4) Kelvin -> 섭씨 적용
Celsius_data = temperature_kelvin – 273.15
3-3 Radiometric 계산에 필요한 값
- H₂O (대기온도와 상대습도로 대기 중 수증기량 계산)
H₂O는 대기 중 수증기량을 의미한다.
수증기량은 대기 온도와 상대 습도로 계산한다.
수증기량이 많으면 ➔ 대기 흡수 증가 ➔ Tau가 작아진다. (Tau에 영향)
결과적으로 습도가 높으면 적외선 신호 손실이 더 커진다는 것을 수식에 반영.
H2O = Humidity * np.exp(1.5587 + 0.06939 * TAtmC - 0.00027816 * TAtmC**2 + 0.00000068455 * TAtmC**3)
- Tau
적외선 신호(IR Radiance)가 센서까지 오면서 대기를 통과하는 동안, 원래 신호가 얼마나 살아남았는지를 나타내는 비율
τ = 1.0이면 → 대기 손실 없음 (완전 투명, 신호 100% 도달)
τ = 0.7이면 → 신호가 70%만 살아남음 (30%는 대기 중에서 흡수되거나 산란됨)
τ = 0.3이면 → 신호 대부분이 대기에서 손실됨
Tau  = X * np.exp(-np.sqrt(Dist) * (A1 + B1 * np.sqrt(H2O))) + (1 - X) * np.exp(-np.sqrt(Dist) * (A2 + B2 * np.sqrt(H2O)))
X대기 감쇠 모델 가중치를 사용해 거리(Dist), 습도(H2O)에 따른 대기 투과율을 모델링
- r1 (물체 표면 반사)
r1은 물체 표면으로부터 반사된 복사열을 보정하기 위해 추가하는 값이다.
r1 = ((1 - Emissivity) / Emissivity) * (R / (np.exp(B / TRefl) - F))
(1 - Emissivity) / Emissivity : 얼마나 반사되는지 비율로 표현한 것 (Emissivity가 낮으면 반사가 많다)
R / (exp(B / TRefl) - F) : 주변 온도로부터 오는 복사량 계산(Planck 이론)
- r2 (대기 자체 방사량)
r2는 대기 자체가 방출한 적외선 복사량을 보정하기 위해 추가하는 값이다.(수증기, 먼지 등)
r2 = ((1 - Tau) / (Emissivity * Tau)) * (R / (np.exp(B / TAtm) - self.F))
(1 - Tau) / (Emissivity * Tau) : 대기에서 흡수되고 재방출된 에너지의 양을 비율로 계산
R / (exp(B / TAtm) - F) : 대기 온도에 기반한 이론적 복사량 (Planck 모델)
- r3 (외부 광학 부품 자체 방사량)
r3는 렌즈나 윈도우 같은 광학 부품이 방출하는 적외선 복사량을 보정하는 값이다.
ExtOpticsTransmission이 1에 가까우면 → 광학 부품 영향 작음.
ExtOpticsTransmission이 낮으면 → 광학 부품 영향 큼.
r3 = ((1 - ExtOpticsTransmission) / (Emissivity * Tau * ExtOpticsTransmission)) * (R / (np.exp(B / ExtOpticsTemp) - F))
(1 - ExtOpticsTransmission) : 광학 부품에서 통과되지 않고 방사된 에너지 비율
Emissivity * Tau * ExtOpticsTransmission : 실제 물체 신호 대비 외부 광학 영향 반영 비율
R / (exp(B / ExtOpticsTemp) - F) : 외부 광학 부품 온도(ExtOpticsTemp)로부터 이론적 복사량 (Planck)
- K2
물체가 방출한 순수한 신호만 남기기 위해 K는(= r1, r2, r3)는 최종 방사신호에서 반드시 빼 주어야 하는 값.
=> 최종 보정 값
K2 = r1 + r2 +r3
3-4 코드 시퀀스
1. ObjectParameter, Measurement 에서 필요한 값을 모두 가져온다.
2. 가져온 값 기반으로 H₂O, Tau, r1, r2, r3, k2값을 모두 구한다.
3. PixelFormat은 Mono16, IRMode는 Radiometric 상태에서 이미지를 Grab한다.
4. 온도값 보정 코드에 적용후 섭씨데이터를 확인한다.
4. 데이터 정규화
이미지 표현 범위인 0~255로 변경하기 위하여 정규화를 진행합니다.
1) 정규화를 하기 위하여 raw를 섭씨로 바꾼 데이터의 최대값과 최솟값을 구해줍니다.
섭씨 데이터에서 최댓값, 최솟값 리턴
max_temperature = np.max(Celsius_data)
min_temperature = np.min(Celsius_data)
2) Celsius_data와 max값, min값을 사용해 정규화를 진행합니다.(정규화 시 cv2.normalize 함수를 사용해도 무관합니다.)
온도 데이터를 0 ~ 255 범위로 정규화
정규화는 0~1 범위로 매핑되고, 255를 곱해서 표현 범위(0~255)로 확장
temp_to_img = 255 * (Celsius_int - min_temperature) / (max_temperature - min_temperature)
output_image = temp_to_img.astype(np.uint8)
output_image = cv2.cvtColor(output_image, cv2.COLOR_GRAY2BGR)
실습 코드는 “온도값 가져오기 실습(3).ipynb” 파일 참고 부탁 드립니다.
📂파일 다운로드 클릭하기!
이번 강좌에서는 Spinnaker SDK의 온도에 관한 Radiometric 모드 변경 및 공식 설명을 중점적으로 진행하였습니다.
다음 강좌에서는 온도값에 Color Pallete적용해보는 내용으로 진행하겠습니다.
감사합니다😊

안녕하세요. 이번 포스팅에서는 Python과 Spinnaker SDK를 활용해
FLIR 카메라를 제어하는 방법을 함께 배워보는 시간을 가져보려 합니다.
강의는 FLIR에서 제공하는 예제를 기반으로 구성되어 있으며
사용된 카메라는 FLIR A Series 모델입니다. 이번 편은 Spinnaker SDK를
활용한 온도값 가져오기 세 번째 시간으로 PySpin을 통해 Radiometric 모드를
설정하고 주요 파라미터를 살펴본 뒤 온도 데이터를 직접 계산하고 이를
이미지 형태로 변환하는 전 과정을 다뤄볼 예정입니다.
카메라에서 실시간으로 열 데이터를 얻고자 하시는 분들께 실질적인 도움이 되길 바랍니다!
그럼 본격적으로 시작해볼까요?
* 강좌 목차
[Python/FLIR] Spinnaker SDK, PySpin 설치 가이드
· FLIR Spinnaker SDK 설치 및 실행(Windows, Ubuntu)
[Python/FLIR] PySpin Node 사용법
· 노드의 개념, 타입, 사용법 설명, spinview에서 노드 정보 확인
[Python/FLIR] PySpin 카메라 스트리밍 기본
· Pyspin 사용하여 카메라 Connect 및 Grab 해보기
[Python/FLIR] PySpin카메라에서 온도값 가져오기(1)
· Nodemap으로 pixelformat 변경, IRFormat 변경하기
[Python/FLIR] PySpin 카메라에서 온도값 가져오기(2)
· emperatureLinear(10K, 100K)으로 온도값 가져오기
[Python/FLIR] PySpin 카메라에서 온도값 가져오기(3)
· Radiometric으로 온도값 가져오기
[Python/FLIR] PySpin 온도 데이터 팔레트 적용
· 온도값 팔레트 이미지 만들어보기
[Python/FLIR] PySpin 카메라 제어(1)
· QueryCase를 사용한 측정 온도 범위 변경 예제
[Python/FLIR] PySpin 카메라 제어(2)
· FPS변경 및 NUC Excute 예제
1. Radiometric 모드 설정
1-1. Pixel Format을 16bit로 설정합니다.
Pixel Format은 스트리밍 하면 변경할 수 없습니다.
PySpin카메라에서 온도값 가져오기(1) 강을 참고하여 Mono16 비트로 설정합니다.
1-2. IR Format을 RadioMetric으로 맞추어 줍니다.
IR Format을 변경하게 되면, 이미지를 grab(GetNextImage)하는 raw데이터가 선택한 모드에 따라 들어오게 됩니다.
IR Format은 스트리밍 중에도 변경이 가능합니다.
이후 RawData를 후처리하여 온도값으로 변경해야 합니다.
PySpin카메라에서 온도값 가져오기(1) 강을 참고하여 IRFormat node를Radiometric 모드로 설정합니다.
*참고자료 : 라디오메트릭 정의 ([Python/FLIR] PySpin카메라에서 온도값 가져오기(1) #4
1) Radiometric
# IRFormat nodemap 가져오기
node_IRFormat = PySpin.CEnumerationPtr(nodemap.GetNode('IRFormat'))
# Radiometric 모드로 변경
2. RadioMetric 계산에 필요한 Parameter
2-1. ObjectParameters
ObjectParameter는 Nodemap에서 ObjectParameters 노드에 모든 파라미터가 들어있습니다.
- Reflected Temperature : 표면의 반사온도
- Atmospheric Temperature : 대기의 온도
- Object Distance : 측정 물체의 거리
- Object Emissvity : 물체의 방사율
- Relative Humidity: 대기의 상대습도
- External Optics Temperature : 외부 광학계 온도
- External Optics Transmission : 외부 광학계 투과율
2-2. Measurement
Measurement는 Nodemap에서 Measurement노드에 모든 파라미터가 들어있습니다.
3. Raw data 섭씨 온도 변환
3-1 Radiometric 온도값 변환 순서
1) 센서 특성 보정 (Offset/Scale)
실제 센서 출력값(raw data)이 플로팅되거나 스케일이 맞지 않기 때문에 오프셋/스케일을 적용해 보정.
관련 항목: J0(GlobalOffset), J1(GlobalGain)
2) 대기 영향 (밀도 / 습도)
적외선 신호가 대기 통과할 때 감쇠되거나 강화되는 것을 보정.
관련 항목 : X, Alpha1, Alpha2, beta1, beta2
X : 대기 밀도에 따른 영향은 X상수로 보정
Alpha1, Alpha2, beta1, beta2 : 대기 습도에 따른 영향을 계수로 모델링
3) Planck 이론적 모델
Planck 방사체 이론을 기반으로 물체 온도와 복사 에너지(적외선 신호) 사이 기본 관계를 만들어 줌.
관련 항목 : R, B
R: integration time(적분 시간)과 wavelength(파장)에 따라 보정하는 요소
B: wavelength(파장)에만 의존하는 방사식 상수
공식 요약
(J0, J1 적용 → 센서 보정)
(X, A1, B1, A2, B2 적용 → 대기 보정)
(R, B 적용 → Planck 모델 계산)
최종 섭씨 온도
3-2 온도값 보정 코드
1) J0, J1 적용 → 센서 보정
sensor_corrected_data = (raw_data -J0) /J1
2) X, A1, B1, A2, B2 적용 → 대기 보정
센서 데이터 → 순수 복사 신호
Emissivity와 Tau를 나눠서 물체 자체 신호만 남긴다.
atmosphere_corrected_radiance = sensor_corrected_data /Emissivity /Tau
Emissivity: 표면 방사율 보정 (물체가 100% 복사체가 아닐 수 있음)
Tau: 대기에서 손실된 복사량을 복원하는 역할
결과: atmosphere_corrected_radiance(= 대기 및 표면 특성까지 고려된 순수 복사 신호)
3) R, B 적용 → Planck 모델 계산
복사 신호 → 물체 온도 구하기
Planck 이론으로 radiance를 temperature로 변환(Planck 방정식 역산 과정)
temperature_kelvin = B / np.log(R / (atmosphere_corrected_radiance - K2) + F)
R, B: Planck 방정식 상수
K2, F: 추가 조정 파라미터 (기기 별 튜닝 값)
결과: temperature_kelvin (Kelvin 온도, 절대 온도)
4) Kelvin -> 섭씨 적용
Celsius_data = temperature_kelvin – 273.15
3-3 Radiometric 계산에 필요한 값
- H₂O (대기온도와 상대습도로 대기 중 수증기량 계산)
H₂O는 대기 중 수증기량을 의미한다.
수증기량은 대기 온도와 상대 습도로 계산한다.
수증기량이 많으면 ➔ 대기 흡수 증가 ➔ Tau가 작아진다. (Tau에 영향)
결과적으로 습도가 높으면 적외선 신호 손실이 더 커진다는 것을 수식에 반영.
H2O = Humidity * np.exp(1.5587 + 0.06939 * TAtmC - 0.00027816 * TAtmC**2 + 0.00000068455 * TAtmC**3)
- Tau
적외선 신호(IR Radiance)가 센서까지 오면서 대기를 통과하는 동안, 원래 신호가 얼마나 살아남았는지를 나타내는 비율
τ = 1.0이면 → 대기 손실 없음 (완전 투명, 신호 100% 도달)
τ = 0.7이면 → 신호가 70%만 살아남음 (30%는 대기 중에서 흡수되거나 산란됨)
τ = 0.3이면 → 신호 대부분이 대기에서 손실됨
Tau  = X * np.exp(-np.sqrt(Dist) * (A1 + B1 * np.sqrt(H2O))) + (1 - X) * np.exp(-np.sqrt(Dist) * (A2 + B2 * np.sqrt(H2O)))
X대기 감쇠 모델 가중치를 사용해 거리(Dist), 습도(H2O)에 따른 대기 투과율을 모델링
- r1 (물체 표면 반사)
r1은 물체 표면으로부터 반사된 복사열을 보정하기 위해 추가하는 값이다.
(1 - Emissivity) / Emissivity : 얼마나 반사되는지 비율로 표현한 것 (Emissivity가 낮으면 반사가 많다)
R / (exp(B / TRefl) - F) : 주변 온도로부터 오는 복사량 계산(Planck 이론)
- r2 (대기 자체 방사량)
r2는 대기 자체가 방출한 적외선 복사량을 보정하기 위해 추가하는 값이다.(수증기, 먼지 등)
(1 - Tau) / (Emissivity * Tau) : 대기에서 흡수되고 재방출된 에너지의 양을 비율로 계산
R / (exp(B / TAtm) - F) : 대기 온도에 기반한 이론적 복사량 (Planck 모델)
- r3 (외부 광학 부품 자체 방사량)
r3는 렌즈나 윈도우 같은 광학 부품이 방출하는 적외선 복사량을 보정하는 값이다.
ExtOpticsTransmission이 1에 가까우면 → 광학 부품 영향 작음.
ExtOpticsTransmission이 낮으면 → 광학 부품 영향 큼.
(1 - ExtOpticsTransmission) : 광학 부품에서 통과되지 않고 방사된 에너지 비율
Emissivity * Tau * ExtOpticsTransmission : 실제 물체 신호 대비 외부 광학 영향 반영 비율
R / (exp(B / ExtOpticsTemp) - F) : 외부 광학 부품 온도(ExtOpticsTemp)로부터 이론적 복사량 (Planck)
- K2
물체가 방출한 순수한 신호만 남기기 위해 K는(= r1, r2, r3)는 최종 방사신호에서 반드시 빼 주어야 하는 값.
=> 최종 보정 값
K2 = r1 + r2 +r3
3-4 코드 시퀀스
1. ObjectParameter, Measurement 에서 필요한 값을 모두 가져온다.
2. 가져온 값 기반으로 H₂O, Tau, r1, r2, r3, k2값을 모두 구한다.
3. PixelFormat은 Mono16, IRMode는 Radiometric 상태에서 이미지를 Grab한다.
4. 온도값 보정 코드에 적용후 섭씨데이터를 확인한다.
4. 데이터 정규화
이미지 표현 범위인 0~255로 변경하기 위하여 정규화를 진행합니다.
1) 정규화를 하기 위하여 raw를 섭씨로 바꾼 데이터의 최대값과 최솟값을 구해줍니다.
섭씨 데이터에서 최댓값, 최솟값 리턴
2) Celsius_data와 max값, min값을 사용해 정규화를 진행합니다.(정규화 시 cv2.normalize 함수를 사용해도 무관합니다.)
온도 데이터를 0 ~ 255 범위로 정규화
정규화는 0~1 범위로 매핑되고, 255를 곱해서 표현 범위(0~255)로 확장
float -> int8 변환
단일 채널(1채널) -> 3채널로 변경
실습 코드는 “온도값 가져오기 실습(3).ipynb” 파일 참고 부탁 드립니다.
📂파일 다운로드 클릭하기!
이번 강좌에서는 Spinnaker SDK의 온도에 관한 Radiometric 모드 변경 및 공식 설명을 중점적으로 진행하였습니다.
다음 강좌에서는 온도값에 Color Pallete적용해보는 내용으로 진행하겠습니다.
감사합니다😊