'histogram'에 해당되는 글 1건

  1. 2026.04.18 [OpenCV] Histogram & Median 히스토그램 & 중앙값
반응형

히스토그램을 그리고 중간 빈도수(중앙값)의 위치를 찾아보자.

 

#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;
}

 

 

 

빈도수의 중앙값 위치를 빨간색 선으로 표시한다.

 

반응형
Posted by J-sean
: