OpenCV- Cant access element of Mat (of descriptors) - opencv

I'm writing a simple program that extracts descriptors from images and writes them to files.
I'm saving the descriptors in a Mat variable, but I'm getting wrong values when trying to access them.
Here is the code:
string s = format("%s\\%s\\img%d.ppm", dataset_dir.c_str(), dsname, k);
Mat imgK = imread(s, 0);
if( imgK.empty() )
break;
detector->detect(imgK, kp);
descriptor->compute(imgK, kp, desc);
//writing the descriptors to a file
char fileName[512];
sprintf(fileName,"C:\\BinaryDescriptors\\OpenCVRes\\%s\\%s\\Descriptors%d.txt",descriptor_name,dsname,k);
FILE * fid;
fid=fopen(fileName,"a+");
for (int ix=0; ix< kp.size(); ix++){
fprintf(fid,"%f \t%f", kp[ix].pt.x,kp[ix].pt.y);
fprintf(fid, "\t1 \t0 \t1");
fflush(fid);
//writing the descriptor
for (int jx=0;jx<desc.cols;jx++){
int gil = desc.at<int>(ix,jx);
printf("AAAA %d", gil);
fprintf(fid,"\t%d",desc.at<int>(ix,jx));
fflush(fid);
}
}
fprintf(fid,"\n");
fclose(fid);
The line where I'm accessing the descriptors matrix is int gil = desc.at int(ix,jx); Is there something I'm doing wrong?
Any help will be greatly appreciated, as I'm quite stuck :)
Thanks,
Gil.

You are accessing the descriptor matrix with int, so that the matrix must be of type CV_32SC1. Are you sure it is that type? Most of the descriptors are coded with float (CV_32F) or unsigned char (CV_8U). Check that desc.type() == CV_32SC1.
By the way, you should use cv::FileStorage to save and load descriptors, it is much easier than directly accessing files.

Related

Iterator of Vector<Vector<Point> >

I know these iterator questions have been asked and answered a thousand times, however when I compile the following code, I still get this error:
error C2440: 'initializing' : cannot convert from
'std::_Vector_iterator<_Myvec>' to 'cv::Vector<_Tp> *'
.
void iterate(vector<vector<cv::Point> >& contours){
Vector<Vector<cv::Point>>::iterator it = contours.begin();
for( int i = 0; i< contours.size(); i++ ){
if(contourArea(contours[i])>1000){
it++;
}else{
contours.erase(it);
}
}
}
I don't see anything wrong with this code. The template type of the vector for the new iterator is the same like the vector I'm getting the iterator from.
Can not convert errors are generally very literal. Often the types used can give hints where in your code somethng is wrong.
Here we have the use of uppercase Vector class to define your iterator, and you are assigning a lowercase Vector class to it.
Note you would probably have gotten a different error if Vector was not a real class.

Convert array<System:Byte>^ to Mat

How do I convert an array<System:Byte>^ to a Mat in openCV. I am being passed a array<System:Byte>^ in c++/cli, but I need to convert it to Mat to be able to read it and display it.
You can use constructor Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP). The conversion may look like this.
void byteArray2Mat(array<System::Byte>^ byteArray, cv::Mat &output)
{
pin_ptr<System::Byte> p = &byteArray[0];
unsigned char* pby = p;
char* pch = reinterpret_cast<char*>(pby);
// assuming your input array has 2 dimensions.
int rows = byteArray->GetLength(0);
int cols = byteArray->GetLength(1);
output = cv::Mat(rows, cols, CV_8UC1, (void*)pch)
}
I don't have c++/CLI to test the program and this may not be most efficient method. At least it should give you an idea on how to get started.

Vec3b does not take three arguments?

Im using classes to create a function. The function must find a selected colour in the image provided. So I made it so that the function takes a Vec3b value since it is an RGB value we are talking about.
class colorcompare
{
private:
int threshold;
Vec3b color;
void setcolor(Vec3b);
Mat process(Mat&);
void setthresh(const int);
int getdist(Vec3b);
};
void colorcompare::setcolor(Vec3b colr)
{
color = colr;
}
int _tmain(int argc, _TCHAR* argv[])
{
colorcompare cc1;
Mat image;
image = imread("c:\\car2.jpg", -1);
cc1.setcolor(19,69,139); //This is where im getting error
cc1.setthresh(100);
namedWindow("meh");
imshow("meh", cc1.process(image));
waitKey(0);
return 0;
}
Now the error I am getting is this: 'colorcompare::setcolor' : function does not take 3 arguments
I know that vec3b is a vector of 3 values, so in other words I can access the individual values of vec3b as color[0], color[1] and color[2].
And I know I can define it like such in the function above but it shouldnt the vec3b be able to take 3 values? Like I did in my code?
Classic mistake: the function expects a cv::Vec3b object, not 3 int variables.
If you want a single line solution, try this:
cc1.setcolor(cv::Vec3b(19,69,139));
You defined setColor to take a Vec3b as parameter, so you should give it a Vec3b:
cv::Vec3b color(19,69,139); // or cv::Vec3b color; color[0]=19, ...
cc1.setColor(color);

How to display successive frames with opencv

I'm looking for a solution to display successive frames in one window using OpenCV. I have a sequence of images (001.jpg, 002.jpg, 003.jpg, etc.), but not a video. I have to display them within a loop.
The standard code to display an image is:
IplImage* src = cvLoadImage("001.jpg");
cvNamedWindow("My pic");
cvShowImage("My pic",src);
cvWaitKey();
As Link suggests, one option would be to write a function that automatically generates the correct filename, for example:
void loadImage(IplImage *image, int number)
{
// Store path to directory
char filename[100];
strcpy(filename, "/path/to/files");
// Convert integer to char
char frameNo[10];
sprintf(frame, "%03i", number);
// Combine to generate path
strcat(filename, frameNo);
strcat(filename, ".bmp");
// Use path to load image
image = cvLoadImage(filename);
}
This could then be used in a loop for a known number of images
IplImage *im;
for (int i = 0; i < nImages; ++i)
{
loadImage(im, i);
/*
Do stuff with im
*/
}
An alternative option would be to investigate the boost directory iterator.
#Chris code works, I want to add an even simpler routine
void loadImage()
{
int nImages = 6;
for (int i = 0; i < nImages; ++i)
{
IplImage *image;
char filename[100];
strcpy(filename, "images/");
char frameNo[10];
sprintf(frameNo, "%03i", i);
strcat(filename, frameNo);
strcat(filename, ".jpg");
image = cvLoadImage(filename);
cvNamedWindow("pic");
cvShowImage("pic",image);
cvWaitKey(1000);
}
}
Try to use XML/YAML persistence mechanisms of OpenCV. Write a list of image paths for loading and use a loop to read those paths and load images. In the example of stereo calibration such a list is used (there is a directory with examples installed with OpenCV).

convert Matrix of type CV_32FC1 to CV_64FC1

How do I convert a cv::Mat of type CV_32FC1 to the type CV_64FC1 (equivalent to a change from float to double)?
I am opening a Matrix that was saved as XML (cvSave) but as a float. This means that the field <dt> has the value f in the file. I need to change it to d to open it. But I'd rather not do this, instead I'd like to open it directly as a Matrix with elements of type double, or convert it later from float to double.
Below is my code for opening the file.
/** Load cv::Mat from XML file.
*/
cv::Mat loadMat(const std::string filename)
{
cv::Mat result;
cv::FileStorage fs(filename, cv::FileStorage::READ);
fs.getFirstTopLevelNode() >> result;
return result;
}
Okay, I'm a dimwit. Here is how it goes:
There is the function convertTo that does exactly what I want.
Thanks for matrix type conversion in opencv for pointing this out.
Here is how I do it:
cv::Mat A = loadMat("mymat.xml"); // See function loadMat in the question!
A.convertTo(A, CV_64F);

Resources