C++ OpenCV——直方图处理

C++ VS2010
Opencv 2.4.9
参考自:https://blog.csdn.net/u013263891/article/details/82987417
参考自:https://www.cnblogs.com/brucemu/archive/2013/10/17/3374558.html

文章目录

  • 直方图均衡
  • 直方图规定
  • 直方图局部均衡
  • 直方图统计增强图像

直方图均衡

#include
#include

using namespace std;
using namespace cv;
void main()
{
	//以灰度图读取图片 使其通道为1
	Mat img = imread("Fig0316(4)(bottom_left).tif",0);
	int gray[256]={0};//记录灰度级别下的像素个数
    int mn;//像素总数
    double r_prob[256]={0};//输入图像的概率
    double pdf[256]={0};//累积概率密度
    double r[256]={0};//r与s的映射
    double s_prob[256]={0};//均衡化之后的概率

	Mat img_temp = img.clone();
	//得出每个灰度级下像素个数
	for(int i = 0;i<img.rows;i++)
	{
		for(int j = 0;j<img.cols;j++)
		{
			int gray_value = img.at<uchar>(i,j);
			gray[gray_value]++;
		}
	}
	//得出每个灰度级概率分布
	mn = img.rows*img.cols;
	for(int i = 0;i<256;i++)
	{
		r_prob[i] = ((double)gray[i])/mn;
	}
	//得出每个灰度级概率密度函数
	pdf[0] = r_prob[0];
	for(int i = 1;i<256;i++)
	{
		pdf[i] = pdf[i-1] + r_prob[i];
	}

	//计算直方图均衡映射的各个灰度级个数
	for(int i = 0;i<256;i++){
		r[i] = (int)cvRound(255*pdf[i]);
	}

	//重新绘制图片 根据上述的灰度值均衡的结果
	for(int i = 0;i<img.rows;i++)
	{
		for(int j = 0;j<img.cols;j++)
		{
			int gray_value = img.at<uchar>(i,j);
			img_temp.at<uchar>(i,j) = r[gray_value];
		}
	}



	imshow("原图像",img);
	imshow("Mine_code",img_temp);


	//直方图显示
	int bins=256;
    int hist_size[]={bins};
    float range[]={0,256};
    const float* ranges[]={range};
    cv::Mat histsrc,histdst;
    int channels[]={0};

	/*
	const Mat* images:输入图像
 	int nimages:输入图像的个数
	const int* channels:需要统计直方图的第几通道
	InputArray mask:掩膜,,计算掩膜内的直方图  ...Mat()
	OutputArray hist:输出的直方图数组
	int dims:需要统计直方图通道的个数
	const int* histSize:指的是直方图分成多少个区间,就是 bin的个数
	const float** ranges: 统计像素值得区间
	bool uniform=true::是否对得到的直方图数组进行归一化处理
	bool accumulate=false:在多个图像时,是否累计计算像素值得个数
	*/
    calcHist(&img,1,channels,Mat(),histsrc,1,hist_size,ranges,true,false);
    calcHist(&img_temp,1,channels,Mat(),histdst,1,hist_size,ranges);
 
    cout<<histsrc.size()<<endl;
 
    int scale=1;
    Mat srcImage(256*scale,256,CV_8U,cv::Scalar(0));
    Mat dstImage(256*scale,256,CV_8U,cv::Scalar(0));
 
    double maxValue=0;
    double minValue=0;
 
    minMaxLoc(histsrc,&minValue,&maxValue,0,0);
	cout<<sum(histsrc)<<endl;
    //int hpt=saturate_cast(255);
	int hpt=255;
	cout<<"原直方图"<<endl;
    for(int i=0;i<256;i++){
        float binValue=histsrc.at<float>(i);
		
		cout<<binValue<<"  ";
        int realValue=saturate_cast<int>(binValue*hpt/maxValue);
        rectangle(srcImage,Point(i*scale,255),Point((i+1)*scale-1,256-realValue),
                      Scalar(255));
    }
 
    minMaxLoc(histdst,&minValue,&maxValue,0,0);
    hpt=saturate_cast<int>(255);
	cout<<"直方图均衡后的直方图"<<endl;
    for(int i=0;i<256;i++){
        float binValue=histdst.at<float>(i);
		cout<<binValue<<"  ";
        int realValue=saturate_cast<int>(binValue*hpt/maxValue);
        rectangle(dstImage,Point(i*scale,255),Point((i+1)*scale-1,256-realValue),
                      Scalar(255));
    }
 
    imshow("srcImage",srcImage);
    imshow("dstImage",dstImage);

    waitKey(0);
}

C++ OpenCV——直方图处理_第1张图片

直方图规定

void histo_match()
{
	Mat src=cv::imread("Fig0308(a)(fractured_spine).tif",0);
	
	
	int gray[256]={0};//记录灰度级别下的像素个数
    int mn=src.cols*src.rows;//像素总数
 
    double r_pdf[256]={0};//输入图像的概率
    double r_cdf[256]={0};//累积概率密度
    double r[256]={0};//对应的s T(r)
 
    int z[256]={0};//对应的G(z)
    double z_pdf[256];//pz(z)
    double z_cdf[256]={0};//z的累积分布概率
 
    cv::Mat dst=src.clone();
    cv::Mat spe=src.clone();

	//记录灰度级别下的像素个数
    for(int row=0;row<src.rows;row++){
        for(int col=0;col<src.cols;col++){
            int g=src.at<uchar>(row,col);
            gray[g]++;
        }
    }

	//统计高斯函数直方图像素总数(虚拟)
	z_pdf[0] = 0;
    double sum=0;
    for(int i=0;i<256;i++){
        double r=(double)i/255.0;
        z_pdf[i+1]=twoModeGauss(r);
        sum+=z_pdf[i+1];
    }


	//计算pr(r) pz(z)概率密度函数
	for(int i = 0;i<256;i++)
	{
		r_pdf[i] = ((double)gray[i])/mn;
		z_pdf[i] = z_pdf[i]/sum;
	}

	//计算r和z的cdf  累计分布函数
    z_cdf[0]=z_pdf[0];
    r_cdf[0]=r_pdf[0];
    for(int i=1;i<256;i++){
        r_cdf[i]=r_cdf[i-1]+r_pdf[i];
        z_cdf[i]=z_cdf[i-1]+z_pdf[i];
    }

	//根据变换函数计算相应灰度值、
	for(int i=0;i<256;i++)
	{
		int s = cvRound(255*r_cdf[i]);
		r[i] = s;
		int z_value = cvRound(255*z_cdf[i]);
		z[i] = z_value;
	}

	//直方图均衡化
	for(int row = 0;row<src.rows;row++)
	{
		for(int col = 0;col<src.cols;col++)
		{
			dst.at<uchar>(row,col) = r[src.at<uchar>(row,col)]; 
		}
	}

	//直方图规定
	for(int row = 0;row<src.rows;row++)
	{
		for(int col = 0;col<src.cols;col++)
		{
			int value = src.at<uchar>(row,col);
			for(int i = 0;i<256;i++)
			{
				if(z[value] == r[i])
				{
					spe.at<uchar>(row,col) = i;
				}
			}
		}
	}



	//显示图片
    cv::imshow("src",src);
    cv::imshow("dst",dst);
    cv::imshow("spe",spe);
 
    //显示直方图
    Mat src_histo = showHisto(src);
	imshow("原图像直方图",src_histo);
    Mat dst_histo = showHisto(dst);
	imshow("直方图均衡图像直方图",dst_histo);
    Mat sqe_histo = showHisto(spe);
	imshow("直方图规定图像直方图",sqe_histo);
    waitKey(0);
}

C++ OpenCV——直方图处理_第2张图片


直方图局部均衡

#include
#include

using namespace std;
using namespace cv;

int box_length = 13;
int box_center = (box_length-1)/2;

void  localhisto(Mat &img)
{

	int gray[256]={0};//记录灰度级别下的像素个数
    int mn;//像素总数
    double r_prob[256]={0};//输入图像的概率
    double pdf[256]={0};//累积概率密度
    double r[256]={0};//r与s的映射
    double s_prob[256]={0};//均衡化之后的概率

	for(int i = 0;i<img.rows;i++)
	{
		for(int j = 0;j<img.cols;j++)
		{
			int gray_value = img.at<uchar>(i,j);
			gray[gray_value]++;
		}
	}
	//得出每个灰度级概率分布
	mn = img.rows*img.cols;
	for(int i = 0;i<256;i++)
	{
		r_prob[i] = ((double)gray[i])/mn;
	}
	//得出每个灰度级概率密度函数
	pdf[0] = r_prob[0];
	for(int i = 1;i<256;i++)
	{
		pdf[i] = pdf[i-1] + r_prob[i];
	}

	//计算直方图均衡映射的各个灰度级个数
	for(int i = 0;i<256;i++){
		r[i] = (int)cvRound(255*pdf[i]);
	}

	//重新绘制图片 根据上述的灰度值均衡的结果
	int gray_value = img.at<uchar>(box_center,box_center);
	img.at<uchar>(box_center,box_center) = r[gray_value];
}


int main(){
	cv::Mat src=cv::imread("Fig0326(a)(embedded_square_noisy_512).tif",0);
	cv::Mat dst=src.clone();
	Mat temp;
	//512  512
	for(int row = box_center;row<src.rows-box_center;row++){
		for(int col = box_center;col<src.cols-box_center;col++)
		{
			temp = dst(Range(row-box_center,row+box_center),Range(col-box_center,col+box_center));
			localhisto(temp);
			dst(Range(row-box_center,row+box_center),Range(col-box_center,col+box_center)) = temp;
		}
	}
	Mat histoglobal = src.clone();	
	Mat seconddst = src.clone();
	for(int row = box_center;row<src.rows-box_center;row+=box_length){
		for(int col = box_center;col<src.cols-box_center;col+=box_length)
		{
			temp = seconddst(Range(row-box_center,row+box_center),Range(col-box_center,col+box_center));
			localhisto(temp);
			seconddst(Range(row-box_center,row+box_center),Range(col-box_center,col+box_center)) = temp;
		}
	}
	localhisto(histoglobal);
	cv::imshow("原图像",src);
	cv::imshow("局部均衡化",dst);
	cv::imshow("局部均衡化(简化版会有棋盘效应)",seconddst);
	cv::imshow("全局均衡化",histoglobal);
	cv::waitKey(0);
	return 0;
}

C++ OpenCV——直方图处理_第3张图片


直方图统计增强图像

#include 
#include
 
double getMean(double*r_pdf){
    double m=0;
    for(int i=0;i<256;i++)
        m+=i*r_pdf[i];
    return m;
}
 
double getVariance(double *r_pdf,double m)
{
    double delta=0;
    for(int i=0;i<256;i++)
        if(r_pdf[i]!=0)
            delta+=(pow((i-m),2)*r_pdf[i]);
    return delta;
}
 
void init(double *r_pdf){
    for(int i=0;i<256;i++){
        r_pdf[i]=0;
    }
}
 
void histStatistic(cv::Mat &src,int dim,float k0,float k1,float k2,float E){
    if(dim%2==0){
       dim = dim+1;
    }
 
    int width=src.rows;
    int height=src.cols;
    int mn=width*height;
    double r_pdf[256]={};
    for(int row=0;row<src.rows;row++){
        for(int col=0;col<src.cols;col++){
            int g=src.at<uchar>(row,col);
            r_pdf[g]+=1.0/mn;
        }
    }
 
    double mean=getMean(r_pdf);
    double delta=getVariance(r_pdf,mean);
    double delta1=std::sqrt(delta);
    double mxy=0;
    double deltaxy=0;
    double local=dim*dim;
    for(int i=dim/2;i<height-dim/2-1;i++)
    {
        for(int j=dim/2;j<width-dim/2;j++){
            init(r_pdf);
            //统计局部直方图
            for(int p=j-dim/2;p<j+dim/2+1;p++){
                for(int q=i-dim/2;q<i+dim/2+1;q++){
                    int g=src.at<uchar>(p,q);
                    r_pdf[g]+=1.0/local;
                }
            }
            mxy=getMean(r_pdf);
            deltaxy=getVariance(r_pdf,mxy);
            double deltaxy1=sqrt(deltaxy);
            if(mxy<=mean*k0&&deltaxy1<=k2*delta1&&deltaxy1>=k1*delta1){
                src.at<uchar>(j,i)=src.at<uchar>(j,i)*E;
            }
        }
    }
}
 
int main(){
    cv::Mat src=cv::imread("Fig0327(a)(tungsten_original).tif",0);
    cv::Mat dst;
    dst=src.clone();
    histStatistic(dst,7,0.4,0.02,0.4,10);
    cv::imshow("src",src);
    cv::imshow("dst",dst);
cv::waitKey(0);
}

C++ OpenCV——直方图处理_第4张图片

你可能感兴趣的:(OpenCV,opencv,图像处理,直方图均衡,直方图规定,直方图统计)