Save vector <DMatch> in FileStorage - opencv

I want to write a vector<DMatch> in a file. I checked that it’s possible write some vector of classes like Keypoints, Mat, etc, but it’s not possible with it. Anyone knows how can I do it? The section of code is the following:
Mat ImDescriptors;
Vector<KeyPoints> ImKeypoints;
FileStorage fs(Name, cv::FileStorage::WRITE);
fs <<” C” << "{";
fs << "Descriptors" << ImDescriptors;
fs << "Keypoints" << ImKeypoints;
fs << “}”;
It works ok, but when I add to this code the element:
Vector<DMatch> good_matches;
fs << “GoodMatches” << good_matches;
I get the following error:
c:\opencv248\build\include\opencv2\core\operations.hpp(2713): error C2665: 'cv::write' : any of the 9 overloads could convert all the argument types.

Related

Data transfer between LibTorch C++ and Eigen

Data transfer between LibTorch C++ and Eigen (Questions and Help)
Hello all,
I'm developing a Data Transfer Tools for C++ Linear Algebra Libraries, as you can see here:
https://github.com/andrewssobral/dtt
(considering bi-dimensional arrays or matrices)
and I'm wondering if you can help me on the following code for data transfer between LibTorch and Eigen:
std::cout << "Testing LibTorch to Eigen:" << std::endl;
// LibTorch
torch::Device device(torch::cuda::is_available() ? torch::kCUDA : torch::kCPU);
torch::Tensor T = torch::rand({3, 3});
std::cout << "LibTorch:" << std::endl;
std::cout << T << std::endl;
// Eigen
float* data = T.data_ptr<float>();
Eigen::Map<Eigen::MatrixXf> E(data, T.size(0), T.size(1));
std::cout << "EigenMat:\n" << E << std::endl;
// re-check after changes
E(0,0) = 0;
std::cout << "EigenMat:\n" << E << std::endl;
std::cout << "LibTorch:" << std::endl;
std::cout << T << std::endl;
This is the output of the code:
--------------------------------------------------
Testing LibTorch to Eigen:
LibTorch:
0.6232 0.5574 0.6925
0.7996 0.9860 0.1471
0.4431 0.5914 0.8361
[ Variable[CPUFloatType]{3,3} ]
EigenMat (after data transfer):
0.6232 0.7996 0.4431
0.5574 0.986 0.5914
0.6925 0.1471 0.8361
# Modifying EigenMat, set element at (0,0) = 0
EigenMat:
0 0.7996 0.4431
0.5574 0.986 0.5914
0.6925 0.1471 0.8361
# Now, the LibTorch matrix was also modified (OK), but the rows and columns were switched.
LibTorch:
0.0000 0.5574 0.6925
0.7996 0.9860 0.1471
0.4431 0.5914 0.8361
[ Variable[CPUFloatType]{3,3} ]
Do someone knows what's happening ?
There's a better way to do that?
I need also to do the same for Armadillo, ArrayFire and OpenCV (cv::Mat).
Thanks in advance!
The reason for the switched rows and columns is that LibTorch (apparently) uses row-major storage, while Eigen by default uses column-major storage. I don't know if you can change the behavior of LibTorch, but with Eigen you can also use row-major storage, like so:
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> MatrixXf_rm; // same as MatrixXf, but with row-major memory layout
and then use it like this:
Eigen::Map<MatrixXf_rm> E(data, T.size(0), T.size(1));

Insufficient Memory Error: Bag of Words OpenCV 2.4.6 Visual Studio 2010

I am implementing the Bag of words Model using SURF and SIFT features and SVM Classifier. I want to train(80% of 2876 images) and test(20% of 2876 images) it. I have kept dictionarySize set to 1000. My Computer configuration is intel Xeon(2 processors)/ 32GB RAM/ 500GB HDD. Here, images are read whenever necessary instead of storing them.
like,
std::ifstream file("C:\\testFiles\\caltech4\\train0.csv", ifstream::in);
if (!file)
{
string error_message = "No valid input file was given, please check the given filename.";
CV_Error(CV_StsBadArg, error_message);
}
string line, path, classlabel;
printf("\nReading Training images................\n");
while (getline(file, line))
{
stringstream liness(line);
getline(liness, path, separator);
getline(liness,classlabel);
if(!path.empty())
{
Mat image = imread(path, 0);
cout << " " << path << "\n";
detector.detect(image, keypoints1);
detector.compute(image, keypoints1,descriptor1);
featuresUnclustered.push_back(descriptor1);
}
}
Here, the train0.csv contains the paths to the images with the labels. It stops from this loop while reading the images, computing the descriptor and adding it to the features to be clustered. Following error apprears on the console:
Here, in the code, I re-sized images being read to the dimension 256*256; the requirement of the memory is reduced. Ergo, the error disappeared.
Mat image = imread(path, 0);
resize(image,image,Size(256,256));
cout << " " << path << "\n";
detector.detect(image, keypoints1);
detector.compute(image, keypoints1,descriptor1);
featuresUnclustered.push_back(descriptor1);
But, it might appear with bigger dataset.

Opencv Write an image with two channel

How write a cv::Mat which the type is CV_32FC2.
Is it possible to write the two channels in TIFF file ? or write each channel separately ?
if you can live with a (large!) textfile, use the FileStorage:
Mat m; // your CV_32FC2
FileStorage fs("my.yml",FileStorage::WRITE);
fs << "mat1" << m; // key, value store
fs.release(); // flush.
FileStorage fs1("my.yml",FileStorage::READ);
fs1["mat1"] >> m;

OpenCV FaceRecognizer wrong shapes for given matrices

I'm trying to make a FisherFaceRecognizer's predict() method work, but I keep getting an error
Bad argument (Wrong shapes for given matrices. Was size(src) =
(1,108000), size(W) = (36000,1).) in subspaceProject, file
/tmp/opencv-DCb7/OpenCV-2.4.3/modules/contrib/src/lda.cpp, line 187
This is similar to a question that was asked at Wrong shapes for given matrices in OPENCV
but in my case, both source and training images are the same data type, full color.
My code is adapted from the tutorial at http://docs.opencv.org/modules/contrib/doc/facerec/facerec_tutorial.html#fisherfaces
however, my test image is larger than the training images, so I needed to work on a region of interest (ROI) of the right size.
Here's how I read the images and converted sizes. I cloned the ROI matrix because an
earlier error message told me the target matrix must be contiguous:
vector<Mat> images;
images.push_back( cvLoadImage( trainingList[i].c_str()));
IplImage* img;
img = cvLoadImage( imgName.c_str() );
// take ROI and clone into a new Mat
Mat testSample1(img, Rect( xLoc, yLoc, images[0].cols, images[0].rows));
Mat testSample = testSample1.clone();
// Create a FisherFaceRecognizer in OpenCV
Ptr<FaceRecognizer> FFR = createFisherFaceRecognizer(0,DBL_MAX);
model->train(images, labels);
cout << " check of data type testSample is " << testSample.type() << " images is " << images[0].type() << endl;
int predictedLabel = model->predict(testSample);
//
I get an exception message at the predict statement.
The cout statement tells me both matrices have type 16, yet somehow it still doesn't believe the matrices are the same size and data type...
You should ensure the shapes, not types
Try
cout << testSample.rows << testSample.cols << images[0].rows << images[0].cols ;
Also
ensure that both ,training img & test img, are in the same color space
If not, Try
cvtColor(testSample, testSample_inSameSpaceOfTraining, CV_BGR2***); // default opencv colors "BGR"
I found out that the FisherFaceRecognizer requires grayscale images, so I should have loaded both training and test images like this:
trainingImages.push_back( imread( trainingList[i].c_str(), CV_LOAD_IMAGE_GRAYSCALE));
and
Mat img;
img = imread( imgName.c_str(), CV_LOAD_IMAGE_GRAYSCALE );
(also reconciled the type of img for consistency). The grayscale-only requirement is documented in the OpenCV reference manual (pdf available online) but apparently not in any of the online tutorials or other documents for FisherFaceRecognizer.

Can not convert with cvMerge,DFT

I am trying to make the dft of one single channeled image, and as cvDft is expecting complex values, I was adviced to merge the original image with another image with all 0's so this last one will be considered as imaginary part.
My problem comes when using cvmerge function,
Mat tmp = imread(filename,0);
if( tmp.empty() )
{cout << "Usage: dft <image_name>" << endl;
return -1;}
Mat Result(tmp.rows,tmp.cols,CV_64F,2);
Mat tmp1(tmp.rows,tmp.cols,CV_64F, 0);
Mat image(tmp.rows,tmp.cols,CV_64F,2);
cvMerge(tmp,tmp1,image);`
It gives me the next error: can not convert cvMAt to cvArr
Anyone could help me? thanks!
1) it seems like you're mixing up 2 different styles of opencv code
cv::Mat (- Mat) is a c++ class from the new version of opencv, cvMerge is a c function from the old version of opencv.
instead of using cvmerge use merge
2) you're trying to merge a matrix (tmp) of type CV_8U (probably) with a CV_64F
use convertTo to get tmp as CV_64F
3) why is your Result & image mats (the destination mat) are initializes to cv::Scalar(2)? i think you're misusing the constractor parameters. see here for more info.
4) you're image mat is a single channel mat and you wanted it as a 2 channel mat (as mentioned in the question), change the declaration to
Mat image(tmp.rows,tmp.cols,CV_64FC2);

Resources