2012-06-17 2 views
14

Может ли кто-нибудь помочь мне в преобразовании скалярного типа openCV в базовые типы, такие как float или double?opencv: convert Scalar to float или double type

Scalar Sum1=sum(arg1),Sum2=sum(arg2); 
theta.at<float>(i,j)=0.5*atan(Sum1/Sum2); 

Я должен суммировать все элементы Мата объекты arg1 и arg2 (окрестности суммы), то я должен выполнить их деление, чтобы найти поле ориентации на каждых пикселях. Я выполнил сумму, но поскольку я должен применить функцию arctan, скалярный тип не подходит. Может ли кто-нибудь помочь мне в преобразовании скалярного типа в базовые типы?

на самом деле я пытаюсь применить лог-Габор фильтр и код я сделал до сих пор:

//function to enhance fingerprint by log-gabor filter 

void filter(Mat src, Mat finalImage) 
{ 

//Sobel derivatives for orientation estimation 

Mat grad_x,grad_y,grad2_x,grad2_y,fImage; 
src.convertTo(fImage, CV_32F); 

//1st and second order gradient 

Sobel(fImage,grad_x,CV_32F,1,0,3); 
Sobel(fImage,grad_y,CV_32F,0,1,3);  
Sobel(fImage,grad2_x,CV_32F,2,0,3); 
Sobel(fImage,grad2_y,CV_32F,0,2,3); 

//orientation estimation 

Mat theta=Mat::zeros(fImage.size(),CV_32F); 
Size block=Size(12,12); 
copyMakeBorder(grad_x, grad_x, block.height/2, block.height/2, 
       block.width/2,block.width/2 , BORDER_CONSTANT, Scalar::all(0)); 

copyMakeBorder(grad2_x, grad2_x, block.height/2, block.height/2, 
       block.width/2,block.width/2 , BORDER_CONSTANT, Scalar::all(0)); 

copyMakeBorder(grad_y, grad_y, block.height/2, block.height/2, 
       block.width/2,block.width/2 , BORDER_CONSTANT, Scalar::all(0)); 

copyMakeBorder(grad2_y, grad2_y, block.height/2, block.height/2, 
       block.width/2,block.width/2 , BORDER_CONSTANT, Scalar::all(0)); 
Size imgSz=grad_x.size(); 
for(int i=block.width/2;i<imgSz.width-block.width/2;++i) 
    for(int j=block.height/2;j<imgSz.height-block.height/2;++j) 
    { 
     Mat roi_gradX=grad_x(Range(i-block.width/2,i+block.width/2), 
          Range(j-block.width/2,j+block.width/2)); 

     Mat roi_gradY=grad_y(Range(i-block.width/2,i+block.width/2), 
          Range(j-block.width/2,j+block.width/2)); 

     Mat roi_gradX2=grad2_x(Range(i-block.width/2,i+block.width/2), 
          Range(j-block.width/2,j+block.width/2)); 

     Mat roi_gradY2=grad2_y(Range(i-block.width/2,i+block.width/2), 
          Range(j-block.width/2,j+block.width/2)); 

     Mat arg1,arg2; 
     multiply(roi_gradX,roi_gradY,arg1); 
     arg1*=2; 
     subtract(roi_gradX2,roi_gradY2,arg2); 
     Scalar Sum1=sum(arg1),Sum2=sum(arg2); 

     theta.at<float>(i,j)=0.5*atan(Sum1/Sum2); 
    } 
} 
+0

я пытаюсь применить срубы Габор фильтр для повышения отпечатков пальцев ..... я редактировал свой пост и добавил код ..... – bistaumanga

ответ

3

EDIT

Из OpenCV документы:

Сумма
...
The func sum рассчитывают и возвращают сумму элементов массива, независимо для каждого канала.

Выходных изображения, которые генерируют Собели бинарные изображения с одним каналом, как ваши Sum1 и Sum2 Скаляров результата из ряда вам нужно использовать atan(Sum1[0]/Sum2[0]) для вычисления главного значения арктангенса.

НЕПРАВИЛЬНО в журнал Габор фильтр должен быть применен ...

Похоже, вы пытаетесь сделать много вещей, которые могут быть обработаны cv::filter2D() ... Если вы хотите, чтобы применить фильтр Габора к изображению, то посмотрите на это, что я нашел here:

#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; 
} 
+0

спасибо за ответ, но это для фильтра gabor и i, m, работающего на фильтре log-gabor ..... немного продвинутого, чем это, но это даст много идей ...... но все же мне нужно преобразовать скалярный тип в базовые типы, такие как float. .... Можете ли вы предложить мне метод для этого? – bistaumanga

+0

Взгляните на мое редактирование. Надеюсь, это правильно – dom

23

Я использую

double s; 
s = sum(arg1)[0]; 
+0

спасибо. ваш ответ очень помог –

1

Scalar - это 4-элементный вектор удвоений, полученных из Vec, как показано в документации opencv (http://docs.opencv.org/2.4.9/modules/core/doc/basic_structures.html#scalar)

Функция cv :: sum суммирует элементы по каждому каналу отдельно, если матрица имеет более одного канала, и хранит их на Scalar Vec. Поэтому для доступа к удвоениям для каждого канала вы должны получить доступ к позициям на векторе. (Документация: http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#sum)

//sum for first channel 
double sum1 = cv::sum(my_mat)[0]; 
//sum for second channel 
double sum2 = cv::sum(my_mat)[1]; 
//sum for third channel 
double sum3 = cv::sum(my_mat)[2];