数字图像处理(5):幂次变换(C语言实现)

幂次变换

幂次变换,点运算的一种,运算公式为s=crγ,其中,c和γ是正常数。

当γ<1,此时扩展低灰度级,压缩高灰度级,在正比函数上方,使图像变亮;

当γ>1,此时扩展高灰度级,压缩低灰度级,在正比函数下方,使图像变暗。
在这里插入图片描述

核磁共振图像

是利用核磁共振(nuclear magnetic resonance,简称NMR)原理,依据所释放的能量在物质内部不同结构环境中不同的衰减,通过外加梯度磁场检测所发射出的电磁波,即可得知构成这一物体原子核的位置和种类,据此可以绘制成物体内部的结构图像。

本图像来源翰·霍普金斯大学Elliot Fishman博士和Karen Horton博士的教学案例和图片。图像大小为455*600,8位灰度图像。为了增强本次实验效果,将此图像人为的进行了亮度调低。
在这里插入图片描述

亮度调低
在这里插入图片描述

代码实现

平台:vs2015
语言:C语言

流程:
1)读取图片
2)对每个像素进行幂次计算
3)输出处理后的图片
4)改变γ的值,重复上述流程

关键代码:

    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            temp = c * pow( Pic[i][j]/255.0 , v )*255; 
            Pic[i][j] = (char)temp;
        }
    }

处理结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分析:

如幂次变换特点——当γ<1,此时扩展低灰度级,压缩高灰度级,使图像变亮;当γ>1,此时扩展高灰度级,压缩低灰度级,使图像变暗。

感觉在γ为0.4时相比于0.6的一些细节更清晰一些,当γ为0.2时图片有点过亮,一些细节反而不容易观察。

而当γ大于1时,原本就比较暗的图像变得更暗,基本上无法观察了。

另外,还测试了γ分别为0.1,0.2,0.3,0.4……0.9的结果,发现确实可以通过幂律变换实现亮暗度变化的对比度增强。

遇到问题

最初写代码直接带入公式,代码写成了如下:

    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            temp = c * pow( Pic[i][j] , v ); 
            Pic[i][j] = (char)temp;
        }
    }

即直接按照公式s=crγ进行带入计算。结果当γ=0.6时,得到的结果如下:
在这里插入图片描述

图像反而变暗了,显然这是不对的。看了一下那些曲线明白了这个公式的含义,修改为:

    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            temp = c * pow( Pic[i][j]/255 , v )*255; 
            Pic[i][j] = (char)temp;
        }
    }

这样运行后反而成了一片黑了,也就是所有像素值为0。发现忽略了Pic[i][j]/255并不是浮点运算,得到的结果必然为0。于是将255改为255.0,解决问题。

附代码:

#include <stdio.h> 
#include <stdlib.h>  
#include <math.h>

#define height 600  
#define width   455 

typedef unsigned char BYTE;    // 定义BYTE类型,占1个字节

//s = cr v
int c = 1;
float v = 0.6;
float temp;

int main(void)
{
    FILE *fp = NULL;
    BYTE *ptr;
    BYTE **Pic = new BYTE *[height];
    for (int i = 0; i != height; ++i)
    {
        Pic[i] = new BYTE[width];
    }
    int i, j;
    fp = fopen("untitled.raw", "rb");
    ptr = (BYTE*)malloc(width * height * sizeof(BYTE));//创建内存
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            fread(ptr, 1, 1, fp);
            Pic[i][j] = *ptr;  // 把图像输入到2维数组中,变成矩阵型式  
            ptr++;
        }
    }
    fclose(fp);
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            temp = c * pow( Pic[i][j]/255.0 , v )*255; 
            Pic[i][j] = (char)temp;
        }
    }
    fp = fopen("output.raw", "wb");
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            fwrite(&Pic[i][j], 1, 1, fp);
        }
    }
    fclose(fp);
    return 0;
}

本工程源码已更新至github,欢迎star,欢迎PR:)

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数字图像压缩的目的是减少图像的存储空间和传输带宽,提高图像的传输速度和存储效率。其中,基于离散余弦变换(DCT)的压缩算法是一种比较常见的压缩算法。 下面是一个基于DCT的数字图像压缩算法C语言实现: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define N 8 // 定义DCT矩阵的大小 // DCT变换函数 void DCT(int **f, double **F) { double cu, cv, sum; int u, v, x, y; for (u = 0; u < N; u++) { for (v = 0; v < N; v++) { if (u == 0) cu = 1 / sqrt(N); else cu = sqrt(2) / sqrt(N); if (v == 0) cv = 1 / sqrt(N); else cv = sqrt(2) / sqrt(N); sum = 0.0; for (x = 0; x < N; x++) { for (y = 0; y < N; y++) { sum += f[x][y] * cos((2 * x + 1) * u * M_PI / (2 * N)) * cos((2 * y + 1) * v * M_PI / (2 * N)); } } F[u][v] = cu * cv * sum; } } } // IDCT变换函数 void IDCT(double **F, int **f) { double cu, cv, sum; int u, v, x, y; for (x = 0; x < N; x++) { for (y = 0; y < N; y++) { sum = 0.0; for (u = 0; u < N; u++) { for (v = 0; v < N; v++) { if (u == 0) cu = 1 / sqrt(N); else cu = sqrt(2) / sqrt(N); if (v == 0) cv = 1 / sqrt(N); else cv = sqrt(2) / sqrt(N); sum += cu * cv * F[u][v] * cos((2 * x + 1) * u * M_PI / (2 * N)) * cos((2 * y + 1) * v * M_PI / (2 * N)); } } f[x][y] = (int)round(sum); } } } // 主函数 int main() { int i, j; int **f; // 原始图像 double **F; // DCT变换后的系数 // 申请空间 f = (int **)malloc(N * sizeof(int *)); F = (double **)malloc(N * sizeof(double *)); for (i = 0; i < N; i++) { f[i] = (int *)malloc(N * sizeof(int)); F[i] = (double *)malloc(N * sizeof(double)); } // 读入原始图像 printf("请输入8x8的图像:\n"); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { scanf("%d", &f[i][j]); } } // DCT变换 DCT(f, F); // 输出DCT系数 printf("DCT系数:\n"); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%lf ", F[i][j]); } printf("\n"); } // IDCT变换 IDCT(F, f); // 输出恢复后的图像 printf("恢复后的图像:\n"); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%d ", f[i][j]); } printf("\n"); } // 释放空间 for (i = 0; i < N; i++) { free(f[i]); free(F[i]); } free(f); free(F); return 0; } ``` 这个程序实现了DCT变换和IDCT变换,可以输入一个8x8的图像,输出DCT系数和恢复后的图像。在实际应用中,可以将DCT系数进行量化和编码,进一步压缩图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值