南宫上天 2023-03-01 22:08 采纳率: 33.3%
浏览 74
已结题

用c对图像做直方图均匀化,为什么只有1/3的图像被作用了呀

用c对图像做直方图均匀化,为什么只有1/3的图像被作用了呀


#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
typedef unsigned char BYTE;  // 定义BYTE为一个字节的类型
typedef unsigned short WORD; // 定义WORD为两个字节的类型
typedef unsigned int DWORD;  // 定义DWORD为四个字节的类型
//#pragma pack(2)
int main()
{
    BYTE* in ;
    BYTE* out;
    BYTE* a;
    BYTE* b;
    BYTE* ptr;
    int shu1[256], shu2[256], shu3[256], p, W, H;
    memset(shu1, 0, sizeof(int) * 256);
    memset(shu2, 0, sizeof(int) * 256);
    memset(shu3, 0, sizeof(int) * 256);
    fopen_s(&in, "E:\\cxc.bmp", "rb+");
    fseek(in, 18, SEEK_SET);
    fread(&W, 4, 1, in);
    fseek(in, 22, SEEK_SET);
    fread(&H, 4, 1, in);
    fseek(in, 0, SEEK_SET);
    ptr = (unsigned char*)malloc((((W * 24 / 8 + 3) / 4 * 4) * H + 54)*sizeof(BYTE));
    fread(ptr, 1, ((W * 24 / 8 + 3) / 4 * 4) * H + 54, in);
    b = ptr + ((W * 24 / 8 + 3) / 4 * 4) * H + 54;
    for (a=ptr+54;a<b;)
    {
        shu1[*(a++)]++;
    }
    for (p = 1, shu2[0] = shu1[0]; p < 256; p++)
    {
        shu2[p] = shu2[p - 1] + shu1[p];
    }
    for (p = 0; p < 256; p++)
    {
        shu3[p] = 255 * shu2[p] / (W * H);
    }
    for (a=ptr+54;a<b;)
    {
        *(a++) = shu3[*a];
    }
    fopen_s(&out, "E:\\gaoqinbancxc.bmp", "wb");
    fwrite(ptr, 1, ((W * 24 / 8 + 3) / 4 * 4) * H + 54, out);
    fclose(in);
    fclose(out);
    return 0;
}
  • 写回答

7条回答 默认 最新

  • 「已注销」 2023-03-01 22:18
    关注

    参考GPT和自己的思路,在你的代码中,像这样 ((W * 24 / 8 + 3) / 4 * 4) * H + 54 的语句,实际上是计算位图文件中像素数组的大小。在位图文件中,像素数组的大小并不一定等于图像宽度乘以高度,它还要考虑到一些对齐等因素,所以需要这样的计算。但是,这个计算公式可能存在问题,导致只有图像的1/3受到影响。

    建议修改计算位图文件像素数组大小的公式,这个公式可以参考如下代码:

    int rowSize = ((W * 24 + 31) / 32) * 4; // 计算每行的字节数,其中+31和/32是为了向上取整
    int pixelArraySize = rowSize * H; // 计算像素数组的总大小
    int fileSize = pixelArraySize + 54; // 计算整个文件的大小,其中54是头部信息的大小
    

    使用上述计算公式替换原来的公式,再重新编译运行程序即可。

    替换后的完整代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef unsigned char BYTE;  // 定义BYTE为一个字节的类型
    typedef unsigned short WORD; // 定义WORD为两个字节的类型
    typedef unsigned int DWORD;  // 定义DWORD为四个字节的类型
    
    int main()
    {
        BYTE* in;
        BYTE* out;
        BYTE* a;
        BYTE* b;
        BYTE* ptr;
        int shu1[256], shu2[256], shu3[256], p, W, H;
        memset(shu1, 0, sizeof(int) * 256);
        memset(shu2, 0, sizeof(int) * 256);
        memset(shu3, 0, sizeof(int) * 256);
    
        // 打开原始位图文件
        fopen_s(&in, "E:\\cxc.bmp", "rb+");
        if (!in) {
            printf("Failed to open input file\n");
            return 1;
        }
    
        // 读取位图信息头中的图像宽度和高度
        fseek(in, 18, SEEK_SET);
        fread(&W, 4, 1, in);
        fseek(in, 22, SEEK_SET);
        fread(&H, 4, 1, in);
    
        // 读取整个位图文件到内存中
        fseek(in, 0, SEEK_SET);
        ptr = (BYTE*)malloc(((W * 24 / 8 + 3) / 4 * 4) * H + 54);
        fread(ptr, 1, ((W * 24 / 8 + 3) / 4 * 4) * H + 54, in);
        fclose(in);
    
        // 计算像素数组开始位置和结束位置
        b = ptr + ((W * 24 / 8 + 3) / 4 * 4) * H + 54;
    
        // 统计原始位图中各个灰度级别的像素数
        for (a = ptr + 54; a < b; a++) {
            shu1[*a]++;
        }
    
        // 计算累计直方图
        for (p = 1, shu2[0] = shu1[0]; p < 256; p++) {
            shu2[p] = shu2[p - 1] + shu1[p];
        }
    
        // 计算映射表
        for (p = 0; p < 256; p++) {
            shu3[p] = 255 * shu2[p] / (W * H);
        }
    
        // 应用映射表对像素进行均衡化
        for (a = ptr + 54; a < b; a++) {
            *a = shu3[*a];
        }
    
        // 创建输出文件并将修改后的位图写入
        fopen_s(&out, "E:\\gaoqinbancxc.bmp", "wb");
        if (!out) {
            printf("Failed to open output file\n");
            free(ptr);
            return 1;
        }
        fwrite(ptr, 1, ((W * 24 / 8 + 3) / 4 * 4) * H + 54, out);
        fclose(out);
    
        free(ptr);
    
        return 0;
    }
    
    
    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 3月9日
  • 创建了问题 3月1日