ラベル OpenCV の投稿を表示しています。 すべての投稿を表示
ラベル OpenCV の投稿を表示しています。 すべての投稿を表示

2017年9月27日水曜日

OpencvSharpでパノラマ画像を作成する

OpenCVでC++の場合のサンプルコードは沢山見かけるのですが、
C#版が無かったので投稿します。

Surfとかはライセンスの関係の問題でOpenCVに付属していないようです。
なので代わりにAKAZEを利用しています。

処理速度や特徴点抽出には申し分ないと思うのでコピペ利用でOKだと思います。



void hoge()
{
    var src = new Mat[2];
    var dst = new Mat[2];
    Mat outImg = new Mat();
    KeyPoint[] keypoints1;
    KeyPoint[] keypoints2;
    var descripter1 = new MatOfFloat();
    var descripter2 = new MatOfFloat();
    var result = new Mat();

    src[0] = Cv2.ImRead("2.JPG");
    src[1] = Cv2.ImRead("1.JPG");
    dst[0] = new Mat();
    dst[1] = new Mat();
    Cv2.CvtColor(src[0], dst[0], ColorConversionCodes.BGR2GRAY);
    Cv2.CvtColor(src[1], dst[1], ColorConversionCodes.BGR2GRAY);

    var akaze = AKAZE.Create();
    akaze.DetectAndCompute(dst[0], null, out keypoints1, descripter1);
    akaze.DetectAndCompute(dst[1], null, out keypoints2, descripter2);

    var matcher = new BFMatcher();
    var matches = matcher.Match(descripter1, descripter2);

    Cv2.DrawMatches(src[0], keypoints1, src[1], keypoints2, matches, outImg);

    using (new Window("OutImg", outImg))
    {
        Cv2.WaitKey();
    }

    //画像合体
    var size = matches.Length;
    var getPoints1 = new Vec2f[size];
    var getPoints2 = new Vec2f[size];

    for (var a = 0; a < size; a++)
    {
        var pt1 = keypoints1[matches[a].QueryIdx].Pt;
        var pt2 = keypoints2[matches[a].TrainIdx].Pt;
        getPoints1[a][0] = pt1.X;
        getPoints1[a][1] = pt1.Y;
        getPoints2[a][0] = pt2.X;
        getPoints2[a][1] = pt2.Y;
        Debug.WriteLine($"{pt2.X - pt1.X}, {pt2.Y - pt1.Y}");
    }

    var hom = Cv2.FindHomography(InputArray.Create(getPoints1), InputArray.Create(getPoints2), HomographyMethods.Ransac);

    Cv2.WarpPerspective(src[0], result, hom, new Size(src[0].Cols * 2.0, src[0].Rows * 2.0));
    for (int y = 0; y < src[0].Rows; y++)
    {
        for (int x = 0; x < src[0].Cols; x++)
        {
            result.Set(y, x, src[1].At<Vec3b>(y, x));
        }
    }

    using (new Window("result", result))
    {
        Cv2.WaitKey();
    }
}

2015年3月20日金曜日

CMOSイメージセンサーのノイズ除去テクニック



まず、カメラの設定条件から
・手ブレしないように固定台を使って固定すること。手ブレすると画像処理で補正は効かない。
逆にピンぼけはシャープネスフィルタで多少マシにできる。
・ レンズはしっかりマウントに取り付けて置く事。ずれてるとピンぼけの原因になる。
・動的被写体はCMOSの場合、画像が歪んでしまうので狙う被写体は静的なもの限定にする。



ここから本題。
 対策の目標として1つ例を挙げると、ノイズの種類を見極めてから1つ1つフィルタで対応していく事でSN比を高めていけるのでこれが結構うまくいく。

・ノイズの種類
  大きく分けると固定パターンノイズとランダムノイズの2つに分けれる。


固定パターンノイズ・・・特定の画素がずっと光っているノイズ。この原因は増幅器のバラツキなので温度特性でも変化してしまう完全に消せそうで消えないノイズ。消すのは比較的簡単。相関二重サンプリングといって
 撮影画像 - 真っ暗な状態 = ノイズが少ない画像
 
ランダムノイズ・・・暗電流。毎回異なる場所で発生するノイズ。もちろん固定パターンノイズをサンプリングする時にも発生する。時間軸に対してメディアンフィルタを書けることで対処できるが、すべて取り除けない。

 ノイズをうまく対処するにはノイズ評価式からデジタル的にノイズは何かを解くところから始まる。

A=ランダムノイズ
B=固定ノイズ
S=信号
Y=出力値
X=時系列ノイズ乱数


これらを式に表すと
  Y = AX + B + S

固定パターンノイズは固定パターンの画像をサンプリングして減算すればOK。
ランダムノイズは、 時系列乱数が加わっているので特定はできないが、乱数の特性を知ることで
対応できる。ちなみに光量によって乱数も変化する事を利用して、全体画素の明るさとノイズ値のグラフを最小二乗法で検量線を作成する。
作り方は真っ暗な画像を100枚、白い紙を写した画像を100枚とって、各画素毎に検量線を作成すればよい。

これらをまとめると 固定パターンノイズだけを取るなら引き算1つで済むけど、
固定パターン+ランダムノイズを除去するには各画素毎に検量線を作ってノイズ成分の値を算出して減算しなくてはならない。



参考URL
 http://cweb.canon.jp/camera/cmos/technology-j/noise_reduction.html

Androider