double getPSNR(cv::InputArray src,
cv::InputArray reference,
const int boundingBox = 0, //bounding box to ignore boundary
const int precision = PSNR_UP_CAST,
const int compare_channel = PSNR_ALL);PSNR (Peak signal-to-noise ratio)を計測します.
OpenCVの関数cv::PSNRとは異なり,入力の型同士が異なっても計測できます.
また画像の劣化が例外的になりやすい外周をboundingBoxで指定可能です.
また,cv::PSNRよりも若干高速です.
この関数はclass PSNRMetricsのラッパーであり,何度も使用する場合はクラスを使ったほうがより高速に動作します.
precision で計測のビット深度を指定できます.
デフォルトはPSNR_UP_CASTであり,srcかreferenceのより高い精度の値が使用されます.
詳細はgetPSNR_PRECISIONを参照してください.
compare_channel カラーの場合のPSNRの色を指定できます.
デフォルトはPSNR_ALLであり,全色のMSEの合計値からPSNRを計測します.
詳細はgetPSNR_CHANNELを参照してください.
なお,例外は以下の値が戻ります.
- 完全に一致する場合は0
- MSEがNaNの場合 -1
- MSEがInfの場合 -2
- AVX/single
- Any depth/color
Mat src = imread("lenna.png");
Mat ref; addNoise(src, ref, 50);
cout << getPSNR(src, ref) << endl;
cout << getPSNR(src, ref, 20) << endl;//using bounding box
cout << getPSNR(src, ref, 20, PSNR_8U) << endl;//using down cast to 8U
cout << getPSNR(src, ref, 20, PSNR_8U, PSNR_Y);//getPSNR for Y channel with YUV convertionTest function in OpenCP
void testPSNR(Mat& src);enum PSNR_PRECISION
{
PSNR_UP_CAST,
PSNR_8U,
PSNR_32F,
PSNR_64F,
PSNR_KAHAN_64F,
PSNR_PRECISION_SIZE
};string getPSNR_PRECISION(const int precision)PSNRやMSEを計算するときに,画素値をダウンキャストするためのオプションのenumです.
ダウンキャストすることで,実際に使用するビット深度におけるPSNRを計測できます.
PSNR_UP_CASTは入力,参照画素のうちデプスの優先順位(uchar<short<int<float<double)が高いほうに計算精度がキャストされます.
PSNR_8U/32F/64Fはそれぞれuchar,float,double精度にキャストして計算します.
PSNR_KAHAN_64Fは,double精度の計算をKahanの精度補償アルゴリズムを用いて計算します.
Kahanの精度補償が必要になるほどの精度はほとんどの場合でありません.
また,getPSNR_PRECISIONでenumの名前をstring型で取得できます.
enum PSNR_CHANNEL
{
PSNR_ALL,
PSNR_Y,
PSNR_B,
PSNR_G,
PSNR_R,
PSNR_CHANNEL_SIZE
};string getPSNR_CHANNEL(const int channel);PSNRやMSEを計算するときに,カラー画像をどのように処理するかのオプションのenumです.
デフォルトは,PSNR_ALLで,すべての画素をMSEとして計算に含めて出力します.
PSNR_Yは内部でYUV変換してYの値でPSNRを測定します.
ITU-R BT.601 / ITU-R BT.709 (1250/50/2:1)もしくは,PAL, SECAMのYの値です.
PSNR_B/G/Rは各チャネルのどれかでPSNRを計測します.
また,getPSNR_CHANNELでenumの名前をstring型で取得できます.
なお,BGRそれぞれのPSNRを平均するオプションはありません.
同一画像の多チャンネルのPSNRを平均する,MSEを平均するといった処理は,多くの場合で正しくありません.
double getMSE(cv::InputArray src1, cv::InputArray src2const, int boundingBox = 0, const int precision = PSNR_UP_CAST, const int compare_channel = PSNR_ALL);double getMSE(cv::InputArray src1, cv::InputArray src2, cv::InputArray mask);getPSNR関数において,PSNRではなくMSEを返します.
挙動としては,getPSNR関数がMSE求めたのちに,inlineMathFunctions.hpp内のMSEtoPSNRインライン関数を呼び出しています.
なお,マスク付きのMSE関数は特殊化されており,マスク無しの関数と挙動が違います.
入力をdoubleでキャストしたのち,必ずPSNR_ALLオプションで出力します.
マスクは,計測しない画素を0にしてください.
class PSNRMetrics
{
public:
double getMSE(cv::InputArray src, cv::InputArray ref, const int boundingBox = 0, const int precision = PSNR_UP_CAST, const int compare_channel = PSNR_ALL);
double getPSNR(cv::InputArray src, cv::InputArray ref, const int boundingBox = 0, const int precision = PSNR_UP_CAST, const int compare_channel = PSNR_ALL);
double operator()(cv::InputArray src, cv::InputArray ref, const int boundingBox = 0, const int precision = PSNR_UP_CAST, const int compare_channel = PSNR_ALL);
void setReference(cv::InputArray src, const int boundingBox = 0, const int precision = PSNR_UP_CAST, const int compare_channel = PSNR_ALL);
double getMSEPreset(cv::InputArray src, const int boundingBox = 0, const int precision = PSNR_UP_CAST, const int compare_channel = PSNR_ALL);
double getPSNRPreset(cv::InputArray src, const int boundingBox = 0, const int precision = PSNR_UP_CAST, const int compare_channel = PSNR_ALL);
};getPSNR,getMSEのラップ元です.
何度もPSNRを計測する場合は,こちらのクラスを使ったほうが,バッファを使いまわすため速く動作します.
このクラス内のgetMSE,getPSNRメソッドの挙動は,関数の場合と同様です.
またoperator()により,getPSNRを省略できます.
もし,参照画像が固定の場合は,setReferenceで比較元をセットしたのちに,getMSEPresetやgetPSNRPresetで入力画像だけ入れることで若干の高速化をすることが可能です.
その場合は,boundingBox, precision, compare_channelの各オプションを,比較元と,入力で必ず一致させる必要があります.
よく間違えるので注意してください.
void localPSNRMap(cv::InputArray src1, cv::InputArray src2, cv::OutputArray dest, const int r, const int compare_channel, const double psnr_infinity_value = 0.0);局所ウィンドウのPSNRを計算し,画像として出力します.
各画素の周辺のPSNRを観測するために使用します.
rが局所ウィンドウの半径,compare_channelはgetPSNR関数と同じ意味です.
内部ですべてdoubleにアップキャストしたのちにPSNRを計算するため,precisionのオプションはありません.
最後の引数でPSNRが無限大の時の値を指定できます.デフォルトは0.0です.
- OpenCV/single
- upcast double, any color
Mat src = imread("lenna.png");
Mat ref; addNoise(src, ref, 50);
Mat dest;
localPSNRMap(src, ref, dest, 10, PSNR_ALL);void guiLocalPSNRMap(cv::InputArray src1, cv::InputArray src2, const bool isWait = true, std::string wname = "AreaPSNR");GUI付きでlocalPSNRMapを試します.
ヘルプはキーワードの?を押してください.
double getInacceptableRatio(cv::InputArray src, const cv::Mat& ref, const int threshold);閾値threshold以上の絶対値差を持つ画素数の割合を返します.
0~100の値が出力されます.
ステレオマッチングの精度評価で用いる,Bad Pixel指標と同じ計算式です.
- グレイ画像のみ対応です.カラー画像は強制的にグレイスケールに変換されます.
- 型は任意の型で動作します.ただし,内部のcvtColorがdoubleで動作しないため,doubleの入力は受け付けません.
- 高速化はされていません.
double getEntropy(cv::InputArray src, cv::InputArray mask = cv::noArray());入力画像のエントロピーが出力されます.
また,計算する領域のマスクを追加することが可能です.
- 8Uか16Sのみ対応しています.
- 高速ははされていません.
double getTotalVariation(cv::InputArray src);入力画像のトータルバリエーションが出力されます.
- 高速ははされていません.