出発しまーす

そろそろ1年経ったので、突然ですが、新天地へ向け、出発します。というわけで、「電子化」は、終了です。


みなさん、これまでいろいろとありがとうございました。またいつか、どこかで、別な「マニアック(ニッチ)な」ものを書きはじめるかもしれませんので、発見したら、お付き合いしてください。トピックは違っても、書きっぷりは一緒にします。


最後に、今の心境です。

西行はなぜ出家したか、幸いその原因については、大いに研究の余地があるらしく、西行研究者たちは多忙なのであるが、ぼくには、興味のないことだ。およそ詩人を解するには、その努めて現わそうとしたところを極めるがよろしく、努めて忘れようとし隠そうとしたところを詮索したとて、何が得られるものではない。保延六年に、原因不明の出家をし、行方不明の歌をひねった幾十幾百の人々の数のなかに、西行も埋めておこう。彼が忘れようとしたところを彼とともに素直に忘れよう。ぼくらは嫌でも、月並みな原因から非凡な結果を生み得た詩人の生得の力に想いを致すであろう。


栗の樹 (講談社文芸文庫―現代日本のエッセイ)

(JP2レイヤー対応)シンプルなSSIM計算ツールを進化させてみました

本日のお題:レイヤー付きのJP2に関して、シンプルにSSIMを計算してみよう


前回(http://d.hatena.ne.jp/denshikA/20100721)、シンプルなSSIM計算ツールを公開したわけですが、一部の方から要望がありまして、JP2のレイヤーに対応してみました。


起動させると、こんなの出てきて、

左の四角に、基準となる画像を放り込んで、右の四角に評価したい画像を放り込むだけで、あらま、不思議、JP2が放り込まれたらレイヤー分解して、各レイヤーのSSIMが計算されます、というもの。もちろん、JP2以外が放り込まれれば、特にレイヤー分解せず、計算していきますよ。


さて、前回同様、簡単操作なツールですので、ぜひ、お試しください。そして、もし、今回のサンプル画像について、同じJP2画像を左右に放り込むとどうなると思いますか?JP2やSSIMの理解度の復習だと思って、実験してみてください。もし、実験前に、結果が予想ついた方は、かなり理解されてますね。


こちらからダウンロードできます。(先着40名*1
http://tinyurl.com/2f6xkqd
(お使いのPCによっては、Microsoft .NET Framework 3.5 Service Pack 1というものが必要かもしれませんが、未だ、詳しいことは分かりません。)

*1:いつものごとく、単にそう言ってみたいだけです

(JP2対応)シンプルなSSIM計算ツールを作ってみました

本日のお題:シンプルにSSIMを計算してみよう


過去3回*1、SSIMの計算ツール(ssim.exe)と、それを使ったバッチ処理の方法を、具体的に提示しておいたわけですが、もっと、お手軽なツールを作ってみました。


起動させると、こんなの出てきて、

四角の部分に、画像を2つ、放り込むだけで、あらま、不思議、SSIMが計算されます、というもの。


お手軽なので、以下の点でも、実験してみてください。今年の電子化検定に出ますよ

  1. まるっきし同じ画像は、本当にSSIMが1.0000になるのか?
  2. 画像の順番を入れ替えると、SSIMの値は変わるのか?
  3. どんな場合に、マイナスのSSIMが出てくるのか?
  4. 果たして、-1.000というのは可能か?

こちらからダウンロードできます。(先着40名*2
http://tinyurl.com/249gwzy
(お使いのPCによっては、Microsoft .NET Framework 3.5 Service Pack 1というものが必要かもしれませんが、詳しいことは分かりません。)


対応している画像フォーマットは、

BMP, DIB, JPEG, JPG, JPE, PNG, PBM, PGM, PPM, SR, RAS, TIFF, TIF, EXR, jp2

です。カラーでも、グレースケールでも、2値でも、なーんでも行っちゃいます。


(個人的なスキルの関係上)OpenCVとVisual C++ Express EditionとVisual Basic 2008 Express Editionを組み合わせてます。

SSIM実習 JPEG2000実習 特定レイヤーのSSIM測定バッチ編

本日は、上級者向けの応用編です。こちらの3つの内容は押えておいてくださいね。


JPEG2000実習 レイヤー編 http://d.hatena.ne.jp/denshikA/20100604
JPEG2000実習 各レイヤーのPSNR確認編 http://d.hatena.ne.jp/denshikA/20100614
SSIM実習 (フォルダ内一括計算) http://d.hatena.ne.jp/denshikA/20100705


すでに、SSIMの計算ツール(C++版)を、ソース付きで公開し、前回は、フォルダ単位で、一気にドビャーっと計算するSSIMの計算バッチを作ってみました。


あとは、ズバリ、JP2ファイルの特定レイヤーのSSIM測定にトライしてみるしかありませんね*1


前回のSSIM計算拠点を使いましょう。

という感じですね。(意味が分からなければ、http://d.hatena.ne.jp/denshikA/20100705を見てください。)


とりあえず、「TIFF87フォルダ、SSIMtool.exe、result.txt」の3つはいりませんので、削除しちゃってください。


次に、3レイヤーで作成したJPEG2000のファイルを用意しておきましたので、こちら(JP2.zip 直)からダウンロードして、展開して、拠点(SSIMフォルダ)においてください。中には、特製JP2ファイルが13個入っています。


そして、今回は、「JP2ファイルの特定レイヤーのSSIM測定」ということですので、2ステップの作業となります。

  1. まず、JP2ファイルをレイヤーごとの画像に分解します
  2. 各レイヤー画像のSSIMを測定します


そんな2つのことをやってくれるバッチプログラムは、こんな感じですかね?

@echo off
echo --------------------------------------------------------
echo JP2をレイヤー分解してから、SSIM検査しますよー Ver2.0
echo --------------------------------------------------------

PAUSE


REM  --------------------------------------------------------

REM 元の画像が入ったフォルダさん (TIFF画像)
set ORIGINAL=TIFF

REM 分解前のJP2が入ったフォルダさん (JP2画像)
set JPEG2000=JP2

REM 比較する画像が入ったフォルダさん (TIFF画像)
set DISTORTED1=LAYER1
set DISTORTED2=LAYER2
set DISTORTED3=LAYER3

REM MAP画像を入れるフォルダさん (PNG画像)
set SSIMMAP=MAP

REM  --------------------------------------------------------



echo ----- こんにちは、これからフォルダ作るよ -----

mkdir %DISTORTED1%,%DISTORTED2%,%DISTORTED3%

echo ----- ほらね、フォルダ作ったよ -----

PAUSE


echo ----- 次は、JP2のレイヤー分解開始だよ -----

FOR %%B IN (%JPEG2000%/*.jp2) DO (
	for /f "tokens=1 delims=." %%i in ("%%B") do (
		echo %%Bのレイヤー1を分解中
		C:\j2k_to_image.exe -i %JPEG2000%/%%B -o %DISTORTED1%/%%i.tif -l 1
		echo %%Bのレイヤー2を分解中
		C:\j2k_to_image.exe -i %JPEG2000%/%%B -o %DISTORTED2%/%%i.tif -l 2
		echo %%Bのレイヤー3を分解中
		C:\j2k_to_image.exe -i %JPEG2000%/%%B -o %DISTORTED3%/%%i.tif -l 3
	)
)

echo ----- どうにか、JP2レイヤー分解できたよ -----

PAUSE

echo ----- 最後に、SSIM検査開始だよ、もう一息! -----

FOR %%B IN (%ORIGINAL%/*.tif) DO (
	for /f "tokens=1 delims=." %%i in ("%%B") do (
		echo %%i: >> result1.txt
		SSIM.exe %ORIGINAL%/%%B %DISTORTED1%/%%i.tif %SSIMMAP%/%%i-1.png >> result1.txt
		echo %%i: >> result2.txt
		SSIM.exe %ORIGINAL%/%%B %DISTORTED2%/%%i.tif %SSIMMAP%/%%i-2.png >> result2.txt
		echo %%i: >> result3.txt
		SSIM.exe %ORIGINAL%/%%B %DISTORTED3%/%%i.tif %SSIMMAP%/%%i-3.png >> result3.txt
		echo %%i: done...
	)
)

echo ----- SSIM検査完了だよ ばいばーい!-----

PAUSE


このプログラムをテキストファイルにコピペして、「SSIMtool2.bat」などと名づけて、先ほどのSSIMフォルダに入れてください。


さて、この「SSIMtool2.bat」を実行させるとどうなるのか?ぜひ、試してみてください。


追伸:noidonさん、tomomi_assistさん、その後、どんな調子ですか?

On 04/03/2010, at 5:58 PM, tomomi_assist wrote:


I would like to create jp2 files by specifying an uniform SSIM value to image files.


If you know the solution to deal with, please teach me the method.


http://tech.groups.yahoo.com/group/kakadu_jpeg2000/message/6052

*1:かなりマニアな領域になりますが

SSIM実習 (フォルダ内一括計算)

本日のお題:フォルダ内の画像を一括計算する

すでに、SSIMの計算ツール(C++版)を、ソース付きで公開しておきましたので、本日は、その応用です。1個1個ちまちまとSSIM計算をしないで、フォルダ単位で、一気にドビャーっと計算してみましょう。


まず準備です。どこでも良いので、SSIM計算の拠点を作りましょう。以下は、Cドライブ直下にSSIMフォルダを作成し、そこを拠点とする例です。


次にサンプルのオリジナル画像を用意してください。これまでに何度が登場していただいてます「ミスターSSIM」こと、Wangさんの論文をサンプル画像としましょう。


Image Quality Assessment: From Error Visibility to Structural Similarity
http://www.cns.nyu.edu/pub/eero/wang03-reprint.pdf


ここ(TIFF.zip 直)にTIFF画像を用意しましたので、ダウンロードして、展開して、先ほどのSSIMフォルダ内に入れてみてください。


次にSSIMの測定をしたい画像を用意するのですが、今回は、SSIMがだいたい0.87になるような画像を作っておきました。こちら(TIFF87.zip 直)からダウンロードして、展開して、先ほどのSSIMフォルダ内に入れてみてください。(本当に0.87なのか、確かめてみましょう。)


次に、空のフォルダを作成し、MAPと名づけておきましょう。前回も「心霊写真」としてご紹介した画像を入れていくためのものです。


さて、あとは、このTIFFフォルダ内のTIFF画像と、TIFF87内のTIFF画像を、順番にSSIM計算にかけ、SSIMマップをMAPフォルダへ作成しつつ、計算結果を表示する、というプログラムを組めばよいですね。とりあえず、こんなんでどうでしょうか?(%ばっかしでみにくいですね)

@echo off
echo --------------------------------------------------------
echo SSIM検査しますよー Ver2.0
echo --------------------------------------------------------

PAUSE


REM  --------------------------------------------------------

REM 元の画像が入ったフォルダさん (TIFF画像)
set ORIGINAL=TIFF

REM 比較する画像が入ったフォルダさん (TIFF画像)
set DISTORTED=TIFF87

REM MAP画像を入れるフォルダさん (PNG画像)
set SSIMMAP=MAP

REM  --------------------------------------------------------


echo ----- SSIM検査開始だよ -----

FOR %%B IN (%ORIGINAL%/*.tif) DO (
	for /f "tokens=1 delims=." %%i in ("%%B") do (
		echo %%i: >> result.txt
		SSIM.exe %ORIGINAL%/%%B %DISTORTED%/%%i.tif %SSIMMAP%/%%i.png >> result.txt
		echo %%i: done...
	)
)

echo ----- SSIM検査完了だよ -----

PAUSE

このプログラムをテキストファイルにコピペして、「SSIMtool.bat」などと名づけて、先ほどのSSIMフォルダに入れてください。


これで準備完了のような気がします。


「SSIMtool.bat」をダブルクリックすると、

という感じでストップするので、電源ボタン以外なら何でも良いので押してください。

という感じで、計算がされていき、しばらくすると、

こんな感じで、作業終了を告げ、再びストップしますので、何か押して、ウィンドウを閉じちゃってください。


先ほどのSSIM計算の拠点(SSIMフォルダ)の中に、result.txtというファイルができました。

その中身を見ると、

0001:
SSIMは0.869934でした。
0002:
SSIMは0.869602でした。
0003:
SSIMは0.869551でした。
0004:
SSIMは0.869784でした。
0005:
SSIMは0.870353でした。
0006:
SSIMは0.870439でした。
0007:
SSIMは0.869701でした。
0008:
SSIMは0.869958でした。
0009:
SSIMは0.870334でした。
0010:
SSIMは0.869611でした。
0011:
SSIMは0.870429でした。
0012:
SSIMは0.86957でした。
0013:
SSIMは0.870167でした。

という結果だったらしいので、0.87±0.0005くらいの精度だ、ということが確認できましたね。


ちなみに、MAPフォルダ内をみると、

こんな感じの画像が入っていて、これは、TIFFフォルダの画像とTIFF87フォルダの画像を比較して、SSIM的に重要な違いがある部分を黒くした、という「SSIMマップ*1」です。(今回のMAPはMAP.zip 直を見てください。)


というわけで、とりあえず、フォルダを指定してやれば、その中の画像をひたすら計算していくプログラムができたわけです。*2


次回は、ズバリ、JP2ファイルの特定レイヤーのSSIM測定にトライしてみるかもしれません。

*1:詳しくは、http://d.hatena.ne.jp/denshikA/20100701を参照。

*2:ただし、この方法だと、大きなサイズのファイルや、すごーく大量のファイルを処理する場合、ヘンテコなことになる可能性がありますので、あしからず。

「ウォーリーをさがせ」で理解するSSIMのスゴい点 その2


本日のお題画像:


心霊写真みたいな画像からスタートしてますが、前回(http://d.hatena.ne.jp/denshikA/20100629)からの続きで、ちょっと、違った角度からSSIMを眺めて、SSIMのことをもっと好きになりましょうね、という流れでしたね。


前回の終わりに、

SSIMというのは、「人ごみの中のウォーリーはあまり重視せず、ポツンと孤立したウォーリーに注目して」計算していきますので、「私たちの感覚により近いと評判*7」なのです。


というわけでまとめますと、意外と知られていないと思うのですが、SSIMがスゴいのは、画像内の間違いを計算するときに、ごちゃごちゃ度合いを考慮して、緩急をつけながら計算しているところなんです。

と書きましたので、確認してみましょう*1


こちらは、http://d.hatena.ne.jp/denshikA/20091204にも登場した「私がかつて住んでいて、いやー、夏はとってもきれいだったな、また住んでみたいな、夏だけ。なんでかっていうと、冬はびっくりするくらい寒いらしいので。そういえば、F1を見に行ったな。そのとき、アレジが優勝して、興奮した観客がフェンスをぶち壊して、コースに乱入する、って事件もあったな。という思い出のモントリオール写真」です。


さて、この写真にノイズを乗せてみます。要するに、ちょびっと画質を落とすわけです。


SSIMを測定する前に、みなさんの「感覚」を確認したいのですが、

空や雲のあたりのノイズは目立ちますが、左下あたりの草や木のあたりのノイズはあまり目立ちません。それと、道の部分も少し目立ちます。

よね?おそらく、それが人間の目で見た場合の感覚じゃないかと思います。


では、早速SSIMを測定するのですが、昨日(http://d.hatena.ne.jp/denshikA/20100630)ご紹介したツールを用意してください。*2


今、Cドライブの中に、SSIMというフォルダがあって、その中身は、こんな感じですね。


次に、オリジナルの画像と、ノイズが乗った画像を用意しましたので、こちらをダウンロードして、SSIMフォルダに入れて見てください。

オリジナル: original.tif 直
ノイズあり: noise.tif 直



そうしたら、コマンドプロンプトで、次のようにやってみましょう。ルールとして、「C:\SSIM\SSIM.exe 画像A 画像B MAPの出力」です。

C:\SSIM\SSIM.exe C:\SSIM\original.tif C:\SSIM\noise.tif C:\SSIM\map.tif



画面を見ると、SSIMの値は、0.462351だそうです。派手にノイズを乗せたので、まぁ、そんなところでしょう。


しかし、今回は、SSIMの値そのものはどうでも良いんです。注目したいのは、先ほどのSSIMフォルダにできた新しいファイルです。

先ほどのSSIM計算をすると、上図のように、map.tifという画像ができます。


そのmap.tifが、冒頭でご紹介した「心霊写真」なのです。


この「心霊写真」について説明をすると、

2つの画像を比較した場合、SSIM的に重要だと思われる「違い」を黒く、あまり重要でないと思われる「違い」を白く、表現したものです。最終的には、この「心霊写真」の平均値を取って、SSIMの値としているわけです。

という感じで、この「心霊写真」こそ、SSIMを計算する上で、一番重要なものなんです。


そして、よーく見ていただくと分かると思いますが、測定前に確認していただいた、みなさんの感覚、

空や雲のあたりのノイズは目立ちますが、左下あたりの草や木のあたりのノイズはあまり目立ちません。それと、道の部分も少し目立ちます。

と、「心霊写真」は、かなり一致しませんか?


というわけで、

画像内の間違いを計算するときに、ごちゃごちゃ度合いを考慮して、緩急をつけながら計算しているところが、SSIMがスゴいところなんです

ということが、少し理解していただけたでしょうか?

*1:ウソかもしれませんので。

*2:昨日書くのを忘れていて、Twitterhttp://twitter.com/denshika/status/17406033384)ではお知らせしたのですが、http://denshika.cc/open/20100630/のSSIM測定ツールは、ssim.mに準拠していますので、理論上計算は正しいはずです。だけど、狙い通りにプログラムが動くのかどうかは、別問題です。ソースを公開したので、あとは、誰かが修正してくれるでしょう。きっと

SSIMを計算するプログラムのソース

ウォーリーの途中ですが、次へ進む前に、ひとつだけツールが必要だということに気がつきました。なので、ソースも含めて、公開します。


興味のある方は、こちらをご覧ください。
http://denshika.cc/open/20100630/


(免責)
使って何か起きても、責任とれませんので、あしからず。


(使い方)

  1. SSIM.zipをダウンロードして、解凍して、Cドライブの直下などにフォルダごと入れます。
  2. Cドライブ直下に入れたとして、A.tifとB.tifのSSIMを計算したい場合、こんな感じです。



  3. 3番目のMAP.tifについては、次回、ウォーリーの続きで説明します。
  4. 今回のプログラムでは、TIFFJPEGなど一般的なフォーマットが対象です。
/* 
 *
 * http://mehdi.rabah.free.fr/SSIM/
 * を参考に、作りましたよー
 * でも、プログラムはアマチュアレベルなので、
 * 細かい部分は、直してくださーい。
 * http://denshikA.cc
 * 
 * 動かすためには、OpenCVが必要
 * http://opencv.jp/
 * 
 */

/* オリジナルメッセージ
 *
 * The equivalent of Zhou Wang's SSIM matlab code using OpenCV.
 * from http://www.cns.nyu.edu/~zwang/files/research/ssim/index.html
 * The measure is described in :
 * "Image quality assessment: From error measurement to structural similarity"
 * C++ code by Rabah Mehdi. http://mehdi.rabah.free.fr/SSIM
 *
 * This implementation is under the public domain.
 * @see http://creativecommons.org/licenses/publicdomain/
 * The original work may be under copyrights. 
 *
 */

#include <iostream>
//std::maxとstd::minを使えるようにするため、こうすると良いと書いてあった
//http://d.hatena.ne.jp/pyopyopyo/20100329/p1
#define NOMINMAX 
//
#include "opencv\cv.h"	
#include "opencv\highgui.h"

/* 
 * SSIM_Cal [a.tif] [b.tif] [map.tif]
 * TIFFを2つ読み込んで、SSIM_MAPを保存して、計算結果を返す
 * 読み込んだ画像がカラーの場合、グレースケール変換
 * 変換のウェイト:Y <- 0.299*R + 0.587*G + 0.114*B
 */
double SSIM_Cal(char* argv1, char* argv2, char* argv3)
{
	// デフォルトさんですね
	const double K1 = 0.01;
	const double K2 = 0.03;
	const int L = 255;
	const double C1 = (K1 * L) * (K1 * L); //6.5025 C1 = (K(1)*L)^2;
	const double C2 = (K2 * L) * (K2 * L); //58.5225 C2 = (K(2)*L)^2;

	// 画像の宣言
	IplImage
		*img1=NULL, *img2=NULL, *img1_img2=NULL,
		*img1_temp=NULL, *img2_temp=NULL,
		*img1_L=NULL, *img2_L=NULL,
		*img1_sq=NULL, *img2_sq=NULL,
		*mu1=NULL, *mu2=NULL,
		*mu1_sq=NULL, *mu2_sq=NULL, *mu1_mu2=NULL,
		*sigma1_sq=NULL, *sigma2_sq=NULL, *sigma12=NULL,
		*ssim_map=NULL, *ssim_map_for_display=NULL, 
		*temp1=NULL, *temp2=NULL, *temp3=NULL;
	

	// 引数にある二つの画像を読み込み
	img1_temp = cvLoadImage(argv1,CV_LOAD_IMAGE_GRAYSCALE);
	img2_temp = cvLoadImage(argv2,CV_LOAD_IMAGE_GRAYSCALE);
	if(img1_temp==NULL || img2_temp==NULL)
		return -1;
	// 縦横のサイズ取得
	int x=img1_temp->width, y=img1_temp->height;

	// ディスタンス(ダウンサンプリング)の設定、短い方の辺を256にする
	int rate_downsampling = std::max(1, int((std::min(x,y) / 256) + 0.5));

	// チャンネルは1で固定、DEPTHは途中計算のため32F
	int nChan=1, d=IPL_DEPTH_32F;

	// ダウンサンプリング前のサイズ
	CvSize size_L = cvSize(x, y);
	// ダウンサンプリング後のサイズ
	CvSize size = cvSize(x / rate_downsampling, y / rate_downsampling);

	// 画像の格納先確保
	img1_L = cvCreateImage( size_L, d, nChan);
	img2_L = cvCreateImage( size_L, d, nChan);
	img1 = cvCreateImage( size, d, nChan);
	img2 = cvCreateImage( size, d, nChan);

	// 8bit整数で読み込み→32bit浮動小数点数にスケール変換
	cvConvert(img1_temp, img1_L);
	cvConvert(img2_temp, img2_L);
	// tempの解放
	cvReleaseImage(&img1_temp);
	cvReleaseImage(&img2_temp);

	// ダウンサンプリング
	cvResize(img1_L, img1);
	cvResize(img2_L, img2);
	// Lの解放
	cvReleaseImage(&img1_L);
	cvReleaseImage(&img2_L);

	// 2乗の格納先確保	
	img1_sq = cvCreateImage( size, d, nChan);
	img2_sq = cvCreateImage( size, d, nChan);
	img1_img2 = cvCreateImage( size, d, nChan);
	
	// 2乗の計算
	cvPow( img1, img1_sq, 2 );
	cvPow( img2, img2_sq, 2 );
	cvMul( img1, img2, img1_img2, 1 );

	// μの格納先確保
	mu1 = cvCreateImage( size, d, nChan);
	mu2 = cvCreateImage( size, d, nChan);
	mu1_sq = cvCreateImage( size, d, nChan);
	mu2_sq = cvCreateImage( size, d, nChan);
	mu1_mu2 = cvCreateImage( size, d, nChan);

	// σの格納先確保
	sigma1_sq = cvCreateImage( size, d, nChan);
	sigma2_sq = cvCreateImage( size, d, nChan);
	sigma12 = cvCreateImage( size, d, nChan);

	// tempの格納先確保
	temp1 = cvCreateImage( size, d, nChan);
	temp2 = cvCreateImage( size, d, nChan);
	temp3 = cvCreateImage( size, d, nChan);

	//ssimマップの格納先確保
	ssim_map = cvCreateImage( size, d, nChan);


	//////////////////////////////////////////////////////////////////////////
	// 予備的な計算ですね

	// μの計算時に、ガウシアンフィルターを適用
	cvSmooth( img1, mu1, CV_GAUSSIAN, 11, 11, 1.5 );
	cvSmooth( img2, mu2, CV_GAUSSIAN, 11, 11, 1.5 );
	
	// μを2乗
	cvPow( mu1, mu1_sq, 2 );
	cvPow( mu2, mu2_sq, 2 );
	cvMul( mu1, mu2, mu1_mu2, 1 );

	// σの計算時に、ガウシアンフィルターを適用
	cvSmooth( img1_sq, sigma1_sq, CV_GAUSSIAN, 11, 11, 1.5 );
	cvAddWeighted( sigma1_sq, 1, mu1_sq, -1, 0, sigma1_sq );
	
	cvSmooth( img2_sq, sigma2_sq, CV_GAUSSIAN, 11, 11, 1.5 );
	cvAddWeighted( sigma2_sq, 1, mu2_sq, -1, 0, sigma2_sq );

	cvSmooth( img1_img2, sigma12, CV_GAUSSIAN, 11, 11, 1.5 );
	cvAddWeighted( sigma12, 1, mu1_mu2, -1, 0, sigma12 );
	

	//////////////////////////////////////////////////////////////////////////
	// 計算しましょう

	// (2*mu1_mu2 + C1)
	cvScale( mu1_mu2, temp1, 2 );
	cvAddS( temp1, cvScalarAll(C1), temp1 );

	// (2*sigma12 + C2)
	cvScale( sigma12, temp2, 2 );
	cvAddS( temp2, cvScalarAll(C2), temp2 );

	// ((2*mu1_mu2 + C1).*(2*sigma12 + C2))
	cvMul( temp1, temp2, temp3, 1 );

	// (mu1_sq + mu2_sq + C1)
	cvAdd( mu1_sq, mu2_sq, temp1 );
	cvAddS( temp1, cvScalarAll(C1), temp1 );

	// (sigma1_sq + sigma2_sq + C2)
	cvAdd( sigma1_sq, sigma2_sq, temp2 );
	cvAddS( temp2, cvScalarAll(C2), temp2 );

	// ((mu1_sq + mu2_sq + C1).*(sigma1_sq + sigma2_sq + C2))
	cvMul( temp1, temp2, temp1, 1 );

	// ((2*mu1_mu2 + C1).*(2*sigma12 + C2))./((mu1_sq + mu2_sq + C1).*(sigma1_sq + sigma2_sq + C2))
	cvDiv( temp3, temp1, ssim_map, 1 );

	// 32bit浮動小数点数→8bit整数にスケール変換
	d=IPL_DEPTH_8U;
	ssim_map_for_display = cvCreateImage( size, d, nChan);
	cvConvertScale(ssim_map, ssim_map_for_display, 255.0, 0.0);
	// ssimマップを保存
	cvSaveImage(argv3, ssim_map_for_display);
	// 画像の解放
	cvReleaseImage(&ssim_map_for_display);
	
	// ssimマップをスカラーに変換
	CvScalar index_scalar = cvAvg( ssim_map );

	// 画像の解放
	cvReleaseImage(&img1);
	cvReleaseImage(&img2);
	cvReleaseImage(&ssim_map);

	return index_scalar.val[0];
}

int main(int argc, char** argv)
{
	if(argc!=4) {
		std::cout << "こんな感じでお願いよ SSIM.exe a.tif b.tif map.tif" << std::endl;
		return -1;
	}
	double SSIM = SSIM_Cal(argv[1],argv[2],argv[3]);
	// 結果の出力
	std::cout << "SSIMは" << SSIM << "でした。" << std::endl;

	return 0;
}