zoukankan      html  css  js  c++  java
  • 直方图匹配+c语言+opencv

    调用:

    	cv::Mat ref_glass, src_glass;
    	cv::Mat dst_glass = cv::Mat::zeros(src_glass.rows, src_glass.cols, src_glass.type());
    	HistSpecify(src_glass, ref_glass, dst_glass);

    class Histogram1D
    {
    private:
    	int histSize[1]; // 项的数量
    	float hranges[2]; // 统计像素的最大值和最小值
    	const float* ranges[1];
    	int channels[1]; // 仅计算一个通道
    
    public:
    	Histogram1D()
    	{
    		// 准备1D直方图的参数
    		histSize[0] = 256;
    		hranges[0] = 0.0f;
    		hranges[1] = 255.0f;
    		ranges[0] = hranges;
    		channels[0] = 0;
    	}
    
    	cv::Mat getHistogram(const cv::Mat &image)
    	{
    		cv::Mat hist;
    		// 计算直方图
    		calcHist(&image,// 要计算图像的
    			1,                // 只计算一幅图像的直方图
    			channels,        // 通道数量
    			cv::Mat(),            // 不使用掩码
    			hist,            // 存放直方图
    			1,                // 1D直方图
    			histSize,        // 统计的灰度的个数
    			ranges);        // 灰度值的范围
    		return hist;
    	}
    
    	cv::Mat getHistogramImage(const cv::Mat &image)
    	{
    		cv::Mat hist = getHistogram(image);
    
    		//查找最大值用于归一化
    		double maxVal = 0;
    
    		minMaxLoc(hist, NULL, &maxVal);
    
    		//绘制直方图的图像
    		cv::Mat histImg(histSize[0], histSize[0], CV_8U, cv::Scalar(255));
    
    		// 设置最高点为最大值的90%
    		double hpt = 0.9 * histSize[0];
    		//每个条目绘制一条垂直线
    		for (int h = 0; h < histSize[0]; h++)
    		{
    			//直方图的元素类型为32位浮点数
    			float binVal = hist.at<float>(h);
    			int intensity = static_cast<int>(binVal * hpt / maxVal);
    			line(histImg, cv::Point(h, histSize[0]),
    				cv::Point(h, histSize[0] - intensity), cv::Scalar::all(0));
    		}
    		return histImg;
    	}
    };
    /**
     * @brief HistSpecify 对灰度图像进行直方图规定化
     * @param src 输入图像
     * @param ref 参考图像,解析参考图像的直方图并用于规定化
     * @param result 直方图规定化后的图像
     * @note 手动设置一个直方图并用于规定化比较麻烦,这里使用一个参考图像来进行
     */
    static void HistSpecify(const cv::Mat &src, const cv::Mat &ref, cv::Mat &result)
    {
    	Histogram1D hist1D;
    	cv::Mat src_hist = hist1D.getHistogram(src);
    	cv::Mat dst_hist = hist1D.getHistogram(ref);
    
    	float src_cdf[256] = { 0 };
    	float dst_cdf[256] = { 0 };
    
    	// 直方图进行归一化处理
    	src_hist /= (src.rows * src.cols);
    	dst_hist /= (ref.rows * ref.cols);
    
    	// 计算原始直方图和规定直方图的累积概率
    	for (int i = 0; i < 256; i++)
    	{
    		if (i == 0)
    		{
    			src_cdf[i] = src_hist.at<float>(i);
    			dst_cdf[i] = dst_hist.at<float>(i);
    		}
    		else
    		{
    			src_cdf[i] = src_cdf[i - 1] + src_hist.at<float>(i);
    			dst_cdf[i] = dst_cdf[i - 1] + dst_hist.at<float>(i);
    		}
    	}
    
    	// 累积概率的差值
    	float diff_cdf[256][256];
    	for (int i = 0; i < 256; i++)
    		for (int j = 0; j < 256; j++)
    			diff_cdf[i][j] = fabs(src_cdf[i] - dst_cdf[j]);
    
    	// 构建灰度级映射表
    	cv::Mat lut(1, 256, CV_8U);
    	for (int i = 0; i < 256; i++)
    	{
    		// 查找源灰度级为i的映射灰度
    		// 和i的累积概率差值最小的规定化灰度
    		float min = diff_cdf[i][0];
    		int index = 0;
    		for (int j = 1; j < 256; j++)
    		{
    			if (min > diff_cdf[i][j])
    			{
    				min = diff_cdf[i][j];
    				index = j;
    			}
    		}
    		lut.at<uchar>(i) = static_cast<uchar>(index);
    	}
    
    	// 应用查找表,做直方图规定化
    	LUT(src, lut, result);
    }
    

      

    
    
  • 相关阅读:
    Windows 10 字体替换
    Windows 任务栏增加秒显示
    CCProxy v8.0 代理服务器
    Git RPM软件包 && 源码包
    Google Chrome 浏览器最新版本 71.0.3578.98(正式版本) (64 位)
    Linux 查询公网出口IP
    Windows 10 Enterprise LTSC做Windows To Go蓝屏无法进入系统
    Nginx编译./configure翻译
    Windows 10 快捷键
    JDBC连接MySQL
  • 原文地址:https://www.cnblogs.com/wjjcjj/p/13999812.html
Copyright © 2011-2022 走看看