图像压缩问题

图像压缩问题的bilibil讲解

1.问题引入

首先,图像是由像素组合成的,每个像素都有灰度值,灰度值是体现像素的颜色的。灰度值从0~255,灰度值占用的位数就是像素占用的位数。我们要存储一个图像就要存储它的所有像素。现在的问题是我们如何存储,使得存储空间最小?

思路:我们需要将图像分成m段,每段中有L[t]个像素,每个要占用b[t]个比特位,每个段都有一个端头,段头是固定的需要占用11位。因此总共需要如下存储空间。

一段像素个数最多有256个,这是题目要求的已知条件。一个像素要最少要占用多少位哩?设第t个像素的灰度值为n,b[t](每个像素占用的位数)要考虑到2种情况,第一种,n是2的整数次方,这时b[t]就是logn;第二种情况,a<logn<b(a,b为整数),这时要保证能表示灰度值,要加一再向上取整。综上,我们要满足这两种情况的并集,b[t]=log(n+1)向上取整,注意不能是log(n)+1向上取整,因为如果(n=2的x次方-1)时,这两种值就不一样了。例如,灰度值为1,我们需要一位来存储。再如,n=7,我们需要3位来存储。第t段最大的像素所占位数为max pk,得到如下图所示:

一个例子:

对于这个问题就转变成了如何分段问题。如果要用暴力求解法,我们要遍历多少种分段方法哩?

假设一共有n个像素,那么就有n-1个分割点,每个分割点可以选择分或不分,一共有2的n-1次方种分段方法

显然,比较浪费时间。

2.用动态规划算法可以减少时间复杂度,那么动态归划算法怎么划分子问题呢?

我们只用一个变量i来表示第i个像素的位置,找到第i个位置的最优解,每次增加一个像素,最终变成规模为n的像素问题。

例子:

上面例子种S[1]=4+11=15

S[2]的最优解在这两种划分方法中(1)分2段:S[1]+4+11=30  (2)分1段:S[0]+4*2+11=19

S[3]的最优解在这三种划分方法中(1)S[1]+4*2+11=34  (2)S[2]+4+11=34 (3)S[0]+4*3+11=23

S[4]的最优解在这四种划分方法中(1)S[3]+8+11=42 (2)S[2]+8*2+11 (3)S[1]+8*3+11 (4)S[0]+8*4+11

依次类推,S[6]的最优解在如上图所示这六种划分算法中。

(1)S[5]+1*2+11 (2)S[4]+2*2+11 (3) S[3]+3*8+11 (4)S[2]+4*8+11

(5)S[1]+5*8+11 (6) S[0]+6*8+11

红色部分对应代码

s[i] = s[i - 1] + bmax;//整个数组从1到i-1的最优解加i单独一段

  s[i] += header;

黄色部分对应代码

//在s[i]+j*bmax中找最好的存储方法
        for (int j = 2; j <= i && j <= Lmax; j++)
        {
            if (bmax < b[i - j + 1])//下标前移,找最大的像素
            {
                bmax = b[i - j + 1];
            }

            if (s[i] > s[i - j] + j * bmax)
            {
                s[i] = s[i - j] + j * bmax;
                l[i] = j;
            }
        }
        s[i] += header;

其中,L[i]记录S[i]的划分段数。

3.接下来,我们看看递推方程怎么表示

j-i+1i个像素中占用位数最大的像素记为b[i-j+1,i]

S[i]表示从第一个像素到第i个像素的最小存储总位数。

4.伪代码实现

s[i]来记录前i个数字的最优处理方式得到的最优解,即最小存储位数
l[i]来记录当前第i个数所在段中有多少个数,
b[i]中存放前i个像素点的最后一段中最大像素位数。

5.代码实现

#include <iostream>   
using namespace std;const int N = 8;int length(int i);
void Compress(int n, int p[], int s[], int l[], int b[]);
void Tracebace(int n, int& i, int s[], int l[]);
void Output(int s[], int l[], int b[], int n);int main()
{int p[] = { 0,10,12,15,255,1,2,0 };//图像灰度数组 下标从1开始计数  int s[N], l[N], b[N];
/**s[i]来记录前i个数字的最优处理方式得到的最优解,即最小存储位数
l[i]来记录当前第i个数所在段中有多少个数,
b[i]中存放前i个像素点的最后一段中最大像素位数。**/cout << "图像的灰度序列为:" << endl;for (int i = 1; i < N; i++) //输出原灰度序列 {cout << p[i] << " ";}cout << endl;Compress(N - 1, p, s, l, b);Output(s, l, b, N - 1);return 0;
}void Compress(int n, int p[], int s[], int l[], int b[])
{int Lmax = 256, header = 11;s[0] = 0;for (int i = 1; i <= n; i++){b[i] = length(p[i]); //计算像素点p需要的存储位数  int bmax = b[i];s[i] = s[i - 1] + bmax;//整个数组从1到i-1的最优解加i单独一段l[i] = 1;
//在s[i]+j*bmax中找最好的存储方法for (int j = 2; j <= i && j <= Lmax; j++){if (bmax < b[i - j + 1])//下标前移,找最大的像素{bmax = b[i - j + 1];}if (s[i] > s[i - j] + j * bmax){s[i] = s[i - j] + j * bmax;l[i] = j;}}s[i] += header;}
}
/***求数组中的元素用多少位二进制表示***/
int length(int i) //i表示p数组中元素的值 
{int k = 1;i = i / 2;while (i > 0){k++;i = i / 2;}return k;
}
/**s[i]来记录前i个数字的最优处理方式得到的最优解,即最小存储位数
l[i]来记录当前第i个数所在段中有多少个数,
b[i]中存放前i个像素点的最后一段中最大像素位数。**/
/*递归找寻分段的位置*/
void Traceback(int n, int& i, int s[], int l[])
{if (n == 0)return;Traceback(n - l[n], i, s, l);s[i++] = n - l[n];//重新为s[]数组赋值,用来存储分段位置  
}void Output(int s[], int l[], int b[], int n)
{//在输出s[n]存储位数后,s[]数组则被重新赋值,用来存储分段的位置  cout << "图像压缩后的最小空间为:" << s[n] << endl;int m = 0;Traceback(n, m, s, l);s[m] = n;cout << "将原灰度序列分成" << m << "段序列段" << endl;for (int j = 1; j <= m; j++){l[j] = l[s[j]];//在下标为s[j]的地方划分b[j] = b[s[j]];}for (int j = 1; j <= m; j++){cout << "段长度:" << l[j] << ",所需存储位数:" << b[j] << endl;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

0502_C高级H1

练习题&#xff1a; 5月2日作业&#xff1a; 第一题&#xff1a; 段错误 str指向申请堆空间内存的首地址&#xff0c;直接拷贝hello world 会导致段错误 第二题&#xff1a; 段错误 临时变量返回地址属于典型的段错误 第三题&#xff1a; hello 第四题&#xff1a; 段错误 free…

ssm(教学评价系统)

开发语言&#xff1a;Java JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09;服务器&#xff1a;tomcat 数据库&#xff1a;mysql 5.6/5.7&#xff08;或8.0&#xff09;数据库工具&#xff1a;Navicat 开发软件&#xff1a;idea 依赖管理包&#xff1a;Maven 代码数据库…

车载电子电器架构 —— 关于bus off汇总

车载电子电器架构 —— 关于bus off汇总 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明…

【uniapp】H5+、APP模拟浏览器环境内部打开网页

前言 今天将智能体嵌入到我的项目中&#xff0c;当作app应用时&#xff0c;发现我使用的webview组件&#xff0c;无论H5怎么登录都是未登录&#xff0c;而APP却可以&#xff0c;于是进行了测试&#xff0c;发现以下几种情况&#xff1a; 方法<a>标签webviewAPP✅✅网页…

Acwing2024蓝桥杯回溯

AcWing 167. 木棒 dfs剪枝: #include<iostream> #include<algorithm> #include<cstring> using namespace std; const int N70; int n,a[N],flag[N],sum,len; //a:每个木棍长度,flag:状态数组 //len:木棒的长度,sum:所有木棍的总长度 //cnt:当前正在拼第几根…

[C++核心编程-01]----C++内存四区详解

前言 结构体&#xff08;Struct&#xff09;是C中一种用户定义的复合数据类型&#xff0c;用于存储不同类型的数据项。结构体可以包含不同类型的数据成员&#xff0c;这些数据成员可以是基本类型&#xff08;如int、float、char等&#xff09;&#xff0c;也可以是数组…

Xcode 对应的 macOS、SDK 版本

最低要求和支持的 SDK 本表截取于 2024-05-04&#xff0c;更多更新可见&#xff1a;https://developer.apple.com/cn/support/xcode/ Xcode 版本要求的最低 OS 版本SDK架构部署目标模拟器SwiftXcode 15.3macOS Sonoma 14iOS 17.4 macOS 14.4 tvOS 17.4 watchOS 10.4 DriverKi…

spring高级篇(八)

本篇对Spring MVC 的执行流程做一个简单总结 MVC执行流程总结 当浏览器发送一个请求&#xff0c;例如http://localhost:8080/hello&#xff0c;请求到达服务器后&#xff0c;一般会进行如下操作&#xff1a; 1、首先会经过DispatcherServlet&#xff0c;默认映射路径为 /&…

GRU模块:nn.GRU层的输出state与output

在 GRU&#xff08;Gated Recurrent Unit&#xff09;中&#xff0c;output 和 state 都是由 GRU 层的循环计算产生的&#xff0c;它们之间有直接的关系。state 实际上是 output 中最后一个时间步的隐藏状态。 GRU 的基本公式 GRU 的核心计算包括更新门&#xff08;update gat…

用于密集预测任务的通道知识蒸馏——关键字:蒸馏

摘要 https://arxiv.org/pdf/2011.13256 知识蒸馏(KD)已被证明是训练紧凑密集预测模型的简单有效工具。通过从大型教师网络转移而来的额外监督来训练轻量级学生网络。大多数先前的针对密集预测任务的KD变体都在空间域中对学生网络和教师网络的激活图进行对齐,通常是通过在每…

【Linux】进程间通信 - 管道

文章目录 1. 进程间通信介绍1.1 进程间通信目的1.2 进程间通信发展1.3 进程间通信分类 2. 管道2.1 什么是管道2.2 匿名管道2.3 用 fork 来共享管道原理2.4 站在文件描述符角度 - 深入理解管道2.5 站在内核角度 - 管道本质2.6 管道读写规则2.7 管道特点 3. 命名管道3.1 匿名管道…

linux代码实操——信号的使用

信号的基本概念 信号是系统响应某个条件而产生的事件&#xff0c;进程接收到信号会执行相应的操作。 与信号有关的系统调用在“signal.h”头文件中有声明 常见信号的值&#xff0c;及对应的功能说明&#xff1a; 修改信号的响应方式 – signal() 我们来做个小实验: 在键盘上…

推荐书单|提升境界、思维能力

1、《别做正常的傻瓜》 豆瓣评分&#xff1a;8.1 通过揭示人们在日常生活中常见的非理性行为&#xff0c;引导读者认识并克服这些行为&#xff0c;从而做出更明智的决策。 2、《活法》 豆瓣评分&#xff1a;8.1 稻盛和夫分享其人生哲学和经营哲学的著作&#xff0c;强调了正确…

软设之段页式存储

页式存储&#xff1a;将程序与内存划分为同样大小的块&#xff0c;以页为单位将程序调入内存。 比如说每页是1M&#xff0c;不管是内存还是程序&#xff0c;每页都是1M 高级程序语言使用逻辑地址&#xff0c;比如C语言用的指针。 运行状态时&#xff0c;内存中使用物理地址。…

【C++】模板初阶:泛型编程的起点

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…

富文本编辑器CKEditor4简单使用-08(段落首行缩进插件 + 处理粘贴 Microsoft Word 中的内容后保持原始内容格式(包括首行缩进))

富文本编辑器CKEditor4简单使用-08&#xff08;段落首行缩进插件 处理粘贴 Microsoft Word 中的内容后保持原始内容格式&#xff08;包括首行缩进&#xff09;&#xff09; 1. 缩进&#xff0c;特殊方式处理——修改原工具栏里的增加缩进量2 缩进&#xff0c;插件处理2.1 下载…

并查集~~

值为v的数封为Node型的节点&#xff0c;除了nodes中保存了V和Node的对应关系外&#xff0c;并查集相关的parents&#xff0c;sizeMap都是用Node来关联的。 #include<iostream> #include<map> #include<vector> #include<stack> using namespace std;t…

建一个wordpress外贸独立站的费用构成与分析

外贸独立站因为独特的优势&#xff0c;越来越被做外贸的跨境电商所青睐。简站主题经常接到做外贸的老板咨询&#xff0c;建一个wordpress外贸独立站大约多少钱&#xff0c;也是被问的最多的问题之一。下面小简就从几个方面讲一下&#xff0c;决定一个wordpress外贸独立站的费用…

TypeScript的使用:可以谈谈TypeScript的优点以及如何在实际项目中引入和使用TypeScript,包括一些基本的语法和编程技巧。

TypeScript是JavaScript的一个超集&#xff0c;它主要提供了类型系统和对ES6的兼容。下面是一些TypeScript的主要优点&#xff1a; 静态类型检查&#xff1a;这是TypeScript最主要的功能&#xff0c;它可以在编译阶段发现和报告错误&#xff0c;帮助开发者提前找到问题。更好的…

TensorFlow轻松入门(二)——小案例:ANN构建一个或运算的模型

或运算&#xff1a; 位与位进行比较&#xff0c;如果有任一个是1&#xff0c;结果为1&#xff1b;两个都为0&#xff0c;结果则为0。 实现步骤 构建Feature与Label数据 创建顺序模型 指定模型的第一层&#xff0c;线性模型 添加一层激活函数 模型编译 模型训练 模型预测…