CCF-CSP真题《202212-3 JPEG 解码》思路+python,c++满分题解

想查看其他题的真题及题解的同学可以前往查看:CCF-CSP真题附题解大全

试题编号:202212-3
试题名称:JPEG 解码
时间限制:1.0s
内存限制:512.0MB
问题描述:

问题背景

        四年一度的世界杯即将画上尾声。在本次的世界杯比赛中,视频助理裁判(Video Assistant Referee, VAR)的应用可谓是大放异彩。VAR 使用视频回放技术帮助主裁判作出正确判罚决定。西西艾弗岛足球联赛的赛场上也引入了一套 VAR 设备。作为技术供应商的技术主管小C,需要存储和编码 VAR 产生的图像数据。小 C 分析比较发现,JPEG 编码算法可以达到较好的压缩效果,并且质量损失是可以接受的。因此,小 C 决定使用 JPEG 编码算法来存储和传输图像数据。JPEG 是一种常用的图片有损压缩算法,它的压缩率高,但是压缩后的图片质量下降较多。JPEG 图片的压缩率一般在 10:1 到 20:1 之间,一般用于存储照片等图片质量要求不高的场景。

        为了简化问题,我们以灰度图片为例,介绍 JPEG 编码算法的过程。一张灰度图片,可以被视为由多个像素点组成。每个像素点对应一个 0 到 255 之间的数值,用于表示像素点的亮度。JPEG 编码算法将图片分割为 8×8 的小块,每个小块被称作一个最小编码单元。对每个小块进行如下的计算:

  1. 将每个像素点的数值减去 128,使得每个像素点的数值都在 -128 到 127 之间。
  2. 将每个小块的像素点排成一个 8×8 的矩阵,并对矩阵进行离散余弦变换(DCT)。进行离散余弦变换后,仍然得到一个 8×8 的矩阵,矩阵中的每个元素都是实数,并且所得矩阵的左上方的数字的绝对值较大,右下方的数字的绝对值较小,甚至接近 0。
  3. 对矩阵进行量化操作。量化操作是指将矩阵中的每个元素都除以一个数字,并取整数。量化操作的目的是为了减少矩阵中的数据,从而减少编码后的文件大小。量化操作的数字越大,矩阵中的数据就越少,但是压缩后的图片质量也会越差。
  4. 对矩阵进行 Z 字形扫描。Z 字形扫描是指从左上角开始,沿着 Z 字形的路径扫描矩阵中的元素,将扫描到的元素依次排成一个数组,由于 Z 字形扫描的路径是从左上角到右下角,数组结尾处可能存在着连续的 0,为了节省空间,可以不存储这些连续的 0。得到的数据被称为扫描数据。

        最后,将得到的各个小块的扫描数据采用哈夫曼编码进行压缩,并置于必要的数据结构中,就能得到一张 JPEG 图片了。

问题描述

        在本题中,你需要实现一个能够解码 JPEG 图片的一个最小编码单元的程序。解码的步骤与上述编码的步骤相反,具体的步骤是:

  1. 读入量化矩阵 Qi,j,其中 i,j 的取值范围为 0∼7。

  2. 初始化一个 8×8 的矩阵 M,令 Mi,j=0。

  3. 读入扫描数据,将扫描数据按照这样的顺序写入矩阵 M:从左上角 M0,0 开始,接下来填充它的右侧相邻的元素 M0,1,然后依次向左下方填充直至 M1,0,接下来从它下侧相邻的元素 M2,0 开始,依次向右上方填充直至 M0,2,依次类推,循环往复,直至填充满整个矩阵或用尽所有扫描数据,如图所示。

    填充顺序
  4. 将矩阵 M 中的每个元素都乘以量化矩阵 Q 中的对应元素。

  5. 对矩阵 M 进行离散余弦逆变换,得到一个 8×8 的矩阵 M′。其中,逆变换的公式如下:

  6. 将矩阵 M′ 中的每个元素都加上 128,并取最接近的整数(四舍五入)。如果得到的整数大于 255,则取 255;如果得到的整数小于 0,则取 0。得到的矩阵即为解码后的图片。例如,假设给定的量化矩阵是:

    给出的扫描数据是:-26, -3, 0, -3, -2, -6, 2, -4, 1, -3, 1, 1, 5, 1, 2, -1, 1, -1, 2, 0, 0, 0, 0, 0, -1 -1,那么填充后的矩阵 M 是:

     与量化矩阵逐项相乘后的矩阵是:

     经过离散余弦逆变换后的矩阵 M′ 是:

    经过加 128 后并取整的矩阵是:

输入格式

从标准输入读入数据。

输入的前 8 行,每行有空格分隔 8 个正整数,是量化矩阵。

接下来的 1 行是 1 个正整数 n,表示扫描数据的个数。

接下来的 1 行是 1 个数字 T,取值为 0、1 或 2,表示要进行的任务。

接下来的 1 行,有空格分隔的 n 个整数,是扫描数据。

输出格式

输出到标准输出中。

输出共 8 行,每行有 8 个空格分隔的整数,表示一个图像矩阵。

当 T 取 0 时,输出填充(步骤 3)后的图像矩阵;当 T 取 1 时,输出量化(步骤 4)后的图像矩阵;当 T 取 2 时,输出最终的解码结果。

样例输入

16 11 10 16 24 40 51 61
12 12 14 19 26 58 60 55
14 13 16 24 40 57 69 56
14 17 22 29 51 87 80 62
18 22 37 56 68 109 103 77
24 35 55 64 81 104 113 92
49 64 78 87 103 121 120 101
72 92 95 98 112 100 103 99
26
2
-26 -3 0 -3 -2 -6 2 -4 1 -3 1 1 5 1 2 -1 1 -1 2 0 0 0 0 0 -1 -1

样例输出

62 65 57 60 72 63 60 82
57 55 56 82 108 87 62 71
58 50 60 111 148 114 67 65
65 55 66 120 155 114 68 70
70 63 67 101 122 88 60 78
71 71 64 70 80 62 56 81
75 82 67 54 63 65 66 83
81 94 75 54 68 81 81 87

样例说明

本组样例即为题目描述中的样例。

子任务

对于 20% 的数据,有 T=0;

对于 40% 的数据,有 T=0 或 1;

对于 100% 的数据,有 T∈{0,1,2},且 n∈[0,64],并且量化矩阵中的各个元素 qi,j 满足 0<qi,j<256,扫描序列中的各个元素 mi 满足 −256<mi<256。

提示

在 C/C++ 语言中,可以通过包含 math.h(C 语言)或 cmath(C++ 语言)来使用数学函数。 π 的值可以通过表达式 acos(-1) 获得。

在 Python 语言中,可以通过 from math import pi 引入 π。

在 Java 语言中,可以使用 Math.PI 来获取 π 的值.

真题来源:JPEG 解码

感兴趣的同学可以如此编码进去进行练习提交

python题解:


c++满分题解:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 8;

int n, T;

int a[N][N], M[N][N], M1[N][N];
double M2[N][N];
int q[64];

double trans(double i, double j)
{
    double res = 0;
    for (int u = 0; u <= 7; u ++ )
        for (int v = 0; v <= 7; v ++ )
            if (u == 0 && v == 0)
                res += (double)M1[u][v] * cos(0) * cos(0) / 2.0;
            else if (u == 0)
                res += (double)M1[u][v] * sqrt(0.5) * cos(acos(-1) * (i + 0.5) * double(u) / 8.0) * cos(acos(-1) * (j + 0.5) * v / 8.0);
            else if (v == 0)
                res += (double)M1[u][v] * sqrt(0.5) * cos(acos(-1) * (i + 0.5) * double(u) / 8.0) * cos(acos(-1) * (j + 0.5) * v / 8.0);
            else
                res += (double)M1[u][v] * cos(acos(-1) * (i + 0.5) * double(u) / 8) * cos(acos(-1) * (j + 0.5) * double(v) / 8.0);

    return (double)res / 4.0;    
}

int main()
{
    for (int i = 0; i < 8; i ++ )
        for (int j = 0; j < 8; j ++ )
            cin >> a[i][j];
    
    cin >> n >> T;
    
    for (int i = 0; i < n; i ++ )
        cin >> q[i];
    
    // T1.
    int k = 0; 
    for (int i = 0; i < 8; i ++ )
        if (i % 2 == 0)
        {
            for (int j = 0; j <= i; j ++ )
                M[i - j][j] = q[k ++ ];
        }
        else
            for (int j = 0; j <= i; j ++ )
                M[j][i - j] = q[k ++ ];
        
    for (int i = 8; i < 15; i ++ )
        if (i % 2 == 0)
            for (int j = i - 7; j <= 7; j ++ )
                M[i - j][j] = q[k ++ ];
        else
            for (int j = i - 7; j <= 7; j ++ )
                M[j][i - j] = q[k ++ ];
    
    
    // T2.
    for (int i = 0; i < 8; i ++ )
        for (int j = 0; j < 8; j ++ )
            M1[i][j] = M[i][j] * a[i][j];
        
    // T3.    
    for (int i = 0; i < 8; i ++ )
        for (int j = 0; j < 8; j ++ )
        {
            M2[i][j] = round(trans(i, j) + 128);
            if (M2[i][j] > 255) M2[i][j] = 255;
            if (M2[i][j] < 0) M2[i][j] = 0;
        }
            
    // 输出    
    if (T == 0)
        for (int i = 0; i < 8; i ++ )
        {
            for (int j = 0; j < 8; j ++ )
                cout << M[i][j] << " ";
            cout << endl;
        }
    
    if (T == 1)
        for (int i = 0; i < 8; i ++ )
        {
            for (int j = 0; j < 8; j ++ )
                cout << M1[i][j] << " ";
            cout << endl;
        }
    
    if (T == 2)
        for (int i = 0; i < 8; i ++ )
        {
            for (int j = 0; j < 8; j ++ )
                cout <<  M2[i][j] << " ";
            cout << endl;
        }
    return 0;
}

运行结果: 


借鉴: ShowerSong

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/1097.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

STM32 OTA应用开发——通过串口/RS485实现OTA升级(方式2)

STM32 OTA应用开发——通过串口/RS485实现OTA升级&#xff08;方式2&#xff09; 目录STM32 OTA应用开发——通过串口/RS485实现OTA升级&#xff08;方式2&#xff09;前言1 环境搭建2 功能描述3 程序编写3.1 BootLoader部分3.2 APP的制作4 修改工程中的内存配置4.1 Bootloader…

面试阿里测开岗失败后,被面试官在朋友圈吐槽了......

前一阵子有个徒弟向我诉苦&#xff0c;说自己在参加某大厂测试面试的时候被面试官怼得哑口无言&#xff0c;场面让他一度十分尴尬印象最深的就是下面几个问题&#xff1a;根据你以前的工作经验和学习到的测试技术&#xff0c;说说你对质量保证的理解&#xff1f;非关系型数据库…

HashMap扩容为什么每次都是之前的2倍

一. 背景介绍HashMap的底层是通过数组链表红黑树的数据结构来存放数据的。我们知道&#xff0c;当新添加元素的key值出现了hash碰撞&#xff0c;就会在同一个bucket中形成链表或者红黑树。当键值对的数量超过阈值时就会扩容&#xff0c;将以前处于同一个链表或者红黑树上的元素…

持续集成 在 Linux 上搭建 Jenkins,自动构建接口测试

本篇把从 0 开始搭建 Jenkins 的过程分享给大家&#xff0c;希望对小伙伴们有所帮助。 文章目录 在 Linux 上安装 Jenkins在 Linux 上安装 Git在 Linux 上安装 Python在 Linux 上安装 Allure配置 Jenkinsjenkins 赋能 - 使用邮箱发送测试报告jenkins 赋能 - 优化测试报告内容…

C语言刷题(6)(猜名次)——“C”

各位CSDN的uu们你们好呀&#xff0c;今天&#xff0c;小雅兰还是在复习噢&#xff0c;今天来给大家介绍一个有意思的题目 题目名称&#xff1a; 猜名次 题目内容&#xff1a; 5位运动员参加了10米台跳水比赛&#xff0c;有人让他们预测比赛结果&#xff1a; A选…

测试管理之路 —— 如何优化测试计划以提高测试覆盖率

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;&#x1f30e;【Austin_zhai】&#x1f30f; &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xf…

Github的使用

Github Date: March 8, 2023 Sum: Github的使用 Github 了解开源相关的概念 1. 什么是开源 2. 什么是开源许可协议 开源并不意味着完全没有限制&#xff0c;为了限制使用者的使用范围和保护作者的权利&#xff0c;每个开源项目都应该遵守开源许可协议&#xff08; Open Sou…

node多版本控制

前言 最近在折腾Python&#xff0c;并将node升级至v18.14.2。突然发现一个旧项目无法运行&#xff0c;也无法打包&#xff0c;里面的node-sass报错&#xff0c;显然这是因为node版本过高导致的。 将node版本降低至以前的v14.16.0&#xff0c;果然立马就能正常运行。 存在不同…

mysql-日志备份

1.binlog 用于数据恢复&#xff0c; 用于数据复制。 mysql> show variables like %log_bin%; -------------------------------------------------------------- | Variable_name | Value | ----------------------------------…

前端代码复用学习笔记:整洁架构与清晰架构

基础代码的复用往往比较简单&#xff0c;但是业务代码的复用通常是困难的&#xff0c;如果没有特殊的手段去治理项目会逐渐发展为难以维护的巨石应用&#xff0c;按照维基百科记载&#xff0c;代码的复用形式主要有三种&#xff0c;程序库&#xff0c;应用框架&#xff0c;设计…

【无标题】 6UVPX 总线架构的高性能实时信号处理

VPX630 是一款基于 6U VPX 总线架构的高速信号处理平台&#xff0c;该平台采用一片 Xilinx 的 Kintex UltraScale 系列 FPGA&#xff08;XCKU115&#xff09;作为主处理器&#xff0c;完成复杂的数据采集、回放以及实时信号处理算法。 采用一片带有 ARM内核的高性能嵌入式处理…

GeoServer发布一张纯图片作为地图教程

从事GIS行业的小伙伴们可能会有这样的需求,就是客户给了一张纯图片。可能是一张手工绘图,也可能是一张影像图片,总归来说就是png,jpeg格式的纯图片,现在需要把这张图片加载到我们的地图上,该如何做呢?本文带你从0开始操作一遍。 首先我先准备好测试数据,是一张jpg格式…

LeetCode刷题——贪心法(C/C++)

这里写目录标题[中等]买卖股票的最佳时机 II[中等]移掉k位数字[中等]跳跃游戏[中等]跳跃游戏 II[中等]加油站[中等]划分字母区间[中等]无重叠区间[中等]用最少数量的箭引爆气球[中等]买卖股票的最佳时机 II 原题链接题解 最简单的思路&#xff0c;效率不高&#xff0c;只要明天…

基于 pytorch 的手写 transformer + tokenizer

先放出 transformer 的整体结构图,以便复习,接下来就一个模块一个模块的实现它。 1. Embedding Embedding 部分主要由两部分组成,即 Input Embedding 和 Positional Encoding,位置编码记录了每一个词出现的位置。通过加入位置编码可以提高模型的准确率,因为同一个词出现在…

Web3中文|政策影响下的新加坡Web3步伐喜忧参半

如果说“亚洲四小龙”是新加坡曾经的荣耀&#xff0c;那么当时代进入21世纪的第二个十年&#xff0c;用新加坡经济协会&#xff08;SEE&#xff09;副主席、新加坡新跃社科大学教授李国权的话来说&#xff0c;新加坡现在的“荣耀”是全球金融的主要“节点”或区块链行业发展的关…

单片机能运行操作系统吗?

先直接上答案&#xff1a;可以&#xff01;但是操作系统不是刚需&#xff0c;上操作系统比较占用单片机的资源&#xff0c;比如占用比较多的FLASH和RAM&#xff0c;间接增加了硬件成本&#xff0c;哪怕成本增加1毛钱&#xff0c;对于上量的产品&#xff0c;分分钟是一个工程师的…

【ChatGPT】论文阅读神器 SciSpace 注册与测试

【ChatGPT】论文阅读神器 SciSpace 注册与测试1. 【SciSpace】网址与用户注册1.1 官网地址&#xff1a;[【SciSpace官网】https://typeset.io](https://typeset.io)1.2 官网注册2. 【SciSpace】实战解说2.1 导入论文2.2 论文分析2.3 中文分析2.4 论文分析进阶2.5 公式表格分析3…

没有关系的话,那就去建立关系吧

今天给大家分享一道链表的好题--链表的深度拷贝&#xff0c;学会这道题&#xff0c;你的链表就可以达到优秀的水平了。力扣 先来理解一下题目意思&#xff0c;即建立一个新的单向链表&#xff0c;里面每个结点的值与对应的原链表相同&#xff0c;并且random指针也要指向新链表中…

Maven聚合开发【实例详解---5555字】

目录 一、Maven聚合开发_继承关系 二、Maven聚合案例 1. 搭建dao模块 2. 搭建service模块 3. 搭建web模块 4. 运行项目 一、Maven聚合开发_继承关系 Maven中的继承是针对于父工程和子工程。父工程定义的依赖和插件子工程可以直接使用。注意父工程类型一定为POM类型工程…

vue的diff算法?

文章目录是什么比较方式原理分析Diff算法的步骤&#xff1a;首尾指针法比对顺序&#xff1a;是什么 diff 算法是一种通过同层的树节点进行比较的高效算法 其有两个特点&#xff1a; 比较只会在同层级进行, 不会跨层级比较 在diff比较的过程中&#xff0c;循环从两边向中间比较…