zoukankan      html  css  js  c++  java
  • 图像缩放

    针对图像的缩放,对于比较小的图像,qt中已经提供了接口,直接调用就行。但是当图像比较大时,就不能使用接口了,因为接口里面实现了图像缩放的算法,图像大时,先计算再显示,计算很耗时,所以会很卡,不适用。本文针对大图像的缩放进行说明。

    方法:参考google map,可以发现,显示的地图都是一层一层的,每一层的比例尺不一样,每一层的图像事先都已经保存在服务器了,用户需要哪一层直接从服务器传过来就可以了。我们这里是客户端软件,所以,每一层的图像必须自己先处理好保存起来,缩放时,需要哪一层图像直接调用图像出来显示这样就很快了。

    每一层图像得到的方法:高斯金字塔,最底层为原图像,往上图像的宽和高依次缩小一倍,最小的图像到显示区域能全部显示为宜。

    难点:如何确定要显示的是哪幅图像

    假设每幅图都是QImage对象,则从金字塔底层向上依次保存在容器中:QVector<QImage*>

    再设定一个变量layer,初始值为0(代表第一层),根据放大缩小按钮递增或递减layer值,然后根据layer在容器中查找该索引处的QImage,显示即可。

    高斯金字塔构建的方法如下:

    步骤:先通过与高斯核做卷积得到图像矩阵(与原图像大小相同),然后间隔采样得到下一层的图像,即为构建的金字塔图。

    高斯核是一个5*5的矩阵,如下:

    1     4      6     4     1

    4    16    24    16    4

    6    24    36    24    6

    4    16    24    16    4

    1     4      6     4     1

    原图像某个位置的像素点的计算过程:以该点为中心,取5*5大小的像素矩阵,与高斯核做卷积,得到的数除以高斯核中数的总和。

    高斯矩阵中每个值代表了像素点在计算中所占的权重,中心点(也是要输出的像素点)的权重当然是最大的,离中心点距离相同的点的权重相同。这样计算的得到的新图像通过间隔采样得到缩小一倍的图像,看起来会是平滑的,当然,缩小一倍看不出来平滑效果,多缩小几次(构建几层)就可以看出来了,较直接通过采样得到的缩略图具有很好的平滑性。

    代码如下,只是得到金字塔上一层的数据,要的到构建多层的数据在代码基础上做循环迭代环就可以。这里我对无法做卷积的图像边界(上下的2行和左右的2列)保持值不变

     1 void Gaussian(unsigned char* input,unsigned char* output,int sizeX,int sizeY)
     2 {
     3     //定义高斯内核模板
     4     int gauKernel[25]={1,4,6,4,1,
     5                        4,16,24,16,4,
     6                        6,24,36,24,6,
     7                        4,16,24,16,4,
     8                        1,4,6,4,1};
     9     int powerSum=0;
    10     //计算高斯模板总权值
    11     for(int i=0;i<25;i++)
    12         powerSum+=gauKernel[i];
    13 
    14     unsigned char* ldata;//高斯迭代后数据
    15     ldata=NULL;
    16     int lwidth=sizeX;
    17     int lheight=sizeY;
    18     int rwidth=sizeX/2;//高斯金字塔采样后的图像宽
    19     int rheight=sizeY/2;//高斯金字塔采样后的图像高
    20 
    21         /*第一次迭代,迭代前数据就是inputData*/
    22         //将input给ldata
    23         ldata=new unsigned char[lwidth*lheight];
    24         for (int m=0;m<lheight;m++)
    25         {
    26             for (int n=0;n<lwidth;n++)
    27                 ldata[m*lwidth+n]=input[m*lwidth+n];
    28         }
    29         //高斯平滑,是同input计算,结果保存于ldata中
    30         for (int m=2;m<lheight-2;m++)
    31         {
    32             for (int n=2;n<lwidth-2;n++)
    33             {
    34                 int sum=0;
    35                 //计算和高斯模板的卷积
    36                 for (int p=0;p<5;p++)
    37                 {
    38                     for (int q=0;q<5;q++)
    39                     {
    40                         sum+=input[(m+2-p)*lwidth+n+q-2]*gauKernel[p*5+q];
    41                     }
    42                 }
    43                 ldata[m*lwidth+n]=sum/powerSum;//像素点值
    44             }
    45         }
    46         //向下采样,去除偶数行和列
    47         for (int m=0;m<rheight;m++)
    48         {
    49             for (int n=0;n<rwidth;n++)
    50             {
    51                 output[m*rwidth+n]=ldata[(m*2+1)*lwidth+n*2+1];
    52             }
    53         }
    54 
    55     if (ldata)
    56     {
    57         delete []ldata;
    58         ldata=NULL;
    59     }
    60 }
  • 相关阅读:
    图论复习
    数据结构复习
    数学复习
    字符串算法复习
    还有9天就要走了
    JS 多个一维数组排例组合的所有可能
    PHP 多个一维数组排列组合的所有可能
    维护DOWNID
    LINUX
    Multiple Versions of PHP run on server
  • 原文地址:https://www.cnblogs.com/Romi/p/2782151.html
Copyright © 2011-2022 走看看