2012-06-17 5 views
14

openCV의 스칼라 유형을 float 또는 double과 같은 기본 유형으로 변환하는 데 도움을 줄 수 있습니까?opencv : 스칼라를 float 또는 double 유형으로 변환

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

는 I는 I 각 화소의 배향 영역을 찾기 위해 자신의 분할을 수행 할 수있는 모든 요소 arg1 매트와 arg2 (이웃 합) 개체를 합산한다. 나는 합계를 수행했지만 arctan 함수를 적용해야하므로 스칼라 유형이 적합하지 않습니다. 스칼라 유형을 기본 유형으로 변환하는 데 도움을 줄 수 있습니까?

실제로 내가 필터와 지금까지 수행 한 코드 가보 로그를 적용하기 위해 노력하고있어 것은 다음 OpenCV의 워드 프로세서에서

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

편집

:

합계
...
func 각 채널에 대해 배열 요소 합계 을 독립적으로 계산하여 반환합니다. 당신의 Sum1Sum2 스칼라 당신이 아크 탄젠트의 주요 값을 계산 atan(Sum1[0]/Sum2[0])를 사용하는 데 필요한에서 결과로 소벨 생성

출력 이미지는 하나 개의 채널 이진 이미지입니다. 당신이 다음 이미지에 가보 필터를 적용 할 경우 ... cv::filter2D()에 의해 처리 될 수있는 물건을 많이 수행하려고처럼

로그 - 가버 필터가 적용되어야로

잘못 ...

이 보이는

#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 필터, 그리고 난, 로그 - gabor 필터 ..... 조금 노력이 있지만, 많은 아이디어를 줄 것이다 ......하지만 여전히 float 같은 기본 형식으로 스칼라 형식으로 변환해야합니다. .... 당신이 나를 위해 그 방법을 제안 할 수 있습니까 ??? – bistaumanga

+0

제 편집을보세요. 희망이 맞네 – dom

23

내가

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

고마워. 당신의 대답은 많은 도움이되었습니다. –

1
사용 : 나는 here을 발견 이것 좀 걸릴스칼라는 Vec에서 파생 된 복소수의 4 요소 벡터입니다. 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];