Как свертывать изображение с различными фильтрами Габора, настроенными в соответствии с локальной ориентацией и плотностью, используя БПФ?
м в настоящее время работает над библиотекой для создания синтетических отпечатков пальцев с использованиемSfinge метод (по Малтони, Майо и Каппелли) ссылка:http://biolab.csr.unibo.it/research.asp?organize=Activities&выберите = &selObj = 12 &pathSubj = 111% 7C% 7C12 &
Один из шагов требует, чтобы я применил разные фильтры Габора к изображению, каждый пиксель в изображении имеет ориентацию и связанную частоту, поэтому свертка не выполняется с одним ядром по всему изображению, но фильтр должен меняться во время процесса в зависимости от на этих атрибутах пикселей, таким образом, каждый пиксель изображения изменяется по-своему.
Если вы примените фильтры таким образом и сверните изображение несколько раз (вам также придется преобразовывать изображение в двоичную форму после каждой свертки), вы получите следующее:
Генератор отпечатков пальцев, на создание этого изображения ушло около 20 секунд (что слишком медленно, поэтому я хочу сделать это с БПФ), поскольку мне пришлось выполнить свертку 5 раз, чтобы завершить его (вы начинаете с нескольких случайные черные точки).
Мои фильтры 30х30, а изображение 275х400. Всего существует 36000 фильтров, по одному на каждый градус и плотность (плотность варьируется от 0 до 100). Я'Я планирую сократить количество фильтров с 36000 до 9000, так как я могу охватить все углы с ними. Также все фильтры предварительно рассчитываются и сохраняются в банке фильтров.
Это исходный код в C # реализации реализации gabor:
Эти два метода выполняют свертку:
///
/// Convolve the image with the different filters depending on the orientation and density of the pixel.
///
/// The image to be filtered.
/// The directional map.
/// The density map.
///
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;
}
///
/// Gets the pixel convolution value.
///
/// The image.
/// The filter.
/// The source X.
/// The source Y.
///
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;
}
Эти два метода генерируют разные фильтры Габора для банка фильтров:
///
/// Creates the gabor filter.
///
/// The size.
/// The angle.
/// The wavelength.
/// The sigma.
///
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;
}
///
/// Gabor filter values generation.
///
/// The x.
/// The y.
/// The wavelength.
/// The orientation.
/// The phaseoffset.
/// The gaussvar.
/// The aspectratio.
///
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 применяет одно и то же ядро ко всему изображению одновременно, и мне нужно изменить ядро на пиксель, потому что каждый пиксель должен быть изменен в зависимости от его атрибутов (плотность и ориентация). В этом постеКак применить вейвлеты Габора к изображению? Рев-Etrange объясняет, как применять разные фильтры Габора к изображению, но дело в том, что он применяет разные фильтры ко всему изображению, а затем суммирует ответы, и мне нужны ответы от разных пикселей на разные фильтры.
Вот что происходит, когда я сворачиваю один фильтр с изображением (используя БПФ):
Это был использованный фильтр:
И это был образ, с которым он был свернут:
Это алгоритм в C # реализации FFT:
///
/// Convolve the image using FFT.
///
/// The image to be filtered.
/// The directional map.
/// The density map.
/// if set to true [FFT].
///
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 раз быстрее?
Также возможно ли сделать одно ядро, используя все фильтры, чтобы я мог применить их ко всему изображению?