图像处理之DCT图像压缩(基于c++ opencv实现)

是老师布置的作业,拖到ddl才开始,opencv也才刚接触,有自己结合百度的一点理解,如有误,请谅解!

DCT图像压缩

先贴一段在matlab上实现的代码,这个在网上都可以查到,就不赘述了

I=imread('cameraman.tif');
I=im2double(I);%将图像转换为双精度
T=dctmtx(8);% 返回8*8的DCT变换矩阵
B=blkproc(I,[8 8],'P1*x*P2',T,T');
% x就是每一个分成的8*8大小的块,P1*x*P2相当于像素块的处理函数,p1=T p2=T’,
%也就是fun=p1*x*p2'=T*x*T'的功能是进行离散余弦变换
mask=   [1 1 1 1 0 0 0 0 
         1 1 1 0 0 0 0 0 
         1 1 0 0 0 0 0 0 
         1 0 0 0 0 0 0 0 
         0 0 0 0 0 0 0 0 
         0 0 0 0 0 0 0 0 
         0 0 0 0 0 0 0 0 
         0 0 0 0 0 0 0 0];% 保留左上角十个系数
B2=blkproc(B,[8 8],'P1.*x',mask);%舍弃每个块中的高频系数,达到图像压缩的目的
I2=blkproc(B2,[8 8],'P1*x*P2',T',T); %进行反余弦变换,得到压缩后的图象
figure(1);
subplot(1,4,1),imshow(I);
subplot(1,4,2),imshow(B);
subplot(1,4,3),imshow(B2);
subplot(1,4,4),imshow(I2);
Z  = imabsdiff(I,I2);
figure(2);
imshow(Z);

思路如下:

     先划分处理块大小,对每个块分别进行DCT变换,再舍弃每个块中的高频系数,再进行反余弦变换,得到压缩图像(即先使用DCT函数将低频的点都集中在左上角,再对右下角的高频数据丢弃)

老师要求我们用c++ + opencv实现。配置环境真的是。。。。

试过用clion和vscode配,失败了,还是老老实实用vs2019吧。

附 大佬配置的视频,十分感谢!

https://www.bilibili.com/video/BV1mE411P76Mp=1&vd_source=393e209b3fa00543c23db5753b265d30

下面是用c++ 实现的代码

RGB图(下面有灰度图,其实差不多)

#include <opencv2/opencv.hpp>     
#include <iostream>  
using namespace cv;
using namespace std;

double T = 100;

int main()
{
    Mat src = imread("D:\\Matlab\\toolbox\\images\\imdata\\kids.tif");//先读入图像,在这里读入的是RGB图像,有三个通道
   

    
 
    imshow("clock", src);//先显示图像



    int big;
    big = 8;//定义一下掩盖矩阵的大小
    vector<Mat> mv;
    split(src, mv);//通道分割



    Mat b = Mat_<float>(mv[0]);
    Mat g = Mat_<float>(mv[1]);
    Mat r = Mat_<float>(mv[2]);

    b.convertTo(b, CV_32F, 1.0 / 255);
    g.convertTo(g, CV_32F, 1.0 / 255);
    r.convertTo(r, CV_32F, 1.0 / 255);

    //要进行DCT变换先转换成float,我也不知道为什么
    Mat bDCT = Mat_<float>(b); //这里先复制矩阵,后面有用
    Mat gDCT = Mat_<float>(g);
    Mat rDCT = Mat_<float>(r);
    int w = b.rows;
    int h = b.cols;//三个通道的大小都是一样的,所以只要取一个就好了
  



    //DCT变换每个通道都做一遍
 
    for (int i1 = 0; i1 < (h / big); i1++) {//注意这里的取值和我们平常遇到的x,y不一样 一张宽度x像素、高度y像素的灰度图保存在一个y * x的矩阵中。
        for (int j1 = 0; j1 < (w / big); j1++) {
            dct(b(Rect(i1 * big, j1 * big, big, big)), bDCT(Rect(i1 * big, j1 * big, big, big)));//Rect是滑块函数,从指定位置取指定大小的矩阵,这就是跟Matlab分块处理一样

        }
    }

    //发现有的图像不是长宽相同的,所以取整除,而没有取到数据,跟之前相同就行了,复制的用处就来啦


    for (int i1 = 0; i1 < (h / big); i1++) {
        for (int j1 = 0; j1 < (w / big); j1++) {
            dct(g(Rect(i1 * big, j1 * big, big, big)), gDCT(Rect(i1 * big, j1 * big, big, big)));

        }
    }

    for (int i1 = 0; i1 < (h / big); i1++) {
        for (int j1 = 0; j1 < (w / big); j1++) {
            dct(r(Rect(i1 * big, j1 * big, big, big)), rDCT(Rect(i1 * big, j1 * big, big, big)));

        }
    }
    


    int mask[8][8] = {//定义掩盖矩阵
        {1, 1, 1, 1, 0, 0, 0, 0},
        {1, 1, 1, 0, 0, 0, 0, 0},
        {1, 1, 0, 0, 0, 0, 0, 0},
        {1, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        
    };

    //根据mask 矩阵 去掉右下角的数据,同样对每个通道做一次
    for (int i1 = 0; i1 < (bDCT.rows / big); i1++) 
    {
        for (int j1 = 0; j1 < (bDCT.cols / big); j1++) 
        {

            for (int i = 0; i < big; i++)
            {

                for (int j = 0; j < big; j++)
                {
                    if (mask[i % big][j % big] == 0)
                    {
                        bDCT.at<int>(i1 * big + i, j1 * big + j) = 0;//这里和mask矩阵相乘是同一个意思,同时扫描mask和DCT变换后的矩阵,当mask矩阵扫描到的值为0时,把DCT矩阵也置零,去掉高频数据
                    }
                }
            }
        }
    }

    for (int i1 = 0; i1 < (gDCT.rows / big); i1++)
    {
        for (int j1 = 0; j1 < (gDCT.cols / big); j1++)
        {

            for (int i = 0; i < big; i++)
            {

                for (int j = 0; j < big; j++)
                {
                    if (mask[i % big][j % big] == 0)
                    {
                        gDCT.at<int>(i1 * big + i, j1 * big + j) = 0;;
                    }
                }
            }
        }
    }    for (int i1 = 0; i1 < (rDCT.rows / big); i1++)
    {
        for (int j1 = 0; j1 < (rDCT.cols / big); j1++)
        {

            for (int i = 0; i < big; i++)
            {

                for (int j = 0; j < big; j++)
                {
                    if (mask[i % big][j % big] == 0)
                    {
                        rDCT.at<int>(i1 * big + i, j1 * big + j) = 0;;
                    }
                }
            }
        }
    }


    Mat iDctb = bDCT;
    Mat iDctg = gDCT;
    Mat iDctr = rDCT;

    //进行逆DCT变换,同做三次
    for (int i1 = 0; i1 < (h / big); i1++) {
        for (int j1 = 0; j1 < (w / big); j1++) {
            idct(bDCT(Rect(i1 * big, j1 * big, big, big)), iDctb(Rect(i1 * big, j1 * big, big, big)));

        }
    }
    for (int i1 = 0; i1 < (h / big); i1++) {
        for (int j1 = 0; j1 < (w / big); j1++) {
            idct(gDCT(Rect(i1 * big, j1 * big, big, big)), iDctg(Rect(i1 * big, j1 * big, big, big)));

        }
    }
    for (int i1 = 0; i1 < (h / big); i1++) {
        for (int j1 = 0; j1 < (w / big); j1++) {
            idct(rDCT(Rect(i1 * big, j1 * big, big, big)), iDctr(Rect(i1 * big, j1 * big, big, big)));

        }
    }

    mv[0] = iDctb;
    mv[1] = iDctg;
    mv[2] = iDctr;
    Mat dst;
    merge(mv, dst);//通道合并


    imshow("DstImage",dst);//显示图像

    waitKey(0);

    return 0;

}

效果如下:

原图:

压缩后:

 如果感觉不明显,可以减少mask矩阵1的个数。

灰度图


int main()
{
    Mat src = imread("D:\\Matlab\\toolbox\\images\\imdata\\coins.png",0);
    imshow("clock", src);
    src = Mat_<float>(src);
    int w = src.rows;
    int h = src.cols;
    
   

   

    int big;
    big = 8;
    src.convertTo(src, CV_32F, 1.0 / 255);
    Mat srcDCT = Mat_<float>(src);

    
   

    
    for (int i1 = 0; i1 < (h / big); i1++) {
        for (int j1 = 0; j1 < (w / big); j1++) {
            dct(src(Rect(i1 * big, j1 * big, big, big)),srcDCT(Rect(i1 * big, j1 * big, big, big)));
          
        }
    }


    int mask[8][8] = {
        {1, 1, 1, 1, 0, 0, 0, 0},
        {1, 1, 1, 0, 0, 0, 0, 0},
        {1, 1, 0, 0, 0, 0, 0, 0},
        {1, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},
        {0, 0, 0, 0, 0, 0, 0, 0},

    };
    double s;  
    for (int i1 = 0; i1 < (srcDCT.rows / big); i1++) {
        for (int j1 = 0; j1 < (srcDCT.cols / big); j1++) {

            for (int i = 0; i < big; i++)
            {

                for (int j = 0; j < big; j++)
                {
                    if (mask[i % big][j % big] == 0) {
                        srcDCT.at<int>(i1 * big + i, j1 * big + j) = 0;;
                        

                    }
                    else {
                        s = 0;
                    }
                }
            }
        }
    }
   Mat iDct1 = srcDCT;
    
    for (int i1 = 0; i1 < (h / big); i1++) {
        for (int j1 = 0; j1 < (w / big); j1++) {
            idct(srcDCT(Rect(i1 * big, j1 * big, big, big)), iDct1(Rect(i1 * big, j1 * big, big, big)));

        }
    }

    imshow("c", srcDCT);




    imshow("DstImage",iDct1);

    waitKey(0);

    return 0;

}

 感谢观看,如有误,请不吝赐教。

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
CT image compression (a) Implement the simplified DCT compression process above for n = 2, 4, and 8 and apply it to the attached image. Show the reconstructed images for these three different cases. [3 images] Compute the PSNR values of the three reconstructed images and discuss what the PSNR value means here. (b) Use the same process in (a) with image transformed to YIQ color model and show the reconstructed image in RGB space. [3 images] Compute the PSNR values of the three reconstructed images and discuss what the PSNR value means here. Dithering 2. Dithering (30%) Convert the image cat2_gray.png to binary (black and white) image with different methods of dithering, show the results, and make some comparison with the results. (a) Apply noise (random) dithering on the provided image and show the result. [1 image] (b) Apply average dithering on the provided image and show the result. [1 image] (c) Apply error diffusion dithering (Floyd-Steinberg algorithm) on the provided image and show the result. [1 image] Image Interpolation Implement the image interpolation function to upsample an image to four times the original width and height. Implement the following two different interpolation methods and show the 4× upsampled images. (a) Apply nearest-neighbor interpolation on the low resolution image, cat3_LR.png, and compute the PSNR with the original high resolution image, cat3_HR.png. [1 image] (b) Apply bilinear interpolation on the low resolution image and compute the PSNR with the high resolution image. [1 image] (c) Apply bicubic interpolation on the low resolution image and compute the PSNR with the high resolution image. [1 image]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值