์ฐ๋ฆฌ๋ ์ ๋ฒ ํฌ์คํ ์ ํตํด์ ํ์คํ ๊ทธ๋จ์ด ๋ฌด์์ธ์ง ์๊ฒ ๋์๋ค.
์ค๋์ Histogram Transformation์ค ํ๋์ธ Histogram Stretching์ ๋ํด์ ์์๋ณด์.
Histogram Stretching (Contrast Stretching)
์ด๋ฏธ์ง์ ํ์คํ ๊ทธ๋จ์ ๋ฝ์๋ดค๋๋ ๋ค์์ฒ๋ผ ๋์๋ค๊ณ ํ์.


ํ์คํ ๊ทธ๋จ์ ๊ฐ๋ค์ด ํ ์ชฝ์ ๋ญ์ณ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด๋ด ๋ ์ฐ๋ฆฌ๋ ์ด ์ด๋ฏธ์ง๋ฅผ ๋๋น๊ฐ ์ฝํ, Flat ํ ์ด๋ฏธ์ง ๋ผ๊ณ ํ๋ค.
Histogram stretching์ ์ด๋ฏธ์ง์ ๋๋น๋ฅผ ์ฆ๊ฐ์ํค๊ธฐ ์ํด์ ํฝ์ ์ ๊ฐ ๋ฒ์๋ฅผ ๋ ๋์ ๋ฒ์๋ก ํ์ฅ์ํค๋ ๊ฒ์ ๋งํ๋ค.


์์ ์ดํดํด ๋ณด๋ฉด, ๊ธฐ์กด์ ๋ฐ๊ธฐ ๋ฒ์
์ฆ, ์๋ ์ด๋ฏธ์ง์ intensity ๋ฒ์๊ฐ
์๋๋ ์์ ์ด๋ฏธ์ง์ stretching์ ์ ์ฉํ ๊ฒฐ๊ณผ์ด๋ค.
ํ์คํ ๊ทธ๋จ์์ intensity์ ๋ฒ์๊ฐ ํ์ฅ๋๊ณ , ์ด๋ฏธ์ง ๋ํ ๋๋น๊ฐ ์ฆ๊ฐํ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์์ค์ฝ๋๋ ์ ์ผ ์๋์ ์ฒจ๋ถํ๋ค.




#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
Mat drawHistogram(const Mat& hist, int histSize, int bar_width, int bar_gap, int hist_h, int margin);
int main() {
Mat img = imread("sunset.jpg", IMREAD_GRAYSCALE);
if (img.empty()) {
cout << "Could not open or find the image!" << endl;
return -1;
}
//์๋ณธ์ด๋ฏธ์ง ์ฝ๊ฐ ์ด๋ก๊ฒ ๋ง๋ค๊ธฐ
Mat dark(img.size(), CV_8UC1, Scalar(0));
Mat dark_img;
addWeighted(img, 0.7, dark, 0.2, 0, dark_img);
// stretching์ ์ ํ์คํ ๊ทธ๋จ ๊ณ์ฐํ๊ธฐ
int histSize = 256;
Mat hist;
float range[] = { 0, 256 };
const float* histRange = { range };
calcHist(&dark_img, 1, 0, Mat(), hist, 1, &histSize, &histRange);
Mat histImg = drawHistogram(hist, histSize, 1, 2, 500, 60);
imshow("Image", dark_img);
imshow("Histogram", histImg);
// normalize ํจ์๋ฅผ ํตํด์ ํ์คํ ๊ทธ๋จ ์คํธ๋ ์นญ
Mat stretched_img;
normalize(dark_img, stretched_img, 0, 255, NORM_MINMAX);
calcHist(&stretched_img, 1, 0, Mat(), hist, 1, &histSize, &histRange);
Mat histImg_ = drawHistogram(hist, histSize, 1, 2, 500, 60);
imshow("stretched_Image", stretched_img);
imshow("normalized_Histogram", histImg_);
waitKey(0);
return 0;
}
Mat drawHistogram(const Mat& hist, int histSize, int bar_width, int bar_gap, int hist_h, int margin)
{
// ๋ง๋ ์ค์
int total_bar_width = bar_width + bar_gap;
int hist_w = histSize * total_bar_width;
Mat histImg(hist_h + 2 * margin, hist_w + 2 * margin, CV_8UC3, Scalar(0, 0, 0));
// ์ต๋ ํ์คํ ๊ทธ๋จ ๊ฐ ์ฐพ๊ธฐ
double maxVal;
minMaxLoc(hist, 0, &maxVal);
// ํ์คํ ๊ทธ๋จ ๋ง๋ ๊ทธ๋ฆฌ๊ธฐ
for (int i = 0; i < histSize; i++) {
rectangle(histImg,
Point(margin + total_bar_width * i, margin + hist_h),
Point(margin + total_bar_width * i + bar_width,
margin + hist_h - cvRound(hist.at<float>(i) * hist_h / maxVal)),
Scalar(255, 255, 255), FILLED);
}
// x์ถ (๋ฐ๊ธฐ๊ฐ, 50 ๋จ์)
for (int i = 0; i <= histSize; i += 50) {
putText(histImg, to_string(i), Point(margin - 10 + total_bar_width * i, margin + hist_h + 20),
FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
line(histImg, Point(margin + total_bar_width * i, margin + hist_h),
Point(margin + total_bar_width * i, margin + hist_h + 5), Scalar(255, 255, 255));
}
// y์ถ (ํฝ์
๊ฐ์, 4๋จ๊ณ)
float step_y = hist_h / 4;
for (int i = 0; i <= hist_h; i += step_y) {
putText(histImg, to_string(int(maxVal - maxVal * i / hist_h)),
Point(5, margin + i + 5), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
line(histImg, Point(margin - 5, margin + i
), Point(margin, margin + i), Scalar(255, 255, 255));
}
// ์ถ ๊ทธ๋ฆฌ๊ธฐ
line(histImg, Point(margin, margin), Point(margin, margin + hist_h), Scalar(255, 255, 255));
line(histImg, Point(margin, margin + hist_h), Point(hist_w + margin, margin + hist_h), Scalar(255, 255, 255));
return histImg;
}
'๐ฆAI > Computer Vision' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Computer Vision/OpenCV] 9. Histogram Matching (0) | 2025.03.27 |
---|---|
[Computer Vision/OpenCV] 8. Histogram Equalization (0) | 2025.03.23 |
[Computer Vision/OpenCV] 6. Histogram (0) | 2025.03.21 |
[Computer Vision/OpenCV] 5. Pixel-wise Arithmetic Operation (1) | 2025.03.20 |
[Computer Vision/OpenCV] 4. 2D Geometric Transformation (0) | 2025.03.19 |