在MATLAB中实现Zig-zag排序的最有效方法是什么?

时间:2015-02-06 15:28:52

标签: algorithm matlab image-processing

我问这个问题主要是因为它困扰了我一段时间,我还没有想出实现这个问题最有效的方法。这主要是出于我自己的好奇心,所以肯定不会急于回答这个问题,但是如果我看到一个非常有效且非常有效的解决方案,我可以奖励一个奖励,以便有一些激励!


主要问题

您可以想到的MATLAB中最有效的方法是采用图像块/矩阵并将其转换为符合Z字形排序的向量?您可以假设该块是,其中行数等于列数。

一些背景

Zigzag ordering最初来自JPEG压缩标准。 JPEG压缩算法背后的基本步骤如下图所示:

enter image description here

来源:Wikipedia

总结一下,对于一个图像,它被分成8 x 8个不同的图像块,在每个块上采用2D Discrete Cosine Transform (DCT),然后执行quantization在每个块上允许编码以最小化比特序列的总熵。对此最重要的阶段是熵编码阶段,是算法的最后一部分。

熵编码阶段的一部分涉及之字形排序 - 将块重新排序为64元素向量,其中来自DCT的最重要的频率成分首先出现,然后是那些组件为了重建块并不重要。

以下是8 x 8块上锯齿形排序的图示:

enter image description here

来源:Wikipedia

蓝色箭头从图像的左上角或原点开始。接下来,箭头移动的方向指示64元素向量如何用元素填充。

以下是参考上图的zigzag的基本算法:

  1. 从街区的左上角开始。
  2. 我们向右移动一个空格,然后沿对角线向下移动,直到我们到达图像边界。
  3. 在步骤2中我们点击图像边框后,我们向下移动一个空格,然后沿对角方向直立移动,直到我们到达图像边框。
  4. 在步骤#2和#3之间交替,直到我们到达块的右下角。
  5. 您需要注意几个角落案例:

    • 转角情况#1 - 如果我们在步骤#2中,我们点击图像边框,我们在块的最后一列,向右移动一个空格。移动一个空格向下
    • 转角情况#2 - 如果我们在步骤#3中,我们点击图像边框,我们在块的最后一行,向下移动一个空格。将一个空格移到右侧

    一旦出现Z字形排序,就会对此重新排序的数据执行任何无损压缩算法,例如Huffman ...以及是甚至熵编码(如此阶段的命名)。这64个元素向量将流式传输到压缩算法,因此您可以获得压缩图像。


    返回问题描述

    你现在可能已经看到了我的困境。由于角落的情况,我没有找到一种有效的方法来做到这一点,而不试图用循环来做这件事。在互联网上进行了一些初步搜索之后,我在Rosetta Code上发现了一个非常类似的帖子,讨论了如何创建一个Z字形矩阵。这里的目标是生成一个大小为M x M的矩阵,其中给定一个整数M > 0,矩阵中的每个位置都从0枚举到M^2 - 1,其中的数字在执行之字形排序的顺序而不是单个向量。通过一些非常简单的修改,您可以解决上述问题,但我想知道是否有任何方法可以比循环更有效。如果你检查代码,它是非常不直观的,除非你开始在命令窗口中显示步骤,否则没有多大意义。即使在这种情况下,它仍然很难理解,我敢说是混淆了。

    对于自包含,这是使用循环实现zig-zag排序的“引用”代码。这是从Rosetta代码中删除的,但我对其进行了修改,使其符合提出的问题。这将采用2D方阵blk,而out是一个矢量,它以锯齿形排序生成从方阵中取出的元素:

    function out = zigzag(blk)
    
        %This is very unintiutive. This algorithm parameterizes the
        %zig-zagging movement along the matrix indicies. The easiest way to see
        %what this algorithm does is to go through line-by-line and write out
        %what the algorithm does on a peace of paper. 
    
        [m,n] = size(blk);
        if m ~= n
            error('Not square');
        end
    
        out = zeros(numel(blk), 1);
        flipCol = true;
        flipRow = false;
        out(1) = blk(1);
        counter = 2;
    
        %This for loop does the top-diagonal of the matrix
        for i = (2:n)
            row = (1:i);
            column = (1:i);
    
            %Causes the zig-zagging. Without these conditionals, 
            %you would end up with a diagonal matrix. 
            %To see what happens, comment these conditionals out.         
            if flipCol
                column = fliplr(column);
                flipRow = true;
                flipCol = false;
            elseif flipRow
                row = fliplr(row);
                flipRow = false;
                flipCol = true;           
            end
    
            %Selects a diagonal of the zig-zag matrix and places the 
            %correct integer value in each index along that diagonal
            for j = (1:numel(row))
                out(counter) = blk(row(j),column(j));
                counter = counter + 1;
            end   
        end
    
        %This for loop does the bottom-diagonal of the matrix
        for i = (2:n)
            row = (i:n);
            column = (i:n);
    
            %Causes the zig-zagging. Without these conditionals, 
            %you would end up with a diagonal matrix. 
            %To see what happens comment these conditionals out. 
            if flipCol
                column = fliplr(column);
                flipRow = true;
                flipCol = false;
            elseif flipRow
                row = fliplr(row);
                flipRow = false;
                flipCol = true;           
            end
    
            %Selects a diagonal of the zig-zag matrix and places the 
            %correct integer value in each index along that diagonal
            for j = (1:numel(row))
                out(counter) = blk(row(j),column(j));
                counter = counter + 1;
            end   
        end
    
    
    end
    

    因此,这是对MATLAB SO社区的调用,以查看是否有更简单的实现,利用MATLAB的向量化和索引构造。

    感谢您抽出时间阅读,并期待您的回答!

0 个答案:

没有答案