Skip to content

Instantly share code, notes, and snippets.

@terakun
Created August 2, 2020 16:29
Show Gist options
  • Save terakun/90801f85e2ae9d64a2b439276dac6e83 to your computer and use it in GitHub Desktop.
Save terakun/90801f85e2ae9d64a2b439276dac6e83 to your computer and use it in GitHub Desktop.
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <vector>
#include <array>
#include <stdio.h>
using namespace std;
using namespace cv;
void make_histogram_img(const cv::Mat &,cv::Mat &);
void histogram_matching(const cv::Mat &ref_img,const cv::Mat &src_img,cv::Mat &dst_img);
int main(){
cv::Mat ref_img,src_img , dst_img;
ref_img = imread( "./image4.jpg",0 );
src_img = imread( "./image5.jpg",0 );
histogram_matching(ref_img,src_img,dst_img);
cv::Mat ref_hist_img,src_hist_img,dst_hist_img;
make_histogram_img(ref_img,ref_hist_img);
make_histogram_img(src_img,src_hist_img);
make_histogram_img(dst_img,dst_hist_img);
cv::imshow("source image",src_img);
cv::imshow("source histogram",src_hist_img);
cv::imwrite("image4_hist.jpg",src_hist_img);
waitKey(0);
cv::imshow("reference image",ref_img);
cv::imshow("reference histogram",ref_hist_img);
cv::imwrite("image5_hist.jpg",ref_hist_img);
waitKey(0);
cv::imshow("destination image",dst_img);
cv::imshow("destination histogram",dst_hist_img);
cv::imwrite("dst.jpg",dst_img);
cv::imwrite("dst_hist.jpg",dst_hist_img);
waitKey(0);
return 0;
}
void make_histogram_img(const cv::Mat &src_img,cv::Mat &hist_img){
int histSize = 256;
float range[] = { 0, 256 } ;
const float* histRange = { range };
bool uniform = true; bool accumulate = false;
cv::Mat hist;
cv::calcHist( &src_img, 1, 0, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate );
int hist_w = 512, hist_h = 400;
int bin_w = cvRound( (double) hist_w/histSize );
hist_img = cv::Mat(hist_h,hist_w,CV_8UC3,cv::Scalar(0,0,0));
cv::normalize(hist, hist, 0, hist_img.rows, NORM_MINMAX, -1, Mat() );
for( int i = 1; i < histSize; i++ ){
line( hist_img, Point( bin_w*(i-1), hist_h - cvRound(hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(hist.at<float>(i)) ),
Scalar( 255, 255, 255), 2, 8, 0 );
}
}
void histogram_matching(const cv::Mat &ref_img,const cv::Mat &src_img,cv::Mat &dst_img){
std::vector<int> g_ref,g_src;
cv::Mat ref_hist,src_hist;
constexpr int histSize = 256;
float range[] = { 0, histSize } ;
const float* histRange = { range };
bool uniform = true; bool accumulate = false;
cv::calcHist( &src_img, 1, 0, Mat(), src_hist, 1, &histSize, &histRange, uniform, accumulate );
cv::calcHist( &ref_img, 1, 0, Mat(), ref_hist, 1, &histSize, &histRange, uniform, accumulate );
src_hist /= src_img.size().area();
ref_hist /= ref_img.size().area();
std::array<double,histSize> src_cdf,ref_cdf;
src_cdf[0] = src_hist.at<float>(0,0);
ref_cdf[0] = ref_hist.at<float>(0,0);
for(int i=1;i<histSize;++i){
src_cdf[i] = src_cdf[i-1] + src_hist.at<float>(0,i);
ref_cdf[i] = ref_cdf[i-1] + ref_hist.at<float>(0,i);
}
std::array<int,histSize> lookuptable;
for(int i=0;i<histSize;++i){
double min_v = 1.0e10;
int min_j;
for(int j=0;j<histSize;++j){
if(min_v > std::abs(src_cdf[i]-ref_cdf[j])){
min_v = std::abs(src_cdf[i]-ref_cdf[j]);
min_j = j;
}
}
lookuptable[i] = min_j;
}
dst_img = cv::Mat(src_img.size(),src_img.type());
for(int r=0;r<src_img.rows;++r){
const uchar *src_img_ptr = src_img.ptr<uchar>(r);
uchar *dst_img_ptr = dst_img.ptr<uchar>(r);
for(int c=0;c<src_img.cols;++c){
dst_img_ptr[c] = lookuptable[src_img_ptr[c]];
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment