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

这篇具有很好参考价值的文章主要介绍了图像处理之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;

}

效果如下:

原图:

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

压缩后:

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

 如果感觉不明显,可以减少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;

}

 感谢观看,如有误,请不吝赐教。文章来源地址https://www.toymoban.com/news/detail-493827.html

到了这里,关于图像处理之DCT图像压缩(基于c++ opencv实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于opencv的c++图像处理(灰度变换)

    基于opencv的c++接口,实现常用的图像灰度变换方法,包括了线性变换、图像反转、对数变换和伽马变换。 函数 cv::normalize 标准化缩放和移动输入数组元素 当 normType=NORM_MINMAX 时(仅适用于密集数组)。可选掩码指定要规范化的子数组。这意味着在子数组上计算范数或 min-n-ma

    2024年02月04日
    浏览(65)
  • 基于DCT+huffman变换的图像压缩解压缩FPGA实现

    目录 一、理论基础 二、verilog程序 三、仿真结果        图像压缩和解压缩是数字图像处理中的重要技术。基于DCT(离散余弦变换)和Huffman变换的图像压缩解压缩方法是一种常见的图像压缩标准,它可以将图像数据压缩成更小的体积,同时保持图像的质量和还原性。 一、

    2023年04月16日
    浏览(63)
  • 基于opencv的图像处理系统的设计与实现

      随着计算机技术的飞速发展,图像技术在各领域的研究和应用日渐深入和广泛。opencv是近年来推出的开源、免费的计算机视觉库,利用其所包含的函数可以很方便地实现数字图像处理。本文旨在对opencv进行一个快速全面简介,通过介绍图像处理的相关函数,使读者能快速形

    2024年04月27日
    浏览(36)
  • 基于 OpenCV 的图像处理与分析应用的设计与实现

    图像处理与分析是计算机视觉中的重要应用领域,通过对图像进行处理和分析,可以提取有用的信息和特征,用于解决实际问题。 OpenCV 是一个强大的开源计算机视觉库,提供了丰富的功能和算法,适用于各种图像处理和分析任务。本文将以设计和实现一个基于 OpenCV 的图像处

    2024年02月16日
    浏览(36)
  • Python+OpenCV+paddleocr基于传统图像处理技术实现车牌识别

    目录 一、前言 二、预处理-提取车牌         1. 转灰度图         2. 顶帽运算         3. Sobel算子提取y方向边缘         4. 自适应二值化         5. 开运算分割(纵向去噪,分隔)         6. 闭运算合并         7. 膨胀/腐蚀         8. 腐蚀

    2024年02月04日
    浏览(49)
  • Python图像处理【10】基于离散余弦变换的图像压缩

    由于图像中相邻像素间的相关性引起的空间冗余、图像序列中不同帧之间存在相关性引起的时间冗余,因此我们需要对图像数据进行压缩。数据压缩的目的就是通过去除这些数据冗余来减少数据表示所占用的存储空间。随着大数据时代的到来,图像数据在质量提高的同时,其

    2024年02月04日
    浏览(59)
  • 基于OpenCV的传统视觉应用 -- OpenCV图像处理 图像模糊处理 图像锐化处理

    图像处理是用计算机对图像进行分析,以获取所需结果的过程,又称为影像处理。图像处理一般是指数字图像的处理。数字图像是用工业相机、摄像机、扫描仪等设备经过拍摄得到的一个大的二维数组,该数组的元素称为像素,其值称为灰度值。 均值滤波是指任意一点的像素

    2024年02月07日
    浏览(68)
  • Opencv C++图像处理(全)

    Opencv(Open Source Computer Vision)官方资料。支持在线查看 / 搜索函数,有超详细的参数说明与函数使用说明(全英文版)。 (BUG1)报错提示:无法打开包括文件 \\\"math.h\\\" 解决方案:配置属性 + 常规 + Windows SDK版本 + 最新安装的版本 (BUG2)报错提示:未定义标识符 \\\"CV_WINDOW_AUTOS

    2024年02月01日
    浏览(85)
  • OpenCV图像处理基础(C++版)

    目录 OpenCV环境搭建 加载 修改 保存图像 矩阵的掩膜操作 Mat对象 图像操作 图像混合 调整图像亮度与对比度 绘制形状与文字 模糊图像一 模糊图像二 膨胀与腐蚀 形态学操作 形态学操作应用-提取水平线和垂直线 图像金字塔-上采集与降采集 基本阈值操作 自定义线性滤波 处理

    2024年02月04日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包