internal static DFTWAVES init_dftwaves(List <double> dft_coefs, int nwaves, int blocksize) { DFTWAVES dftwaves = new DFTWAVES(); DFTWAVE dftwaveResult = new DFTWAVE(); double pi_factor, freq, x; dftwaves.nwaves = nwaves; dftwaves.wavelen = blocksize; dftwaves.waves = new List <DFTWAVE>(); //count = nwaves pi_factor = 2.0 * M_PI / (double)blocksize; for (int i = 0; i < nwaves; ++i) { dftwaveResult = new DFTWAVE(); dftwaveResult.sin = new List <double>(); // count = blocksize dftwaveResult.cos = new List <double>(); // count = blocksize freq = pi_factor * dft_coefs[i]; for (int j = 0; j < blocksize; ++j) { x = freq * j; dftwaveResult.cos.Add(Math.Cos(x)); dftwaveResult.sin.Add(Math.Sin(x)); } dftwaves.waves.Add(dftwaveResult); } return(dftwaves); }
internal static DFTWAVES init_dftwaves(List<double> dft_coefs, int nwaves, int blocksize) { DFTWAVES dftwaves = new DFTWAVES(); DFTWAVE dftwaveResult = new DFTWAVE(); double pi_factor, freq, x; dftwaves.nwaves = nwaves; dftwaves.wavelen = blocksize; dftwaves.waves = new List<DFTWAVE>(); //count = nwaves pi_factor = 2.0 * M_PI / (double)blocksize; for (int i = 0; i < nwaves; ++i) { dftwaveResult = new DFTWAVE(); dftwaveResult.sin = new List<double>(); // count = blocksize dftwaveResult.cos = new List<double>(); // count = blocksize freq = pi_factor * dft_coefs[i]; for (int j = 0; j < blocksize; ++j) { x = freq * j; dftwaveResult.cos.Add(Math.Cos(x)); dftwaveResult.sin.Add(Math.Sin(x)); } dftwaves.waves.Add(dftwaveResult); } return dftwaves; }
internal static int lfs_detect_minutiae_V2(ref int[,] odmap, ref int[,] olcmap, ref int[,] olfmap, ref int[,] ohcmap, ref int[,] obdata, Bitmap idata, int iw, int ih, ref int mw, ref int mh, string name) { int[,] pdata = new int[iw, ih]; int[,] bdata = new int[iw, ih]; DIR2RAD dir2rad = new DIR2RAD(); DFTWAVES dftwaves = new DFTWAVES(); ROTGRIDS dftgrids = new ROTGRIDS(); ROTGRIDS dirbingrids = new ROTGRIDS(); int[,] direction_map = new int[iw, ih]; int[,] low_contrast_map = new int[iw, ih]; int[,] low_flow_map = new int[iw, ih]; int[,] high_curve_map = new int[iw, ih]; int maxpad = 0; int pw = 0, ph = 0; // initialization maxpad = get_max_padding_V2(lfsparms.windowsize, lfsparms.windowoffset, lfsparms.dirbin_grid_w, lfsparms.dirbin_grid_h); dir2rad = init_dir2rad(lfsparms.num_directions); dftwaves = init_dftwaves(dft_coefs, lfsparms.num_dft_waves, lfsparms.windowsize); dftgrids = init_rotgrids(iw, ih, maxpad, lfsparms.start_dir_angle, lfsparms.num_directions, lfsparms.windowsize, lfsparms.windowsize, RELATIVE2ORIGIN); if (maxpad > 0) { // печать pdata = pad_uchar_image(ref pw, ref ph, idata, iw, ih, maxpad, lfsparms.pad_value); // PrintMap(pdata, "pdata"); } else { for (int i = 0; i < iw; i++) { for (int j = 0; j < ih; j++) { pdata[i, j] = idata.GetPixel(i, j).R; } } pw = iw; ph = ih; } gen_image_maps(ref direction_map, ref low_contrast_map, ref low_flow_map, ref high_curve_map, ref mw, ref mh, pdata, pw, ph, dir2rad, dftwaves, dftgrids, name); /* Assign results to output pointers. */ odmap = direction_map; olcmap = low_contrast_map; olfmap = low_flow_map; ohcmap = high_curve_map; obdata = bdata; return(0); }
internal static int lfs_detect_minutiae_V2(ref int[,] odmap, ref int[,] olcmap, ref int[,] olfmap, ref int[,] ohcmap, ref int[,] obdata, Bitmap idata, int iw, int ih, ref int mw, ref int mh, string name) { int[,] pdata = new int[iw, ih]; int[,] bdata = new int[iw, ih]; DIR2RAD dir2rad = new DIR2RAD(); DFTWAVES dftwaves = new DFTWAVES(); ROTGRIDS dftgrids = new ROTGRIDS(); ROTGRIDS dirbingrids = new ROTGRIDS(); int[,] direction_map = new int[iw, ih]; int[,] low_contrast_map = new int[iw, ih]; int[,] low_flow_map = new int[iw, ih]; int[,] high_curve_map = new int[iw, ih]; int maxpad = 0; int pw = 0, ph = 0; // initialization maxpad = get_max_padding_V2(lfsparms.windowsize, lfsparms.windowoffset, lfsparms.dirbin_grid_w, lfsparms.dirbin_grid_h); dir2rad = init_dir2rad(lfsparms.num_directions); dftwaves = init_dftwaves(dft_coefs, lfsparms.num_dft_waves, lfsparms.windowsize); dftgrids = init_rotgrids(iw, ih, maxpad, lfsparms.start_dir_angle, lfsparms.num_directions, lfsparms.windowsize, lfsparms.windowsize, RELATIVE2ORIGIN); if (maxpad > 0) { // печать pdata = pad_uchar_image(ref pw, ref ph, idata, iw, ih, maxpad, lfsparms.pad_value); // PrintMap(pdata, "pdata"); } else { for (int i = 0; i < iw; i++) { for (int j = 0; j < ih; j++) { pdata[i, j] = idata.GetPixel(i, j).R; } } pw = iw; ph = ih; } gen_image_maps(ref direction_map, ref low_contrast_map, ref low_flow_map, ref high_curve_map, ref mw, ref mh, pdata, pw, ph, dir2rad, dftwaves, dftgrids, name); /* Assign results to output pointers. */ odmap = direction_map; olcmap = low_contrast_map; olfmap = low_flow_map; ohcmap = high_curve_map; obdata = bdata; return (0); }
/// <summary> /// Проводит DFT анализ для блока. /// Блок отбирается по ряду направлений и по нескольким видам сигнала (волн) /// различной частоты, применённой для каждого направления. /// Для каждого направления пиксели суммируются по строкам и получается /// вектор сумм. Каждый DFT вид сигнала затем применяется индивидуально этому вектору. /// Значение мощности DFT вычисляется для каждого типа сигнала. /// (frequency) на каждом направлении блока. /// Более того итоговый результат - вектор N сигналов * M направлений /// Используется для определения доминирующего направления. /// </summary> /// <param name="powers"></param> /// <param name="pdata"></param> /// <param name="blkoffset"></param> /// <param name="blkoffsetX"></param> /// <param name="blkoffsetY"></param> /// <param name="pw"></param> /// <param name="ph"></param> /// <param name="dftwaves"></param> /// <param name="dftgrids"></param> internal static void dft_dir_powers(ref double[,] powers, ref int[,] pdata, int blkoffset, int blkoffsetX, int blkoffsetY, int pw, int ph, DFTWAVES dftwaves, ROTGRIDS dftgrids) { if (dftgrids.grid_w != dftgrids.grid_h) { throw new Exception("ERROR : dft_dir_powers : DFT grids must be square\n"); } int[] rowsums = new int[dftgrids.grid_w]; // для кажого направления for (int dir = 0; dir < dftgrids.ngrids; dir++) { sum_rot_block_rows(ref rowsums, pdata, blkoffsetX, blkoffsetY, dftgrids.grids[dir], dftgrids.grid_w); // для каждого варианта сигнала\волны for (int w = 0; w < dftwaves.nwaves; w++) { powers[w, dir] = dft_power(rowsums, dftwaves.waves[w], dftwaves.wavelen); } } }
/// <summary> /// Вычисляем карты для изображения (для Version 2 of the NIST LFS System) /// карта направлений (Direction Map) - матрица, целые значения, доминирующее направление /// карта контрастов (Low Contrast Map) - матрица, помечены блоки низкого контраста /// карта потоков (Low Flow Map) - нет выделенного направления /// карта кривизны (High Curve Map) - блоки высокой кривизны /// Изображение: произвольное, не квадратное /// </summary> /// <param name="odmap">карта направлений</param> /// <param name="olcmap">карта контраста</param> /// <param name="olfmap">карта потоков</param> /// <param name="ohcmap">карта кривизны</param> /// <param name="omw"> количество блоков по горизонтали</param> /// <param name="omh">количество блоков по вертикали</param> /// <param name="pdata">padded входное изображение</param> /// <param name="pw">padded ширина</param> /// <param name="ph">padded высота</param> /// <param name="dir2rad">Поисковая таблица преобразования целых направлений</param> /// <param name="dftwaves">структура для DFT сигналов (wave forms)</param> /// <param name="dftgrids">структура смещений для повёрнутых пикселей окна\грида (rotated pixel grid offsets)</param> internal static void gen_image_maps(ref int[,] odmap, ref int[,] olcmap, ref int[,] olfmap, ref int[,] ohcmap, ref int omw, ref int omh, int[,] pdata, int pw, int ph, DIR2RAD dir2rad, DFTWAVES dftwaves, ROTGRIDS dftgrids, string name) { int[,] direction_map = new int[omw, omh]; int[,] low_contrast_map = new int[omw, omh]; int[,] low_flow_map = new int[omw, omh]; int mw = 0, mh = 0; if (dftgrids.grid_w != dftgrids.grid_h) { throw new Exception("ERROR : gen_image_maps : DFT grids must be square\n"); } int iw = pw - (dftgrids.pad << 1); int ih = ph - (dftgrids.pad << 1); // int blkoffsCount = ((int)Math.Ceiling(iw / (double)lfsparms.blocksize)) * // (int)Math.Ceiling(ih / (double)lfsparms.blocksize); // blkoffsCount = blkoffs.GetLength(0) * blkoffs.GetLength(1) - проверено // считаем смещения для блоков // предполагая, что у нас +12 пикселей со всех сторон изображения со значениями 128 // чтобы нормально считать в окнах int[,] blkoffs = block_offsets(ref mw, ref mh, iw, ih, dftgrids.pad, lfsparms.blocksize); // PrintMap(blkoffs, "blkoffs"); gen_initial_maps(ref direction_map, ref low_contrast_map, ref low_flow_map, blkoffs, mw, mh, ref pdata, pw, ph, dftwaves, dftgrids); // печать // PrintMap(direction_map, "direction_map"); // PrintMap(low_contrast_map, "low_contrast_map"); // PrintMap(low_flow_map, "low_flow_map"); // direction_map не меняется, также low_flow = 0 // но low_contrast = 1 morph_TF_map(ref low_flow_map, mw, mh); remove_incon_dirs(ref direction_map, mw, mh, dir2rad); smooth_direction_map(ref direction_map, ref low_contrast_map, mw, mh, dir2rad); interpolate_direction_map(ref direction_map, ref low_contrast_map, mw, mh); remove_incon_dirs(ref direction_map, mw, mh, dir2rad); smooth_direction_map(ref direction_map, ref low_contrast_map, mw, mh, dir2rad); set_margin_blocks(ref direction_map, mw, mh, INVALID_DIR); int[,] high_curve_map = gen_high_curve_map(ref direction_map, mw, mh); odmap = direction_map; olcmap = low_contrast_map; olfmap = low_flow_map; ohcmap = high_curve_map; omw = mw; omh = mh; // печать //PrintMap(direction_map, name + "_direction_map"); //PrintMap(low_contrast_map, name + "_low_contrast_map"); //PrintMap(low_flow_map, name + "_low_flow_map"); //PrintMap(high_curve_map, name + "_high_curve_map"); }
/// <summary> /// Создаёт начальную карту направлений (Direction Map) /// Важно, чтобы были те самые padding - чтобы не вылезти за границы /// Странные направления сгладятся и уйдут после основанного на DFT анализа /// Валидные значения >=0, невалидные -1 /// Также возвращаются две карты: /// карта контрастов (Low Contrast Map) /// - помечает блоки с низким контрастом (у них невалидное значение - направление) /// карта потоков(Low Flow Map) /// - помечает блоки, в которых DFT анализ не нашёл направления (также невалидное направление) /// </summary> /// <param name="odmap">карта направлений</param> /// <param name="olcmap">карта контрастов</param> /// <param name="olfmap">карта потоков</param> /// <param name="blkoffs">смещения блоков</param> /// <param name="mw">количество блоков по горизонтали в padded изображении</param> /// <param name="mh">количество блоков по вертикали в padded изображении</param> /// <param name="pdata">padded входное изображение</param> /// <param name="pw">ширина padded изображения</param> /// <param name="ph">высота padded изображения</param> /// <param name="dftwaves">структура для DFT сигналов (wave forms)</param> /// <param name="dftgrids">структура смещений для повёрнутых пикселей окна\грида (rotated pixel grid offsets)</param> internal static void gen_initial_maps(ref int[,] odmap, ref int[,] olcmap, ref int[,] olfmap, int[,] blkoffs, int mw, int mh, ref int[,] pdata, int pw, int ph, DFTWAVES dftwaves, ROTGRIDS dftgrids) { int nstats = dftwaves.nwaves - 1; int[,] direction_map = new int[mw, mh]; int[,] low_contrast_map = new int[mw, mh]; int[,] low_flow_map = new int[mw, mh]; double[,] powers = new double[dftwaves.nwaves, dftgrids.ngrids]; int[] wis = new int[nstats]; double[] powmaxs = new double[nstats]; int[] powmax_dirs = new int[nstats]; double[] pownorms = new double[nstats]; int xminlimit = dftgrids.pad; int xmaxlimit = pw - dftgrids.pad - lfsparms.windowsize - 1; int yminlimit = dftgrids.pad; int ymaxlimit = ph - dftgrids.pad - lfsparms.windowsize - 1; int win_x, win_y, low_contrast_offset; int blkdir; int dft_offset; for (int jndex = 0; jndex < mh; jndex++) { for (int index = 0; index < mw; index++) { // инициализируем карты // direction_map -1 // low_contrast_map 0 // low_flow_map 0 direction_map[index, jndex] = INVALID_DIR; low_contrast_map[index, jndex] = 0; low_flow_map[index, jndex] = 0; } } for (int jndex = 0; jndex < mh; jndex++) { for (int index = 0; index < mw; index++) { // dft_offset = blkoffs[bi] - (lfsparms->windowoffset * pw) - lfsparms->windowoffset; dft_offset = blkoffs[index, jndex] - (lfsparms.windowoffset * pw) - lfsparms.windowoffset; win_x = dft_offset % pw; win_y = (int)(dft_offset / pw); // проверка на попадание в padding (т.е. рамку) win_x = Max(xminlimit, win_x); win_x = Min(xmaxlimit, win_x); win_y = Max(yminlimit, win_y); win_y = Min(ymaxlimit, win_y); low_contrast_offset = (win_y * pw) + win_x; // просто передаём координаты if (low_contrast_block(low_contrast_offset, win_x, win_y, lfsparms.windowsize, pdata, pw, ph)) { /* block is low contrast ... */ low_contrast_map[index, jndex] = TRUE; continue; } // вычислить dft веса // blkoffs[bi] ? low_contrast_offset, win_x, win_y dft_dir_powers(ref powers, ref pdata, low_contrast_offset, win_x, win_y, pw, ph, dftwaves, dftgrids); // вычислить статистики для dft весов (?) dft_power_stats(ref wis, ref powmaxs, ref powmax_dirs, ref pownorms, powers, 1, dftwaves.nwaves, dftgrids.ngrids); // Проведение _первичного_ теста для определения направления blkdir = primary_dir_test(ref powers, wis, powmaxs, powmax_dirs, pownorms, nstats); if (blkdir != INVALID_DIR) { direction_map[index, jndex] = blkdir; continue; } // Проведение _вторичного_ теста для определения направления (вилка) blkdir = secondary_fork_test(ref powers, wis, powmaxs, powmax_dirs, pownorms, nstats); if (blkdir != INVALID_DIR) { direction_map[index, jndex] = blkdir; continue; } low_flow_map[index, jndex] = TRUE; } } odmap = direction_map; olcmap = low_contrast_map; olfmap = low_flow_map; }