首页 > 编程语言 >【计算机视觉1】----- 图像增强算法(对比度增强、直方图均衡化)

【计算机视觉1】----- 图像增强算法(对比度增强、直方图均衡化)

时间:2023-05-21 15:32:45浏览次数:36  
标签:std 灰度级 均衡化 图像增强 直方图 vector 图像 cv


直方图均衡化

直方图修正(Histogram Equalization)是一种常见的图像增强技术,它通过重新分布图像像素的灰度值来增强图像的对比度和亮度。直方图修正的基本思想是将图像的灰度值范围映射到一个更广泛的范围,从而使图像的灰度级分布更加均匀。

注意,在运行代码之前,请确保已安装并配置了OpenCV库。

·计算直方图

首先,统计图像中每个灰度级的像素数量,形成一个直方图。直方图表示了图像中不同灰度级的像素分布情况。

// 计算输入图像的最小灰度值和最大灰度值
    double minValue, maxValue;
    cv::minMaxLoc(image, &minValue, &maxValue);

    // 将图像的灰度值范围映射到更广泛的范围(例如,0-255)
    cv::Mat mappedImage;
    cv::convertScaleAbs(image, mappedImage, 255.0 / (maxValue - minValue), -minValue * 255.0 / (maxValue - minValue));

    // 显示原始图像和映射后的图像
    cv::imshow("原始图像", image);
    cv::imshow("映射后的图像", mappedImage);

    cv::waitKey(0);
    cv::destroyAllWindows();

minMaxLoc() 函数找到输入图像的最小灰度值和最大灰度值。然后,使用 convertScaleAbs() 函数将图像的灰度值范围映射到一个更广泛的范围(例如,0-255),以进行直方图修正。

最后,通过 imshow() 函数显示原始图像和灰度值范围映射后的图像。

请注意,这种方法只是简单地将图像的灰度值范围线性映射到一个更广泛的范围。对于更复杂的直方图修正方法,可能需要使用其他算法和技术。 假设输入图像为灰度图像。如果要计算彩色图像的直方图,需要先将图像转换为灰度图像。

·计算累积直方图

通过对直方图进行累积操作,计算出每个灰度级之前的像素总数。并将累积直方图归一化为表示图像中小于等于某个灰度级的像素所占比例。

// 计算直方图
    cv::Mat hist;
    int histSize = 256;
    float range[] = {0, 256};
    const float* histRange = {range};
    cv::calcHist(&image, 1, nullptr, cv::Mat(), hist, 1, &histSize, &histRange);

    // 计算累积直方图
    cv::Mat cumulativeHist(histSize, 1, CV_32F);
    cumulativeHist.at<float>(0) = hist.at<float>(0);
    for (int i = 1; i < histSize; ++i)
    {
        cumulativeHist.at<float>(i) = cumulativeHist.at<float>(i - 1) + hist.at<float>(i);
    }

    // 归一化累积直方图
    cv::normalize(cumulativeHist, cumulativeHist, 0, 1, cv::NORM_MINMAX);

calcHist() 函数计算输入图像的直方图,并通过累积操作计算出每个灰度级之前的像素总数。然后,使用 normalize() 函数将累积直方图归一化,以表示图像中小于等于某个灰度级的像素所占比例,imshow() 函数显示原始图像和累积直方图。

这边要注意,假设输入图像为灰度图像,如果要计算彩色图像的直方图或累积直方图,需要将图像转换为灰度图像或分别对各个通道进行处理


·归一化累积直方图

归一化累积直方图的原理是将累积直方图的取值范围映射到 [0, 1] 之间,使其具有统一的尺度。这样做的目的是消除不同图像之间的像素总数差异,使得它们的累积直方图能够更好地进行比较和分析。

// 计算累积直方图
std::vector<int> computeCumulativeHistogram(const std::vector<int>& histogram) 
{
    std::vector<int> cumulativeHistogram(histogram.size(), 0);
    cumulativeHistogram[0] = histogram[0];

    for (int i = 1; i < histogram.size(); ++i) {
        cumulativeHistogram[i] = cumulativeHistogram[i - 1] + histogram[i];
    }

    return cumulativeHistogram;
}

// 归一化累积直方图
std::vector<double> normalizeCumulativeHistogram(const std::vector<int>& cumulativeHistogram, int totalPixels)
{
    std::vector<double> normalizedHistogram(cumulativeHistogram.size());

    for (int i = 0; i < cumulativeHistogram.size(); ++i) {
        normalizedHistogram[i] = static_cast<double>(cumulativeHistogram[i]) / totalPixels;
    }

    return normalizedHistogram;
}
void CalculatehistogramModel
{
  // 示例直方图
    std::vector<int> histogram = {10, 20, 30, 40, 50};

    // 计算累积直方图
    std::vector<int> cumulativeHistogram = computeCumulativeHistogram(histogram);

    // 总像素数
    int totalPixels = cumulativeHistogram.back();

    // 归一化累积直方图
    std::vector<double> normalizedHistogram = normalizeCumulativeHistogram(cumulativeHistogram, totalPixels);
}

1.定义computeCumulativeHistogram 和 normalizeCumulativeHistogram函数,用于计算累积直方图和归一化累积直方图,computeCumulativeHistogram 函数接收一个直方图作为输入,返回计算得到的累积直方图。我们使用一个循环遍历直方图的每个灰度级,并将当前灰度级的像素值与前一个灰度级的累积值相加,以获得当前灰度级的累积直方图值。

2.normalizeCumulativeHistogram 函数接收累积直方图和总像素数作为输入,返回归一化的累积直方图。在此函数中,我们使用一个循环遍历累积直方图的每个值,并将其除以总像素数,以获得每个灰度级在图像中的占比,在 CalculatehistogramModel函数中,定义了一个直方图 histogram,其中包含了一些灰度级的像素数量,调用 computeCumulativeHistogram 函数,将示例直方图作为参数传递给它,以获得累积直方图。

3…获取累积直方图中的最后一个值,即总像素数,调用 normalizeCumulativeHistogram 函数,将累积直方图和总像素数作为参数传递给normalizeCumulativeHistogram函数,以获得归一化的累积直方图。 这样,得到了归一化的累积直方图,其中每个灰度级在图像中的占比值都被限制在 [0, 1] 范围内。


·计算目标直方图

计算目标直方图通常是指计算一幅图像或者一段图像区域中某个特定目标的灰度级分布情况。

// 计算目标直方图
std::vector<int> computeTargetHistogram(const std::vector<std::vector<int>>& image, int targetValue) {
    std::vector<int> histogram(256, 0);

    for (const auto& row : image) {
        for (int pixelValue : row) {
            if (pixelValue == targetValue) {
                histogram[pixelValue]++;
            }
        }
    }

    return histogram;
    
// 归一化直方图
std::vector<double> normalizeHistogram(const std::vector<int>& histogram, int totalPixels) {
    std::vector<double> normalizedHistogram(histogram.size());

    for (int i = 0; i < histogram.size(); ++i) {
        normalizedHistogram[i] = static_cast<double>(histogram[i]) / totalPixels;
    }

    return normalizedHistogram;
}

     // 示例图像
    std::vector<std::vector<int>> image = {
        {0, 1, 2, 2, 1},
        {1, 3, 2, 0, 2},
        {2, 1, 2, 3, 0},
        {2, 2, 1, 0, 1}
       };
    // 目标灰度级
    int targetValue = 2;

    // 计算目标直方图
    std::vector<int> targetHistogram = computeTargetHistogram(image, targetValue);
}

1.定义computeTargetHistogram 和 normalizeHistogram函数。用于计算目标直方图和归一化直方图。

2.computeTargetHistogram 函数接收一个图像和目标灰度级作为输入,返回计算得到的目标直方图。使用两个嵌套循环遍历图像中的每个像素值,并统计目标灰度级出现的次数,将其记录在对应的直方图位置上。

3.normalizeHistogram 函数接收直方图和总像素数作为输入,返回归一化的直方图。在此函数中,使用一个循环遍历直方图的每个值,并将其除以总像素数,以获得每个灰度级在图像中的占比。在 main 函数中,我们定义了一个示例图像 image,其中包含了一些像素值。

4.指定了目标灰度级 targetValue,用于计算目标直方图,调用 computeTargetHistogram 函数,将示例图像和目标灰度级作为参数传递给它,以获得目标直方图。计算总像素数,遍历图像的每一行,累加每一行的像素数量。

5.调用 normalizeHistogram 函数,将目标直方图和总像素数作为参数传递给它,以获得归一化的直方图。使用一个循环遍历归一化直方图的每个值。

这样,就得到了目标直方图和归一化的目标直方图,用于表示图像或图像区域中特定目标的灰度级分布情况。


·直方图映射(Histogram Equalization)

直方图映射是一种常用的图像增强技术,通过对图像的直方图进行调整,使得图像的对比度增强。

// 直方图映射
std::vector<int> histogramMapping(const std::vector<std::vector<int>>& image, const std::vector<int>& histogram) {
    std::vector<int> mappedImage;

    // 计算映射函数
    std::vector<int> mappingFunction(256, 0);
    int totalPixels = 0;
    for (int i = 0; i < histogram.size(); ++i) {
        totalPixels += histogram[i];
        mappingFunction[i] = static_cast<int>(round(255.0 * totalPixels / (image.size() * image[0].size())));
    }

    // 进行直方图映射
    for (const auto& row : image) {
        for (int pixelValue : row) {
            mappedImage.push_back(mappingFunction[pixelValue]);
        }
    }

    return mappedImage;
int main() {
    // 示例图像
    std::vector<std::vector<int>> image = {
        {100, 150, 200},
        {50, 75, 100},
        {200, 175, 125}
    };

    // 计算原始图像的直方图
    std::vector<int> histogram = computeHistogram(image);

    // 进行直方图映射
    std::vector<int> mappedImage = histogramMapping(image, histogram);
}

定义histogramMapping函数,用于计算原始图像的直方图和进行直方图映射,函数接收图像和原始图像的直方图作为输入,返回经过直方图映射后的图像。在此函数中,我们首先计算映射函数,即将原始图像的灰度级映射到新的灰度级。我们使用一个循环遍历原始图像直方图的每个灰度级,计算每个灰度级在新图像中所占的像素数量。定义一个嵌套循环遍历原始图像的函数循环遍历原始图像中的每个像素值,并根据映射函数将其映射到新的灰度级,将映射后的像素值存储在新的图像中。

将示例图像和原始图像的直方图作为参数传递给histogramMapping函数,以获得经过直方图映射后的图像。通过直方图映射后的图像,我们可以增强图像的对比度,是的图像像素中的细节更加明显。


·直方图均衡化

将图像的直方图进行变换,将原始图像的灰度级分布映射到一个更广泛的范围,从而增强图像的视觉效果。

// 计算直方图
    cv::Mat hist;
    int histSize = 256;
    float range[] = {0, 256};
    const float* histRange = {range};
    cv::calcHist(&image, 1, nullptr, cv::Mat(), hist, 1, &histSize, &histRange);

    // 计算累积直方图
    cv::Mat cumulativeHist(histSize, 1, CV_32F);
    cumulativeHist.at<float>(0) = hist.at<float>(0);
    for (int i = 1; i < histSize; ++i)
    {
        cumulativeHist.at<float>(i) = cumulativeHist.at<float>(i - 1) + hist.at<float>(i);
    }

    // 归一化累积直方图
    cv::normalize(cumulativeHist, cumulativeHist, 0, histSize - 1, cv::NORM_MINMAX);

    // 映射灰度值
    cv::Mat equalizedImage = image.clone();
    for (int i = 0; i < image.rows; ++i)
    {
        for (int j = 0; j < image.cols; ++j)
        {
            int pixel = image.at<uchar>(i, j);
            equalizedImage.at<uchar>(i, j) = cv::saturate_cast<uchar>(cumulativeHist.at<float>(pixel));
        }
    }

    // 显示原始图像、直方图和均衡化后的图像
    cv::imshow("原始图像", image);
    cv::imshow("直方图", hist);
    cv::imshow("均衡化后的图像", equalizedImage);

    cv::waitKey(0);
    cv::destroyAllWindows();

这段代码示例实现了一个基本的直方图修正算法,但要注意,这是一个全局的图像增强方法,可能会增加图像中噪声的可见性。在实际应用中,可能需要结合其他技术来进一步改进图像的质量和视觉效果。







标签:std,灰度级,均衡化,图像增强,直方图,vector,图像,cv
From: https://blog.51cto.com/u_16104273/6319577

相关文章

  • Python从零到壹丨图像增强的顶帽运算和底帽运算
    摘要:这篇文章详细介绍了顶帽运算和底帽运算,它们将为后续的图像分割和图像识别提供有效支撑。本文分享自华为云社区《[Python从零到壹]四十九.图像增强及运算篇之顶帽运算和底帽运算》,作者:eastmount。数学形态学(MathematicalMorphology)是一种应用于图像处理和模式识别领域的新......
  • 22.基于MATLAB的裂缝检测系统 可以实现直方图均衡化,中值滤波,对比度增
    22.基于MATLAB的裂缝检测系统可以实现直方图均衡化,中值滤波,对比度增强,然后二值化,提取出轮廓边缘,通过比较横向和纵向的像素变化,判断裂缝,通过图像像素本身,算出阈值信息,面积信息,长度信息,最大宽度信息,最小宽度信息,形状信息纵向裂缝等ID:995665749727603......
  • 1.图片去雾MATLAB代码 图像去雾技术 包括全局及局部直方图均衡化
    1.图片去雾MATLAB代码图像去雾技术包括全局及局部直方图均衡化和基于RETINEX理论去雾三种算法局部直方图和retinex(MSR)的参数,懂算法可以自己调节图像亮度含GUI界面只有代码。ID:495615931294745......
  • MATLAB图像增强代码 代码些许复杂,由本人一个朋友编写 是
    MATLAB图像增强代码代码些许复杂,由本人一个朋友编写是机器视觉和图像增强领域的应用,有gui界面,可以载入原图和参照强化的图像,读取参照图像的RGB或者HSV分量,并强化原图像,运行,corrction.m.结果如下图ID:925620010658083......
  • 【RDH隐藏】基于减少直方图移位中像素的无效移位的可逆数据隐藏附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • OpenCV图像直方图(16)
    在分析图像、物体和视频信息的时候,我们经常用直方图来表达我们关注的信息。直方图在计算机视觉中应用广泛。例如,通过判断帧与帧之间边缘和颜色的统计量是否出现巨大变化,来检测视频中场景的变换。在数字图像处理中,通常使用的是灰度直方图,灰度直方图是一种计算代价非常小但很有用的工......
  • 25.图像直方图
    1、图像直方图绘制图像直方图是图像处理中非常重要的像素统计结果,图像直方图不再表征任何的图像纹理信息,而是对图像像素的统计。由于同一物体无论是旋转还是平移在图像中都具有相同的灰度值,因此直方图具有平移不变性、放缩不变性等优点,因此可以用来查看图像整体的变化形式,例......
  • 图像增强
    两类图像增强方法空域:直接对像素操作频域:傅里叶变换,小波变换空域图像灰度级分布特点对比度越高,灰度级在空间内分布更加均匀。 直方图均衡化计算步骤原始图像直方图->累积概率分布直方图->均值化后的直方图核心:将累积概率分布的值以为总灰度级个数对其进行近似划......
  • opencv-python 4.10.4. 反投影直方图
    理论它由MichaelJ.Swain,DanaH.Ballard在他们的论文“Indexingviacolorhistograms”中提出。用简单的话来说,它到底是什么?它用于图像分割或查找图像中感兴趣的对象。简单地说,它创建了与输入图像大小相同(但是是单一通道)的图像,其中每个像素对应于该像素属于对象的概率。在......
  • opencv-python 4.10.3. 直方图3:2D直方图
    介绍我们学习计算并绘制了一维直方图。它之所以被称为一维,是因为我们只考虑一个特征,即像素的灰度强度值。但在二维直方图中,需要考虑两个特征。通常,它用于查找颜色直方图,其中两个特征是每个像素的色调值和饱和度值。OpenCV中的2D直方图它很简单,使用相同的函数cv.calcHist()计......