基于C++的BMP图像直方图均衡化处理

一、实验目的

本次实验旨在通过C++语言实现对BMP格式图像文件的解析,并应用直方图均衡化算法来增强图像的对比度。实验过程中,我们不依赖任何第三方图像处理库,完全依靠标准C++和BMP文件格式规范自行编写代码。通过这个实验,我们将加深对图像文件结构的理解,并掌握直方图均衡化的基本原理和实现方法。

二、实验环境

开发工具:Visual Studio 2022

编程语言:C++

操作系统:Windows 11

图像格式:BMP(24位RGB)

三、实验步骤

1. BMP 文件解析

首先,我们需要编写一个函数LoadBitmap来读取BMP文件并解析其头部信息。该函数负责打开指定路径的BMP文件,读取文件头和信息头,检查文件格式是否为24位RGB,并将图像数据加载到内存中。

#pragma pack(push, 1)
struct BITMAPFILEHEADER {
    uint16_t bfType;
    uint32_t bfSize;
    uint16_t bfReserved1;
    uint16_t bfReserved2;
    uint32_t bfOffBits;
};

struct BITMAPINFOHEADER {
    uint32_t biSize;
    int32_t  biWidth;
    int32_t  biHeight;
    uint16_t biPlanes;
    uint16_t biBitCount;
    uint32_t biCompression;
    uint32_t biSizeImage;
    int32_t  biXPelsPerMeter;
    int32_t  biYPelsPerMeter;
    uint32_t biClrUsed;
    uint32_t biClrImportant;
};
#pragma pack(pop)

bool LoadBitmap(const std::string& filename, std::vector& imageBuffer, int& width, int& height) {
    std::ifstream file(filename, std::ios::binary);
    if (!file.is_open()) return false;

    BITMAPFILEHEADER fileHeader;
    BITMAPINFOHEADER infoHeader;
    file.read(reinterpret_cast<char*>(&fileHeader), sizeof(fileHeader));
    file.read(reinterpret_cast<char*>(&infoHeader), sizeof(infoHeader));

    if (fileHeader.bfType != 0x4D42 || // 'BM'
        infoHeader.biBitCount != 24) {  // Only 24-bit images are supported for simplicity
        file.close();
        return false;
    }

    width = infoHeader.biWidth;
    height = infoHeader.biHeight;
    size_t imageSize = infoHeader.biSizeImage ? infoHeader.biSizeImage : (width * height * 3);

    imageBuffer.resize(imageSize);
    file.seekg(fileHeader.bfOffBits, std::ios::beg);
    file.read(reinterpret_cast<char*>(imageBuffer.data()), imageSize);

    file.close();
    return true;
}

2. 直方图均衡化算法实现

接下来,我们实现了直方图均衡化的算法。这包括以下几个步骤:

灰度转换:将彩色图像转换为灰度图像。

计算直方图:统计每个灰度值出现的频率。

累积分布函数(CDF)计算:根据直方图计算累积分布函数。

映射新像素值:使用CDF将原始像素值映射到新的值,以增强对比度。

反向转换:将处理后的灰度图像重新转换为彩色图像。

void GetGrayScale(const std::vector& input, std::vector& output, int width, int height) {
    output.resize(width * height);
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            int pos = (y * width + x) * 3;
            output[y * width + x] = static_cast(0.299 * input[pos + 2] + 0.587 * input[pos + 1] + 0.114 * input[pos]);
        }
    }
}

void PutGrayScale(const std::vector& input, std::vector& output, int width, int height) {
    for (int y = 0; y < height; ++y) {
        for (int x = 0; x < width; ++x) {
            int pos = (y * width + x) * 3;
            uint8_t gray = input[y * width + x];
            output[pos] = gray;
            output[pos + 1] = gray;
            output[pos + 2] = gray;
        }
    }
}

void HistogramEqualization(const std::vector& input, std::vector& output, int width, int height) {
    std::vector hist(256, 0);
    for (size_t i = 0; i < input.size(); ++i) {
        hist[input[i]]++;
    }

    std::vector cdf(hist.size(), 0);
    cdf[0] = hist[0];
    for (size_t i = 1; i < hist.size(); ++i) {
        cdf[i] = cdf[i - 1] + hist[i];
    }

    int totalPixels = width * height;
    for (size_t i = 0; i < input.size(); ++i) {
        output[i] = static_cast(cdf[input[i]] * 255 / totalPixels);
    }
}

void ApplyHistogramEqualization(std::vector& image, int width, int height) {
    std::vector grayScale;
    GetGrayScale(image, grayScale, width, height);

    std::vector eqGrayScale(grayScale.size());
    HistogramEqualization(grayScale, eqGrayScale, width, height);

    PutGrayScale(eqGrayScale, image, width, height);
}

3. 保存处理后的图像

为了验证直方图均衡化的效果,我们将处理后的图像保存为新的BMP文件。为此,我们编写了SaveBitmap函数,它能够将图像数据写入BMP文件。

bool SaveBitmap(const std::string& filename, const std::vector& imageBuffer, int width, int height) {
    std::ofstream file(filename, std::ios::binary);
    if (!file.is_open()) return false;

    BITMAPFILEHEADER fileHeader;
    BITMAPINFOHEADER infoHeader;

    // 设置文件头信息
    fileHeader.bfType = 0x4D42; // 'BM'
    fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (width * height * 3);
    fileHeader.bfReserved1 = 0;
    fileHeader.bfReserved2 = 0;
    fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

    // 设置信息头信息
    infoHeader.biSize = sizeof(BITMAPINFOHEADER);
    infoHeader.biWidth = width;
    infoHeader.biHeight = -height; // 负值表示图像从上到下存储
    infoHeader.biPlanes = 1;
    infoHeader.biBitCount = 24;
    infoHeader.biCompression = 0; // BI_RGB
    infoHeader.biSizeImage = 0;
    infoHeader.biXPelsPerMeter = 0;
    infoHeader.biYPelsPerMeter = 0;
    infoHeader.biClrUsed = 0;
    infoHeader.biClrImportant = 0;

    // 写入文件头和信息头
    file.write(reinterpret_cast<char*>(&fileHeader), sizeof(fileHeader));
    file.write(reinterpret_cast<char*>(&infoHeader), sizeof(infoHeader));

    // 写入图像数据
    file.write(reinterpret_cast(imageBuffer.data()), imageBuffer.size());

    file.close();
    return true;
}

4. 主程序

最后,我们将上述功能整合到主程序中,加载图像、应用直方图均衡化并保存处理后的图像。

int main() {
    std::string inputFilename = "path_to_your_bmp_file.bmp"; // 替换为实际路径
    std::string outputFilename = "output_hist_eq.bmp"; // 输出文件路径
    std::vector imageBuffer;
    int width = 0, height = 0;

    if (!LoadBitmap(inputFilename, imageBuffer, width, height)) {
        std::cerr << "Failed to load bitmap file." << std::endl;
        return 1;
    }

    std::cout << "Loaded image: " << width << "x" << height << std::endl;

    // 创建一个副本用于直方图均衡化
    std::vector eqImageBuffer = imageBuffer;

    // 应用直方图均衡化
    ApplyHistogramEqualization(eqImageBuffer, width, height);

    std::cout << "Histogram equalization applied." << std::endl;

    // 保存处理后的图像
    if (SaveBitmap(outputFilename, eqImageBuffer, width, height)) {
        std::cout << "Saved processed image to " << outputFilename << std::endl;
    }
    else {
        std::cerr << "Failed to save the processed image." << std::endl;
        return 1;
    }

    return 0;
}

四、实验结果与分析

1. 结果展示

我们选择了几张不同类型的BMP图像进行测试,并将处理前后的图像进行了对比。以下是部分测试结果:
原图:

原图

处理结果:
处理结果

2. 效果分析

通过对多张图像的测试,我们可以观察到直方图均衡化对图像对比度的显著提升。具体表现在以下几个方面:

对比度增强:经过直方图均衡化处理,图像的整体对比度得到了明显改善,暗部和亮部细节更加清晰可见。

色彩保真度:虽然直方图均衡化通常应用于灰度图像,但在本实验中,我们对彩色图像的每个通道分别进行了均衡化处理,结果表明色彩保持了原有的色调,没有明显的偏色现象。

噪声放大:在一些低对比度区域,直方图均衡化确实导致了一定程度的噪声放大,但这在大多数情况下是可以接受的,特别是在需要突出图像细节的应用场景中。

视觉效果:从视觉感受来看,处理后的图像整体质量有所提升,尤其是在亮度分布较为均匀的情况下,图像的层次感和立体感得到了加强。

五、结论

通过本次实验,我们成功实现了对BMP图像文件的解析和直方图均衡化处理。实验结果显示,直方图均衡化能够有效增强图像的对比度,改善视觉效果。同时,我们也注意到该算法在某些情况下可能会放大噪声,因此在实际应用中需要根据具体情况权衡利弊。

此外,实验过程中我们严格遵守了不使用任何第三方图像处理库的要求,完全依靠标准C++和BMP文件格式规范自行编写代码。这不仅加深了我们对图像文件结构的理解,也提高了我们的编程能力和问题解决能力。

作者:星尘旅人
1.本网站部分素材来源于网络,仅供大家参考学习,如有侵权,请联系博主删除处理。
2.本网站一切内容不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
3.版权&许可请详阅版权声明
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
//音乐播放