【问题标题】:Is there a way to equalize the histogram of a 16-bits per sample image using OpenCV?有没有办法使用 OpenCV 均衡每个样本图像 16 位的直方图?
【发布时间】:2014-03-11 15:21:30
【问题描述】:

我正在使用 16 位/示例图像。
是否有(简单)方法来执行此类图像的直方图均衡(不能转换为 8bps)?

【问题讨论】:

    标签: c++ opencv image-processing histogram


    【解决方案1】:

    OpenCV 中的equalizeHist 只需要 8 位数据。

    但 OpenCV 中的图像归一化不限于 8 位数据。请参阅它的描述here。在您的情况下,对函数的调用应如下所示:

    normalize(src_image, dst_image, 0, 65535, NORM_MINMAX);
    

    如果你想提高图像的对比度,首先尝试标准化,只有当这不起作用时才尝试均衡。标准化速度更快,破坏性更小。

    参考:http://answers.opencv.org/question/3176/improve-contrast-of-a-16u-image/

    【讨论】:

    • 对不起,我没有提到,图像已经标准化(0-65535),但大多数样本在 5000-9000 范围内。谢谢。
    • 好吧,再想一想,我可以做一个简单的非线性变换,它会扩展 5000-9000 的值范围并以低频(低出现次数)缩小剩余的两个值范围.我刚刚发现您提到的链接线程中存在相同的答案。无论如何,谢谢你的想法:)
    【解决方案2】:

    截至目前,OpenCV equalizeHist 仅支持 8 位图像。我基于 OpenCV 实现 here 创建了 16 位直方图均衡函数 here

    void equalizeHist16Bit(const cv::Mat &_src, cv::Mat &_dst)
    {
        _dst = _src.clone();
    
        const int hist_sz = 65536;
        int *hist = new int[hist_sz] {};
        int *lut = new int[hist_sz] {};
    
        for (int y = 0; y < _src.rows; y++)
            for (int x = 0; x < _src.cols; x++)
                hist[(int)_src.at<unsigned short int>(y, x)]++;
    
        auto i = 0;
        while (!hist[i]) ++i;
    
        auto total = (int)_src.total();
        if (hist[i] == total) 
        {
            _dst.setTo(i);
            return;
        }
    
        float scale = (hist_sz - 1.f) / (total - hist[i]);
        auto sum = 0;
    
        for (lut[i++] = 0; i < hist_sz; ++i) 
        {
            sum += hist[i];
            lut[i] = cv::saturate_cast<ushort>(sum * scale);
        }
    
        for (int y = 0; y < _src.rows; y++)
            for (int x = 0; x < _src.cols; x++)
            {
                _dst.at<unsigned short int>(y, x) = lut[(int)_src.at<unsigned short int>(y, x)];
            }
    }
    

    【讨论】:

      【解决方案3】:
      #Simple implementation in python 
      #Reference: https://github.com/torywalker/histogram-equalizer/blob/master/HistogramEqualization.ipynb
      
      import cv2
      import numpy as np
      import matplotlib.pyplot as plt
      img_tif=cv2.imread("scan.tif",cv2.IMREAD_ANYDEPTH)
      img = np.asarray(img_tif)
      flat = img.flatten()
      hist = get_histogram(flat,65536)
      #plt.plot(hist)
      
      cs = cumsum(hist)
      # re-normalize cumsum values to be between 0-255
      
      # numerator & denomenator
      nj = (cs - cs.min()) * 65535
      N = cs.max() - cs.min()
      
      # re-normalize the cdf
      cs = nj / N
      cs = cs.astype('uint16')
      img_new = cs[flat]
      #plt.hist(img_new, bins=65536)
      #plt.show(block=True)
      img_new = np.reshape(img_new, img.shape)
      cv2.imwrite("contrast.tif",img_new)
      

      【讨论】:

      • 欢迎来到 Stack Overflow!请详细说明此代码的作用以及它如何帮助解决问题。仅代码的答案在这里被认为质量有点差,应该加上一些解释。
      【解决方案4】:

      Python 中的简单实现
      参考:https://github.com/torywalker/histogram-equalizer/blob/master/HistogramEqualization.ipynb

      import cv2
      import numpy as np
      import matplotlib.pyplot as plt
      img_tif=cv2.imread("scan_before threthold_873.tif",cv2.IMREAD_ANYDEPTH)
      img = np.asarray(img_tif)
      flat = img.flatten()
      hist = get_histogram(flat,65536)
      #plt.plot(hist)
      #
      cs = cumsum(hist)
      # re-normalize cumsum values to be between 0-255
      
      # numerator & denomenator
      nj = (cs - cs.min()) * 65535
      N = cs.max() - cs.min()
      
      # re-normalize the cdf
      cs = nj / N
      cs = cs.astype('uint16')
      img_new = cs[flat]
      #plt.hist(img_new, bins=65536)
      #plt.show(block=True)
      img_new = np.reshape(img_new, img.shape)
      cv2.imwrite("contrast.tif",img_new)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-01-18
        • 1970-01-01
        • 2010-12-23
        • 2020-03-16
        • 1970-01-01
        • 2013-02-07
        • 1970-01-01
        相关资源
        最近更新 更多