2012-06-17 19 views
14

¿Alguien me puede ayudar a convertir el tipo escalar de openCV a tipos básicos como float o double?opencv: convertir escalar a flotante o tipo doble

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

tengo que resumir todos los elementos de la estera objetos arg1 y arg2 (suma barrio), entonces tengo que llevar a cabo su división de encontrar campo de orientación en cada uno de píxeles. Realicé suma, pero como tengo que aplicar la función arctan, el tipo escalar no encaja. ¿Alguien puede ayudarme a convertir el tipo escalar a tipos básicos?

realidad estoy tratando de aplicar el filtro y el código que he hecho hasta ahora-Gabor log es:

//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

estoy tratando de aplicar el filtro para la mejora de la huella digital-Gabor ingrese ..... He editado mi post y añadido el código ..... – bistaumanga

Respuesta

3

EDITAR

De los documentos OpenCV:

suma
...
El func ciones suma calcular y devolver la suma de elementos de la matriz, de forma independiente para cada canal.

Las imágenes de salida que genera Sobel son imágenes binarias con un canal, ya que sus Sum1Sum2 y escalares como resultado de la que necesita para utilizar atan(Sum1[0]/Sum2[0]) para calcular el valor principal de la tangente del arco.

MAL como filtro de Log-Gabor se debe aplicar ...

Parece que se intenta hacer un montón de cosas, lo que podría ser manejado por cv::filter2D() ... Si desea aplicar un filtro Gabor a su imagen a continuación, echar un vistazo a esto, lo que me pareció 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

gracias por su respuesta, pero esto es para el filtro gabor, y yo, estoy trabajando en el filtro log-gabor ... poco avanzado que esto, pero dará muchas ideas ... pero aún tengo que convertir el tipo escalar a tipos básicos como float. ¿me puedes sugerir método para eso? – bistaumanga

+0

Echa un vistazo a mi edición. Espero que sea correcto – dom

23

utilizo

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

gracias. tu respuesta ayudó mucho –

1

Scalar es un vector de 4 elementos de dobles derivado de Vec, como se muestra en la documentación de opencv (http://docs.opencv.org/2.4.9/modules/core/doc/basic_structures.html#scalar)

La función cv :: sum suma los elementos de cada canal por separado, si la matriz tiene más de un canal, y los almacena en Scalar Vec. Por lo tanto, para acceder a los dobles de cada canal, debe acceder a las posiciones en el vector. (Documentación: 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]; 
Cuestiones relacionadas