Перейти к содержимому
Compvision.ru
MikeWhite

Обработка отпечатков пальцев

Recommended Posts

Здравствуйте! на просторах интернета набрел на ваш форум и прошу у вас помощи.

Пишу проект для обработки отпечатков пальцев на платформе Android, OpenCV подключил, информацию по обработке впитал но на практике что то ничего не получается:

Для начала как я понимаю мне необходимо построить карту направлений и в последствии построить Габор изображение которое сгладит все неровности и после его бинаризации строится скелет в котором находим конечные точки и развлетвления.

конкретно после всех преобразований должно получиться подобное изображение:
Screenshot_2015-09-30-12-32-54.thumb.png

для нахождения карты направлений я использовал алгоритм: Smorodov с сайта stackoverflow
конкретно моя реализация:

        Imgproc.cvtColor(mRgba, src_f, Imgproc.COLOR_BGR2GRAY);
        //src_f.convertTo(src_f, CvType.CV_8UC1);
        normalize(src_f, src_f, 0, 255, Core.NORM_MINMAX, CvType.CV_8UC1);
        threshold(src_f, src_f, 128, 255, Imgproc.THRESH_BINARY);


        // orientation
        if(orientCalc) {
            int scale = 2;
            int delta = 0;
            Imgproc.Sobel(src_f, mHist, CvType.CV_32F, 1, 0, 7, scale, delta);
            Imgproc.Sobel(src_f, mGray, CvType.CV_32F, 0, 1, 7, scale, delta);
            int aprox_size=10;
            aproxorientation=new Mat(mHist.rows()/aprox_size,mHist.cols()/aprox_size,CvType.CV_32F,new Scalar(0, 0, 0));
            orientation = new Mat(mHist.rows(), mHist.cols(), CvType.CV_32F); //to store the gradients
            magnit=new Mat(mHist.rows(), mHist.cols(), CvType.CV_32F);
            phase(mHist, mGray, orientation, false);
            magnitude(mHist, mGray, magnit);
            normalize(magnit, magnit, 0, 1, Core.NORM_MINMAX);
            showBitmap(R.id.imageViewX, mHist);
            showBitmap(R.id.imageViewY, mGray);
            orientCalc=false;
            float results;
            merge(Arrays.asList(src_f, src_f, src_f), img);
            logMInfo(orientation);
            for (int l=0;l<= mHist.rows()-aprox_size;l+= aprox_size) {
                for (int k=0;k<= mHist.cols()-aprox_size;k+= aprox_size)
                {
                    results =  GetAngle(l,k,aprox_size);
                    Point p1,p2;
                    p1=new Point((k + aprox_size/2), (l + aprox_size/2));
                    p2=new Point((k + aprox_size/2), (l + aprox_size/2));
                    p1.x=p1.x-(aprox_size/2)*Math.cos(results);
                    p1.y=p1.y-(aprox_size/2)*Math.sin(results);

                    p2.x=p2.x+(aprox_size/2)*Math.cos(results);
                    p2.y=p2.y+(aprox_size/2)*Math.sin(results);
                    Imgproc.line(img,p1,p2,new Scalar(255,0,0),1);
                }
            }
        }
        showBitmap(R.id.imageViewO, orientation);

код апроксимации с кешем:

float GetAngle(int x,int y,int d){
        float res=0;
        if(orientCalc==false){
            res=(float)aproxorientation.get(x/d,y/d)[0];
            if(res==0){
                res=GetWeightedAngle(new Mat(magnit,new Rect(y, x, d, d)),new Mat(orientation,new Rect(y, x, d, d)));
                aproxorientation.put(x/d,y/d,res);
            }
        }
        return res;
    }
    float GetWeightedAngle(Mat mag,Mat ang)
    {
        float res=0;
        float n=0;
        double a=0;
        for (int i=0;i< mag.rows();++i)
        {
            for (int j=0;j< mag.cols();++j)
            {
                ang.put(i,j,ang.get(i,j)[0]*mag.get(i,j)[0]);
                res+=(float)ang.get(i,j)[0];
                n+=mag.get(i,j)[0];
            }
        }
        if(n==0)return 0;
        res/=n;
        return res;
    }

после этого я получил изображения:

Screenshot_2015-10-08-14-13-44.thumb.pngScreenshot_2015-10-08-14-15-00.thumb.png

где видно что на участках близких к 2pi появляются артефакты и направления расчитываются неверно, как это побороть я не знаю.

но даже с такой картой ориентации я постарался постороить габор фильтр:

if(((CheckBox)findViewById(R.id.checkBox)).isChecked()) {
            int kernel_size = 3;
            double sig = 0.5, th = 0, lm = 0.85, gm = 1, ps = 274;
            sig = ((SeekBar) findViewById(R.id.seekBarSig)).getProgress() / 100.0;
            lm = ((SeekBar) findViewById(R.id.seekBarLambda)).getProgress() / 1000.0;
            int grid_size = 10;
            Log.i("Finger", "getGaborKernel(" + sig + "," + th + "," + lm + ")");
            Log.i("Finger", "src_f.type() " + CvType.typeToString(src_f.type()) + " size() " + src_f.cols() + "x" + src_f.rows());
            int x1, x2;
            src_f.convertTo(src_f, CvType.CV_32F);
            Imgproc.blur(src_f, src_f, new Size(3, 3));
            Mat kernel;

            for (int l=0;l<= src_f.rows()-grid_size;l+= grid_size) {
                for (int k=0;k<= src_f.cols()-grid_size;k+= grid_size)
                {

                    Mat roi3 = new Mat(src_f, new Rect(k, l, grid_size, grid_size));
                    double ang = GetAngle(l,k,grid_size);
                    kernel = Imgproc.getGaborKernel(new Size(kernel_size, kernel_size), sig, ang, lm, gm);
                    Imgproc.filter2D(roi3, roi3, CvType.CV_32F, kernel);
                }
            }


            src_f.copyTo(tmp);
        }

получилось вообще непонятно что:

Screenshot_2015-10-08-14-20-17.thumb.png

 

Посему прошу у вас помощи в редактировании кода либо если завалялось что готовое, это мой первый проект на opencv и посему не сильно ругайтесь я уже третий месяц пытаюсь во всем этом разобраться и в теории все понятно а практических реализаций я не нашел.

Заранее Огромное Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

По поводу углов, заверните их в интервал 0-180, это должно решить проблему.

По поводу клеток, сделайте свертку полного изображения 8-12 фильтрами с разными ориентациями, и для каждого угла берите точку из своего изображения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

заворачивал в 0-180 не помогает:

Screenshot_2015-10-08-09-33-35.thumb.pngScreenshot_2015-10-08-09-34-45.thumb.png

причитна в появлении артифактов в себелевском смещении (с лева 2 картинки по X и Y) на них явно видно искажения

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Посмотрите  проект на питоне, думаю он делает как раз то что Вам нужно:

https://github.com/rtshadow/biometrics

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Огромное спасибо за пример, по нему я собрал расчет углов (хотя очень медленно).

А вот дальше я опять застрял пытаясь понять как строится gabor изображение? требуется по мимо углов еще доп параметры смещений, как их рассчитать? После запуска примера его описанные функции работают а вот именно преобразование из исходного в enhanced не работает.

Есть ли подобный пример но с использование OpenCV (C++,Java)?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну, примеров на CPP нет, но могу теории подкинуть :)

https://drive.google.com/file/d/0Bxk3hR536PxSWHJ4V2dZanJHbms/view?usp=sharing

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×