Can anyone help me in converting scalar type of openCV to basic types like float or double?
Scalar Sum1=sum(arg1),Sum2=sum(arg2);
theta.at<float>(i,j)=0.5*atan(Sum1/Sum2);
I have to sum all elements of Mat objects arg1
and arg2
(neighbourhood sum), then I have to perform their division to find orientation field at each pixels. I performed sum, but since I have to apply arctan function, scalar type does not fit. Can anyone help me in converting scalar type to basic types?
actually I'm trying to apply log-gabor filter and the code I've done so far is:
//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);
}
}
I use
double s;
s = sum(arg1)[0];
EDIT
From the OpenCV docs:
sum
...
The functions sum calculate and return the sum of array elements, independently for each channel.
The output images which Sobel generates are binary images with one channel, as your Sum1
and Sum2
Scalars result out of the you need to use atan(Sum1[0]/Sum2[0])
to compute principal value of the arc tangent.
WRONG as Log-Gabor filter should be applied …
Looks like you try to do a lot of stuff, which could be handled by cv::filter2D()
… If you want to apply a Gabor filter to your image then take a look at this, which I found 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;
}
Scalar is a 4-element vector of doubles derived from Vec, as shown in the opencv documentation (http://docs.opencv.org/2.4.9/modules/core/doc/basic_structures.html#scalar)
The function cv::sum sums the elements from each channel separately, if the matrix has more than one channel, and stores them on the Scalar Vec. Therefore, to access the doubles for each channel you must access the positions on the vector. (documentation: 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];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With