OpenCV GaborFilter - eiichiromomma/CVMLAB GitHub Wiki

(OpenCV) Gabor Filter

Gabor Filterで遊んでみた

原画像

カーネル(20倍表示)

操作画面

二乗した画像

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

OpenCV 2.4.x以降

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

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)

とすると

のようになる。あとは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()

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

getGaborKernelを使ったサンプル

# encoding: utf-8
# gabor.py
# 2012-3-8
# 2013-8-30 getGaborKernel
# 2016-6-19 fixed bugs
# Eiichiro Momma
__author__ = 'momma'
import numpy as np
import cv2 as cv

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()

ちゃんとしたGabor Filterの実装

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

サンプル(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;
      }

サンプル(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()
⚠️ **GitHub.com Fallback** ⚠️