[OpenCV] Histogram & Median 히스토그램 & 중앙값
Computer Vision 2026. 4. 18. 10:18 |반응형
히스토그램을 그리고 중간 빈도수(중앙값)의 위치를 찾아보자.
#include <iostream>
#include <opencv2/opencv.hpp>
// src의 히스토그램을 계산하고 중간 빈도수의 값(위치)을 반환하는 함수
int Median(const cv::Mat& src)
{
cv::Mat hist;
int nImages = 1;
int channels[] = { 0 };
int dims = 1;
int histSize[] = { 256 };
float graylevel[] = { 0, 256 };
const float* ranges[] = { graylevel };
cv::calcHist(&src, nImages, channels, cv::noArray(), hist, dims, histSize, ranges);
// 히스토그램에서 각 밝기 값의 빈도수를 모두 더해서 총 빈도수를 계산한다
//int total = 0;
//for (int i = 0; i < hist.rows; ++i)
// total += hist.at<float>(i, 0);
// 그러나 위 코드는 비효율적이다. src 이미지의 총 픽셀 수를 직접 계산하여 총 빈도수로 사용할 수 있다.
int total = src.total(); // src.total()는 src 이미지의 총 픽셀 수를 반환한다.
int median = 0;
int cumulative = 0;
// 누적 빈도수가 총 빈도수의 절반에 도달하는 위치값을 찾는다
for (int i = 0; i < hist.rows; ++i) {
cumulative += hist.at<float>(i, 0);
if (cumulative >= total / 2) {
median = i;
break;
}
}
std::cout << "Total: " << total << std::endl <<
"Cumulative: " << cumulative << std::endl <<
"Median Index: " << median << std::endl;
return median;
}
cv::Mat getHistImage(const cv::Mat& src)
{
int nImages = 1;
int channels[] = { 0 };
cv::Mat hist; // calcHist()에서 반환되는 hist는 256X1 크기의 행렬로, 각 행은 해당 밝기 값의 빈도수를 나타낸다.
int dims = 1;
const int histSize[] = { 256 };
float graylevel[] = { 0, 256 };
const float* ranges[] = { graylevel };
cv::calcHist(&src, nImages, channels, cv::noArray(), hist, dims, histSize, ranges);
double maxVal;
// 히스토그램에서 최대 빈도수 값을 찾는다
cv::minMaxLoc(hist, nullptr, &maxVal);
cv::Mat histImage(100, 256, CV_8UC3, cv::Scalar(255, 255, 255));
for (int i = 0; i < 256; ++i)
// 각 빈도수를 최대 빈도수로 정규화하여 100픽셀 높이로 표현한다
cv::line(histImage, cv::Point(i, 100), cv::Point(i, 100 - cvRound(hist.at<float>(i, 0) / maxVal * 100)), cv::Scalar(0));
// 옵션: 히스토그램에서 중간빈도수 위치에 빨간색 선을 그려서 시각적으로 표시한다
int midFreq = Median(src);
cv::line(histImage, cv::Point(midFreq, 100), cv::Point(midFreq, 0), cv::Scalar(0, 0, 255));
return histImage;
}
int main() {
cv::Mat image = cv::imread("palvin1.png");
if (image.empty()) {
std::cerr << "Could not read the image" << std::endl;
return 1;
}
cv::cvtColor(image, image, cv::COLOR_BGR2GRAY);
cv::Mat histImage = getHistImage(image);
cv::imshow("Image", image);
cv::imshow("Histogram", histImage);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}



빈도수의 중앙값 위치를 빨간색 선으로 표시한다.
반응형
'Computer Vision' 카테고리의 다른 글
| [OpenCV] Image Resize 영상 리사이즈 (feat.LogLevel) (0) | 2026.04.23 |
|---|---|
| [OpenCV] Nozzle Number, Stream & Suckback Level Detection 노즐 번호, 물줄기 및 Suckback 높이 검출 (0) | 2026.04.18 |
| [NVR] 하나의 랜 카드에 두 개의 네트워크 IP 지정하기 (0) | 2026.04.11 |
| [CGI] IP Camera Motion Detection Signal IP 카메라 움직임 감지 시그널 전달하기 (0) | 2026.04.09 |
| [OpenCV] 다수의 영상 파일 재생 (0) | 2026.03.27 |
