Converting MATLAB Code to OpenCV C++ - c++

I'm new to OpenCV and trying to convert the following MATLAB code to OpenCV using C++:
[FX,FY]=gradient(mycell{index});
I have tried the following so far but my values are completely different from my MATLAB results
Mat abs_FXR;
Mat abs_FYR;
int scale = 1;
int delta = 0;
// Gradient X
Sobel(myImg, FXR, CV_64F, 1, 0, 3, scale, delta, BORDER_DEFAULT);
convertScaleAbs( FXR, abs_FXR );
imshow( window_name2, abs_FXR );
// Gradient Y
Sobel(myImg, FYR, CV_64F, 0, 1, 3, scale, delta, BORDER_DEFAULT);
convertScaleAbs( FYR, abs_FYR );
imshow( window_name3, abs_FYR );
I also tried using filter2D as per this question, but it still gave different results: Matlab gradient equivalent in opencv
Mat kernelx = (Mat_<float>(1,3)<<-0.5, 0, 0.5);
Mat kernely = (Mat_<float>(3,1)<<-0.5, 0, 0.5);
filter2D(myImg, FXR, -1, kernelx);
filter2D(myImg, FYR, -1, kernely);
imshow( window_name2, FXR );
imshow( window_name3, FYR );
I don't know if this is way off track or if it's just a parameter I need to change. Any help would be appreciated.
UPDATE
Here is my expected output from MATLAB:
But here is what I'm getting from OpenCV using Sobel:
And here is my output from OpenCV using the Filter2D method (I have tried increasing the size of my gaussian filter but still get different results compared to MATLAB)
I have also converted my image to double precision using:
eye_rtp.convertTo(eye_rt,CV_64F);

It is correct that you need to do a central difference computation instead of using the Sobel filter (although Sobel does give a nice derivative) in order to match gradient. BTW, if you have the Image Processing Toolbox, imgradient and imgradientxy have the option of using Sobel to compute the gradient. (Note that the answer in the question you referenced is wrong that Sobel only provides a second derivative, as there are first and second order Sobel operators available).
Regarding the differences you are seeing, you may need to convert myImg to float or double before filter2D. Check the output type of FXL, etc.
Also, double precision is CV_64F and single precision is CV_32F, although this will probably only cause very small differences in this case.

Related

Accessing elements of cv::Mat OpenCV

I'm trying to apply derivative based color constancy on images and I'm using opencv in c++ to do so.
I'm using Sobel derivatives to calculate my gradients but I don't know what I should cast pixel values of gradient image to in order to be able to read and change them.
Sobel( gradr1, gradr1, gradr1.depth(), 1, 0, 3, 1, 0, BORDER_DEFAULT );
gradr1.at<char>(i,j)
What should I use instead of char?

OpenCV equivalent for thresholding in MATLAB

I want to implement this MATLAB statement in OpenCV C++:
bwImgLabeled(bwImgLabeled > 0) = 1;
As far as I understand from then OpenCV docs, http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html?highlight=threshold#threshold,
I need to do:
cv::threshold(dst, dst, 0, 1, CV_THRESH_BINARY);
Am I correct here?
Yes you are correct. What the MATLAB code is doing is that it searches for any pixels that are non-zero and sets them to 1.
Recall the definition of cv::threshold:
double threshold(InputArray src, OutputArray dst,
double thresh, double maxval, int type)
So the first two inputs are the source and destination images, where in your case, you want to take the destination image and mutate it to contain the final image. thresh = 0 and maxval = 1, with type=CV_THRESH_BINARY. Recall when using the CV_THRESH_BINARY, the following relationship occurs:
(source: opencv.org)
Therefore, if you specify thresh to be 0, maxval to be 1, you are effectively doing what the MATLAB code is doing. Any pixels that are greater than thresh=0, which are essentially non-zero, you set those intensities to 1. I'm assuming you want the input and output images to be floating-point, so make sure the image is of a compatible type, such as CV_32FC1, or CV_32FC3, and so on.

How to get cv::calcOpticalFlowSF to work?

I am useing the 2.4.4 version of OpenCV. - i know its a beta
but there is an example about cv::calcOpticalFlowSF the method in the example folder called: simpleflow_demo.cpp. But when i copy this demo and use it with my input images, it starts processing and after some seconds it came back a crash report.
The documentation about the method is a little bit strange, saying the output files are a x- and yflow instead of the cv::Mat& flow which the method actually wants.
Any ideas how to fix the problem to get the function working?
Try this simple demo that worked for me, then modify for your needs (display help from here):
Mat frame1 = imread("/home/radford/Desktop/1.png");
Mat frame2 = imread("/home/radford/Desktop/2.png");
namedWindow("flow");
Mat flow;
calcOpticalFlowSF(frame1, frame2, flow, 3, 2, 4);
Mat xy[2];
split(flow, xy);
//calculate angle and magnitude
Mat magnitude, angle;
cartToPolar(xy[0], xy[1], magnitude, angle, true);
//translate magnitude to range [0;1]
double mag_max;
minMaxLoc(magnitude, 0, &mag_max);
magnitude.convertTo(magnitude, -1, 1.0/mag_max);
//build hsv image
Mat _hsv[3], hsv;
_hsv[0] = angle;
_hsv[1] = Mat::ones(angle.size(), CV_32F);
_hsv[2] = magnitude;
merge(_hsv, 3, hsv);
//convert to BGR and show
Mat bgr;//CV_32FC3 matrix
cvtColor(hsv, bgr, COLOR_HSV2BGR);
imshow("flow", bgr);
waitKey(0);
In the example opencv/samples/cpp/simpleflow_demo.cpp there is a code block
if (frame1.type() != 16 || frame2.type() != 16) {
printf(APP_NAME "Images should be of equal type CV_8UC3\n");
exit(1);
}
So, grey images should be converted to CV_8UC3. For example using cvtColor(grey, grey3, CV_GRAY2RGB);

OpenCV: normalization is too slow or I am doing it in a wrong way?

I am trying to normalize one matrix in OpenCV, I am doing it like this:
cv::Mat matrix = cv::Mat::zeros ( 3, 480000, CV_8UC1 );
cv::Mat matrix_norm = cv::Mat::zeros ( 3, 480000, CV_8UC1 );
... // give values to matrix
I read the documentation for "normalize" function, but couldn't fully understand how to give values for "alpha" and "beta". So from the example:
http://docs.opencv.org/doc/tutorials/features2d/trackingmotion/harris_detector/harris_detector.html
I did it like:
cv::normalize ( matrix, matrix_norm, 0, 255, NORM_MINMAX, CV_8UC1, Mat() );
But it crashed here, which I don't surprise. I think the matrix size is too big, right? Or am I doing the normalization incorrectly here?
And is there any way to speed up the normalization?
It's always useful if you normalize your matrix by writing your own code. Using Histogram for normalising your matrix values help you customise the function.It is even faster than the normal noramlisation function provided by OpenCV.

histogram function in OpenCV

I am seeking a way to compare 2 images and get the most matching image as output.
Using histogram function in OpenCV can I do this?
Can anyone please help me?
But I dont know how to do it since I am not very much familiar with OpenCV.
Thank you.
The histogram will just ensure that the two images have similar color distributions. The color distributions could be similar in very different images.
As an example, imagine a black and white 8x8 checkboard and an image whose left side is all black and the ride side pure white. These images have the same histogram.
Both of these answers discuss histograms in OpenCV:
Horizontal Histogram in OpenCV
Horizontal Histogram in OpenCV
If your aim is to find the most matching image then OpenCV has a function cvMatchTemplate() which does this. Is does use histogram matching but it is not needed to declare anything else in the code. It is possible to find the portion of the image which corresponds best to the template being matched and other variations available in the documentation.
For every image calculate HSV histogram:
Mat src_mat = imread("./image.jpg");
Mat hsv_mat;
cvtColor( src_mat, hsv_mat, CV_BGR2HSV );
MatND HSV_histogram;
int histSize[] = { 240, 240 };
float h_ranges[] = { 0, 255 };
float s_ranges[] = { 0, 180 };
const float* ranges[] = { h_ranges, s_ranges };
int channels[] = { 0, 1 };
calcHist( &hsv_mat, 1, channels, Mat(), HSV_histogram, 2, histSize, ranges, true, false );
normalize( HSV_histogram, HSV_histogram, 0, 1, NORM_MINMAX, -1, Mat() );
Then make a pairwise comparison and get a similarity score:
double score_ij = compareHist( HSV_histogram_i, HSV_histogram_j, CV_COMP_BHATTACHARYYA );
You can increase your accuracy by dividing image in smaller regions and average the results.