FrontPage | changes | index | create | search | preferences

Gabor Filter

Last-Modified: Fri Aug 30 18:18 2013; Revision: 1.12; by momma
edit | copy | diff | history | raw
  1. OpenCV 2.4.x以降
    1. Pythonの場合
    2. getGaborKernelを使ったサンプル
  2. ちゃんとしたGabor Filterの実装
  3. サンプル(C++)
  4. サンプル(Python)

Gabor Filterで遊んでみた

http://www.eml.ele.cst.nihon-u.ac.jp/~momma/img/cat.jpg

原画像

http://www.eml.ele.cst.nihon-u.ac.jp/~momma/img/Gabor01.png

カーネル(20倍表示)

http://www.eml.ele.cst.nihon-u.ac.jp/~momma/img/Gabor02.png

操作画面

http://www.eml.ele.cst.nihon-u.ac.jp/~momma/img/Gabor03.png

二乗した画像

動作が怪しいので作り直し。

[edit]

OpenCV 2.4.x以降

このバージョンからカーネルの取得が標準で出来るようになった。

[edit]

Pythonの場合

  getGaborKernel(...)
    getGaborKernel(ksize, sigma, theta, lambd, gamma[, psi[, ktype]]) -> retval

が定義されていて

  kern = cv2.getGaborKernel((21,21), 5,np.pi/2, 50, 5/21., ktype=cv2.CV_32F)

のような感じで

  plt.imshow(kern)

とすると

http://www.eml.ele.cst.nihon-u.ac.jp/~momma/img/GaborCV24.png

のようになる。あとはfilter2Dで使えば良い。 ksizeがカーネルサイズのtupleな点と角度はラジアン表記な点に注意。

作成されるカーネルは値が小さいのでsamples/python2/gabor_threads.pyでも

  kern = cv2.getGaborKernel((ksize, ksize), 4.0, theta, 10.0, 0.5, 0, ktype=cv2.CV_32F)
  kern /= 1.5*kern.sum()

のようにしている。(下のサンプルではやってない)

[edit]

getGaborKernelを使ったサンプル

    # encoding: utf-8
    # gabor.py
    # 2012-3-8
    # 2013-8-30 getGaborKernel
    # Eiichiro Momma
    __author__ = 'momma'
    import numpy as np
    import cv2 as cv
    
    src_f = 0
    kernel_size =21
    pos_sigma = 5
    pos_lm = kernel_size-2
    pos_th = 0
    pos_gam = 100
    pos_psi = 90
    
    def Process():
        sig = pos_sigma
        lm = pos_lm+2
        th = pos_th*np.pi/180.
        gm = pos_gam/100.
        ps = (pos_psi-180)*np.pi/180
        print 'kern_size=' + str(kernel_size) + ', sig=' + str(sig) + ', th=' + str(th) + ', lm=' + str(lm) +', gm=' + str(gm) + ', ps=' + str(ps)
        kernel = cv.getGaborKernel((kernel_size,kernel_size),sig,th,lm,gm,ps)
        kernelimg = kernel/2.+0.5
        global src_f
        dest = cv.filter2D(src_f, cv.CV_32F,kernel)
        cv.imshow('Process window', dest)
        cv.imshow('Kernel', cv.resize(kernelimg, (kernel_size*20,kernel_size*20)))
        cv.imshow('Mag', np.power(dest,2))
    
    def cb_sigma(pos):
        global pos_sigma
        if pos > 0:
            pos_sigma = pos
        else:
            pos_sigma = 1
        Process()
    
    def cb_lm(pos):
        global pos_lm
        pos_lm = pos
        Process()
    
    def cb_th(pos):
        global pos_th
        pos_th = pos
        Process()
    
    def cb_psi(pos):
        global pos_psi
        pos_psi = pos
        Process()
    
    def cb_gam(pos):
        global pos_gam
        pos_gam = pos
        Process()
    
    if __name__ == '__main__':
        image = cv.imread("cat.jpg",1);
        cv.imshow('Src',image)
        src = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        #global src_f
        src_f = np.array(src, dtype=np.float32)
        src_f /= 255.
        if not kernel_size%2:
            kernel_size += 1
    
        cv.namedWindow('Process window',1)
        cv.createTrackbar('Sigma','Process window',pos_sigma,kernel_size/2,cb_sigma)
        cv.createTrackbar('Lambda', 'Process window', pos_lm, kernel_size-2, cb_lm)
        cv.createTrackbar('Theta', 'Process window', pos_th, 360, cb_th)
        cv.createTrackbar('gamma', 'Process window', pos_psi, 300, cb_gam)
        cv.createTrackbar('Psi', 'Process window', pos_psi, 360, cb_psi)
        Process()
        cv.waitKey(0)
        cv.destroyAllWindows()
[edit]

ちゃんとしたGabor Filterの実装

Pythonでも使いたかったので、今回は使わず。

[edit]

サンプル(C++)

    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <math.h>

    cv::Mat mkKernel(int ks, double sig, double th, double lm, double ps)
    {
        int hks = (ks-1)/2;
        double theta = th*CV_PI/180;
        double psi = ps*CV_PI/180;
        double del = 2.0/(ks-1);
        double lmbd = lm;
        double sigma = sig/ks;
        double x_theta;
        double y_theta;
        cv::Mat kernel(ks,ks, CV_32F);
        for (int y=-hks; y<=hks; y++)
        {
            for (int x=-hks; x<=hks; x++)
            {
                x_theta = x*del*cos(theta)+y*del*sin(theta);
                y_theta = -x*del*sin(theta)+y*del*cos(theta);
                kernel.at<float>(hks+y,hks+x) = (float)exp(-0.5*(pow(x_theta,2)+pow(y_theta,2))/pow(sigma,2))* cos(2*CV_PI*x_theta/lmbd + psi);
            }
        }
        return kernel;
    }

    int kernel_size=21;
    int pos_sigma= 5;
    int pos_lm = 50;
    int pos_th = 0;
    int pos_psi = 90;
    cv::Mat src_f;
    cv::Mat dest;

    void Process(int , void *)
    {
        double sig = pos_sigma;
        double lm = 0.5+pos_lm/100.0;
        double th = pos_th;
        double ps = pos_psi;
        cv::Mat kernel = mkKernel(kernel_size, sig, th, lm, ps);
        cv::filter2D(src_f, dest, CV_32F, kernel);
        cv::imshow("Process window", dest);
        cv::Mat Lkernel(kernel_size*20, kernel_size*20, CV_32F);
        cv::resize(kernel, Lkernel, Lkernel.size());
        Lkernel /= 2.;
        Lkernel += 0.5;
        cv::imshow("Kernel", Lkernel);
        cv::Mat mag;
        cv::pow(dest, 2.0, mag);
        cv::imshow("Mag", mag);
    }

    int main(int argc, char** argv)
    {
        cv::Mat image = cv::imread("cat.jpg",1);
        cv::imshow("Src", image);
        cv::Mat src;
        cv::cvtColor(image, src, CV_BGR2GRAY);
        src.convertTo(src_f, CV_32F, 1.0/255, 0);
        if (!kernel_size%2)
        {
            kernel_size+=1;
        }
        cv::namedWindow("Process window", 1);
        cv::createTrackbar("Sigma", "Process window", &pos_sigma, kernel_size, Process);
        cv::createTrackbar("Lambda", "Process window", &pos_lm, 100, Process);
        cv::createTrackbar("Theta", "Process window", &pos_th, 180, Process);
        cv::createTrackbar("Psi", "Process window", &pos_psi, 360, Process);
        Process(0,0);
        cv::waitKey(0);
        return 0;
    }
[edit]

サンプル(Python)

    # encoding: utf-8
    # gabor.py
    # 2012-3-8
    # Eiichiro Momma
    __author__ = 'momma'
    import numpy as np
    import cv2 as cv
    def mkKernel(ks, sig, th , lm, ps):
        if not ks%2:
            exit(1)
        hks = ks/2
        theta = th * np.pi/180.
        psi = ps * np.pi/180.
        xs=np.linspace(-1.,1.,ks)
        ys=np.linspace(-1.,1.,ks)
        lmbd = np.float(lm)
        x,y = np.meshgrid(xs,ys)
        sigma = np.float(sig)/ks
        x_theta = x*np.cos(theta)+y*np.sin(theta)
        y_theta = -x*np.sin(theta)+y*np.cos(theta)
        return np.array(np.exp(-0.5*(x_theta**2+y_theta**2)/sigma**2)*np.cos(2.*np.pi*x_theta/lmbd + psi),dtype=np.float32)

    src_f = 0

    kernel_size =21
    pos_sigma = 5
    pos_lm = 50
    pos_th = 0
    pos_psi = 90

    def Process():
        sig = pos_sigma
        lm = 0.5+pos_lm/100.
        th = pos_th
        ps = pos_psi
        kernel = mkKernel(kernel_size, sig, th, lm, ps )
        kernelimg = kernel/2.+0.5
        global src_f
        dest = cv.filter2D(src_f, cv.CV_32F,kernel)
        cv.imshow('Process window', dest)
        cv.imshow('Kernel', cv.resize(kernelimg, (kernel_size*20,kernel_size*20)))
        cv.imshow('Mag', np.power(dest,2))

    def cb_sigma(pos):
        global pos_sigma
        if pos > 0:
            pos_sigma = pos
        else:
            pos_sigma = 1
        Process()

    def cb_lm(pos):
        global pos_lm
        pos_lm = pos
        Process()

    def cb_th(pos):
        global pos_th
        pos_th = pos
        Process()

    def cb_psi(pos):
        global pos_psi
        pos_psi = pos
        Process()

    if __name__ == '__main__':
        image = cv.imread("cat.jpg",1);
        cv.imshow('Src',image)
        src = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        #global src_f
        src_f = np.array(src, dtype=np.float32)
        src_f /= 255.
        if not kernel_size%2:
            kernel_size += 1

        cv.namedWindow('Process window',1)
        cv.createTrackbar('Sigma','Process window',pos_sigma,kernel_size,cb_sigma)
        cv.createTrackbar('Lambda', 'Process window', pos_lm, 100, cb_lm)
        cv.createTrackbar('Phase', 'Process window', pos_th, 180, cb_th)
        cv.createTrackbar('Psi', 'Process window', pos_psi, 360, cb_psi)
        Process()
        cv.waitKey(0)
        cv.destroyAllWindows()
[edit]

Powered by WiKicker

日本大学理工学部へ 電気工学科へ 計測工学研究室へ