image - 푸리에 - FFT를 사용하여 로컬 방향 및 밀도에 따라 조정 된 다른 가보 필터로 이미지를 컨버팅하는 방법은 무엇입니까?




푸리에 변환 기초 (2)

CUDA를 사용해 보셨습니까? 컨볼 루션과 FFT (이 경우 커프)를 사용하면 더 빨라집니다! 병렬화의 가능성이 있는지 확인해보십시오. 사실은 그 작업에 착수했습니다. 개선이 엄청나다고 말할 수 있습니다. 현재 Gabor 필터링을 구현하려고합니다.

저는 현재 SFinGe 방법 (Maltoni, Maio 및 Cappelli) 링크를 사용하여 합성 지문을 생성하는 라이브러리를 작업 중입니다 : http://biolab.csr.unibo.it/research.asp?organize=Activities&select=&selObj=12&pathSubj=111%7C%7C12&

그 중 하나는 이미지에 다른 gabor 필터를 적용해야한다는 것입니다. 이미지의 각 픽셀은 방향과 주파수가 연관되어 있으므로 이미지 전체에 걸쳐 하나의 커널에서는 처리되지 않지만 필터는 프로세스 중에 변경되어야합니다 픽셀의 속성에서 이미지의 각 픽셀이 다른 방식으로 변경됩니다.

이 방법으로 필터를 적용하고 이미지를 여러 번 컨볼 루션하면 (각 컨볼 루션 후 이미지를 2 진수 화해야 함) 다음과 같이 구할 수 있습니다.

마스터 지문이 이미지를 생성하는 데 약 20 초가 걸렸습니다 (waaay가 너무 느려서 FFT로이 작업을하고 싶은 이유입니다). 왜냐하면 5 회 반복하여 회선을 완료해야했기 때문입니다. 임의의 검은 점).

내 필터는 30x30이고 이미지는 275x400입니다. 총 36000 개의 필터가 있으며, 각 정도와 밀도에 대해 하나씩 (밀도는 0에서 100까지입니다). 필자는 필터의 수를 36000에서 9000으로 줄이기 위해 모든 각도를 커버 할 수 있기 때문에 계획하고 있습니다. 또한 모든 필터는 미리 계산되어 필터 뱅크에 저장됩니다.

이것은 Gabor 컨볼 루션 구현의 C # 소스 코드입니다.

이 두 가지 방법은 회선을 실행합니다.

    /// <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;
    }

이 두 가지 방법은 필터 뱅크에 대해 서로 다른 가버 필터를 생성합니다.

    /// <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 초 미만으로 줄이는 것입니다 (같은 시간대에 똑같은 일을하는 몇 가지 프로그램이 있습니다). 그래서 직접 컨볼 루션 방식이 저에게 효과적이지 않기 때문에 Fast Fourier Transform Convolution을 구현하기로 결정했습니다. 그러나이 문제는 FFT가 동일한 커널을 전체 이미지에 한 번에 적용한다는 것과 픽셀 당 커널을 변경해야한다는 것입니다. 왜냐하면 각 픽셀은 그의 속성 (밀도 및 방향)에 따라 변경되어야하기 때문입니다. 이 포스트 에서 이미지에 가버 웨이블릿을 적용하는 방법은 무엇입니까? reve-etrange 는 이미지에 다른 gabor 필터를 적용하는 방법을 설명합니다. 그러나 그 방법은 그가하는 일은 다른 필터를 전체 이미지에 적용한 다음 응답을 합산하는 것이고, 필요한 것은 다른 픽셀의 응답입니다. 다른 필터로

이것은 (FFT를 사용하여) 이미지로 하나의 필터를 컨벌루션 할 때 일어나는 일입니다.

사용 된 필터는 다음과 같습니다.

그리고 이것은 그것이 convolved 된 이미지였습니다 :

이것은 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 배 더 빠른 직접 컨볼 루션을 개선 할 수있는 방법이 있습니까?

또한 모든 필터를 사용하여 하나의 커널을 만들 수 있으므로 전체 이미지에 적용 할 수 있습니까?


다른 가보 필터를 사용하여 이미지를 콘볼 루션하고 FFT를 사용하여 픽셀 특성에 대한 픽셀 기반의 응답을 수집하는 방법을 찾았습니다.

이는 컨텍스트 필터링이라고 부릅니다. 일반적으로 이미지를 필터링 할 때 단일 커널 만 전체에 적용하지만 로컬 컨텍스트 (이 경우 픽셀의 밀도 및 방향)에 따라 필터 변경의 특성을 컨텍스트 필터링 할 때 사용합니다.

직접 컨볼 루션 과정은 매우 간단합니다. 컨볼 루션의 각 단계에서 커널을 변경하기 만하면되지만 FFT 컨볼 루션에서는 커널이 주파수 도메인의 이미지에 적용되므로 프로세스 중에 필터 속성을 변경할 수 없습니다. 그래서 당신이하는 방법은 각 필터를 개별적으로 이미지의 컨볼 루션 (convolution)을 만드는 것입니다. N 개의 필터 된 이미지를 N 개의 필터 뱅크에있는 필터 번호로 제공합니다. 그런 다음 최종 이미지를 생성해야합니다. 다시 만드는 픽셀의 컨텍스트를 기반으로 필터링 된 다른 이미지.

따라서 각 픽셀에 대해 오리엔테이션 및 밀도 속성을 살펴본 다음 원본 이미지를 동일한 속성의 필터와 컨벌루션하여 생성 된 필터링 된 이미지에서 픽셀 위치의 값을 가져옵니다. 다음은 프로세스의 예입니다.

이것은 방향성지도의 그래픽 표현입니다.

생성 된 필터의 양을 줄이기 위해 모든 픽셀에 동일한 밀도를 사용했습니다.

원본 이미지입니다.

다음은 세 가지 필터 (0도, 45도, 90도)의 예입니다.

다음은 소스 이미지가 서로 다른 각도에서 서로 다른 필터와 컨볼 루션되는 세 가지 예입니다.

그리고 마지막으로 이것은 결과 이미지입니다. 이미지는 픽셀의 방향과 밀도에 따라 서로 다른 필터링 된 이미지의 픽셀 값을 사용하여 만들어졌습니다.

이 프로세스는 직접 컨볼 루션보다 훨씬 느립니다 = (모든 필터로 원본 이미지를 먼저 컨버전해야하기 때문에 최종 이미지 생성에 약 1 분이 걸렸습니다.) 지금까지는 직접 컨볼 루션이 붙어 있습니다. = /.

읽어 주셔서 감사합니다.