How to fill the tensor in tensorflow c++? - c++

I am loading the .pb file in tensorflow c++. Now I need to fill the input tensor with my data and get the output tensors.
To fill data, I am using below code:
tensorflow::Tensor points_tensor{tensorflow::DataType::DT_FLOAT, tensorflow::TensorShape({number_of_points,4})};
auto pointsMapped = points_tensor.tensor<float, 2>();
for(int i=0; i<number_of_points; i++){
//to the shifting here only
pointsMapped(i,0) = point_cloud.points[i].x;
pointsMapped(i,1) = point_cloud.points[i].y;
pointsMapped(i,2) = point_cloud.points[i].z;
pointsMapped(i,3) = point_cloud.points[i].intensity;
}
point_cloud is a vector of point object.
But I do not think so, it is better way to do it in c++. Because I need to access my tensor shape so.
Can someone help me with this?

Actually The above mentioned method is the better way to fill the tensor in tensorflow

Related

Giving a vector of pixels as input to tensorflow

I am using Tensorflow for a image classification problem in C++.
I created the graph and tried using the example code here.
When I give an image (.jpeg) as the input to the main function (for string image in the main function) it works fine. But I have the pixel values of an image (luminance values only) in a 2d vector std::vector<std::vector<int>> vec2d. How can I give this vector as input for making a prediction?
I got a tensor created as follows, but I cannot figure out how to fit that to the existing code.
tensorflow::Tensor input(tensorflow::DT_FLOAT,
tensorflow::TensorShape({32, 32}));
auto input_map = input.tensor<float, 2>();
for (int b = 0; b < 32; b++) {
for (int c = 0; c < 32; c++) {
input_map(b, c) = (vec2d)[b][c];
}
}
Or is there an inbuilt way to pass pixel values in tensorflow?
I do not want to create an image with the pixel values and re-read it. I already did and it works but it takes time for file read/write operations and time is very crucial in my system.

How to slice or acces a row of a Tensor?

I have a dataset stored in a 3D Tensor. I'd like to have an own tensor per each sample for profiling purposes. Unfortunately I only know the brute force method of accessing such a container:
auto tensor_dataset_map = dataset.tensor<float,3>();
for(int sample = 0; sample < maxSamples; sample++)
for(int time = 0; time < periodSize; time++)
for(int feature = 0; feature < amountOfFeatures; feature++)
cout << tensor_dataset_map(sample,time,feature);
I would love to avoid this. However if I try with common sense to get all elements for the first sample (=0):
tensor_dataset_map(0)
it is the same like
tensor_dataset_map(0,0,0)
which is of shape (1) and I need tensors of shape (1,periodSize,amountOfFeatures)
Is there an easy way for this I do I really have to go this unoptimized way?
I found an answer in the source code. Each Tensor has the function Slice(): Slice this tensor along the 1st dimension. where one needs to state the parameters begin of slicing and offset.
In other words for iterating in my case one needs to:
cout<<dataset.Slice(0,1).tensor<float,3>()<<endl
cout<<dataset.Slice(1,2).tensor<float,3>()<<endl
cout<<dataset.Slice(2,3).tensor<float,3>()<<endl
cout<<dataset.Slice(3,4).tensor<float,3>()<<endl
...
But because the lack of other documentation I think this might get deprecated

HOG Descriptor Vector layout and how to save them to text file

I am new to open CV so currently struggling with it. I have extracted HOG features using following definition:
HOGDescriptor hog(Size(16,16), Size(16,16), Size(16,16), Size(8,8), 9);
It returns 36 dimensional feature vector / pixel. Now I want to separate all these 36 values in a row and save it in text file. I don't know how to do it. Please do guide me.
Thanks in advance.
After you compute the features, i.e. descriptors by cv::HOGDescriptor::compute, it's a vector<float>, so just access it like normal vector<float>s.
And if you want to split them into 36-by-36 style, you can do like this:
for (int i=0; i<descriptors.size()/36; i++)
{
// ... handle 36 values here
for (int j=0; j<36; j++)
{
if (36*i+j < descriptors.size()) // make sure not out-of-bound
{
float temp = descriptors[36*i+j];
...
}
}
}

Sending a matrix with each iteration: Matlab "engine.h" c++

This question comes after solving the problem I got in this question. I have a c++ code that processes frames from a camera and generates a matrix for each processed frame. I want to send to matlab engine each matrix, so at the end of the execution I have in stored all the matrices.
I am conffused about how to do this, I send a matrix in each iteration but it is overwritting it all the time, so at the end I only have one. Here is a code example:
matrix.cpp
#include helper.h
mxArray *mat;
mat = mxCreateDoubleMatrix(13, 13, mxREAL);
memcpy(mxGetPr(mat),matrix.data, 13*13*sizeof(double));
engPutVariable(engine, "mat", mat);
I also tried to use a counter to dinamically name the different matrices, but it didn't work as matlab engine requires the variables to be defined first. Any help will be appreciated. Thanks.
You can create a cell array in matlab workspace like this:
mwSize size = 10;
mxArray* cell = mxCreateCellArray(1, &size);
for(size_t i=0;i<10;i++)
{
mxArray *mat;
mat = mxCreateDoubleMatrix(13, 13, mxREAL);
memcpy(mxGetPr(mat),matrix.data, 13*13*sizeof(double));
mwIndex subscript = i;
int index = mxCalcSingleSubscript(cell , 1,&subscript);
mxSetCell(m_cell , index, mat);
}
engPutVariable(engine, "myCell", cell);
If you don't know the number of frames a priori, don't try to expand the mxArray in C. It is not convenient. You were already close to start. All your problems can be solved with:
engEvalString(engine, "your command here")
Read more here.
The simplest approach is something like:
engPutVariable(engine, "mat", mat);
engEvalString("frames{length(frames)+1} = mat;");
Don't do it exactly that, it is an illustration and will be very slow. Much better to preallocate, say 1000 frames then expand it another 1000 (or a more appropriate number) when needed. Even better is to not use cell arrays which are slow. Instead you could use a 3D array, such as:
frames = zeros(13,13,1000);
frames(:,:,i) = mat;
i = i + 1;
Again, preallocate in blocks. You get the idea. If you really need to be fast, you could build the 3D arrays in C and ship them to MATLAB when they fill.
Maybe you can use vector<mxArray> from stdlib.

OpenCV 1.1 K-Means Clustering in High Dimensional Spaces

I am trying to write a bag of features system image recognition system. One step in the algorithm is to take a larger number of small image patches (say 7x7 or 11x11 pixels) and try to cluster them into groups that look similar. I get my patches from an image, turn them into gray-scale floating point image patches, and then try to get cvKMeans2 to cluster them for me. I think I am having problems formatting the input data such that KMeans2 returns coherent results. I have used KMeans for 2D and 3D clustering before but 49D clustering seems to be a different beast.
I keep getting garbage values for the returned clusters vector, so obviously this is a garbage in / garbage out type problem. Additionally the algorithm runs way faster than I think it should for such a huge data set.
In the code below the straight memcpy is only my latest attempt at getting the input data in the correct format, I spent a while using the built in OpenCV functions, but this is difficult when your base type is CV_32FC(49).
Can OpenCV 1.1's KMeans algorithm support this sort of high dimensional analysis?
Does someone know the correct method of copying from images to the K-Means input matrix?
Can someone point me to a free, Non-GPL KMeans algorithm I can use instead?
This isn't the best code as I am just trying to get things to work right now:
std::vector<int> DoKMeans(std::vector<IplImage *>& chunks){
// the size of one image patch, CELL_SIZE = 7
int chunk_size = CELL_SIZE*CELL_SIZE*sizeof(float);
// create the input data, CV_32FC(49) is 7x7 float object (I think)
CvMat* data = cvCreateMat(chunks.size(),1,CV_32FC(49) );
// Create a temporary vector to hold our data
// we'll copy into the matrix for KMeans
int rdsize = chunks.size()*CELL_SIZE*CELL_SIZE;
float * rawdata = new float[rdsize];
// Go through each image chunk and copy the
// pixel values into the raw data array.
vector<IplImage*>::iterator iter;
int k = 0;
for( iter = chunks.begin(); iter != chunks.end(); ++iter )
{
for( int i =0; i < CELL_SIZE; i++)
{
for( int j=0; j < CELL_SIZE; j++)
{
CvScalar val;
val = cvGet2D(*iter,i,j);
rawdata[k] = (float)val.val[0];
k++;
}
}
}
// Copy the data into the CvMat for KMeans
// I have tried various methods, but this is just the latest.
memcpy( data->data.ptr,rawdata,rdsize*sizeof(float));
// Create the output array
CvMat* results = cvCreateMat(chunks.size(),1,CV_32SC1);
// Do KMeans
int r = cvKMeans2(data, 128,results, cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 1000, 0.1));
// Copy the grouping information to our output vector
vector<int> retVal;
for( int y = 0; y < chunks.size(); y++ )
{
CvScalar cvs = cvGet1D(results, y);
int g = (int)cvs.val[0];
retVal.push_back(g);
}
return retVal;}
Thanks in advance!
Though I'm not familiar with "bag of features", have you considered using feature points like corner detectors and SIFT?
You might like to check out http://bonsai.ims.u-tokyo.ac.jp/~mdehoon/software/cluster/ for another open source clustering package.
Using memcpy like this seems suspect, because when you do:
int rdsize = chunks.size()*CELL_SIZE*CELL_SIZE;
If CELL_SIZE and chunks.size() are very large you are creating something large in rdsize. If this is bigger than the largest storable integer you may have a problem.
Are you wanting to change "chunks" in this function?
I'm guessing that you don't as this is a K-means problem.
So try passing by reference to const here. (And generally speaking this is what you will want to be doing)
so instead of:
std::vector<int> DoKMeans(std::vector<IplImage *>& chunks)
it would be:
std::vector<int> DoKMeans(const std::vector<IplImage *>& chunks)
Also in this case it is better to use static_cast than the old c style casts. (for example static_cast(variable) as opposed to (float)variable ).
Also you may want to delete "rawdata":
float * rawdata = new float[rdsize];
can be deleted with:
delete[] rawdata;
otherwise you may be leaking memory here.