文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

C语言数字图像处理之图像缩放

2024-04-02 19:55

关注

本文实例为大家分享了C语言实现图像缩放的具体代码,供大家参考,具体内容如下

1. 定义(摘自维基百科)

在计算机图形学中,图像缩放指的是通过增加或去掉像素来改变图片的尺寸。由于要在效率和图像质量比如平滑度和清晰度之间做折衷,图像缩放并不是个简单的过程。当图像尺寸增大的时候,组成图像的像素也越来越大,图像看上去就变"柔和"了。而缩小图像的时候,图像就变得平滑和清晰了。

除了为了适应显示区域而缩小图片外,图像缩小技术更多的是被用来产生预览图片。图像放大技术一般被用来令一个较小的图像填充一个大的屏幕。当你放大一张图像时,你不能可能获得更多的细节,因此图像的质量将不可避免的下降。不过也有很多技术可以保证在放大图像即增加像素的时候,图像的质量不变。

2.方法及实现

2.1 图像缩小

为了能够更好的观察效果,选用了比较小的图片(200*200)进行处理。

图像缩小相对比较简单,由于缩小必定损失信息量,所以个人感觉需要考虑的是怎么尽可能多的保留原始信息。

最简单的方法为直接选取部分数据。譬如,图像缩小一倍,则隔一行(列)取一个数据,图像缩小为原来的四分之一,则隔三行(列)取一个数据。

处理结果:

这种方式相当于直接舍去了1/2(3/4)的信息,于是尝试通过取相邻像素的平均值代替原来单纯的一个像素以尽可能多的保留原始信息。

分析:

可以看到,后者得到的图片效果明显好于前者。在进行图像缩小操作时,要考虑的是在图像信息必然损失的情况下,尽可能多的保留原始信息。

第一种处理关键代码为:


for (int i = 0; i < height; i+=3){
        for (int j = 0; j < width; j+=3){
            PicZoomOut[i / 4][j / 4] =Pic[i][j];
        }
    }

第二种处理关键代码为:


for(int i = 0; i < 100; i++){
          for(int j = 0; j < 100; j++){
                 PicZoomOut[i][j] = (Pic[i * 2][j * 2]+ Pic[i * 2 + 1][j * 2] + Pic[i * 2][j * 2 + 1] + Pic[i * 2+ 1][j * 2 + 1])/4;
          }
   }

图像缩小,第二种方法,缩为原来1/4,代码


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

#define height  200
#define width   200

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

int main(void)
{
FILE *fp = NULL;
BYTE PicZoomOut[100][100];
BYTE *ptr;
BYTE **Pic = new BYTE *[height];
for (int i = 0; i != height; ++i)
{
Pic[i] = new BYTE[width];
}

fp = fopen("1.raw", "rb");
ptr = (BYTE*)malloc(width * height * sizeof(BYTE));//创建内存
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
fread(ptr, 1, 1, fp);
Pic[i][j] = *ptr;  // 把图像输入到2维数组中,变成矩阵型式
ptr++;
}
}
fclose(fp);
for (int
i = 0; i < 50; i++)
{
for (int
j = 0; j < 50; j++)
{
PicZoomOut[i][j]
= (Pic[i * 4][j * 4]     + Pic[i * 4 + 1][j * 4]     + Pic[i * 4 + 2][j *
4]     + Pic[i * 4 + 3][j * 4] + Pic[i * 4][j * 4 + 1] + Pic[i * 4 + 1][j * 4 + 1] + Pic[i * 4 + 2][j * 4 + 1] + Pic[i * 4 + 3][j * 4 + 1] + Pic[i * 4][j * 4 + 2] + Pic[i * 4 + 1][j * 4 + 2] + Pic[i * 4 + 2][j * 4 + 2] + Pic[i * 4 + 3][j * 4 + 2] + Pic[i * 4][j * 4 + 3] + Pic[i * 4 + 1][j * 4 + 3] + Pic[i * 4 + 2][j * 4 + 3] + Pic[i * 4 + 3][j * 4 + 3])/16;
}
}
fp = fopen("output.raw", "wb");
for (int i = 0; i < 50; i++)
{
for (int j = 0; j < 50; j++)
{
fwrite(&PicZoomOut[i][j], 1, 1, fp);
}
}
fclose(fp);
return 0;
}

2.2 图像放大

为了能够更好的观察效果,选用了比较小的图片(100*100)进行处理。

图像放大由于信息量已定,所以个人感觉需要考虑的是怎么尽可能多的使用原始信息并且能呈现出比较好的放大效果。。

最简单的方法为近邻取样插值,也称零阶插值。它输出的像素灰度值就等于距离它映射到的位置最近的输入像素的灰度值。但当图像中包含像素之间灰度级有变化的细微结构时,最邻近算法会在图像中产生人为加工的痕迹。

测试如下:

放大后的图像保留了原始图像的所有细节,但结果并不让人满意,有阶梯状锯齿。于是尝试采用其他缩放方法。

双线型内插值算法是一种比较好的图像缩放算法,它充分的利用了源图中虚拟点四周的四个真实存在的像素值来共同决定目标图中的一个像素值,因此缩放效果比简单的最邻近插值要好很多。

对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(i+u,j+v) (其中i、j均为浮点坐标的整数部分,u、v为浮点坐标的小数部分,是取值[0,1)区间的浮点数),则这个像素得值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)

其中f(i,j)表示源图像(i,j)处的的像素值,以此类推。

效果如下:

可见,相比于邻取样插值算法,这个算法的效果就好很多。不过导致了不期望的细节柔化。

在PS软件中用来图像放大的最佳算法是二次立方,测试如下:

双立方插值计算涉及到16个像素点, 而最终插值后的图像中的(x, y)处的值即为16个像素点的权重卷积之和

将上面三种算法得到的结果依次放到一起对比观察如下

分析:显然,近邻取样插值效果最差。虽然保留了原始图像的所有细节,但出现了阶梯状锯齿。双线型内插值效果与二次立方插值效果都比近邻取样插值好,二者相比,双线型内插值有一点细节柔化(比如眼珠部位)。

综上,二次立方插值效果最好。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯