• [OpenCV] 直方图均衡化


    直方图是图像处理中最最最最基本的操作之一,这个基本操作是在太太太太常见了,同时也是很容易理解的操作,对于一些对比度稍微较低的图像,这是一个还挺不错的预处理操作。

    1、直方图

    先说直方图,直方图就是图像像素的统计表,这个表里记录着一幅图像中每个像素值在图像中出现的个数,一幅图只有一个灰度直方图,但是多幅图可能有相同的直方图,这是N对1的关系。所以在制作直方图的时候就很容易啦,创建一个包含所有像素灰阶的数组(比如,0到255),然后遍历图像,对应像素的在数组中的值加一即可。

    2、直方图均衡化

    最普通最常见最简单也是比较有效的直方图均衡化,就是在得到直方图后,将直方图的值逐个累加得到一个累计直方图,累计直方图的每个值除以图像总的像素个数,这样就得到了每阶像素在这个图像中的占比,以这个占比乘以255就得到均衡化处理过后的像素值。

    在代码实现上也比较简单,先申请一块大小为256的内存,然后遍历原图像,统计并记录像素:

    cv::Mat histMat = cv::Mat::zeros(1, 256, CV_32FC1);
    float *ptrHis = histMat.ptr<float>(0);
    for (int i = 0; i < src.rows; i++)
    {
        uchar *ptrSrc = src.ptr<uchar>(i);
        for (int j = 0; j < src.cols; j++)
        {
            int pix = (int)*(ptrSrc + j);
            *(ptrHis + pix) = *(ptrHis + pix) +  1;
        }
    }

    然后计算累计直方图:

    cv::Mat cHistMat = cv::Mat::zeros(1, 256, CV_32FC1);
    *(cHistMat.ptr<float>(0)) = *(histMat.ptr<float>(0));
    for (int i = 1; i < 256; i++)
    {
        *(cHistMat.ptr<float>(0) + i) = *(cHistMat.ptr<float>(0) + i - 1) + *(histMat.ptr<float>(0) + i);
    }
    for (int i = 0; i < 256; i++)
    {
        *(cHistMat.ptr<float>(0) + i) = *(cHistMat.ptr<float>(0) + i) / src.rows / src.cols * 255;
    }

    然后重新遍历图像,将新的像素值代替原来的像素值:

    cv::Mat dst;
    src.copyTo(dst);
    for (int i = 0; i < src.rows; i++)
    {
        uchar *ptrDst = dst.ptr<uchar>(i);
        for (int j = 0; j < src.cols; j++)
        {
            int pix = (int)*(ptrDst + j);
            *(ptrDst + j) = (uchar)(*(cHistMat.ptr<float>(0) + pix));
        }
    }

    完成,测试结果:

    洛阳城里见秋风,

    欲作家书意万重。

    复恐匆匆说不尽,

    行人临发又开封。

    上善若水,为而不争。
  • 相关阅读:
    贪婪与非贪婪模式
    Arduino语言介绍
    POJ 3249 记忆化搜索或拓扑排序
    POJ 3177 缩点 + 边双连通图
    POJ 1637 网络流构图
    hdu 1285 拓扑排序+优先队列
    POJ 3160 缩点+拓扑排序+简单dp
    POJ 3592 缩点+拓扑排序+最长路
    针对11级队员的暑假训练计划(初稿)
    POJ 2762 缩点+判断是否是最长链
  • 原文地址:https://www.cnblogs.com/Bearoom/p/11721740.html
Copyright © 2020-2023  润新知