Statistics jpeg文件中的字节分布

Statistics jpeg文件中的字节分布,statistics,compression,distribution,jpeg,chi-squared,Statistics,Compression,Distribution,Jpeg,Chi Squared,在观察压缩数据时,我希望得到几乎均匀分布的字节流。当使用卡方检验来测量分布时,我得到了这个结果,例如对于ZIP文件和其他压缩数据,但对于JPG文件则没有。最后几天我一直在寻找原因,但我找不到任何原因 当计算JPG的熵时,我得到了一个很高的结果(例如7,95位/字节)。我认为熵和分布之间一定有联系:当每个字节以几乎相同的概率出现时,熵是高的。但当使用卡方检验时,a得到的p值约为4,5e-5 我只是想了解不同的分布如何影响测试结果。。。我想我可以用两个测试来测量相同的属性,但显然我不能 非常感谢您的

在观察压缩数据时,我希望得到几乎均匀分布的字节流。当使用卡方检验来测量分布时,我得到了这个结果,例如对于ZIP文件和其他压缩数据,但对于JPG文件则没有。最后几天我一直在寻找原因,但我找不到任何原因

当计算JPG的熵时,我得到了一个很高的结果(例如7,95位/字节)。我认为熵和分布之间一定有联系:当每个字节以几乎相同的概率出现时,熵是高的。但当使用卡方检验时,a得到的p值约为4,5e-5

我只是想了解不同的分布如何影响测试结果。。。我想我可以用两个测试来测量相同的属性,但显然我不能

非常感谢您的任何提示! tom

在jpeg文件中的分布 忽略元信息和jpeg头数据,jpeg的有效载荷由描述或编码MCU的块(最小编码单位,大小为16x16的方形块)组成。可能还有其他的,但这是最常见的

这些块由
0xFF 0xSS
分隔,其中
0xSS
是特定的起始代码。这里是第一个问题:
0xFF
比注释中提到的要频繁一些

编码的MCU中可能会出现
0xFF
。为了区分此正常有效负载和新块的开始,插入了
0xFF 0x00
。如果未填充有效负载的分布完全均匀,
0x00
在填充数据中的频率将是原来的两倍。更糟糕的是,每个MCU都填满了二进制MCU以获得字节对齐(稍微偏向较大的值),我们可能需要再次填充

可能还有其他一些我不知道的因素。如果需要更多信息,必须提供jpeg文件

关于你的基本假设: 对于rand_数据:

 dd if=/dev/urandom of=rand_data count=4096 bs=256
对于rand_pseudo(python):

在字节值方面,两者应该是一致的,不是吗?;)


均匀分布可能表示高,但这不是保证。此外,rand_数据可能由1MB的
0x00
组成。这极不可能,但也有可能。

在这里您可以找到两个文件:第一个是随机数据,由dev/unrandom生成(约46MB),第二个是正常的JPG文件(约9MB)。很明显,JPG文件的符号并不像在dev/uradom中那样均匀分布

如果我比较两个文件:

熵: JPG:7969247位/字节 RND:7999996位/字节

卡方检验的p值: JPG:0 RND:03621

熵怎么会导致这么高的结果

这是我的java代码

         public static double getShannonEntropy_Image(BufferedImage actualImage){
         List<String> values= new ArrayList<String>();
           int n = 0;
           Map<Integer, Integer> occ = new HashMap<>();
           for(int i=0;i<actualImage.getHeight();i++){
             for(int j=0;j<actualImage.getWidth();j++){
               int pixel = actualImage.getRGB(j, i);
               int alpha = (pixel >> 24) & 0xff;
               int red = (pixel >> 16) & 0xff;
               int green = (pixel >> 8) & 0xff;
               int blue = (pixel) & 0xff;
//0.2989 * R + 0.5870 * G + 0.1140 * B greyscale conversion
//System.out.println("i="+i+" j="+j+" argb: " + alpha + ", " + red + ", " + green + ", " + blue);
                int d= (int)Math.round(0.2989 * red + 0.5870 * green + 0.1140 * blue);
               if(!values.contains(String.valueOf(d)))
                   values.add(String.valueOf(d));
               if (occ.containsKey(d)) {
                   occ.put(d, occ.get(d) + 1);
              } else {
                  occ.put(d, 1);
              }
              ++n;
       }
    }
    double e = 0.0;
    for (Map.Entry<Integer, Integer> entry : occ.entrySet()) {
         int cx = entry.getKey();
         double p = (double) entry.getValue() / n;
         e += p * log2(p);
    }
 return -e;
  }
公共静态双getShannonEntropy_映像(BuffereImage实现映像){
列表值=新的ArrayList();
int n=0;
Map occ=newhashmap();
对于(int i=0;i 24)&0xff;
int red=(像素>>16)和0xff;
绿色整数=(像素>>8)&0xff;
蓝色整数=(像素)&0xff;
//0.2989*R+0.5870*G+0.1140*B灰度转换
//System.out.println(“i=“+i+”j=“+j+”argb:“+alpha+”、“+red+”、“+green+”、“+blue”);
整数d=(整数)数学四舍五入(0.2989*红色+0.5870*绿色+0.1140*蓝色);
如果(!values.contains(String.valueOf(d)))
value.add(String.valueOf(d));
如果(occ.containsKey(d)){
occ.put(d,occ.get(d)+1);
}否则{
货币监理署署长(d,1);
}
++n;
}
}
双e=0.0;
对于(Map.Entry:occ.entrySet()){
int cx=entry.getKey();
double p=(double)entry.getValue()/n;
e+=p*log2(p);
}
返回-e;
}

您是只测量了主体还是包含了未压缩的标题?谢谢您提出的有趣问题。我试图排除元信息。。。因此,我跳过了第一个和最后一个4096字节(每个1个集群)。JPEG和许多其他格式在整个文件中都有节头和其他元数据,而不仅仅是在开头和/或结尾。如果你真的想跳过所有的元数据,你需要分析标题,找出其他部分在哪里,这样你也可以跳过它们…我已经浏览了一些文件,但找不到任何类似元数据的内容,所有内容看起来都是一致的。非常感谢!显然,我需要对jpg文件格式有更深入的了解。无论如何,我仍然不明白为什么熵是高的,但是卡方计算得出的p值非常低(远低于ZIP/DOC/PDF)…我想推这篇文章,因为我仍然没有找到答案。。。大家新年快乐(顺便说一句:)
$ ll rand_*
-rw-r--r-- 1 apuch apuch 1048576 2012-12-04 20:11 rand_data
-rw-r--r-- 1 apuch apuch 1048967 2012-12-04 20:13 rand_data.tar.gz
-rw-r--r-- 1 apuch apuch 1048576 2012-12-04 20:14 rand_pseudo
-rw-r--r-- 1 apuch apuch    4538 2012-12-04 20:15 rand_pseudo.tar.gz
         public static double getShannonEntropy_Image(BufferedImage actualImage){
         List<String> values= new ArrayList<String>();
           int n = 0;
           Map<Integer, Integer> occ = new HashMap<>();
           for(int i=0;i<actualImage.getHeight();i++){
             for(int j=0;j<actualImage.getWidth();j++){
               int pixel = actualImage.getRGB(j, i);
               int alpha = (pixel >> 24) & 0xff;
               int red = (pixel >> 16) & 0xff;
               int green = (pixel >> 8) & 0xff;
               int blue = (pixel) & 0xff;
//0.2989 * R + 0.5870 * G + 0.1140 * B greyscale conversion
//System.out.println("i="+i+" j="+j+" argb: " + alpha + ", " + red + ", " + green + ", " + blue);
                int d= (int)Math.round(0.2989 * red + 0.5870 * green + 0.1140 * blue);
               if(!values.contains(String.valueOf(d)))
                   values.add(String.valueOf(d));
               if (occ.containsKey(d)) {
                   occ.put(d, occ.get(d) + 1);
              } else {
                  occ.put(d, 1);
              }
              ++n;
       }
    }
    double e = 0.0;
    for (Map.Entry<Integer, Integer> entry : occ.entrySet()) {
         int cx = entry.getKey();
         double p = (double) entry.getValue() / n;
         e += p * log2(p);
    }
 return -e;
  }