본문 바로가기

OpenCV

OpenCV 이미지 임계값 처리 Thresholding

반응형

 

아래 그림 1의 애니메이션을 주의 깊게 살펴보세요. 숫자가 몇 개 보이시나요? 대부분 여러 개의 숫자가 보일 것입니다. 하지만 이미지에는 눈에 보이는 것 이상의 의미가 있습니다.

 

 

 

OpenCV에서 이미지 임계값을 지정하는 데 사용할 입력 이미지입니다.

 

 

 

애니메이션이 순환하면서 원본 이미지의 임계값이 적용된 버전이 표시됩니다.

 

  • 모든 숫자는 완전히 흰색으로 보입니다(즉, 회색조 값이 255입니다).
  • 또한 원본 이미지에는 있었지만 회색조 값이 5였기 때문에 보이지 않았던 숫자 '5'도 볼 수 있습니다.

 

실제로 원본 이미지의 모든 숫자는 해당 숫자 값과 같은 회색조 값을 갖습니다. 따라서 '255'가 가장 밝고 '5'가 가장 어둡습니다. 회색조의 명암비는 순수한 검은색(0)부터 순수한 흰색(255)까지 다양합니다.

 

따라서 임계값이 적용된 이미지에서 숫자를 읽는 것은 원본 이미지에서 숫자를 읽는 것보다 훨씬 쉽습니다. 당연히 텍스트 인식 알고리즘조차도 원본 이미지보다 임계값이 적용된 이미지를 처리하는 것이 더 쉽습니다. 따라서 임계값 설정은 컴퓨터 비전 분야에서 다양한 용도로 사용되며, 많은 처리 파이프라인의 초기 단계에서 수행되는 경우가 많습니다. 임계값 설정 알고리즘에는 여러 유형이 있습니다. 여기서는 '전역' 임계값 설정에 대해 살펴보겠습니다.

 

이 게시물은 다음 게시물로 구성된 OpenCV 시작하기 시리즈의 일부입니다 .

 

OpenCV를 사용하여 이미지 읽기, 표시 및 쓰기

OpenCV를 사용하여 비디오 읽기 및 쓰기

OpenCV를 사용한 이미지 크기 조정

OpenCV를 사용하여 이미지 자르기

OpenCV를 사용한 이미지 회전 및 변환

OpenCV를 사용하여 이미지에 주석 달기

OpenCV의 색상 공간

OpenCV에서 합성곱을 사용한 이미지 필터링

OpenCV의 이미지 임계값 설정

OpenCV를 사용한 에지 감지

OpenCV GUI를 사용한 마우스 및 트랙바

OpenCV를 사용한 윤곽선 감지

OpenCV DNN 모듈을 활용한 딥러닝: 확실한 가이드

 

Table of Contents

  1. 글로벌 임계값
  2. 이진 임계값 설정
  3. 역이진 임계값 설정
  4. 임계값 자르기
  5. 임계값을 0으로
  6. 역 임계값을 0으로 설정

 

글로벌 임계값

 

그렇다면 '전역' 임계값 설정이란 무엇일까요? 임계값 설정 규칙이 이미지의 모든 픽셀에 동일하게 적용되고 임계값이 고정되어 있을 때, 이러한 연산을 전역 연산이라고 합니다.

 

전역 임계값 알고리즘은 소스 이미지(src)와 임계값(thresh)을 입력으로 받아 소스 픽셀 위치(x,y)의 픽셀 강도를 임계값과 비교하여 출력 이미지(dst)를 생성합니다. src(x,y)>임계값이면 dst(x,y)에 어떤 값이 할당됩니다. 그렇지 않으면 dst(x,y)에 다른 값이 할당됩니다.

 

전역 임계값 설정의 가장 간단한 형태는 이진 임계값 설정 이라고 합니다 .

 

  • 소스 이미지(src)와 임계값(thresh) 외에 최대값( maxValue)이라는 또 다른 입력 매개변수를 사용합니다.
  • 각 픽셀 위치에서 (x,y)해당 위치의 픽셀 강도는 임계값 thresh와 비교됩니다 .

 

src(x,y)가 thresh보다 크면 임계값 연산은 대상 이미지 픽셀 dst(x,y)의 값을 maxValue로 설정합니다. 그렇지 않으면 아래 의사 코드와 같이 0으로 설정합니다.

 

# Simple threshold function pseudo code
if src(x,y) > thresh
  dst(x,y) = maxValue
else
  dst(x,y) = 0

 

 

임계값 알고리즘은 dst(x,y)를 얻기 위해 src(x,y)에 적용되는 다양한 임계값 규칙에 따라 달라집니다. 여기서는 OpenCV에서 사용할 수 있는 다섯 가지 임계값 유형을 살펴보겠습니다.

 

 

임계값 예: Python 및 C++

 

먼저 여러 임계값 설정 규칙을 보여주는 코드를 살펴보겠습니다. 각 줄을 자세히 설명하여 완전히 이해하도록 하겠습니다.

 

파이썬:

 

# import opencv 
import cv2 
 
# Read image 
src = cv2.imread("threshold.png", cv2.IMREAD_GRAYSCALE); 
 
# Basic threhold example 
th, dst = cv2.threshold(src, 0, 255, cv2.THRESH_BINARY); 
cv2.imwrite("opencv-threshold-example.jpg", dst); 
 
# Thresholding with maxValue set to 128
th, dst = cv2.threshold(src, 0, 128, cv2.THRESH_BINARY); 
cv2.imwrite("opencv-thresh-binary-maxval.jpg", dst); 
 
# Thresholding with threshold value set 127 
th, dst = cv2.threshold(src,127,255, cv2.THRESH_BINARY); 
cv2.imwrite("opencv-thresh-binary.jpg", dst); 
 
# Thresholding using THRESH_BINARY_INV 
th, dst = cv2.threshold(src,127,255, cv2.THRESH_BINARY_INV); 
cv2.imwrite("opencv-thresh-binary-inv.jpg", dst); 
 
# Thresholding using THRESH_TRUNC 
th, dst = cv2.threshold(src,127,255, cv2.THRESH_TRUNC); 
cv2.imwrite("opencv-thresh-trunc.jpg", dst); 
 
# Thresholding using THRESH_TOZERO 
th, dst = cv2.threshold(src,127,255, cv2.THRESH_TOZERO); 
cv2.imwrite("opencv-thresh-tozero.jpg", dst); 
 
# Thresholding using THRESH_TOZERO_INV 
th, dst = cv2.threshold(src,127,255, cv2.THRESH_TOZERO_INV); 
cv2.imwrite("opencv-thresh-to-zero-inv.jpg", dst);

 

C++:

 

#include "opencv2/opencv.hpp"
 
using namespace cv;
using namespace std;
 
int main( int argc, char** argv )
{
 
 // Read image 
 Mat src = imread("threshold.png", IMREAD_GRAYSCALE); 
 Mat dst; 
  
 // Basic threhold example 
 threshold(src,dst,0, 255, THRESH_BINARY); 
 imwrite("opencv-threshold-example.jpg", dst); 
 
 // Thresholding with maxval set to 128
 threshold(src, dst, 0, 128, THRESH_BINARY); 
 imwrite("opencv-thresh-binary-maxval.jpg", dst); 
  
 // Thresholding with threshold value set 127 
 threshold(src,dst,127,255, THRESH_BINARY); 
 imwrite("opencv-thresh-binary.jpg", dst); 
  
 // Thresholding using THRESH_BINARY_INV 
 threshold(src,dst,127,255, THRESH_BINARY_INV); 
 imwrite("opencv-thresh-binary-inv.jpg", dst); 
  
 // Thresholding using THRESH_TRUNC 
 threshold(src,dst,127,255, THRESH_TRUNC); 
 imwrite("opencv-thresh-trunc.jpg", dst); 
 
 // Thresholding using THRESH_TOZERO 
 threshold(src,dst,127,255, THRESH_TOZERO); 
 imwrite("opencv-thresh-tozero.jpg", dst); 
 
 // Thresholding using THRESH_TOZERO_INV 
 threshold(src,dst,127,255, THRESH_TOZERO_INV); 
 imwrite("opencv-thresh-to-zero-inv.jpg", dst); 
}

 

시스템에 이미 OpenCV가 설치되어 있다고 가정합니다. OpenCV를 설치해야 하는 경우 아래 관련 링크를 방문하세요.

 

Windows에 OpenCV 설치

MacOS에 OpenCV 설치

Ubuntu에 OpenCV 설치

 

입력 이미지

 

다음 예제에서는 이 이미지를 입력으로 사용합니다. 입력 이미지에는 숫자 자체와 동일한 명도(회색조 값)로 표시된 숫자가 포함되어 있습니다. 예를 들어, 숫자 '200'의 픽셀 명도는 200이고, 숫자 '32'의 명도는 32입니다. '32'가 '200'보다 훨씬 어둡게 보이는 것은 당연한 일입니다.

 

 

그림 2: 입력 이미지

 

아래의 각 예에서 우리는 의사 코드를 통해 임계값 설정 규칙을 설명하고, 예와 임계값이 설정된 출력 이미지에 대한 실제 Python 및 C++ 코드를 제공합니다.

 

1. 이진 임계값 설정(THRESH_BINARY)

 

이것은 가장 일반적이고 가장 간단한 임계값 설정 유형입니다.

 

임계값 규칙

 

# Binary Threshold
if src(x,y) > thresh
  dst(x,y) = maxValue
else
  dst(x,y) = 0

 

파이썬:

 

# import opencv
import cv2
 
# Read image
src = cv2.imread("threshold.png", cv2.IMREAD_GRAYSCALE)
 
# Set threshold and maxValue
thresh = 0
maxValue = 255
 
# Basic threshold example
th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_BINARY);

 

C++:

 

using namespace cv; 
 
// Read image
Mat src = imread("threshold.png", IMREAD_GRAYSCALE);
Mat dst;
 
// Set threshold and maxValue
double thresh = 0;
double maxValue = 255; 
 
// Binary Threshold
threshold(src,dst, thresh, maxValue, THRESH_BINARY);

 

이진 임계값의 결과

 

그림 3은 입력 이미지에 이진 임계값을 적용한 결과(thresh = 0, maxValue = 255)를 보여줍니다.

 

 

그림 3: 이진 임계값(thresh = 0 및 maxValue = 255)

 

127로 변경하면 thresh 127 이하의 모든 숫자가 제거됩니다.

 

 

그림 4: 이진 임계값(thresh = 127 및 maxValue = 255)

 

128로 변경하면 maxValue 임계값 영역의 값이 128로 설정됩니다.

 

 

그림 5: maxValue가 128로 설정된 이진 임계값

 

2. 역이진 임계값 설정(THRESH_BINARY_INV)

 

역이진 임계값 설정은 이진 임계값 설정의 반대 개념입니다. 대상 픽셀은 다음과 같이 설정됩니다.

 

  • 0, 해당 소스 픽셀이 임계값보다 큰 경우
  • maxValue, 소스 픽셀이 임계값보다 작은 경우

 

임계값 규칙

 

# Inverse Binary Threshold
if src(x,y) > thresh
  dst(x,y) = 0
else
  dst(x,y) = maxValue

 

파이썬:

 

th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_BINARY_INV)

 

C++:

 

threshold(src,dst, thresh, maxValue, THRESH_BINARY_INV);

 

역이진 임계값의 결과

 

그림 6에 표시된 역이진 임계값 설정의 결과가 그림 4의 결과와 정확히 반대라는 점에 유의하세요.

 

 

그림 6: 역이진 임계값 설정(thresh = 127, maxValue = 0)

 

3. 임계값 자르기(THRESH_TRUNC)

 

이 유형의 임계값 설정에서는:

 

  • 소스 픽셀 값이 임계값보다 큰 경우 대상 픽셀은 임계값( thresh) 으로 설정됩니다.
  • 그렇지 않으면 소스 픽셀 값으로 설정됩니다.
  • 최대값은 무시됩니다.

 

임계값 규칙

 

# Truncate Threshold
if src(x,y) > thresh
  dst(x,y) = thresh
else
  dst(x,y) = src(x,y)

 

파이썬:

 

th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_TRUNC)

 

C++:

 

threshold(src,dst, thresh, maxValue, THRESH_TRUNC);

 

임계값 자르기 결과

 

그림 7은 입력 이미지에 Truncate Thresholding을 적용한 결과를 보여줍니다. 다음 사항에 유의하세요.

 

  • 임계값(127) 이상의 모든 값은 127로 설정됩니다.
  • 127 이하의 모든 값은 변경되지 않습니다.
  • 최대값은 무시됩니다.

 

 

그림 7: 임계값 자르기(임계값 = 127)

 

4. 임계값을 0으로 설정(THRESH_TOZERO)

 

이 유형의 임계값 설정에서는

 

  • 소스 픽셀 값이 임계값보다 큰 경우, 대상 픽셀 값은 해당 소스의 픽셀 값으로 설정됩니다.
  • 그렇지 않으면 0으로 설정됩니다.
  • maxValue은 무시됩니다

 

임계값 규칙

 

# Threshold to Zero
if src(x,y) > thresh
  dst(x,y) = src(x,y)
else
  dst(x,y) = 0

 

파이썬:

 

th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_TOZERO)

 

C++:

 

threshold(src,dst, thresh, maxValue, THRESH_TOZERO);

 

임계값을 0으로 설정한 결과

 

 

그림 8: 임계값을 0으로 설정(thresh = 127)

 

 

5. 역 임계값을 0으로 설정(THRESH_TOZERO_INV)

 

역 임계값을 0으로 설정하면

 

  • 소스 픽셀 값이 임계값보다 큰 경우 대상 픽셀 값은 0으로 설정됩니다.
  • 그렇지 않으면 소스 픽셀 값으로 설정됩니다.
  • 최대값은 무시됩니다.

 

임계값 규칙

 

# Inverted Threshold to Zero
if src(x,y) > thresh
  dst(x,y) = 0
else
  dst(x,y) = src(x,y)

 

파이썬:

 

th, dst = cv2.threshold(src, thresh, maxValue, cv2.THRESH_TOZERO_INV)

 

C++:

 

threshold(src,dst, thresh, maxValue, THRESH_TOZERO_INV);

 

역 임계값을 0으로 변환한 결과

 

그림 9는 입력 이미지에 역 임계값을 0으로 적용한 결과를 보여줍니다.

 

  • 임계값 아래의 숫자는 회색조 값을 유지합니다.
  • 임계값 위의 숫자는 경계를 제외하고 0입니다.

 

일부 숫자 경계에 있는 아티팩트를 확인해 보세요! 경계의 픽셀 값이 0에서 숫자 값으로 변할 때, 매우 적은 픽셀에서 경계 픽셀 중 일부가 임계값 아래로 떨어집니다. 그래서 이러한 아티팩트가 발생하는 것입니다.

 

 

그림 9: 역 임계값을 0으로 설정(thresh = 127)

 

 

요약

 

임계값 설정을 사용하여 이미지에서 특정 객체를 분리하는 방법을 논의했습니다. 여러 전역 임계값 설정 알고리즘을 시연하고 각 알고리즘에 대한 코드 예제를 제공했습니다. OpenCV에서 단 하나의 함수만으로도 적절한 임계값 설정 플래그를 전달하는 것만으로 다양한 유형의 임계값 설정을 수행할 수 있다는 것을 배웠습니다.

 

반응형

'OpenCV' 카테고리의 다른 글

OpenCV 윤곽선 탐지 Python, C++  (0) 2025.09.11
OpenCV GUI에서 마우스와 트랙바  (0) 2025.09.11
OpenCV 에지 검출  (0) 2025.09.11
OpenCV 블롭 탐지 Python, C++  (0) 2025.09.10
OpenCV 색 공간 C++, Python  (1) 2025.09.10
OpenCV 이미지 변환 및 회전  (0) 2025.09.09
OpenCV 이미지 자르기  (0) 2025.09.09
OpenCV 이미지 크기 조정  (0) 2025.09.09

더욱 좋은 정보를 제공하겠습니다.~ ^^