hawkes_bay.bmp
0.99MB
lenna.bmp
0.75MB
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
#define TC 2
//TC1,2 == Histogram stretching
//TC3,4 == Histogram equalization
/*두 기법 모두 히스토그램이 그레이스케일 전체구간에서 픽셀값 분ㅊ포를 골고루 나타나도록 변경하게 해줌.. 히스토그램 평활화는 균등화, 균일화, 평탄화라고 불림*/
/*히스토그램 평활화위한 변환 함수 구하기: 정규화된 히스토그램 구하기 -> 누적분포 함수(cdf) 구하기 */
Mat calcGrayHist(const Mat& img) {
CV_Assert(img.type() == CV_8U);
Mat hist;
int channels[] = { 0 };
int dims = 1;
const int histSize[] = { 256 };
float graylevel[] = { 0,256 };
const float* ranges[] = { graylevel };
calcHist(&img, 1, channels, noArray(), hist, dims, histSize, ranges, true);
return hist;
}
Mat getGrayHistImage(const Mat& hist) {
CV_Assert(!hist.empty());
CV_Assert(hist.type() == CV_32F);
double histMax = 0;
minMaxLoc(hist, 0, &histMax);
Mat imgHist(100, 256, CV_8UC1, Scalar(255));
for (int x = 0; x < 256; ++x) {
line(imgHist, Point(x, 100), Point(x, 100 - cvRound(hist.at<float>(x) * 100 / histMax)), Scalar(0));
}
return imgHist;
}
int main()
{
//Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
Mat src = imread("hawkes_bay.bmp", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image laod failed!" << endl;
return -1;
}
#if TC == 1
//히스토그램 스트레칭 직접 수식작성
double gmin, gmax;
minMaxLoc(src, &gmin, &gmax);
Mat dst = (src - gmin) * 255 / (gmax - gmin); //opencv 이용한 연산자 오버로딩으로 연산.
#elif TC == 2
//TC1 을 OPENCV 내장함수 normalize 이용해서 구함.
Mat dst;
normalize(src, dst, 0, 255, NORM_MINMAX);
#elif TC == 3
//equalizeHist 직접구현
Mat dst(src.rows, src.cols, src.type());
int hist[256] = {};
for (int y = 0; y < src.rows; ++y) {
for (int x = 0; x < src.cols; ++x) {
hist[src.at<uchar>(y, x)]++; //
}
} //해당 코드 수행 시 hist배열에 입력영상 히스토그램 정보가 저장됨. 이를 이용해 히스토그램 그래프 그림.
float cdf[256]{};
cdf[0] = float(hist[0]) / src.total(); //누적분포 함수 계산 후
for (int x = 1; x < 256; ++x) cdf[x] = cdf[x - 1] + float(hist[x]) / src.total(); // cdf 배열에 저장
for (int y = 0; y < src.rows; ++y) { //영상 전체 픽셀 차례대로 방문 후 입력영상 x,y 좌표를 cdf 배열로 지정해 그, 값을 grayscale 최대 255를 곱해
for (int x = 0; x < src.cols; ++x) { // uchar로 설정해 dst에 저장.
dst.at<uchar>(y, x) = uchar(cdf[src.at<uchar>(y, x)] * 255);
}
}
#elif TC ==4
Mat dst;
equalizeHist(src, dst); // 입력영상 8비트 1채널 , dst src크기와 타입 동일
#endif
imshow("src", src);
imshow("dst", dst);
imshow("hist_src", getGrayHistImage(calcGrayHist(src)));
imshow("hist_dst", getGrayHistImage(calcGrayHist(dst))); // 명암비가 높아짐.
waitKey();
}
히스토그램 스트레칭 직선의 방정식 을 사용해 뭉쳐진 픽셀 펴줌 ( 구간에따라 픽셀갯수가 많코 적고를 구분 가능, 픽셀간 펼쳐진 거리가 좁음)
히스토그램 평활화는 곡선에 가까운 변환함수 생성하여 결과물을 만듦 (픽셀간 펼쳐진 거리가 좀 넓음, 갯수가 작은건 전반적으로 펼쳐지지 않음)
둘다 공통적으로 입력영상보단 명암비가 좋아짐
사진과 코드를 활용해 두 변환함수 차이와 공통점을 구분하자.
'프로그래머스 > OPENCV' 카테고리의 다른 글
opencv 동영상 (1) (0) | 2022.12.02 |
---|---|
영상의 산술 및 논리연산 (0) | 2022.12.02 |
(4) 히스토그램분석 (0) | 2022.12.01 |
영상의 명암비 조절 (0) | 2022.12.01 |
영상의 밝기조절(2) (3) | 2022.12.01 |