히스토그램 개념
(1) 히스토그램?
- 이미지의 픽셀 값이 어떻게 분포돼 있는지 나타내는 그래프
- 가로축 : 픽셀값 (밝기 수준, 0 ~ 255)
- 세로축 : 해당 픽셀값을 가진 픽셀의 개수
(2) 히스토그램의 특징
- 밝기 분포를 분석할 수 있음
- 이미지가 어두운지, 밝은지, 혹은 대비(contrast)가 낮은지 쉽게 파악 가능
- 예:
- 어두운 이미지: 픽셀 값이 0에 몰려 있음
- 밝은 이미지: 픽셀 값이 255에 몰려 있음
- 대비가 낮은 이미지: 픽셀 값이 특정 영역에만 분포
OpenCV에서 히스토그램 계산
: openCV에서 cv::calcHist를 사용해 히스토그램 계산
함수 정의
cv::calcHist(const Mat* images, int nimages, const int* channels,
InputArray mask, OutputArray hist, int dims, const int* histSize,
const float** ranges, bool uniform=true, bool accumulate=false);
주요 매개변수
- images: 입력 이미지 (1채널 또는 3채널 cv::Mat)에 대한 배열
- nimages: 이미지 수 (보통 1).
- channels: 계산할 채널 (예: Grayscale은 [0], BGR은 [0, 1, 2]).
- mask: 특정 영역의 히스토그램만 계산할 때 사용 (cv::Mat::ones로 전체 영역 사용) --> (옵션) 사용 안할 경우 cv::Mat()로
- hist: 출력 히스토그램 (결과 저장 변수).
- dims: 히스토그램 차원 (보통 1).
- histSize: 히스토그램의 bin 개수 (예: [256]) - 빈도수를 분류할 칸의 개수
- ranges: 픽셀 값 범위 (예: [0, 256]).
추가 개념
(1) bin
- 히스토그램의 bin
- 픽셀 값을 그룹으로 나누는 단위
- 픽셀 값 0~255를 bin 개수에 따라 분리:
- 256개 bin → 각 bin이 하나의 픽셀 값(예: 0, 1, ..., 255) 담당.
- 128개 bin → 각 bin이 두 개의 픽셀 값 담당(예: [0, 1], [2, 3], ...)
- bin 개수의 선택
- bin 개수가 크면 더 정밀한 히스토그램.
- bin 개수가 작으면 더 간단한 히스토그램.
- 왜 예제에서 256 사용?
- Grayscale 이미지는 0~255의 256가지 픽셀 값을 가지므로, 각 값에 대응하는 bin을 생성하기 위해 bin 개수를 256으로 설정.
(2) cv::Mat::ones와 cv::Mat()
- cv::Mat::ones
- 초기화된 Mat 생성자
- 지정된 크기와 데이터 유형을 가진 1로 초기화된 행렬을 생성
- 메모리가 할당되고 모든 요소가 1로 초기화
- 초기화된 Mat 생성자
cv::Mat mat = cv::Mat::ones(3, 3, CV_8U); // 3x3 크기의 8비트 단일 채널 이미지, 모든 값이 1
- cv::Mat()
- 기본 생성자
- 크기와 값을 지정하지 않은 빈 cv::Mat 객체를 생성.
- 메모리는 할당되지 않음.
- 기본 생성자
(3) 배열 사용 이유 (int histSize[], const float* histRange[])
- openCV 유연성을 위한 설계
- cv::calcHist 함수는 다양한 차원의 히스토그램을 계산할 수 있도록 설계됨
- histSize[]:
- 각 차원의 bin 개수를 지정.
- 예: 1D 히스토그램 → {256}, 2D 히스토그램 → {256, 256}.
- histRange[]:
- 각 차원의 값 범위를 지정.
- 예: 1D 히스토그램 → {[0, 256]}, 2D 히스토그램 → {[0, 256], [0, 256]}.
- histSize[]:
- cv::calcHist 함수는 다양한 차원의 히스토그램을 계산할 수 있도록 설계됨
(4) 픽셀 값 범위가 0~255인데 왜 256을 쓰는가?
- 히스토그램 범위
- 히스토그램 계산에서 범위 끝값은 포함되지 않습니다.
- 즉, [0, 256) 범위는 0~255 픽셀 값을 포함.
- OpenCV는 cv::calcHist에서 마지막 값을 포함하지 않는 방식으로 작동.
- 히스토그램 계산에서 범위 끝값은 포함되지 않습니다.
float range[] = {0, 256}; // 실제로는 0~255 값만 계산됨
- bin의 수와 범위의 관계
- bin 개수가 256이고, 범위가 [0, 256)이면 각 bin이 정확히 1개의 픽셀 값을 담당.
- bin 0: 픽셀 값 0.
- bin 1: 픽셀 값 1.
- ...
- bin 255: 픽셀 값 255.
- bin 개수가 256이고, 범위가 [0, 256)이면 각 bin이 정확히 1개의 픽셀 값을 담당.
단일 채널 히스토그램 계산
코트
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
cv::Mat img_1 = cv::imread("../test.png",0);
if(img_1.empty()) {
std::cerr << "Error: Cannot load image!" << std::endl;
return -1;
}
//히스토그램 계산
cv::Mat hist;
int histSize[] = {256}; //bin의 수 , histSize[0]=256
float range[] = {0, 256}; //픽셀값 범위
const float* histRange[] = {range};
bool uniform = true, accumulate = false;
cv::calcHist(&img_1, 1, 0, cv::Mat(), hist, 1, histSize, histRange, uniform, accumulate);
std::cout<< "Hoistogram : " << hist << std::endl;
cv::waitKey(0);
return 0;
}
결과

다음 글에서 위 데이터를 그래프로 출력해 보도록하겠다.
'비디오 코덱' 카테고리의 다른 글
이미지 밝기 조절하기 : grayscale 직접 연산 (0) | 2024.11.28 |
---|---|
waitKey(30) >= 0 알아보기 (0) | 2024.11.27 |
일반 동영상 불러오기 : VideoCapture() (0) | 2024.11.27 |
실시간 영상 프레임 읽어오기 : VideoCapture (1) | 2024.11.27 |
흑백 변환 : cvtColor() vs imread() (0) | 2024.11.27 |