天天看点

OpenCV学习(25) 直方图(2)

      在OpenCV中,也可以对三通道的图像,比如BGR,HSV等计算直方图。方法和计算单通道图像直方图相似,下面的代码描述了如何计算一个BGR三通道图像的直方图,需要注意的是,因为是三通道,每个通道取值都是[0,255],所以bin的数目达到了256*256*256,这时如果使用普通三维矩阵输出直方图结果,需要很大的空间,所以我们通常使用稀疏矩阵来保存输出结果。因为稀疏矩阵只保存非零值,这样可以节省存储空间。

int main( int argc, char** argv )

    {

    Mat src, dst;

    /// 打开图像

    src = imread( "../lenna.jpg");

    if( !src.data )

        { return -1; }

    /// 设定bin数目

    int histSize[3];

    float hranges[2];

    const float* ranges[3];

    int channels[3];

    // BGR彩色直方图

    // 准备一个color直方图数据, BGR格式

    histSize[0]= histSize[1]= histSize[2]= 256;

    hranges[0]= 0.0;    // BGR分量的范围

    hranges[1]= 255.0;

    ranges[0]= hranges; // BGR三个通道都是0-255范围

    ranges[1]= hranges;

    ranges[2]= hranges;

    channels[0]= 0;       // 三通道

    channels[1]= 1;

    channels[2]= 2;

    //结果直方图

    cv::SparseMat histo(3,histSize,CV_32F);

    // 计算直方图

    cv::calcHist(&src,

        1,            // 仅一副图像的直方图

        channels,    // 使用的channel

        cv::Mat(),    // 没有使用mask

        histo,        // 计算的结果

        3,           // 3D直方图

        histSize,    // bin的数量

        ranges       // BGR像素的范围

        );

    SparseMatConstIterator_<float>     it = histo.begin<float>(), it_end = histo.end<float>();

    double s = 0;

    int dims = histo.dims();

    int count=0;

    for(; it != it_end; ++it)

        {

       // 打印出稀疏矩阵的值

        const SparseMat::Node* n = it.node();

        printf("(");

        for(int i = 0; i < dims; i++)

            printf("%d%s", n->idx[i], i < dims-1 ? ", " : ")");

        printf(": %g\n", it.value<float>());

        s += *it;

        count++;

        }

    printf("Element sum is %g\n", s);

    printf("element num is %d\n", count);

    while(1)

        waitKey(0);

    return 0;

    }

程序运行效果如下,可以看到实际上稀疏矩阵中只存储了69579项,也就是图像只有69579种颜色。

OpenCV学习(25) 直方图(2)

程序代码:工程FirstOpenCV19

继续阅读