opencv源码阅读之直方图均衡化(1)

         opencv实现直方图均衡化的函数为equalizeHist();在看了直方图均衡化原理后想要实现他,于是看了一下opencv的equalizeHist(),同时提高一下自己的编程水平。最后找到了这个函数的位置D:\OpenCV\opencv\sources\modules\imgproc\src
void cv::equalizeHist( InputArray _src, OutputArray _dst ) //InputArray接口类,只能作为函数的形参参数使用
{
    Mat src = _src.getMat();   //将传入的参数转换为Mat的结构
    CV_Assert( src.type() == CV_8UC1 ); //检查运行情况,如果出现错误,则显示错误信息。

    _dst.create( src.size(), src.type() ); //OutputArray是InputArray的派生类,需要注意在使用_OutputArray::getMat()之前一定要调用_OutputArray::create()为矩阵分配空间。
    Mat dst = _dst.getMat();

    if(src.empty())
        return;

    Mutex histogramLockInstance;

    const int hist_sz = EqualizeHistCalcHist_Invoker::HIST_SZ; //HIST_SZ = 256
    int hist[hist_sz] = {0,};
    int lut[hist_sz];

    EqualizeHistCalcHist_Invoker calcBody(src, hist, &histogramLockInstance);
    EqualizeHistLut_Invoker      lutBody(src, dst, lut);
    cv::Range heightRange(0, src.rows); //高度范围

    if(EqualizeHistCalcHist_Invoker::isWorthParallel(src)) //判断原始图像是否大于等于640*480;大于时
        parallel_for_(heightRange, calcBody);
    else
        calcBody(heightRange); //见补充一

    int i = 0;
    while (!hist[i]) ++i;

    int total = (int)src.total();//图像中元素总数
    if (hist[i] == total)你
    {
        dst.setTo(i); //将全部元素设置为i
        return;
    }

    float scale = (hist_sz - 1.f)/(total - hist[i]);//?
    int sum = 0;

    for (lut[i++] = 0; i < hist_sz; ++i)
    {
        sum += hist[i];
        lut[i] = saturate_cast<uchar>(sum * scale);//直方图均衡
    }

    if(EqualizeHistLut_Invoker::isWorthParallel(src))
        parallel_for_(heightRange, lutBody);//?
    else
        lutBody(heightRange);
}


//==========================补充说明一=========================//
calcBody(heightRange);//类的()重载
    void operator()( const cv::Range& rowRange ) const
    {
        int localHistogram[HIST_SZ] = {0, };

        const size_t sstep = src_.step;//每行的字节数

        int width = src_.cols;
        int height = rowRange.end - rowRange.start;

        if (src_.isContinuous()) //图像是否连续
        {
            width *= height;
            height = 1;
        }

        for (const uchar* ptr = src_.ptr<uchar>(rowRange.start); height--; ptr += sstep) //指向Mat矩阵行的首地址,ptr完成一次循环向后移动整行
        {
            int x = 0;
            for (; x <= width - 4; x += 4) //每4列进行一次处理
            {
                int t0 = ptr[x], t1 = ptr[x+1];
                localHistogram[t0]++; localHistogram[t1]++;  // int localHistogram[256] = { 0, };int数组;直方图每一维存储数据
                t0 = ptr[x+2]; t1 = ptr[x+3];
                localHistogram[t0]++; localHistogram[t1]++;
            }

            for (; x < width; ++x)
                localHistogram[ptr[x]]++;
        }

        cv::AutoLock lock(*histogramLock_);

        for( int i = 0; i < HIST_SZ; i++ )
            globalHistogram_[i] += localHistogram[i];
    }
    //========================补充说明二======================//
     lutBody(heightRange);//类的()重载
    void operator()( const cv::Range& rowRange ) const
    {
        const size_t sstep = src_.step;//每行的字节数
        const size_t dstep = dst_.step;

        int width = src_.cols;
        int height = rowRange.end - rowRange.start;
        int* lut = lut_;

        if (src_.isContinuous() && dst_.isContinuous())
        {
            width *= height;
            height = 1;
        }

        const uchar* sptr = src_.ptr<uchar>(rowRange.start);
        uchar* dptr = dst_.ptr<uchar>(rowRange.start);

        for (; height--; sptr += sstep, dptr += dstep)
        {
            int x = 0;
            for (; x <= width - 4; x += 4)
            {
                int v0 = sptr[x];
                int v1 = sptr[x+1];
                int x0 = lut[v0];
                int x1 = lut[v1];
                dptr[x] = (uchar)x0;
                dptr[x+1] = (uchar)x1;

                v0 = sptr[x+2];
                v1 = sptr[x+3];
                x0 = lut[v0];
                x1 = lut[v1];
                dptr[x+2] = (uchar)x0;
                dptr[x+3] = (uchar)x1;
            }

            for (; x < width; ++x)
                dptr[x] = (uchar)lut[sptr[x]];
        }
    }

\histogram.hpp(根据每个人的opencv安装位置不同决定)
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值