直方图对于暗图像不准确

时间:2014-04-17 11:53:23

标签: c++ c histogram yuv

我正在使用下一个算法来计算YUV420sp图像的直方图。似乎工作,但对于完全黑暗的图像,结果不是100%准确。当图像较暗时,我希望在直方图的左侧有一个高选择,显示图像太暗,但这种情况下的算法显示的是平线,没有选择。在其他光线情况下,直方图似乎是准确的。

void calculateHistogram(const unsigned char* yuv420sp, const int yuvWidth, const int yuvHeight, const int histogramControlHeight, int* outHistogramData)
{
    const int BINS = 256;

    // Clear the output

    memset(outHistogramData, 0, BINS * sizeof(int));

    // Get YUV brightness values

    const int totalPixels = yuvWidth * yuvHeight;

    for (int index = 0; index < totalPixels; index++)
    {
        char brightness = yuv420sp[index];
        outHistogramData[brightness]++;
    }

    // Get the maximum brightness

    int maxBrightness = 0;

    for (int index = 0; index < BINS; index++)
    {
        if (outHistogramData[index] > maxBrightness)
        {
            maxBrightness = outHistogramData[index];
        }
    }

    // Normalize to fit the UI control height

    const int maxNormalized = BINS * histogramControlHeight / maxBrightness;

    for(int index = 0; index < BINS; index++)
    {
        outHistogramData[index] = (outHistogramData[index] * maxNormalized) >> 8;
    }
}

[由galop1n解决]虽然Galop1n实现更好,但我正在更新这个更正,以防万一对任何人都有用。

的变化:

1)将亮度值读入unsigned char而不是char。

2)将UI规范化划分放入规范化循环。

void calculateHistogram(const unsigned char* yuv420sp, const int yuvWidth, const int yuvHeight, const int histogramCanvasHeight, int* outHistogramData)
{
    const int BINS = 256;

    // Clear the output

    memset(outHistogramData, 0, BINS * sizeof(int));

    // Get YUV brightness values

    const int totalPixels = yuvWidth * yuvHeight;

    for (int index = 0; index < totalPixels; index++)
    {
        unsigned char brightness = yuv420sp[index];
        outHistogramData[brightness]++;
    }

    // Get the maximum brightness

    int maxBrightness = 0;

    for (int index = 0; index < BINS; index++)
    {
        if (outHistogramData[index] > maxBrightness)
        {
            maxBrightness = outHistogramData[index];
        }
    }

    // Normalize to fit the UI control height

    for(int index = 0; index < BINS; index++)
    {
        outHistogramData[index] = outHistogramData[index] * histogramCanvasHeight / maxBrightness;
    }
}

2 个答案:

答案 0 :(得分:1)

您的实施中至少存在两个错误。

  1. 由于使用临时类型的签名字符而按亮度编制索引。
  2. 最终归一化结果可能受控制高度值和bin中像素的最大计数的影响。由于这个原因,这个部门实际上不能放在循环之外。
  3. 我还建议使用std::array(需要c ++ 11)来存储结果而不是原始指针,因为调用者没有为使用该函数的内容分配足够的空间。< / p>

    #include <algorithm>
    #include <array>
    
    void calculateHistogram(const unsigned char* yuv420sp, const int yuvWidth, const int yuvHeight, const int histogramControlHeight, std::array<int, 256> &outHistogramData ) {
        outHistogramData.fill(0);
        std::for_each( yuv420sp, yuv420sp + yuvWidth * yuvHeight, [&](int e) {
           outHistogramData[e]++;
        } );
        int maxCountInBins = * std::max_element( begin(outHistogramData), end(outHistogramData) );
        for( int &bin : outHistogramData )
            bin = bin * histogramControlHeight / maxCountInBins;
    }
    

答案 1 :(得分:0)

如果图像maxBrightness的最大亮度为零,则maxNormalized的计算将除以零。我怀疑这是你的问题所在。

如果没有更好地了解您正在尝试建立的规范化条件,我不确定您现在可以选择哪种替代方案。