How to filter a single column mat with Gaussian in OpenCV - c++

I have mat with only one column and 1600 rows. I want to filter it using a Gaussian.
I tried the following:
Mat AFilt=Mat(palm_contour.size(),1,CV_32F);
GaussianBlur(A,AFilt,cv::Size(20,1),3);
But I get the exact same values in AFilt (the filtered mat) and A. It looks like GaussianBlur has done nothing.
What's the problem here? How can I smooth a single-column mat with a Gaussian kernel?
I read about BaseColumnFilt, but haven't seen any usage examples so I'm not sure how to use them.
Any help given will be greatly appreciated as I don't have a clue.
I'm working with OpenCV 2.4.5 on windows 8 using Visual Studio 2012.
Thanks
Gil.

You have a single column but you are specifying the width of the gaussian to be big instead of specifying the height! OpenCV use row,col or x,y notation depending on the context. A general rule is whenever you use Point or Size, they behave like x,y and whenever the parameters are separate values they behave like row,col.
The kernel size should also be odd. If you specify the kernel size you can set sigma to zero to let OpenCV compute a suitable sigma value.
To conclude, this should work better:
GaussianBlur(A,AFilt,cv::Size(1,21),0);

The documentation og GaussianBlur says the kernel size must be odd, I would try using an odd size kernel and see if that makes any difference

Related

The meaning of sigma_s and sigma_r in detailEnhance function on OpenCV

The detailEnhance function provided by openCV have parameters InputArray, OutputArray, sigma_s and sigma_r. What does sigma s and r mean and what is it used for?
Here is the source: http://docs.opencv.org/3.0-beta/modules/photo/doc/npr.html#detailenhance
Thank you in advance.
sigma_s controls how much the image is smoothed - the larger its value, the more smoothed the image gets, but it's also slower to compute.
sigma_r is important if you want to preserve edges while smoothing the image. Small sigma_r results in only very similar colors to be averaged (i.e. smoothed), while colors that differ much will stay intact.
See also: https://www.learnopencv.com/non-photorealistic-rendering-using-opencv-python-c/

Adaptive bilateral filter in opencv python2.7 implimentation

I want to use adaptive bilateral filter in python using opencv. But I am not able to understand how to put the parameters or what should be the values. This is what I found in OpenCV 2.4 documentation.
cv2.adaptiveBilateralFilter(src, ksize, sigmaSpace[, dst[, maxSigmaColor[, anchor[, borderType]]]])
Can anybody give me example for implementation of this function?
Read this - https://arxiv.org/pdf/1811.02308.pdf
It has the math of adaptive bilateral filter. Let me know if you need help.
The kernel size is used for the local variance calculation, and where pixels will contribute (in a weighted manner).
sigmaSpace filters sigma in the coordinate space. The larger value of the parameter means that farther pixels will influence each other
For Example:
img = cv2.bilateralFilter(image, 20, 5)

Refining Camera parameters and calculating errors - OpenCV

I've been trying to refine my camera parameters with CvLevMarq but after reading about it, it seems to be causing mixed results - which is exactly what I am experiencing. I read about the alternatives and came upon EIGEN - and also found this library that utilizes it.
However, the library above seems to use a stitching class that doesn't support OpenCV and will probably require me to port it to OpenCV.
Before going ahead and doing so, which will probably not be an easy task, I figured I'd ask around first and see if anyone else had the same problem?
I'm currently using:
1. Calculating features with FASTFeatureDetector
Ptr<FeatureDetector> detector = new FastFeatureDetector(5,true);
detector->detect(firstGreyImage, features_global[firstImageIndex].keypoints); // Previous picture
detector->detect(secondGreyImage, features_global[secondImageIndex].keypoints); // New picture
2. Extracting features with SIFTDescriptorExtractor
Ptr<SiftDescriptorExtractor> extractor = new SiftDescriptorExtractor();
extractor->compute(firstGreyImage, features_global[firstImageIndex].keypoints, features_global[firstImageIndex].descriptors); // Previous Picture
extractor->compute(secondGreyImage, features_global[secondImageIndex].keypoints, features_global[secondImageIndex].descriptors); // New Picture
3. Matching features with BestOf2NearestMatcher
vector<MatchesInfo> pairwise_matches;
BestOf2NearestMatcher matcher(try_use_gpu, 0.50f);
matcher(features_global, pairwise_matches);
matcher.collectGarbage();
4. CameraParams.R quaternion passed from a device (slightly inaccurate which causes the issue)
5. CameraParams.Focal == 389.0f -- Played around with this value, 389.0f is the only value that matches the images horizontally but not vertically.
6. Bundle Adjustment (cvLevMarq, calcError & calcJacobian)
Ptr<BPRefiner> adjuster = new BPRefiner();
adjuster->setConfThresh(0.80f);
adjuster->setMaxIterations(5);
(*adjuster)(features,pairwise_matches,cameras);
7. ExposureCompensator (GAIN)
8. OpenCV MultiBand Blender
What works so far:
SeamFinder - works to some extent but it depends on the result of the cvLevMarq algoritm. I.e. if the algoritm is off, seamFinder is going to be off too.
HomographyBasedEstimator works beautifully. However, since it "relies" on the features, it's unfortunately not the method that I'm looking for.
I wouldn't want to rely on the features since I already have the matrix, if there's a way to "refine" the current matrix instead - then that would be the targeted result.
Results so far:
cvLevMarq "Russian roulette" 6/10:
This is what I'm trying to achieve 10/10 times. But 4/10 times, it looks like the picture below this one.
By simply just re-running the algorithm, the results change. 4/10 times it looks like this (or worse):
cvLevMarq "Russian roulette" 4/10:
Desired Result:
I'd like to "refine" my camera parameters with the features that I've matched - in hope that the images would align perfectly. Instead of hoping that cvLevMarq will do the job for me (which it won't 4/10 times), is there another way to ensure that the images will be aligned?
Update:
I've tried these versions:
OpenCV 3.1: Using CVLevMarq with 3.1 is like playing Russian roulette. Some times it can align them perfectly, and other times it estimates focal as NAN which causes segfault in the MultiBand Blender (ROI = 0,0,1,1 because of NAN)
OpenCV 2.4.9/2.4.13: Using CvLevMarq with 2.4.9 or 2.4.13 is unfortunately the same thing minus the NAN issue. 6/10 times it can align the images perfectly, but the other 4 times it's completely off.
My Speculations / Thoughts:
Template Matching using OpenCV. Maybe if I template match the ends of the images (i.e. x = 0, y = 0,height = image.height, width = 50). Any thoughts about this?
I found this interesting paper about Levenberg Marquardt applied in Homography. That looks like something that could solve my problem since the paper uses corner detection and whatnot to detect the features in the images. Any thoughts about this?
Maybe the problem isn't in CvLevMarq but instead in BestOf2NearestMatcher? However, I've searched for days and I couldn't find another method that returns the pairwise matches to pass to BPRefiner.
Hough Line Transform Detecting the lines in the first/second image and use that to align the images. Any thoughts on this? -- One thing might be, what if the images doesn't have any lines? I.e. empty wall?
Maybe I'm overkilling something so simple.. Or maybe I'm not? Basically, I'm trying to align a set of images so I can warp them without overlapping each-other. Drop a comment if it doesn't make sense :)
Update Aug 12:
After trying all kinds of combinations, the absolute best so far is CvLevMarq. The only problem with it is the mixed results shown in the images above. If anyone has any input, I'd be forever grateful.
It seems your parameter initialization is the problem. I would use a linear estimator first, i.e. ignore your noisy sensor, and then use this as the initial values for the non-linear optimizer.
A quick method is to use getaffinetransform, as you have mostly rotation.
Maybe you want to take a look at this library: https://github.com/ethz-asl/kalibr.
Cheers
If you want to stitch the images, you should see stitching_detailed.cpp. It will probably solve your problem.
In addition, I have used Graph Cut Seam Finding method with Canny Edge Detection for better stitching results in this code. If you want to optimize this code, see here.
Also, if you are going to use it for personal use, SIFT is good. You should know, SIFT is patented and will cost you if you use it for commercial purposes. Use ORB instead.
Hope it helps!

OpenCV OCL logical indexing

I am working on an algorithm with many computations done on a GPU. I'm working mainly with oclMat structures and am trying to avoid copying from CPU to GPU and vice versa, yet I cannot find an easy way to:
compare all elements in an ocl matrix to a specific single value (be it float or double, for instance) and create a logical matrix in accordance
create an oclMat matrix with a given size and type initialized with all elements to a specific value (for example all elements are float and equal to 1.234567)
For example:
cv::ocl::oclMat M1 =...
// DO STUFF WITH M1
cv::ocl::oclMat logicalM1 = M1>1.55; // compare directly to a single value
cv::ocl::oclMat logicalM2 = ... ; // i.e. I want a 100x100 CV_32FC1 matrix with all elements set to be equal to 1.234567
By reading the documentation, it seems using cv::ocl::compare only works with both matrices the same dimensions and type, so maybe my first request isn't feasible. On the other hand, I don't know how to initialize a specific matrix directly in ocl (with cv::Mat I know how it's done).
I assume an easy workaround exists, but haven't found one yet... Thanks!
You are right. Looks like cv::ocl::compare supports only two cv::oclMat on input.
But you can create oclMat filled with specific value as follows:
cv::ocl::oclMat logicalM2(M1.size(), M1.type);
logicalM2.setTo(cv::Scalar(1.234567));
cv::ocl::oclMat logicalM1;
cv::ocl::compare(M1, logicalM2, logicalM1, cv::CMP_GT);
P.S. Also I suggest you trying new OpenCV 3.0 with Transparent-API which makes processing on GPU using OpenCL much easier.

How to create a depth map from PointGrey BumbleBee2 stereo camera using Triclops and FlyCapture SDKs?

I've got the BumbleBee 2 stereo camera and two mentioned SDKs.
I've managed to capture a video from it in my program, rectify stereo images and get a disparity map. Next thing I'd like to have is a depth map similar to one, the Kinect gives.
The Triclops' documentation is rather short, it only references functions, without typical workflow description. The workflow is described in examples.
Up to now I've found 2 relevant functions: family of triclopsRCDxxToXYZ() functions and triclopsExtractImage3d() function.
Functions from the first family calculate x, y and z coordinate for a single pixel. Z coordinate perfectly corresponds to the depth in meters. However, to use this function I should create two nested loops, as shown in the stereo3dpoints example. That gives too much overhead, because each call returns two more coordinates.
The second function, triclopsExtractImage3d(), always returns error TriclopsErrorInvalidParameter. The documentation says only that "there is a geometry mismatch between the context and the TriclopsImage3d", which is not clear for me.
Examples of Triclops 3.3.1 SDK do not show how to use it. Google brings example from Triclops SDK 3.2, which is absent in 3.3.1.
I've tried adding lines 253-273 from the link above to current stereo3dpoints - got that error.
Does anyone have an experience with it?
Is it valid to use triclopsExtractImage3d() or is it obsolete?
I also tried plotting values of disparity vs. z, obtained from triclopsRCDxxToXYZ().
The plot shows almost exact inverse proportionality: .
That is z = k / disparity. But k is not constant across the image, it varies from approximately 2.5e-5 to 1.4e-3, that is two orders of magnitude. Therefore, it is incorrect to calculate this value once and use forever.
Maybe it is a bit to late and you figured it out by yourself but:
To use triclopsExtractImage3d you have to create a 3dImage first.
TriclopsImage3d *depthImage;
triclopsCreateImage3d(triclopsContext, &depthImage);
triclopsExtractImage3d(triclopsContext, depthImage);
triclopsDestroyImage3d(&depthImage);