14

私は現在、SFinGeメソッド(Maltoni、Maio、Cappelliによる)を使用して合成指紋を生成するライブラリに取り組んでいます。リンク:http ://biolab.csr.unibo.it/research.asp?organize = Activities&select =&selObj = 12&pat​​hSubj = 111%7C%7C12&

手順の1つでは、画像にさまざまなガボールフィルターを適用する必要があります。画像の各ピクセルには方向と周波数が関連付けられているため、画像全体で1つのカーネルを使用して畳み込みを行うことはありませんが、プロセス中にフィルターを変更する必要があります。ピクセルのこれらの属性では、画像上の各ピクセルが異なる方法で変更されます。

この方法でフィルターを適用し、画像を数回畳み込むと(各畳み込みの後に画像を2値化する必要があります)、次のようになります。

ここに画像の説明を入力してください

マスター指紋、この画像は生成されるのに約20秒かかりました(これは遅すぎるので、FFTで実行したいのです)。これは、それを完了するために5回の畳み込みを実行する必要があったためです(数回から開始します)。ランダムな黒い点)。

私のフィルターは30x30で、画像は275x400です。各次数と密度に1つずつ、合計36000のフィルターがあります(密度は0〜100になります)。すべての角度をカバーできるので、フィルターの数を36000から9000に減らすことを計画しています。また、すべてのフィルターは事前に計算され、フィルターバンクに保存されます。

これは、gabor畳み込み実装のC#のソースコードです。

この2つの方法は、畳み込みを実行します。

    /// <summary>
    /// Convolve the image with the different filters depending on the orientation and density of the pixel.
    /// </summary>
    /// <param name="image">The image to be filtered.</param>
    /// <param name="directionalMap">The directional map.</param>
    /// <param name="densityMap">The density map.</param>
    /// <returns></returns>
    public double[,] Filter(double[,] image, double[,] directionalMap, double[,] densityMap)
    {
        int       midX                          = FILTER_SIZE / 2;
        int       midY                          = FILTER_SIZE / 2;
        double[,] filteredImage                 = new double[image.GetLength(0), image.GetLength(1)];
        double[,] filteredImageWithValuesScaled = new double[image.GetLength(0), image.GetLength(1)];
        double[,] finalImage                    = new double[image.GetLength(0), image.GetLength(1)];

        for (int i = 0; i < image.GetLength(0); i++)
            for (int j = 0; j < image.GetLength(1); j++)
            {

                double pixelValue = GetPixelConvolutionValue(image, this.filterBank[(int)Math.Floor((directionalMap[i, j] * 180 / Math.PI))][Math.Round(densityMap[i, j], 2)], i - midX, j - midY);

                filteredImage[i, j] = pixelValue;
            }

        filteredImageWithValuesScaled = this.RescaleValues(filteredImage, 0.0, 255.0);

        return filteredImageWithValuesScaled;
    }
    /// <summary>
    /// Gets the pixel convolution value.
    /// </summary>
    /// <param name="image">The image.</param>
    /// <param name="filter">The filter.</param>
    /// <param name="sourceX">The source X.</param>
    /// <param name="sourceY">The source Y.</param>
    /// <returns></returns>
    private double GetPixelConvolutionValue(double[,] image, double[,] filter, int sourceX, int sourceY)
    {
        double result      = 0.0;
        int    totalPixels = 0;

        for (int i = 0; i < filter.GetLength(0); i++)
        {
            if(i + sourceX < 0 || i + sourceX >= image.GetLength(0))
                continue;

            for (int j = 0; j < filter.GetLength(1); j++)
            {
                if(j + sourceY < 0 || j + sourceY >= image.GetLength(1))
                    continue;

                double deltaResult = image[sourceX + i,sourceY + j] * filter[i, j];
                result += deltaResult;

                ++totalPixels;
            }
        }

        double filteredValue = result / totalPixels;
        return filteredValue;
    }

この2つの方法は、フィルターバンク用に異なるガボールフィルターを生成します。

    /// <summary>
    /// Creates the gabor filter.
    /// </summary>
    /// <param name="size">The size.</param>
    /// <param name="angle">The angle.</param>
    /// <param name="wavelength">The wavelength.</param>
    /// <param name="sigma">The sigma.</param>
    /// <returns></returns>
    public double[,] CreateGaborFilter(int size, double angle, double wavelength, double sigma)
    {
        double[,] filter    = new double[size, size];
        double    frequency = 7 + (100 - (wavelength * 100)) * 0.03;

        int windowSize = FILTER_SIZE/2;

        for (int y = 0; y < size; ++y)
        {
            for (int x = 0; x < size; ++x)
            {
                int dy = -windowSize + y;
                int dx = -windowSize + x;

                filter[x, y] = GaborFilterValue(dy, dx, frequency, angle, 0, sigma, 0.80);
            }
        }

        return filter;
    }
    /// <summary>
    /// Gabor filter values generation.
    /// </summary>
    /// <param name="x">The x.</param>
    /// <param name="y">The y.</param>
    /// <param name="lambda">The wavelength.</param>
    /// <param name="theta">The orientation.</param>
    /// <param name="phi">The phaseoffset.</param>
    /// <param name="sigma">The gaussvar.</param>
    /// <param name="gamma">The aspectratio.</param>
    /// <returns></returns>
    double GaborFilterValue(int x, int y, double lambda, double theta, double phi, double sigma, double gamma)
    {
        double xx = x * Math.Cos(theta) + y * Math.Sin(theta);
        double yy = -x * Math.Sin(theta) + y * Math.Cos(theta);

        double envelopeVal = Math.Exp(-((xx * xx + gamma * gamma * yy * yy) / (2.0f * sigma * sigma)));

        double carrierVal = Math.Cos(2.0f * (float)Math.PI * xx / lambda + phi);

        double g = envelopeVal * carrierVal;

        return g;
    }

私の目標は、この時間を1秒未満に短縮することです(このような時間にまったく同じことを行うプログラムがいくつかあります)。したがって、直接畳み込みアプローチが機能しないため、高速フーリエ変換畳み込みを実装することにしましたが、これに伴う問題は、FFTが同じカーネルを画像全体に一度に適用し、ピクセルごとにカーネルを変更する必要があることです。各ピクセルは、属性(密度と方向)に応じて変更する必要があるためです。この投稿では、Gaborウェーブレットを画像に適用する方法は? reve-etrangeは、画像にさまざまなガボールフィルターを適用する方法を説明していますが、彼のやり方は、画像全体にさまざまなフィルターを適用してから応答を合計することです。必要なのは、さまざまなピクセルからの応答です。さまざまなフィルターに。

これは、1つのフィルターを画像で畳み込むときに発生することです(FFTを使用)。

ここに画像の説明を入力してください

これは使用されたフィルターでした:

ここに画像の説明を入力してください

そして、これはそれが畳み込まれたイメージでした:

ここに画像の説明を入力してください

これは、FFT実装のC#のアルゴリズムです。

    /// <summary>
    /// Convolve the image using FFT.
    /// </summary>
    /// <param name="image">The image to be filtered.</param>
    /// <param name="directionalMap">The directional map.</param>
    /// <param name="densityMap">The density map.</param>
    /// <param name="FFT">if set to <c>true</c> [FFT].</param>
    /// <returns></returns>
    public double[,] Filter(double[,] image, double[,] directionalMap, double[,] densityMap, bool FFT)
    {
        double[,] filter        = null;
        double[,] paddedFilter  = null;
        double[,] paddedImage   = null;
        double[,] croppedImage  = null;
        double[,] filteredImage = new double[image.GetLength(0), image.GetLength(1)];
        double[,] filteredImageWithValuesScaled = new double[image.GetLength(0), image.GetLength(1)];
        double[,] finalImage = new double[image.GetLength(0), image.GetLength(1)];

        filter = this.filterBank[70][0];
        paddedFilter = PadImage(filter, 512, 512, 0, 0); // Pad the filter to have a potency of 2 dimensions.
        paddedImage = PadImage(image, 512, 512, 0, 0);   // Pad the image to have a potency of 2 dimensions.

        FFT fftOne = new FFT(paddedImage);
        FFT fftTwo = new FFT(paddedFilter);

        fftOne.ForwardFFT();
        fftTwo.ForwardFFT();

        FFT result = fftOne * fftTwo;

        result.InverseFFT();

        filteredImage = result.GreyImage;

        filteredImageWithValuesScaled = this.RescaleValues(filteredImage, 0.0, 255.0);

        croppedImage = CropImage(filteredImageWithValuesScaled, image.GetLength(0), image.GetLength(1));

        return croppedImage;
    }

だから私が求めているのは、FFTを使ってさまざまなピクセルからさまざまなカーネルへの応答をどのように取得するのですか?これが不可能な場合、直接畳み込みを改善して少なくとも20倍速くする方法はありますか?

また、すべてのフィルターを使用して1つのカーネルを作成できるので、それらを画像全体に適用できますか?

4

2 に答える 2

8

さまざまなガボールフィルターを使用して画像を畳み込み、FFTを使用してローカル特性に基づいてピクセルの応答を収集する方法を見つけました。

これはコンテキストフィルタリングと呼ばれ、通常、画像をフィルタリングする場合は、単一のカーネルのみを全体に適用しますが、コンテキストフィルタリングでは、ローカルコンテキスト(この場合はピクセルの密度と方向)に応じてフィルターの特性が変化します。

直接畳み込みでは、プロセスは非常に簡単です。畳み込みの各ステップでカーネルを変更するだけですが、FFT畳み込みでは、カーネルが周波数領域の画像に適用されるため、プロセス中にフィルタープロパティを変更することはできません。したがって、各フィルターを使用して画像の畳み込みを個別に行う方法です。これにより、フィルター処理された画像の数がNになります。ここで、Nはフィルターバンク内のフィルターの数です。次に、次の情報を取得して最終的な画像を作成する必要があります。再作成するピクセルのコンテキストに基づいて、フィルター処理されたさまざまな画像。

したがって、各ピクセルについて、彼の向きと密度のプロパティを確認し、元の画像を同じプロパティのフィルターで畳み込むことによって生成されたフィルター処理された画像からそのピクセル位置の値を取得します。プロセスの例を次に示します。

これは、方向マップのグラフィック表現です。

ここに画像の説明を入力してください

生成されるフィルターの量を減らすために、すべてのピクセルに同じ密度を使用しました。

これはソース画像です:

ここに画像の説明を入力してください

これは、使用される3つのフィルター(0度、45度、90度)の例です。

ここに画像の説明を入力してくださいここに画像の説明を入力してくださいここに画像の説明を入力してください

これらは、さまざまな程度でさまざまなフィルターと畳み込まれているソース画像の3つの例です。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ここに画像の説明を入力してください

そして最後に、これが結果の画像です。画像は、ピクセルの方向と密度に基づいて、さまざまなフィルター処理された画像からピクセルの値を取得して作成されました。

ここに画像の説明を入力してください

このプロセスは、最初にすべてのフィルターを使用して元の画像を畳み込む必要があるため、直接畳み込み=(よりもかなり遅くなります。最終的な画像が生成されるまでに約1分かかりました。これまでのところ、直接畳み込みに固執しているようです =/。

読んでくれてありがとう。

于 2012-10-14T21:42:58.470 に答える
0

CUDAで試してみましたか?畳み込みとFFT(この場合はカフ)を使用すると、より高速になります!並列化の可能性があるかどうか試してみてください。実際に取り組んでおり、大幅な改善が見られます。現在、ガボールフィルタリングを実装します

于 2015-08-04T13:02:29.673 に答える