OpenCV 3.4.1で背景差分

背景差分

f:id:whoopsidaisies:20180301131807p:plain

画像の前景と背景を分離する手法。2013年にOpenCV 2.4.7での背景差分の記事を書いたが、2018年になったいまOpenCV 3.4.1で背景差分を行おうとしたら使えるアルゴリズムが増えていたのでまとめておく。

アルゴリズム

MOG, MOG2, GMG

OpenCV 2.4.7でも使えた。以下のページに日本語でわかりやすい説明がある。

背景差分 — OpenCV-Python Tutorials

KNN

K近傍方に基づく背景差分。前景の画素数が少ない場合は効率が良いらしい。

Efficient adaptive density estimation per image pixel for the task of background subtraction - ScienceDirect

CNT

低スペックな計算機でもほかのアルゴリズムより高速に処理ができる。CNTという名前は「CouNT」の省略らしい。Raspberry Pi3でのベンチマークではMOG2が41秒に対し、CNTは18秒。

https://sagi-z.github.io/BackgroundSubtractorCNT/

LSBP

Local SVG Binary Pattern。注目画素とその周辺画素の大小関係を符号化するLBP(Local Binary Pattern)は、高速に計算可能な画像特徴量として知られている。局所的なノイズや隣接画素が類似しているような場合にもロバストにするようにSVD(特異値分解)を使った特徴量で背景差分を行っているそう。ちゃんと勉強してないのでよくわらからない。

https://www.cv-foundation.org/openaccess/content_cvpr_2016_workshops/w24/papers/Guo_Background_Subtraction_Using_CVPR_2016_paper.pdf

GSOC

LSBP特徴を使ってる。ノイズ除去とか穴埋めといった後処理をしているらしい。GSOC(Google Summer of Code)2017中で開発されたとかで元論文等はないらしいのでソースコードを読もう。

opencv_contrib/bgfg_gsoc.cpp at 6520dbaa224a661ca8105b1ab0b71451fd715f4c · opencv/opencv_contrib · GitHub

コード

実行にはopencv_contribが必要。

C++

opencv_contribをダウンロードし、opencvcmake時に例えば以下のようにOPENCV_EXTRA_MODULES_PATHオプションを指定してビルドする。

$ cmake -DOPENCV_EXTRA_MODULES_PATH=<opencv_contrib>/modules -DBUILD_opencv_legacy=OFF <opencv_source_directory>

ソースコード

#include <opencv2/opencv.hpp>
#include <opencv2/core/utility.hpp>
#include <opencv2/bgsegm.hpp>

int main()
{
    // 動画ファイルの読み込み
    cv::VideoCapture cap = cv::VideoCapture("video.mp4");
    // 背景差分器の生成
    cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorGSOC();
    //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorCNT();
    //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorGMG();
    //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorLSBP();
    //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::bgsegm::createBackgroundSubtractorMOG();
    //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::createBackgroundSubtractorMOG2();
    //cv::Ptr<cv::BackgroundSubtractor> bgfs = cv::createBackgroundSubtractorKNN();

    while (cv::waitKey(1) == -1)
    {
        cv::Mat frame, foreGroundMask, segm;

        cap >> frame;
        if (frame.empty())
            break;

        bgfs->apply(frame, foreGroundMask);
        frame.convertTo(segm, 0, 0.5);
        cv::add(frame, cv::Scalar(100, 100, 0), segm, foreGroundMask);
    
        cv::imshow("output", segm);
    }
    return 0;
}

Python

pipで管理している場合、以下のようにopencv-pythonをアンインストール後にopencv-contrib-pythonをインストールすればopencv_contribが使える。

pip uninstall opencv-python
pip install opencv-contrib-python

ソースコード

import cv2

cap = cv2.VideoCapture('video.mp4')
bgs = cv2.bgsegm.createBackgroundSubtractorLSBP()

while(cap.isOpened()):
    ret, frame = cap.read()
    mask = bgs.apply(frame)
    bg = bgs.getBackgroundImage()
    cv2.imshow('mask', mask)
    cv2.imshow('bg', bg)
    if cv2.waitKey(1) != -1:
        break

cap.release()
cv2.destroyAllWindows()

適用結果

比較のために各アルゴリズムを並べてみた。パラメータ調整もしてないから比較もくそもない気はするけど。GSOCが綺麗。LSBPはあんまり

www.youtube.com

あと、背景差分やるだけだったらたぶん以下のページで紹介されているBGSLibraryを使ったほうが良さそうではある。

blog.negativemind.com

tensorflowでMASK R-CNNによるSemantic Segmentation

セマンティックセグメンテーション

下の写真みたいに、入力画像を物体ごとに領域分割する技術。

f:id:whoopsidaisies:20180227180905p:plain https://wiki.tum.de/display/lfdv/Image+Semantic+Segmentation

Mask R-CNN

数あるセマンティックセグメンテーションを実現する手法の中で、2018年2月現在有力とされているものの一つ(たぶん)。

www.youtube.com

アルゴリズムの詳細についての説明は他に譲る。以下のページとかを参考にする。

TensorFlowのインストール

Google先生が公開している機械学習オープンソースライブラリ。インストール方法は巷にあふれているので適当にググってインストールする。

Tensorflow Object Detection APIのインストール

以下のGitHubのレポジトリで様々なTensorfFlowのモデルが公開されている。公式サポートではないが物体検出とセマンティックセグメンテーションのモデルも数多く公開されているので、今回はそれを使う。

github.com

インストールは公式の手順通りだが以下に適当にメモ。 models/installation.md at master · tensorflow/models · GitHub

  • 依存パッケージのインストール
apt install protobuf-compiler
pip install pillow lxml jupyter matplotlib
cd [PATH to models]/research
protoc object_detection/protos/*.proto --python_out=.
  • PYTHONPATHの追加
cd [PATH to models]/research
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

モデルファイルのダウンロード

Tensorflow detection model zooから物体検出やセマンティックセグメンテーションのトレーニング済みモデルをダウンロード出来る。とりあえず一番mAPの高いmask_rcnn_inception_resnet_v2_atrous_cocoというモデルを使う。

wget http://download.tensorflow.org/models/object_detection/mask_rcnn_inception_resnet_v2_atrous_coco_2018_01_28.tar.gz
tar -zxvf mask_rcnn_inception_resnet_v2_atrous_coco_2018_01_28.tar.gz

セマンティックセグメンテーションのpythonコード

import tensorflow as tf
import numpy as np
from PIL import Image
from object_detection.utils import ops as utils_ops

import sys
sys.path.append('[modelsのパス]/research/object_detection')
from utils import label_map_util
from utils import visualization_utils as vis_util

# 学習済モデルの読み込み
PATH_TO_CKPT = 'mask_rcnn_inception_resnet_v2_atrous_coco_2018_01_28/frozen_inference_graph.pb'

detection_graph = tf.Graph()
with detection_graph.as_default():
  od_graph_def = tf.GraphDef()
  with tf.gfile.GFile(PATH_TO_CKPT, 'rb') as fid:
    serialized_graph = fid.read()
    od_graph_def.ParseFromString(serialized_graph)
    tf.import_graph_def(od_graph_def, name='')

# ラベルの読み込み
PATH_TO_LABELS = '[modelsへのパス]/research/object_detection/data/mscoco_label_map.pbtxt'
NUM_CLASSES = 90

label_map = label_map_util.load_labelmap(PATH_TO_LABELS)
categories = label_map_util.convert_label_map_to_categories(label_map, max_num_classes=NUM_CLASSES, use_display_name=True)
category_index = label_map_util.create_category_index(categories)

# 画像の読み込みとnumpy配列への変換
def load_image_into_numpy_array(image):
  (im_width, im_height) = image.size
  return np.array(image.getdata()).reshape(
      (im_height, im_width, 3)).astype(np.uint8)

filename = '[画像ファイルのパス]'
image = Image.open(filename)
image_np = load_image_into_numpy_array(image)

# セマンティックセグメンテーションの処理
with detection_graph.as_default():
    with tf.Session() as sess:
        # 入出力用テンソルのハンドルを取得
        image_tensor = tf.get_default_graph().get_tensor_by_name('image_tensor:0')
        tensor_dict = {}
        tensor_dict['num_detections'] = tf.get_default_graph().get_tensor_by_name('num_detections:0')
        tensor_dict['detection_boxes'] = tf.get_default_graph().get_tensor_by_name('detection_boxes:0')
        tensor_dict['detection_scores'] = tf.get_default_graph().get_tensor_by_name('detection_scores:0')
        tensor_dict['detection_classes'] = tf.get_default_graph().get_tensor_by_name('detection_classes:0')
        tensor_dict['detection_masks'] = tf.get_default_graph().get_tensor_by_name('detection_masks:0')
        
        # バッチ内の最初の画像の結果を取り出す
        detection_boxes = tf.squeeze(tensor_dict['detection_boxes'], [0])
        detection_masks = tf.squeeze(tensor_dict['detection_masks'], [0])
        
        # 各検出ボックスのマスクを画像全体上のマスクへ変換
        real_num_detection = tf.cast(tensor_dict['num_detections'][0], tf.int32)
        detection_boxes = tf.slice(detection_boxes, [0, 0], [real_num_detection, -1])
        detection_masks = tf.slice(detection_masks, [0, 0, 0], [real_num_detection, -1, -1])
        detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(
            detection_masks, detection_boxes, image_np.shape[0], image_np.shape[1])
        detection_masks_reframed = tf.cast(
            tf.greater(detection_masks_reframed, 0.5), tf.uint8)
        
        # バッチ分の次元を追加
        tensor_dict['detection_masks'] = tf.expand_dims(
            detection_masks_reframed, 0)
        
        # 実行
        output_dict = sess.run(tensor_dict,
                               feed_dict={image_tensor: np.expand_dims(image_np, 0)})
        
        # バッチ分の次元の削除と型変換
        output_dict['num_detections'] = int(output_dict['num_detections'][0])
        output_dict['detection_classes'] = output_dict[
            'detection_classes'][0].astype(np.uint8)
        output_dict['detection_boxes'] = output_dict['detection_boxes'][0]
        output_dict['detection_scores'] = output_dict['detection_scores'][0]
        output_dict['detection_masks'] = output_dict['detection_masks'][0]

# 画像にマスクとバウンディングボックスを書き込んで出力
vis_util.visualize_boxes_and_labels_on_image_array(
    image_np,
    output_dict['detection_boxes'],
    output_dict['detection_classes'],
    output_dict['detection_scores'],
    category_index,
    instance_masks=output_dict.get('detection_masks'),
    use_normalized_coordinates=True,
    line_thickness=8)
Image.fromarray(image_np).save('out.png')

結果

拾ってきたフリー写真に適用した結果が以下。手だけ写ってても人間って判断してくれるのね。

f:id:whoopsidaisies:20180227183425p:plain

nvidia-dockerインストール、コンテナ等メモ

基本的に公式サイトの説明とかの通りにやるだけなんだけど自分用にメモ。

ホストOS:ubuntu 16.04LTS

dockerのインストール

参考: Get Docker for Ubuntu - Docker

# https通信で公開鍵ダウンロードするため
apt-get update
apt-get install curl ca-certificates

# dockerレポジトリの公開鍵の登録
curl -fsSL https://yum.dockerproject.org/gpg | apt-key add -

# add-apt-repositoryコマンドのインストール
apt-get install software-properties-common

# dockerレポジトリ追加
add-apt-repository "deb https://apt.dockerproject.org/repo/ ubuntu-$(lsb_release -cs) main"

# aptでhttps通信するため
apt-get install apt-transport-https

# dockerのインストール
apt-get update
apt-get install docker-engine

NVIDIAドライバのインストール

これが一番ハマって大変な場合が多い気がするが、ここでは省略。どうにかうまいことインストールする。

NVIDIA Dockerのインストール

# debパッケージのダウンロード(2017/1/22現在で最新のもの)
curl -LO https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.0/nvidia-docker_1.0.0-1_amd64.deb
# インストール
dpkg -i nvidia-docker_1.0.0-1_amd64.deb
rm nvidia-docker_1.0.0-1_amd64.deb
# 動作確認(GPU情報が表示されると良い)
nvidia-docker run --rm nvidia/cuda nvidia-smi

バージョンについては下記ページでチェックして適宜ダウンロードするものを確認する。

Releases · NVIDIA/nvidia-docker · GitHub

NVIDIA Dockerコンテナメモ

便利なものがあれば随時追記予定。

C#で3次元グラフを表示する ILNumerics

ILNumericsは.NETで使用可能な数値計算等のライブラリである.グラフ表示機能も備わっているので,それを使ってC#のWindowsフォーム上に3次元グラフを表示する.

ILNumericsのインストール

現在最新バージョン(4.x系)のILNumericsは14日間のトライアル版以外は有償だが,Community Editionという無償版が提供されていた3.x系のバージョンNuGetでインストール可能なのでそれを使う.

まず,Visual StudioでWindowsフォームアプリケーションを作成する.

そして,プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「ILNumerics」を検索・インストールする.

グラフ表示用コントロールの配置

フォームデザイナを開きツールボックスの適当なところで右クリックして「アイテムの選択(I)...」を選択する.

「.NET Framework コンポーネント」タブの「参照(B)...」ボタンを押して,「(ソリューションのパス)\packages\ILNumerics.3.3.3.0\lib\ILNumerics.dll」を選択したらOK.

するとツールボックスIL○○というコントロールが追加される.その中の,ILPanelコントロールをフォーム上に配置する.

f:id:whoopsidaisies:20141202163400p:plain

使ってみる

曲面

例として,以下の2変数関数を表示させてみる.
z=\frac{\sin(\sqrt{x^2+y^2})}{\sqrt{x^2+y^2}}

まず,コードの適当な場所に以下のusingを書いておく.

using ILNumerics.Drawing;
using ILNumerics.Drawing.Plotting;

そして,フォームロードイベントとかの適当なイベントに以下のコードを書く.

// グラフを格納するオブジェクトの生成
var scene = new ILScene
{
    // 3次元モードでプロット領域を生成
    new ILPlotCube(twoDMode: false)
    {
        // 曲面の生成
        new ILSurface(
            (x,y) => (float)(
                Math.Sin(Math.Sqrt(x*x + y*y))/Math.Sqrt(x*x + y*y)))
    }
};
// 描画用コントロールに生成したグラフをセット
ilPanel1.Scene = scene;

実行すると以下のように3次元グラフが表示される.マウスドラッグとかホイールとかで視点や拡大率を変えられる.

f:id:whoopsidaisies:20141202172655p:plain

等高線

サンプル用の地形データも用意されていて,以下のように使うことが出来る.

var scene = new ILScene
{
    new ILPlotCube(twoDMode: false){
        new ILSurface(ILNumerics.ILMath.tosingle(ILNumerics.ILSpecialData.terrain))
    }
};
ilPanel1.Scene = scene;

f:id:whoopsidaisies:20141202180125p:plain

ここまでは曲面表示のためILSurfaceクラスを使ってきたが,ILContourPlotクラスを使えば以下のように等高線表示も出来る.

var scene = new ILScene
{
    new ILPlotCube{
        new ILContourPlot(ILNumerics.ILMath.tosingle(ILNumerics.ILSpecialData.terrain))
    }
};
ilPanel1.Scene = scene;

f:id:whoopsidaisies:20141202180132p:plain

散布図

ILPointsクラスで散布図を表示させることも出来る.以下はランダムに点を打って対数軸にして表示した例.

ILNumerics.ILArray<float> p = ILNumerics.ILMath.tosingle(ILNumerics.ILMath.rand(3, 10000));
var scene = new ILScene{
    new ILPlotCube(twoDMode:false){
        new ILPoints
        {
            Positions = p,
            Color = null,
            Colors =  p,
            Size = 1,
        }
    }
};
var scaleModes = scene.First<ILPlotCube>().ScaleModes;
scaleModes.XAxisScale = AxisScale.Logarithmic;
scaleModes.YAxisScale = AxisScale.Logarithmic;
scaleModes.ZAxisScale = AxisScale.Logarithmic;

ilPanel1.Scene = scene;

f:id:whoopsidaisies:20141202182150p:plain

Python+OpenCVで特徴量記述・アルゴリズムまとめ

Python+OpenCVで画像の特徴点の特徴量を記述する.OpenCV2.4.9およびOpenCV3.0 alphaについて使用できるアルゴリズムをまとめる.

Python+OpenCVで特徴点抽出・使えるアルゴリズムまとめ OpenCV2.4.9と3.0 alpha - whoopsidaisies's diary
の続き.

環境

WindowsでOpenCV公式サイトのダウンロードページから2.4.9および3.0 alphaのビルド済みバイナリをダウンロードしてきて解凍したものを使う.

特徴量記述器の使い方

特徴点抽出のときのFeatureDetectorと同じように,特徴量記述についてもDescriptorExtractorという共通インターフェースが用意されている.

使い方は以下の通り.

# 引数でどの特徴量記述子を使うか指定 
extractor = cv2.DescriptorExtractor_create(extractor_name)
# 引数として画像と特徴点を渡す
# 戻り値は特徴点と特徴量
keypoints, descriptors = extractor.compute(img, keypoints)

DescriptorExtractor_createメソッドで指定出来る特徴量記述子を以下にまとめた.

OpenCVバージョン 実数ベクトル バイナリコード
2.4.9 SIFT, SURF BRIEF, BRISK, ORB, FREAK
3.0 alpha KAZE AKAZE, BRISK, ORB

(2.4.9でORBがなぜかランタイムエラーが出るので追々調査予定)

特徴量の中身

descriptorsの中身は2次元のarrayになっており,特徴点ごとに特徴量のベクトルが格納されている.

KAZEで記述した特徴量を表示してみるとこんな感じ(0番目の点).

>>descriptors[0]
array([ -7.38840317e-04,  -6.34267868e-04,   2.61819176e-03,
         3.50267510e-03,  -1.59906253e-04,  -4.56994586e-03,
         4.39605350e-03,   9.44076758e-03,  -1.75689301e-03,
         8.05667194e-04,   3.55383591e-03,   4.12554527e-03,
        -1.54193444e-03,   1.58668880e-03,   2.78847502e-03,
         3.14337271e-03,  -1.62520558e-02,   1.65848620e-02,
         3.65739577e-02,   2.07063138e-01,   2.64649391e-02,
        -6.13974873e-03,   9.64385048e-02,   2.91850477e-01,
         5.54781593e-02,   6.74537197e-03,   6.74520805e-02,
         8.45865980e-02,  -2.12559430e-03,   1.18403265e-03,
         5.09992335e-03,   4.04977519e-03,  -1.28035052e-02,
         6.93068025e-04,   3.93203236e-02,   4.54802722e-01,
        -2.96720478e-04,   6.83288351e-02,   8.15773308e-02,
         6.17026806e-01,  -1.08468741e-01,   5.95125668e-02,
         1.92962006e-01,   2.17324436e-01,  -1.21422755e-02,
         2.50244630e-03,   1.34693161e-02,   6.25377288e-03,
         2.55310140e-03,  -4.21544649e-02,   2.98030730e-02,
         1.50349155e-01,   4.27789390e-02,  -9.73087847e-02,
         1.63991615e-01,   1.90487400e-01,   3.39032081e-03,
        -2.32313443e-02,   1.98113456e-01,   6.58137947e-02,
        -1.16498368e-02,   2.66303378e-03,   1.25482017e-02,
         4.14769724e-03], dtype=float32)

グラフ表示だとこんな感じ.

import matplotlib.pyplot as plt
plt.plot(descriptors[0])

f:id:whoopsidaisies:20141201234637p:plain

KAZEは64次元の実数ベクトルで特徴量記述をするので以上のようになるが,記述子によってデータ量が違うため配列の長さや型が変わってくる.

Python+OpenCVで特徴点抽出・使えるアルゴリズムまとめ OpenCV2.4.9と3.0 alpha

軽量プログラミング言語が苦手なので敬遠していたが,世間ではPythonからOpenCVを呼ぶのが流行っているようなので,練習がてらOpenCVで使える特徴点抽出アルゴリズムをまとめてみる.

OpenCV2.4.9とOpenCV3.0 alphaについてまとめる.3.0 betaはなぜか動かなかったのでいつか暇があれば調査.

環境

WindowsでOpenCV公式サイトのダウンロードページから2.4.9および3.0 alphaのビルド済みバイナリをダウンロードしてきて解凍したものを使う.

PythonからのOpenCVの呼び出し方はこことかを参照.

特徴点抽出の使い方

OpenCVで実装されている特徴点抽出のアルゴリズムはいくつかあるが,FeatureDetectorという共通インターフェースを使うことでどのアルゴリズムでも同様の記述で使える.使い方は以下.

# 画像読み込み
img = cv2.imread('gazou.bmp')
# FeatureDetectorのインスタンスを生成
detector = cv2.FeatureDetector_create(detector_type)
# 特徴点を抽出
keypoints = detctor.detect(img)

FeatureDetector_createメソッドの引数にアルゴリズム名を文字列で渡すことで,どのアルゴリズムで特徴点抽出するかを選択することが出来る.例えば,ORBアルゴリズムで特徴点を抽出して表示するのは以下のようになる.

import cv2

img = cv2.imread('gazou.bmp')
# アルゴリズム名を引数で渡す
detector = cv2.FeatureDetector_create('ORB')
keypoints = detctor.detect(img)
# 画像への特徴点の書き込み
out = cv2.drawKeypoints(img, keypoints, None)
# 表示
cv2.imshow(name, out)
cv2.waitKey(0)

結果は以下のようになる.
f:id:whoopsidaisies:20141201024751p:plain

ちなみに特徴点の書き込み部分を以下のようにすると,特徴点のサイズと方向を表す円が描画される.

out = cv2.drawKeypoints(img, keypoints, None, None, cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

f:id:whoopsidaisies:20141201024104p:plain

FeatureDetectorインターフェースで使えるアルゴリズム

FeatureDetectorインターフェースで指定できる特徴点抽出アルゴリズムはOpenCVのバージョンで変わるようなので,OpenCV2.4.9で使えるものとOpenCV3.0 alphaで使えるものを以下にまとめる.

バージョン アルゴリズム名
2.4.9 BRISK, Dense, FAST, FASTX, GFTT, HARRIS, MSER, ORB, SIFT, STAR, SURF, SURF_OCL, SimpleBlob
3.0 alpha AKAZE, BRISK, FAST, GFTT, HARRIS, KAZE, MSER, ORB, SimpleBlob


C++版については以下の記事にまとめてある.
OpenCV3.0.0-alphaの特徴抽出・マッチングまとめ - whoopsidaisies's diary
OpenCVで画像の特徴抽出・マッチングを行う - whoopsidaisies's diary

C#で画像をWavelet変換 Accord.NET

C#で画像のWavelet変換を行う.コンピュータビジョン等の.NET向けのオープンソースのライブラリであるAccord.NET Frameworkを使う.

Accord.NETのインストール

NuGet経由でインストール可能.プロジェクトを右クリックして「NuGetパッケージの管理」を選択する.オンラインから「Accord.Imaging」を検索・インストール.

WaveletTransformクラス

Accord.NETのWaveletTransformクラスによってWavelet変換を行える.入力画像はグレースケールで,解像度が2のべき乗でないといけない.

ソースコード

WaveletTransformクラスの初期化時にWavelet母関数を指定する.その引数でWavelet変換のレベルを指定できる.ここではHaar関数でレベル2とした.

// 入力画像
var img = new Bitmap(@"Penguins.jpg");
// 画像の解像度が2のべき乗になるように調整
var bitWidth = Convert.ToString(img.Width - 1, 2).Length;
var bitHeight = Convert.ToString(img.Height - 1, 2).Length;
var width = (int)Math.Pow(2, bitWidth);
var height = (int)Math.Pow(2, bitHeight);
// 隙間の部分はゼロ埋め
var imgPadded = new Bitmap(width, height, img.PixelFormat);
var graphics = Graphics.FromImage(imgPadded);
graphics.DrawImage(img, 0, 0);
graphics.Dispose();
// グレースケール化
var gray = new AForge.Imaging.Filters.Grayscale(0.2125, 0.7154, 0.0721).Apply(imgPadded);
// Wavelet変換クラスの作成
//  Harrクラスの初期化時にレベルを指定出来る
var wavelet = new Accord.Imaging.Filters.WaveletTransform(new Accord.Math.Wavelets.Haar(2));
// Wavelet変換
var imgWavelet = wavelet.Apply(gray);
pictureBox1.Image = imgWavelet;

結果

f:id:whoopsidaisies:20141130095415p:plain

逆変換

WaveletTransformクラスのBackwordプロパティをtrueにしてApplyメソッドを実行すると逆変換が出来る.

wavelet.Backward = true;
var gyaku = wavelet.Apply(imgWavelet);