There is any other way/trick to store the depth map in the database? Basically, we are trying to store 300000 double values. If it helps we can convert the array into a NSMutableArray or similar so that we can serialize it. I don’t know yet how to do it. I tried to find a way to convert it to a binary file instead of ASCII but no luck yet.
You can save a lot of memory by storing the raw binary data in a BLOB.
If you don't have fixed rows and cols of your matrix, you can put at the beginning of the file two integers for rows and cols.
I'll add a simple example on how to save and load the data of matrix, preceded by rows and cols.
#include <opencv2/opencv.hpp>
#include <fstream>
using namespace cv;
using namespace std;
int main()
{
Mat1d m = (Mat1d(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
Mat1d n;
{
ofstream ofs("test.bin", fstream::binary);
ofs.write((char*)&m.rows, sizeof(int)); // Save rows
ofs.write((char*)&m.cols, sizeof(int)); // Save cols
ofs.write((char*)m.data, m.total()*sizeof(double)); // Save data
}
{
ifstream ifs("test.bin", fstream::binary);
int rows, cols;
ifs.read((char*)&rows, sizeof(int)); // Load rows
ifs.read((char*)&cols, sizeof(int)); // Load cols
n = Mat1d(rows, cols); // Resize the matrix according to rows, cols
ifs.read((char*)n.data, rows*cols*sizeof(double)); // Load data
}
// Now m and n are equal
return 0;
}
If you need further compression you can read and write the stream using gzstream
Related
I am aware there are several ways to read and write a pixel value of an OpenCV cv::Mat image/matrix.
A common one is the .at<typename T>(int, int) method http://opencv.itseez.com/2.4/modules/core/doc/basic_structures.html#mat-at .
However, this requires the typename to be known, for instance .at<double>.
The same thing applies to more direct pointer access OpenCV get pixel channel value from Mat image .
How can I read a pixel value without knowing its type? For instance, it would be ok to receive a more generic CvScalar value in return. Efficiency is not an issue, as I would like to read rather small matrices.
Kind of. You can construct cv::Mat_ and provide explicit type for elements, after that you don't have to write element type each time. Quoting opencv2/core/mat.hpp
While Mat is sufficient in most cases, Mat_ can be more convenient if you use a lot of element
access operations and if you know matrix type at the compilation time. Note that
Mat::at(int y,int x) and Mat_::operator()(int y,int x) do absolutely the same
and run at the same speed, but the latter is certainly shorter.
Mat_ and Mat are very similar. Again quote from mat.hpp:
The class Mat_<_Tp> is a thin template wrapper on top of the Mat class. It does not have any
extra data fields. Nor this class nor Mat has any virtual methods. Thus, references or pointers to
these two classes can be freely but carefully converted one to another.
You can use it like this
Mat_<Vec3b> dummy(3,3);
dummy(1, 2)[0] = 10;
dummy(1, 2)[1] = 20;
dummy(1, 2)[2] = 30;
cout << dummy(1, 2) << endl;
Why I said 'kind of' in the first place? Because if you want to pass this Mat_ somewhere - you have to specify it's type. Like this:
void test(Mat_<Vec3b>& arr) {
arr(1, 2)[0] = 10;
arr(1, 2)[1] = 20;
arr(1, 2)[2] = 30;
cout << arr(1, 2) << endl;
}
...
Mat_<Vec3b> dummy(3,3);
test(dummy);
Technically, you are not specifying your type during a pixel read, but actually you still have to know it and cast the Mat to the appropriate type beforehand.
I guess you can find a way around this using some low-level hacks (for example make a method that reads Mat's type, calculates element size and stride, and then accesses raw data using pointer arithmetic and casting...). But I don't know any 'clean' way to do this using OpenCV's functionality.
If you already know the type, you can use Mat_<> type for easy access. If you don't know the type, you can:
convert the data to double, so data won't be truncated in any case
switch over the number of channels to access correctly the double matrix. Note that you can have at most of 4 channels, since Scalar has at most 4 elements.
The following code will convert only the selected element of the source matrix to a double value (with N channels).
You get a Scalar containing the value at position row, col in the source matrix.
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Scalar valueAt(const Mat& src, int row, int col)
{
Mat dst;;
src(Rect(col, row, 1, 1)).convertTo(dst, CV_64F);
switch (dst.channels())
{
case 1: return dst.at<double>(0);
case 2: return dst.at<Vec2d>(0);
case 3: return dst.at<Vec3d>(0);
case 4: return dst.at<Vec4d>(0);
}
return Scalar();
}
int main()
{
Mat m(3, 3, CV_32FC3); // You can use any type here
randu(m, Scalar(0, 0, 0, 0), Scalar(256, 256, 256, 256));
Scalar val = valueAt(m, 1, 2);
cout << val << endl;
return 0;
}
I would like to access and modify single entries in a non-contiguous submatrix view. I tried it like this:
#include <armadillo> // version 5.200.2
int main()
{
arma::mat A(4, 4, arma::fill::zeros);
arma::uvec b(4);
b << 2 << 3;
auto view = A.elem(b, b);
view(0, 0) = 1.0; // Error: No operator()
}
This doesn't work because the expression returned by A.elem(b, b) appears to have no operator() defined. I found that the same thing works with contiguous views like e.g. submat(). Is there any solution/workaround for this or is it simply not possible in the non-contiguous case?
I know how we use memset to set the contents of an array to a particular value. Now, I am interested in something that does the same for a given range.
scanf("%d %d",&a,&b);
//set the content from A[a] to A[b] as '0' without looping
I don't want to go through for loop. Please tell if there is some other and efficient method to achieve this.
Assigning values with memset works only with 2 values : 0 and -1,
Rest will only give garbage values
Still, Let me help you to use memset for a range.
I'm using an example to explain your query below:
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int main()
{
int a[10]; // Array of 10 elements with val of 0;
memset(a,0,sizeof(a));
// Sets all array elements to 0
memset(a+2,-1,sizeof(int)*5);
// Sets value of array elements from 2 to 6 index equals to -1
for(int i=0;i<10;i++)
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
Output: 0 0 -1 -1 -1 -1 -1 0 0 0
* I've checked the code on various IDE's before posting. Hope it helps a bit!
I have the following code:
//newImg is a mat of an image and orderedKeyPoint is the result from Fast
cv::FREAK extractor;
cv::Mat queryDescriptors;
extractor.compute(newImg, orderedKeyPoint, queryDescriptors);
I am trying to access individual freak descriptors using queryDescriptors.at< ???>(r,0) where r is an arbitrary valid row value but I am not sure of the type. All documentation states that it is just a descriptor, but is that of type Mat or double or something else? Is this the best way of doing it?
cv::Mat descriptor2 = queryDescriptors.at<cv::Mat>(2,0);
I would like to be able to reconstruct queryDescriptors (Mat of descriptors) from individual descriptors by taking them and putting them in the row values of a cv::Mat, ex:
queryDescriptors.at<cv::Mat>(2,0) = descriptor2;
Any help or insight would be greatly appreciated,
Isaac
the FREAK descriptor is a uchar Mat with 64 cols and numkeypoints rows.
so, to get to an element of it:
uchar elm = descriptor.at<uchar>(row,col);
where row is the keypoint id, and col is the element id.
If you have a look into \opencv\modules\features2d\src\freak.cpp you can see:
int FREAK::descriptorSize() const
{
return FREAK_NB_PAIRS / 8; // descriptor length in bytes
}
int FREAK::descriptorType() const
{
return CV_8U;
}
int FREAK::defaultNorm() const
{
return NORM_HAMMING;
}
} // END NAMESPACE CV
So uchar seems to be the type as berak already suggested.
Presently Iam working in finding disparity of stereo pair. I have got a situation in creating 20 channel data set, When I declare array of 3 dimension it was giving error, Instead can I create image of 20 channels so that I can store data. If I can what are the additional conditions I have to include to get results without any error of memory allocation or sort of .... Creating an Image of 20 channels will be even comfortable for me...
The C++ interface of OpenCV presents cv::Mat, which replaces and improves the IplImage type of the C interface. This new type provides several constructors, including the one below which can be used to specify the desired number of channels through the param type:
Mat::Mat(int rows, int cols, int type)
Sample code:
#include <cv.h>
#include <highgui.h>
#include <iostream>
void test_mat(cv::Mat mat)
{
std::cout << "Channels: " << mat.channels() << std::endl;
}
int main(int argc, char* argv[])
{
cv::Mat mat20(1024, 768, CV_8UC(20));
test_mat(mat20);
return 0;
}
Opencv implements template class for small matrices whose type and size are known at compilation time:
template<typename _Tp, int m, int n> class Matx {...};
You can create a specified template of a partial case of Matx, which is cv::Vec like those already written in opencv for 1,2, or 3 "channels" like that:
typedef Vec<uchar, 3> Vec3b; // 3 channel -- written in opencv
typedef Vec<uchar, 20> Vec20b; // the one you need
And then, declare a Matrix of your new (20 channel of uchar) object:
cv::Mat_<Vec20b> myMat;
myMat.at<Vec20b>(i,j)(10) = .. // access to the 10 channel of pixel (i,j)