i am new to opencv and has less knowledge on cpp..i need to dynamically create an array of Mat object with the given initial values its giving me error
Mat *M=new Mat[variable](rows,cols,CV_8UC1,Scalar(0));
error:ISO C++ forbids initialization in array new[-fpermissive]
please suggest a correct syntax for my semantics
You need to initialize them all in a loop:
Mat *M = new Mat [variable];
for (int i=0; i<variable; i++)
M[i].create(rows,cols,CV_8UC1,Scalar(0));
Or use a 3-dimensional Mat:
int dims[3] = {variable,rows,cols};
Mat M(3,dims,CV_8UC1,Scalar(0));
But when you want to read/write images with imread() or imwrite(), I suggest using the first solution.
Related
due to my current work with OpenVino I have to use OpenCV. I have to convert a std::vector to a cv::Mat-array. My exemplaric code looks like this:
std::vector<float> inputvector(10*10,1.1111);
cv::Mat image = cv::Mat(10,10,CV_32FC1);
for(int i=0;i<10;i++)
{
for (int j=0;j<10;j++)
{
image.at<float>(i,j) = inputvector.at(10*i+j);
}
}
Now I have to wrap my data by Blob::Ptr without allocation of new memory:
Blob::Ptr imgBlob = wrapMat2Blob(image);
For the last line above I get the following error message from OpenVINO inference engine:
Doesn't support conversion from not dense cv::Mat
I do not understand this as my 10*10 array holds the 1.1111-value in every position. Can somebody explain that? Thanks!
I am trying to write a code that uses opencv Mat objects it goes something like this
Mat img;
vector<Mat> images;
for (i = 1; i < 5; i++)
{
img.create(h,w,type) // h,w and type are given correctly
// input an image from somewhere to img correctly.
images.push_back(img);
img.release()
}
for (i = 1; i < 5; i++)
images[i].release();
I however still seem to have memory leakage can anyone tell me why it is so?
I thought that if the refcount of a mat object = 0 then the memory should be automatically deallocated
You rarely need to call release explicitly, since OpenCV Mat objects take automatically care of internal memory.
Also take care that Mat copy just copies creates a new header pointing to the same data. If the original Mat goes out of scope you are left with an invalid matrix. So when you push the image into the vector, use a deep copy (clone()) to avoid that it the image into the vector becomes invalid.
Since you mentioned:
I have a large 3D image stored in a Mat object. I am running over it using for loops. creating a 2D mat called "image" putting the slices into image, pushing back image to vector images. releasing the image. And later doing a for loop on the images vector releasing all the matrices one by one.
You can store all slices into the vector with the following code. To release the images in the vector, just clear the vector.
#include <opencv2/opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
// Init the multidimensional image
int sizes[] = { 10, 7, 5 };
Mat data(3, sizes, CV_32F);
randu(data, Scalar(0, 0, 0), Scalar(1,1,1));
// Put slices into images
vector<Mat> images;
for (int z = 0; z < data.size[2]; ++z)
{
// Create the slice
Range ranges[] = { Range::all(), Range::all(), Range(z, z + 1) };
Mat slice(data(ranges).clone()); // with clone slice is continuous, but still 3d
Mat slice2d(2, &data.size[0], data.type(), slice.data); // make the slice a 2d image
// Clone the slice into the vector, or it becomes invalid when slice goes of of scope.
images.push_back(slice2d.clone());
}
// You can deallocate the multidimensional matrix now, if needed
data.release();
// Work with slices....
// Release the vector of slices
images.clear();
return 0;
}
Please try this code, which is basically what you do:
void testFunction()
{
// image width/height => 80MB images
int size = 5000;
cv::Mat img = cv::Mat(size, size, CV_8UC3);
std::vector<cv::Mat> images;
for (int i = 0; i < 5; i++)
{
// since image size is the same for i==0 as the initial image, no new data will be allocated in the first iteration.
img.create(size+i,size+i,img.type()); // h,w and type are given correctly
// input an image from somewhere to img correctly.
images.push_back(img);
// release the created image.
img.release();
}
// instead of manual releasing, a images.clear() would have been enough here.
for(int i = 0; i < images.size(); i++)
images[i].release();
images.clear();
}
int main()
{
cv::namedWindow("bla");
cv::waitKey(0);
for(unsigned int i=0; i<100; ++i)
{
testFunction();
std::cout << "another iteration finished" << std::endl;
cv::waitKey(0);
}
std::cout << "end of main" << std::endl;
cv::waitKey(0);
return 0;
}
After the first call of testFunction, memory will be "leaked" so that the application consumes 4 KB more memory on my device. But not more "leaks" after additional calls for me...
So this looks like your code is ok and the "memory leak" isn't related to that matrix creation and releasing, but maybe to some "global" things happening within the openCV library or C++ to optimize future function calls or memory allocations.
I encountered same problems when iterate openCV mat. The memory consumption can be 1.1G, then it stopped by warning that no memory. In my program, there are macro #define new new(FILE, LINE), crashed with some std lib. So I deleted all Overloading Operator about new/delete. When debugging, it has no error. But when it runs, I got "Debug Assertion Failed! Expression: _pFirstBlock == pHead". Following the instruction
Debug Assertion Error in OpenCV
I changed setting from MT (Release)/MTd (Debug)to
Project Properties >> Configuration Properties >> C/C++ >> Code Generation and changing the Runtime Library to:
Multi-threaded Debug DLL (/MDd), if you are building the Debug version of your code.
Multi-threaded DLL(/MD), if you are building the Release version of your code.
The memory leak is gone. The memory consumption is 38M.
I have extracted some feature points of an image using the following code
vector<Point2f> cornersFrame1;
goodFeaturesToTrack( frame1, cornersFrame1, maxCorners, qualityLevel, minDistance, Mat(), blockSize, useHarrisDetector, k );
After that i want to read the values of present at these feature points. So, i am using the following code:
for(int i=0; i<cornersFrame1.size(); i++)
{
float frame1 = calculatedU.at<float>( cornersFrame1[i].x, cornersFrame1[i].y );
}
then i get Segmentation fault.
But if i use the following code in "For loop" then it work.
float frame1 = calculatedU.at<float>( cornersFrame1[i].y, cornersFrame1[i].x );
I am confused because i think that "Point2f" stores pixel information as (row , col). Isn't it?
No, it is not. All types of points in OpenCV are just normal points that you can think about: (x,y). When it comes to coordinate in image this means that 'x' is a column and 'y' is a row. On the other hand at<> requires as input (row, column). This is why you had to provide (y,x) instead of (x,y).
Just to prevent future confusion, one of the ways of using at<> is this one:
float frame1 = calculatedU.at<float>( cornersFrame1[i] );
This way you don't need to think whether you should provide (x,y) or (y,x).
Here's my problem. I manually extracted key points features with SURF on multiple images. But I also already know which pair of points are going to match. The thing is, I'm trying to create my matching pairs, but I don't understand how. I tried by looking at the code, but it's a mess.
Right now, I know that the size of the features.descriptors, a matrix, is the same as the number of key points (the other dimension is 1). In the code, to detect matching pairs, it's only using the descriptors, so it's comparing rows (or columns, I'm not sure) or two descriptors matrix and determined if there's anything in common.
But in my case, I already know that there's a match between keypoint i from image 1 and keypoint j from image 2. How do I describe that as a MatchesInfo value. Particularly the element matches of type std::vector< cv::DMatch >.
EDIT: So, for this, I don't need to use any matcher or anything like this. I know which pairs are going together!
If I understood you're question correctly, I assume that you want the keypoint matches in std::vector<cv::DMatch> for the purpose of drawing them with the OpenCV cv::drawMatches or usage with some similar OpenCV function. Since I was also doing matching "by hand" recently, here's my code that draws up arbitrary matches contained originally in a std::vector<std::pair <int, int> > aMatches and displays them in a window:
const cv::Mat& pic1 = img_1_var;
const cv::Mat& pic2 = img_2_var;
const std::vector <cv::KeyPoint> &feats1 = img_1_feats;
const std::vector <cv::KeyPoint> &feats2 = img_2_feats;
// you of course can work directly with original objects
// but for drawing you only need const references to
// images & their corresponding extracted feats
std::vector <std::pair <int, int> > aMatches;
// fill aMatches manually - one entry is a pair consisting of
// (index_in_img_1_feats, index_in_img_2_feats)
// the next code draws the matches:
std::vector <cv::DMatch> matches;
matches.reserve((int)aMatches.size());
for (int i=0; i < (int)aMatches.size(); ++i)
matches.push_back(cv::DMatch(aMatches[i].first, aMatches[i].second,
std::numeric_limits<float>::max()));
cv::Mat output;
cv::drawMatches(pic1, feats1, pic2, feats2, matches, output);
cv::namedWindow("Match", 0);
cv::setWindowProperty("Match", CV_WINDOW_FULLSCREEN, 1);
cv::imshow("Match", output);
cv::waitKey();
cv::destroyWindow("Match");
Alternatively, if you need fuller information about the matches for purposes more complicated than drawing then you might also want to set the distance between matches to a proper value. E.g. if you want to calculate distances using L2 distance, you should replace the following line:
for (int i=0; i < (int)aMatches.size(); ++i)
matches.push_back(cv::DMatch(aMatches[i].first, aMatches[i].second,
std::numeric_limits<float>::max()));
with this (note, for this a reference to feature descriptor vectors is also needed):
cv::L2<float> cmp;
const std::vector <std::vector <float> > &desc1 = img_1_feats_descriptors;
const std::vector <std::vector <float> > &desc2 = img_2_feats_descriptors;
for (int i=0; i < (int)aMatches.size(); ++i){
float *firstFeat = &desc1[aMatches[i].first];
float *secondFeat = &desc2[aMatches[i].second];
float distance = cmp(firstFeat, secondFeat, firstFeat->size());
matches.push_back(cv::DMatch(aMatches[i].first, aMatches[i].second,
distance));
}
Note that in the last snippet, descX[i] is a descriptor for featsX[i], each element of the inner vector being one component of the descriptor vector. Also, note that all descriptor vectors should have the same dimensionality.
I have a pointer to image:
IplImage *img;
which has been converted to Mat
Mat mt(img);
Then, the Mat is sent to a function that gets a reference to Mat as input void f(Mat &m);
f(mt);
Now I want to copy back the Mat data to the original image.
Do you have any suggestion?
Best
Ali
Your answer can be found in the documentation here: http://opencv.willowgarage.com/documentation/cpp/c++_cheatsheet.html
Edit:
The first half of the first code area indeed talks about the copy constructor which you already have.
The second half of the first code area answers your question. Reproduced below for clarity.
//Convert to IplImage or CvMat, no data copying
IplImage ipl_img = img;
CvMat cvmat = img; // convert cv::Mat -> CvMat
For the following case:
double algorithm(IplImage* imgin)
{
//blabla
return erg;
}
I use the following way to call the function:
cv::Mat image = cv::imread("image.bmp");
double erg = algorithm(&image.operator IplImage());
I have made some tests and how it looks the image object will manage the memory. The operator IplImage() will only construct the header for IplImage. Maybe this could be useful?
You can use this form:
Your Code:
plImage *img;
Mat mt(img);
f(mt);
Now copy back the Mat data to the original image.
img->imageData = (char *) mt.data;
You can also copy the data instead of pointer:
memcpy(mt.data, img->imageData, (mt.rows*mt.cols));
(mt.rows*mt.cols) is the size that you should use for copy all data the mt to img.
Hope I helped