首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

动态规划经典题目-数据压缩之图像压缩

  • 25-03-07 18:21
  • 2432
  • 10052
blog.csdn.net

文章目录

  • 一、题目描述
  • 二、解题思路
    • 1. 定义状态
    • 2. 定义状态转移方程
    • 3. 初始化
    • 4. 计算方式
  • 三、代码实现
  • 四、执行结果
  • 五、思考

一、题目描述

​ 计算机中的图像由一系列像点构成,每个像点称为一个像素,图像分辨率越高,使用的像素就越多,例如Windows桌面的图片经常使用的设置是1024×768个,大概达到106量级.图像传输和视频处理有时在1秒钟内要处理几十帧图片,这些图片的像素就很可观了,因此图像处理常常需要大量的存储空间和高的处理速度,图像压缩问题就成了计算机科学技术中的重要研究课题之一.

​ 以黑白图像的处理来说明图像压缩中的问题.每幅黑白图像由像点构成,每个像点具有灰度值,用0~255之间的整数表示.如果每个整数都用相同的二进制位来表示,那么需要用8个二进制位.假设一幅图像有n个像素,那么这n个像素的灰度值构成一个整数序列:P = 1,p2,…,pn>

​ 其中p表示第i个像素的灰度.存储这幅图片时,可以像数组一样连续把这些整数存起来,共需要8n个二进制位.

​ 下面考虑一种图像压缩方法.一般来说,在一幅图片中许多连续区域中像点的灰度值是接近的.比如有些交通标志图片,大片的区域是白的,可能少量区域有颜色,而且是比较单调的颜色.对这样的图片是否可以采用分段存储的方法:对灰度值较小的段的像素采用比较少的位数,比如2位;对灰度值较大的段的像素采用较多的位数,比如8位,这样就可能减少空间的占用.这就是变位压缩技术的基本想法.这种技术节省了空间,但在读取图像时带来了新的问题.在每个像素8位的存储方法中,读取图像时每8位就是一个像素的灰度值,不会出错.但是对于分段压缩的图像,看起来就是一个长长的0-1序列.当读取这个序列时,怎么知道每段的划分位置及每段像素占用的二进制位数呢?这里需要对段的划分和段中像素使用的二进制位数(要求同一段内不同像素用的存储位数都一样)给出明确的信息.为此,我们对每个段给出两个整数值,一个表示该段含有的像素个数,一个表示每个像素所占用的二进制位数.比如第i段,有l[i]个像素,每个像素用b[i]位.由于某些技术要求,规定每段像素总数不超过256,即l[i]≤256.于是可以用8位来表示l[i](8位二进制数恰好有256个值).此外,由于每个灰度值在0~255之间,表达每个灰度值所用二进制数的位数b[i]不超过8,于是记录b[i]还需要3个二进制位.对每段来说,这额外的11位作为段头信息.从直觉上来说,分段越多,每段内部像素所占用的位数会减少,但过多的段头会消耗较多的二进制位.相反,分段越少,段内像素的空间消耗会增加,但是段头消耗少.

示例:

​ 请看下面的例子.设输入的灰度值序列是:

​ P =<10,12,15,255,1,2,1,1,2,2,1,1>

  • 分法1 S1= <10,12,15>,S2 =<255>,S3=<1,2,1,1,2,2,1,1>

  • 分法2 S1=<10,12,15,255,1,2,1,1,2,2,1,1>

  • 分法3 S1=<10>,S2=<12>,S3=<15>,S4=<255>,S5=<1>,S6=<2>,S7=<1>,S8=<1>,S9=<2>,S10=<2>,S11=<1>,S12=<1>

    ​ 分法1有3段,第1段3个像素,每个像素用4位;第2段1个像素,每个像素用8位;第3段8个像素,每个像素用2位;加上3个段头,每个段头11位,总计位数是:
    4×3+8×1+2×8+3×11=69

    ​ 分法2有1段,12个像素,每个像素用8位,段头11位,总计位数是:
    8×12+11=107

    ​ 分法3有12段,前3段的像素用4位,第4段像素用8位,后面有5段像素用1位,3段像素用2位,还有12个段头,每个11位,总计位数是:
    4×3+8×1+1×5+2×3+11×12=163

    看起来分法1占用的位数最少.我们的问题是寻找存储位数最少的分段方法.

二、解题思路

1. 定义状态

​ 设dp[i]表示字符串前i个像素点的保存的最少二进制数的数量,i从1开始计数,那么我们最终要求出的是dp[P.length]即为像素序列P的最少消耗空间;

​ 假设每个分段数量为j,则由于题目约束可得 1 ≤ j < = m i n ( i , 256 ) 1 \leq j <=min(i,256) 1≤j<=min(i,256), 假设像素序列i的后j个像素序列分为一段,则有dp[i] = dp[i - j] + j x log2max(Pi-j+1,…,Pi) + 11 ,当然j值可能有多个,我们取最小花费那个。

2. 定义状态转移方程

当 1 ≤ j < = m i n ( i , 256 ) 1 \leq j <=min(i,256) 1≤j<=min(i,256),有

​ d p [ i ] = m i n ( d p [ i − j ] + j × l o g 2 m a x ( P i − j + 1 , . . , P i ) + 11 ) dp[i] = min(dp[i - j] + j \times log_2max(P_{i-j+1},..,P_i) + 11) dp[i]=min(dp[i−j]+j×log2​max(Pi−j+1​,..,Pi​)+11)

3. 初始化

​ 当 i = 0时,有 d p [ 0 ] = 0 dp[0] = 0 dp[0]=0

4. 计算方式

​ 自左向右计算

三、代码实现

/**
 * 最优图像压缩位数
 *
 *  @author hh
 *  @date 2021-5-21 21:46
 */
public class OptimalImageCompression {

    public int optimalBits(int[] dots,int[] traces){
        int[] dp = new int[dots.length + 1];
        int cost = Integer.MAX_VALUE;
        //初始化行
        dp[0] = 0;
        for(int i = 1; i <= dots.length; i++){
            dp[i] = Integer.MAX_VALUE;
            for(int j = 1; j <= Math.min(i,256); j++){
                cost = dp[i -j] + j * (this.minBits(this.max(dots,i -j + 1,i))) +11;
                if(cost < dp[i]){
                    dp[i] = cost;
                    traces[i] = j;
                }
            }
        }
        return dp[dots.length];
    }

    public void print(int[] traces, int length){
        length -= traces[length];
        if(length <= 0){
            return;
        }
        print(traces,length);
        System.out.print(length + " ");
    }

    private int max(int[] dots,int start,int end){
        int[] copy =  Arrays.copyOfRange(dots,start -1,end);
        Arrays.sort(copy);
        return copy[copy.length -1];
    }

    private int minBits(int number){
        int bits = 0;
        for(int i = 1; i <= 8; i++){
            if(Math.pow(2,i-1) - 1 <= number && Math.pow(2,i) - 1 >= number){
                bits = i;
                break;
            }
        }
        return bits;
    }

    public static void main(String[] args){
        int[] dots = new int[]{10,12,15,255,1,2,1,1,2,2,1,1};
        int[] traces = new int[dots.length + 1];
        OptimalImageCompression optimalImageCompression = new OptimalImageCompression();
        System.out.println("最少二进制位:" + optimalImageCompression.optimalBits(dots,traces));
        System.out.print("切分位置:");
        optimalImageCompression.print(traces,dots.length);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

四、执行结果

在这里插入图片描述

五、思考

​ 本题和文本压缩的做法非常相似,都是对dp数组进行线性划分,读者有时间可以看我的另一篇文章动态规划经典题目-数据压缩之文本压缩,进行举一反三。

文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览64430 人正在系统学习中
注:本文转载自blog.csdn.net的仁者乐山智者乐水的文章"https://blog.csdn.net/qq_39559641/article/details/117201636"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top