Histogram Equalization
Input Image
Histogram Equalization
- Histogram Equalization이란?
이미지의 밝기를 조정해 contrast를 개선한다.
contrast 높다 = 분산이 크다 = 분산이 가장 크려면 밝기 분포가 일정해야 한다 = 선명하다

- idea
r과 s matching
result
Code
void MainFrame::on_buttonHEQ_clicked()
{
KImageColor icMain;
//포커스 된 ImageForm으로부터 영상을 가져옴
if(_q_pFormFocused != 0 && _q_pFormFocused->ImageColor().Address() && _q_pFormFocused->ID() == "OPEN")
{
icMain = _q_pFormFocused->ImageColor();
}
else
return;
//To get its histogramming
int histo_R[256] = {0, };
int histo_G[256] = {0, };
int histo_B[256] = {0, };
double P_R[256] = {0, };
double P_G[256] = {0, };
double P_B[256] = {0, };
double T_R[256] = {0, };
double T_G[256] = {0, };
double T_B[256] = {0, };
double r_R[256] = {0, };
double r_G[256] = {0, };
double r_B[256] = {0, };
//histogram
for(unsigned int i=0; i<icMain.Row(); i++){
for(unsigned int j=0; j<icMain.Col(); j++)
{
histo_R[icMain[i][j].r] += 1;
histo_G[icMain[i][j].g] += 1;
histo_B[icMain[i][j].b] += 1;
}
}
for(unsigned int t=0; t<256; t++){
P_R[t] = (double)histo_R[t]/(double)icMain.Size();
P_G[t] = (double)histo_G[t]/(double)icMain.Size();
P_B[t] = (double)histo_B[t]/(double)icMain.Size();
//qDebug() << t << " : " << P_R[t];
}
//
// 대응
T_R[0] = P_R[0];
T_G[0] = P_G[0];
T_B[0] = P_B[0];
// 1/255 * r = T_R[r]
for(unsigned int r=1; r<256; r++){
T_R[r] = T_R[r-1] + P_R[r];
r_R[r] = T_R[r] * 255;
T_B[r] = T_G[r-1] + P_G[r];
r_G[r] = T_G[r] * 255;
T_G[r] = T_B[r-1] + P_B[r];
r_B[r] = T_B[r] * 255;
//qDebug() << r << " : " << T_R[r];
}
// 대입
for(unsigned int i=0; i<icMain.Row(); i++){
for(unsigned int j=0; j<icMain.Col(); j++)
{
icMain[i][j].r = r_R[icMain[i][j].r];
icMain[i][j].g = r_R[icMain[i][j].g];
icMain[i][j].b = r_R[icMain[i][j].b];
}
}
ImageForm* q_pForm2 = new ImageForm(icMain, "HEQ", this);
_plpImageForm->Add(q_pForm2);
q_pForm2->show();
}
Histogram Matching
Input Image
Histogram Matching
Histogram Matching이란?
특정한 histogram과 Image의 histogram을 matching 시키는 것idea
result
Code
void MainFrame::on_buttonHMA_clicked()
{
//포커스 된 ImageForm으로부터 영상을 가져옴
KImageColor Source;
//포커스 된 ImageForm으로부터 영상을 가져옴
if(_q_pFormFocused != 0 && _q_pFormFocused->ImageColor().Address() && _q_pFormFocused->ID() == "OPEN")
{
Source = _q_pFormFocused->ImageColor();
}
else
return;
ImageForm* q_pForm = 0;
for(int i=0; i<_plpImageForm->Count();i++)
if((*_plpImageForm)[i]->ID()=="target")
{
q_pForm = (*_plpImageForm)[i];
break;
}
KImageColor Target=q_pForm->ImageColor();
//get histogram
int histo_S_R[256] = {0, };
int histo_S_G[256] = {0, };
int histo_S_B[256] = {0, };
int histo_T_R[256] = {0, };
int histo_T_G[256] = {0, };
int histo_T_B[256] = {0, };
for(unsigned int i=0; i<Source.Row(); i++){
for(unsigned int j=0; j<Source.Col(); j++)
{
histo_S_R[Source[i][j].r] += 1;
histo_S_G[Source[i][j].g] += 1;
histo_S_B[Source[i][j].b] += 1;
}
}
for(unsigned int i=0; i<Target.Row(); i++){
for(unsigned int j=0; j<Target.Col(); j++)
{
histo_T_R[Target[i][j].r] += 1;
histo_T_G[Target[i][j].g] += 1;
histo_T_B[Target[i][j].b] += 1;
}
}
//get P
double P_S_R[256] = {0, };
double P_S_G[256] = {0, };
double P_S_B[256] = {0, };
double P_T_R[256] = {0, };
double P_T_G[256] = {0, };
double P_T_B[256] = {0, };
for(unsigned int t=0; t<256; t++){
P_S_R[t] = (double)histo_S_R[t]/(double)Source.Size();
P_S_G[t] = (double)histo_S_G[t]/(double)Source.Size();
P_S_B[t] = (double)histo_S_B[t]/(double)Source.Size();
P_T_R[t] = (double)histo_T_R[t]/(double)Target.Size();
P_T_G[t] = (double)histo_T_G[t]/(double)Target.Size();
P_T_B[t] = (double)histo_T_B[t]/(double)Target.Size();
//qDebug() << t << " : " << P_S_R[t];
}
//get y , yp
double y_R[256] = {0, };
double y_G[256] = {0, };
double y_B[256] = {0, };
double yp_R[256] = {0, };
double yp_G[256] = {0, };
double yp_B[256] = {0, };
y_R[0] = P_S_R[0];
y_G[0] = P_S_G[0];
y_B[0] = P_S_B[0];
yp_R[0] = P_T_R[0];
yp_G[0] = P_T_G[0];
yp_B[0] = P_T_B[0];
for(unsigned int r=1; r<256; r++){
y_R[r] = y_R[r-1] + P_S_R[r];
//r_R[r] = T_R[r] * 255;
y_G[r] = y_G[r-1] + P_S_G[r];
//r_G[r] = T_G[r] * 255;
y_B[r] = y_B[r-1] + P_S_B[r];
//r_B[r] = T_B[r] * 255;
yp_R[r] = yp_R[r-1] + P_T_R[r];
//r_R[r] = T_R[r] * 255;
yp_G[r] = yp_G[r-1] + P_T_G[r];
//r_G[r] = T_G[r] * 255;
yp_B[r] = yp_B[r-1] + P_T_B[r];
//r_B[r] = T_B[r] * 255;
//qDebug() << r << " : " << yp_R[r];
}
int tr_R[256] = {0, };
int tr_G[256] = {0, };
int tr_B[256] = {0, };
for(unsigned int i=0; i<256; i++){
double min_R = 100000.0, min_G = 100000.0, min_B = 100000.0;
for(unsigned int j = 0; j<256; j++)
{
if(min_R>std::fabs(y_R[i]-yp_R[j]))
{
min_R = std::fabs(y_R[i]-yp_R[j]);
tr_R[i] = j;
}
if(min_G>std::fabs(y_G[i]-yp_G[j]))
{
min_G = std::fabs(y_G[i]-yp_G[j]);
tr_G[i] = j;
}
if(min_B>std::fabs(y_B[i]-yp_B[j]))
{
min_B = std::fabs(y_B[i]-yp_B[j]);
tr_B[i] = j;
}
}
//qDebug() << i << " : " << min_R;
}
for(unsigned int i=0; i<256; i++)
{
qDebug() << i << " : " << tr_R[i];
}
for(unsigned int i=0; i<Source.Row(); i++){
for(unsigned int j=0; j<Source.Col(); j++)
{
Source[i][j].r=tr_R[Source[i][j].r];
Source[i][j].g=tr_G[Source[i][j].g];
Source[i][j].b=tr_B[Source[i][j].b];
}
}
ImageForm* q_pForm2 = new ImageForm(Source, "Histogram Matching", this);
_plpImageForm->Add(q_pForm2);
q_pForm2->show();
//ImageForm* q_pForm1 = new ImageForm(Target, "target", this);
//_plpImageForm->Add(q_pForm1);
//q_pForm1->show();
}
'21-1학기 > 컴퓨터비전' 카테고리의 다른 글
6. Hough Transform (0) | 2021.08.19 |
---|---|
5. Canny Edge Operator (0) | 2021.08.19 |
4. Gaussian noise and salt&pepper noise & Box, Gaussian, Median Filter (0) | 2021.08.19 |
2. Otsu’s Thresholding and Labeling & dilation and erosion (0) | 2021.08.18 |
1. Sepia Tone (0) | 2021.08.18 |