I'm trying to fit a 2d gauss function to an image (in cv::Mat format), and I'm using the NLopt library.
I put my object function like this:
for(i for each row)
for(j for each col)
{
//compute the gauss function value
double valuenow=x[0]*exp(-( x[3]*(j-x[1])*(j-x[1]) + 2*x[4]*(j-x[1])*(i-x[2]) + x[5]*(i-x[2])*(i-x[2]) ));
//add square residual to result
result+=(valuenow-fitdata.at<double>(i,j))*(valuenow-fitdata.at<double>(i,j));
}
return result;
My matrix is about 1000*1000 size, I'm using LN_COBYLA algorithm. When I ran this, it turned out to be extremely slow. I think there must be something wrong with the way I specify my object function, because I used to do the same thing in Matlab with lsqnonlinear, which returned in a second.
Can someone help me please? Thanks in advance.
The at<>() function is slow. If speed is of essence, it's not a good idea to use it inside loops. Take a pointer outside the loop and then just use that pointer inside the loop.
A related question:
OpenCV Mat array access, which way is the fastest for and why?
Related
I am trying to use an opencv function that accepts std::vector<cv::Point3f> among other parameters. In my program, I have an std::vector<cv::Point3f> worldPoints and another std::vector<int> mask, both of larger dimension than what I want to send.
What I want to do is pass to the opencv function only the entries that have a respective non-zero mask, as efficiently as possible.
std::vector<cv::Point3f> worldPointsSubset;
for (int i=0; i<mask.size(); i++) {
if (mask[i] != 0) {
worldPointsSubset.push_back(worldPoints[i]);
}
}
// Then use worldPointsSubset in function
Is there any other way around, possibly involving no copying of data?
EDIT 1: The function I am referring to is solvePnPRansac()
The function that you call requires a vector of Point3f, so if the only thing you have is a masked vector, then you have to copy the data first. There is no way around this if the function doesn't accept a vector and its mask.
To see if this copy is an issue, you must measure the drop in performance first and see if this copy is a bottleneck. If it is a bottleneck, the first thing is to count the number of points you need and reserve that capacity in worldPointsSubset.
There is no way to convert data from std::vector<int> to std::vector<cv::Point3f> without a copy because despite the fact you see the same values the size of data might be different.
But you can change the type of data you are working on (std::vector<int> to std::vector<cv::Point3f>) and work directly with cv::Point3f and when needed pass it to solvePnPRansac().
I have a function which requires me to pass a fairly large matrix (which I created using Eigen) - and ranges from dimensions 200x200 -> 1000x1000. The function is more complex than this, but the bare bones of it are:
#include <Eigen/Dense>
int main()
{
MatrixXi mIndices = MatrixXi::Zero(1000,1000);
MatrixXi* pMatrix = &mIndices;
MatrixXi mTest;
for(int i = 0; i < 10000; i++)
{
mTest = pMatrix[0];
// Then do stuff to the copy
}
}
Is the reason that it takes much longer to run with a larger size of matrix because it takes longer to find the available space in RAM for the array when I set it equal to mTest? When I switch to a sparse array, this seems to be quite a lot quicker.
If I need to pass around large matrices, and I want to minimise the incremental effect of matrix size on runtime, then what is best practice here? At the moment, the same program is running slower in c++ than it is in Matlab, and obviously I would like to speed it up!
Best,
Ben
In the code you show, you are copying a 1,000,000 element 10,000 times. The assignment in the loop creates a copy.
Generally if you're passing an Eigen matrix to another function, it can be beneficial to accept the argument by reference.
It's not really clear from your code what you're trying to achieve however.
I have this matlab code ,where i tried to find the 'j' in matrix color.I cant find a usefull function in opencv which can do the same job like matlab find do.i have tried some iterative method with 3 for loops ,but that were too cumbersome,Can you guys help me out?
if (find(Colorr==j))
tt=tt+1;
test=[test;ColorValues(:,j,1),ColorValues(:,j,2),ColorValues(:,j,3)];
end
this is the code i have written to covert to opencv
for(j=0;j<ColorValues.cols/2;j++)
for(i=0;i<Color.cols;i++){
if(j=input[Color.step*i+1]){
tt++;
for(k=0;k<ColorValues.rows;k++){
}
}
}
Assuming Color is a properly initialized single-channel cv::Mat, you can use the combination of overloaded operator== and cv::countNonZero() to do what you wish. operator== returns a mask where each element is one if the value in Color matches j, or zero otherwise.
if(cv::countNonZero(Color == j))
{
// Do something...
}
I am wondering about the way of accessing data in Mat in OpenCV. As you know, we can access to get data in many ways. I want to store image (Width x Height x 1-depth) in Mat and looping access each pixel in the image. Using ptr<>(irow) to get row-pixel and then access each column in the row is the best way? or using at<>(irow,jcol) is the best? or using directly calculate the index by using index = irow*Width + jrow is the best? Anyone know the reason.
Thanks in advance
You can find information here in the documentation: the basic image container and how to scan images.
I advice you to practice with at (here) if you are not experienced with OpenCV or with C language types hell. But the fastest way is ptr as Nolwenn answer because you avoid the type checking.
at<T> does a range check at every call, thus making it slower than ptr<T>, but safer.
So, if you're confident that your range calculations are correct and you want the best possible speed, use ptr<T>.
I realize this is an old question, but I think the current answers are somehow misleading.
Calling both at<T>(...) and ptr<T>(...) will check the boundaries in the debug mode. If the _DEBUG macro is not defined, they will basically calculate y * width + x and give you either the pointer to the data or the data itself. So using at<T>(...) in release mode is equivalent to calculating the pointer yourself, but safer because calculating the pointer is not just y * width + x if the matrix is just a sub-view of another matrix. In debug mode, you get the safety checks.
I think the best way is to process the image row-by-row, getting the row pointer using ptr<T>(y) and then using p[x]. This has the benefit that you don't have to count with various data layouts and still plain pointer for the inner loop.
You can use plain pointers all the way, which would be most efficient because you avoid one the multiplication per row, but then you need to use step1(i) to advance the pointer. I think that using ptr<T>(y) is a nice trade-off.
According to the official documentations, they suggest that the most efficient way is to get the pointer to the row first, and then just use the plain C operator []. It also saves a multiplication for each iteration.
// compute sum of positive matrix elements
// (assuming that M isa double-precision matrix)
double sum=0;
for(int i = 0; i < M.rows; i++)
{
const double* Mi = M.ptr<double>(i);
for(int j = 0; j < M.cols; j++)
sum += std::max(Mi[j], 0.);
}
Hey guys,
I'm working on a project. I need to use the function cvFindHomography in openCV before this step I have applied LK optical flow function, so I get the features in the first frame and in the second frame as INTEGERS, well in cvFindHomography I need to use these features but as cvMat not as integers.
Do you have any I idea how to put these integers in a Matrix in order to use them in the function mentioned above.
Thank you.
You can use the cvMat() constructor:
CV_INLINE CvMat cvMat( int rows, int cols, int type, void* data CV_DEFAULT(NULL))