Access multidimensional Mat range OpenCV - opencv

I have a 3x3x1000 OpenCV Mat matrix created using
int sz[] = {3,3,1000};
Mat bigCube(3, sz, CV_8U);
I want to do matrix operations on the 1000 separate 3x3 sub-matrices. But I can not find a way to do this.
The most obvious would be in a for-loop using Range, something like;
bigCube(Range(0,3),Range(0,3),Range(i,i+1));
//Do some operations...
But this won't compile. Is there a way to do this?

Related

How to convert a Mat (OpenCV) to INDArray (DL4J)?

I have a keras network model that takes INDArray but I don't know how to convert a Mat to an INDArray. I know that this is the same question of How to convert Mat (opencv) to INDArray (DL4J)? but it did not help me. Is there some API that performs this task? Thanks
You can use a NativeImageLoader for the conversion.
import org.datavec.image.loader.NativeImageLoader;
(...)
Mat cvImage();
// Fill in your Mat with something
NativeImageLoader nil = new NativeImageLoader();
INDArray image = nil.asMatrix(cvImage).div;
Make sure you have the dependency for datavec in your pom.xml. What error do you get?

How to transfer KeyPointVector to Mat in javaCV

I want to make an calcOpticalFlowPyrLK from feature points get from image, when I use goodFeaturesToTrack, everything is OK as following:
goodFeaturesToTrack(blackOutImagePrev, prevCorners, 200, 0.04, 30);
calcOpticalFlowPyrLK(blackOutImagePrev, blackOutImageNext, prevCorners, nextCorners, status, err);
Due to the processing speed issue, I want to change the function that I get feature points to surf or fast method. For the surf, the function is:
final KeyPointVector kp = new KeyPointVector();
final SURF surf = SURF.create(2500, 4, 2, true, false);
surf.detect(image, kp);
Since the surf get feature points are stored in KeyPointVector, but the type of prevCorners is Mat. How could I transfer it to Mat so I can call the calcOpticalFlowPyrLK? Or there is any workaround?
Looks like a KeyPointVector is just a vector of KeyPoints. The KeyPoints type has the pt() method which will return a Point2f which you can construct a Mat with. So create the new Mat, and loop through the keypoints vector, get the points with pt() and insert.

Conversion between cv::Mat and arma::mat

I am using OpenCV and also want to add some of cool functions from mlpack, which is using Armadillo matrices.
Is there an easy way to convet between cv::Mat and arms::mat?
Thanks!
OpenCV's Mat has a pointer to its data. Armadillo has a constructor that is capable of reading from external data. It's easy to put them together. Remember that Armadillo stores in column-major order, whereas OpenCV uses row-major. I suppose you'll need to add another step for transformation, before or after.
cv::Mat opencv_mat; //opencv's mat, already transposed.
arma::mat arma_mat( reinterpret_cast<double*>opencv_mat.data, opencv_mat.rows, opencv_mat.cols )
The cv::Mat constructor has a form that accepts pointer to data, and arma::mat has a function for a double* pointer to its data called memptr().
So, if you'd like to convert from arma::mat to cv::Mat, this should work:
cv::Mat opencv_mat( rows, cols, CV_64FC1, arma_mat.memptr() )

Multiple single channel matrix converted to single multi channel matrix

i am working in opencv c++ api with matrices
I have 4 single channel Mat that i will like to merge into one 4 channel matrix. It is basically the rgba channels i have in 4 matrices and want to combine into one rgba image/matrix. Anyone who knows how to do that?
You can use cv::merge to do what you want. One possible usage:
cv::Mat r,g,b,a;
//Fill r,g,b,a with data
cv::Mat result;
std::vector<cv::Mat> channels;
channels.push_back(r);
channels.push_back(g);
channels.push_back(b);
channels.push_back(a);
cv::merge(channels, result);

Extracting HoG Features using OpenCV

I am trying to extract features using OpenCV's HoG API, however I can't seem to find the API that allow me to do that.
What I am trying to do is to extract features using HoG from all my dataset (a set number of positive and negative images), then train my own SVM.
I peeked into HoG.cpp under OpenCV, and it didn't help. All the codes are buried within complexities and the need to cater for different hardwares (e.g. Intel's IPP)
My question is:
Is there any API from OpenCV that I can use to extract all those features / descriptors to be fed into a SVM ? If there's how can I use it to train my own SVM ?
If there isn't, are there any existing libraries out there, which could accomplish the same thing ?
So far, I am actually porting an existing library (http://hogprocessing.altervista.org/) from Processing (Java) to C++, but it's still very slow, with detection taking around at least 16 seconds
Has anyone else successfully to extract HoG features, how did you go around it ? And do you have any open source codes which I could use ?
Thanks in advance
You can use hog class in opencv as follows
HOGDescriptor hog;
vector<float> ders;
vector<Point> locs;
This function computes the hog features for you
hog.compute(grayImg, ders, Size(32, 32), Size(0, 0), locs);
The HOG features computed for grayImg are stored in ders vector to make it into a matrix, which can be used later for training.
Mat Hogfeat(ders.size(), 1, CV_32FC1);
for(int i=0;i<ders.size();i++)
Hogfeat.at<float>(i,0)=ders.at(i);
Now your HOG features are stored in Hogfeat matrix.
You can also set the window size, cell size and block size by using object hog as follows:
hog.blockSize = 16;
hog.cellSize = 4;
hog.blockStride = 8;
// This is for comparing the HOG features of two images without using any SVM
// (It is not an efficient way but useful when you want to compare only few or two images)
// Simple distance
// Consider you have two HOG feature vectors for two images Hogfeat1 and Hogfeat2 and those are same size.
double distance = 0;
for(int i = 0; i < Hogfeat.rows; i++)
distance += abs(Hogfeat.at<float>(i, 0) - Hogfeat.at<float>(i, 0));
if (distance < Threshold)
cout<<"Two images are of same class"<<endl;
else
cout<<"Two images are of different class"<<endl;
Hope it is useful :)
I also wrote the program of 2 hog feature comparing with the help of the above article.
And I apply this method to check ROI region changing or not.
Please refer to the page here.
source code and simple introduction
Here is GPU version as well.
cv::Mat temp;
gpu::GpuMat gpu_img, descriptors;
cv::gpu::HOGDescriptor gpu_hog(win_size, Size(16, 16), Size(8, 8), Size(8, 8), 9,
cv::gpu::HOGDescriptor::DEFAULT_WIN_SIGMA, 0.2, gamma_corr,
cv::gpu::HOGDescriptor::DEFAULT_NLEVELS);
gpu_img.upload(img);
gpu_hog.getDescriptors(gpu_img, win_stride, descriptors, cv::gpu::HOGDescriptor::DESCR_FORMAT_ROW_BY_ROW);
descriptors.download(temp);
OpenCV 3 provides some changes to the way GPU algorithms (i.e. CUDA) can be used by the user, see the Transition Guide - CUDA.
To update the answer from user3398689 to OpenCV 3, here is a snipped code:
#include <opencv2/core/cuda.hpp>
#include <opencv2/cudaimgproc.hpp>
[...]
/* Suppose you load an image in a cv::Mat variable called 'src' */
int img_width = 320;
int img_height = 240;
int block_size = 16;
int bin_number = 9;
cv::Ptr<cv::cuda::HOG> cuda_hog = cuda::HOG::create(Size(img_width, img_height),
Size(block_size, block_size),
Size(block_size/2, block_size/2),
Size(block_size/2, block_size/2),
bin_number);
/* The following commands are optional: default values applies */
cuda_hog->setDescriptorFormat(cuda::HOG::DESCR_FORMAT_COL_BY_COL);
cuda_hog->setGammaCorrection(true);
cuda_hog->setWinStride(Size(img_width_, img_height_));
cv::cuda::GpuMat image;
cv::cuda::GpuMat descriptor;
image.upload(src);
/* May not apply to you */
/* CUDA HOG works with intensity (1 channel) or BGRA (4 channels) images */
/* The next function call convert a standard BGR image to BGRA using the GPU */
cv::cuda::GpuMat image_alpha;
cuda::cvtColor(image, image_alpha, COLOR_BGR2BGRA, 4);
cuda_hog->compute(image_alpha, descriptor);
cv::Mat dst;
image_alpha.download(dst);
You can then use the descriptors in 'dst' variable as you prefer like, e.g., as suggested by G453.

Resources