グレースケール画像クラス MonoDouble のその後(Matlab)

以前紹介した MonoDouble ですが、その後も必要に応じて拡張しています。少しだけ紹介します。

  • プロパティが増えました。前回はブロックはブロックサイズでしか移動しませんでしたが、個別に移動量(shiftWidht, shiftHeight)の設定も行えるようにしています。また、端への移動時に指定したブロックサイズよりも小さいブロックを許可するかどうかのフラグ(smallBlockOk)も追加しました。
classdef MonoDouble < handle
    properties 
        buffer % array buffer
        bits % the number of bits
        blockWidth % width of block
        blockHeight % height of block
        shiftWidth % shift width of block
        shiftHeight % shift height of block
        nowx % x of now position (from 0 to width-1)
        nowy % y of now position (from 0 to height-1)
        block % reference for sub MonoDouble
        smallBlockOk % 0 ... smallBlockNo, 1 ... smallBlockOk
    end
  • 周期拡張、対称拡張を追加しました。超富豪的プログラミングです。今やっている処理では最初に一回しか呼ばないので、効率よりもわかりやすさ優先で書いてます。
        function self = extRing_(self, top, left, bottom, right)
            if nargin == 4
                right= left;
            elseif nargin == 3
                bottom = top;
                right = left;
            elseif nargin == 2
                left = top;
                bottom = top;
                right = top;
            end
            b = self.buffer;
            mid = [b b b; b b b; b b b];
            sy = self.height;
            sx = self.width;
            self.buffer = mid(sy-top+1:sy*2+bottom, sx-left+1:sx*2+right);
        end

        function self = extWS_(self, top, left, bottom, right)
            if nargin == 4
                right= left;
            elseif nargin == 3
                bottom = top;
                right = left;
            elseif nargin == 2
                left = top;
                bottom = top;
                right = top;
            end
            b = self.buffer;
            ud = flipud(b);
            lr = fliplr(b);
            rt = fliplr(ud);
            mid = [rt ud rt; lr b lr; rt ud rt];
            sy = self.height;
            sx = self.width;
            mid([sy, sy*2], :) = [];
            mid(:, [sx, sx*2]) = [];
            self.buffer = mid(sy-top:sy*2+bottom-1, sx-left:sx*2+right-1);
        end

        function out = extRing(self, top, left, bottom, right)
            if nargin == 2
                out = self.copy.extRing_(top, top, top, top);
            elseif nargin == 3
                out = self.copy.extRing_(top, left, top, left);
            elseif nargin == 4
                out = self.copy.extRing_(top, left, bottom, left);
            else
                out = self.copy.extRing_(top, left, bottom, right);
            end
        end

        function out = extWS(self, top, left, bottom, right)
            if nargin == 2
                out = self.copy.extWS_(top, top, top, top);
            elseif nargin == 3
                out = self.copy.extWS_(top, left, top, left);
            elseif nargin == 4
                out = self.copy.extWS_(top, left, bottom, left);
            else
                out = self.copy.extWS_(top, left, bottom, right);
            end
        end
  • ブロック周りの初期設定処理を変更しました。引数が少ない場合は、前回と同じブロックサイズと同じ移動設定になります。ここを変えても、setBlock_ や getBlock_メソッドは変更ありません。
        function self = setBlockSize_(self, by, bx, sbok, sy, sx)
            if by > self.height
                by = self.height;
            end
            if bx > self.width
                bx = self.width;
            end
            if nargin == 4
                sy = by;
                sx = bx;
            elseif nargin == 3
                self.smallBlockOk = 1;
                sy = by;
                sx = bx;
            else
                self.smallBlockOk = sbok;
            end
            self.blockWidth = bx;
            self.blockHeight = by;
            self.shiftWidth = sx;
            self.shiftHeight = sy;
            self.nowx = 0;
            self.nowy = 0;
            self.block = MonoDouble(zeros(self.blockHeight, self.blockWidth));
        end
  • next は大きく変わりました。smallBlock が許可される場合とされない場合では大きく違うので、別処理になっています。
        function out = next_(self)
            if self.nowx == -1
                out = 0;
            else
                out = 1;
                if self.smallBlockOk == 1
                    self.nowx = self.nowx + self.shiftWidth;
                    if self.nowx >= self.width
                        self.nowx = 0;
                        self.nowy = self.nowy + self.shiftHeight;
                        if self.nowy >= self.height
                            self.nowx = -1;
                            self.nowy = -1;
                            out = 0;
                        end
                    end
                else
                    self.nowx = self.nowx + self.shiftWidth;
                    if self.nowx + self.blockWidth > self.width
                        self.nowx = 0;
                        self.nowy = self.nowy + self.shiftHeight;
                        if self.nowy + self.blockHeight > self.height
                            self.nowx = -1;
                            self.nowy = -1;
                            out = 0;
                        end
                    end
                end
            end
        end
  • ブロック内の値の総和を得るメソッドを追加しました。
        function out = sum(self)
            out = sum(sum(self.buffer));
        end
  • 以上の拡張によってブロックマッチングが、簡単に書けるようになったので、メソッド化しました。
        function [out, vy, vx, min] = blockMatching(self, other)
            vy = 0;
            vx = 0;
            min = 1e300;
            oy = other.height;
            ox = other.width;
            self.setBlockSize_(oy, ox, 0, 1, 1);
            cond = true;
            while (cond)
                bk = self.getBlock_;
                se = bk.sub_(other).square_.sum;
                if se < min
                    min = se;
                    vy = self.nowy;
                    vx = self.nowx;
                end
                cond = self.next_;
            end
            self.setBlockSize_(oy, ox);
            self.setNowPos(vy, vx);
            out = self.getBlock_;
        end

このメソッドを使った例は明日.