I' trying to get cloud of points from two stereo images using OpenCV, but I can't get coordinates.
I found points coordinates using Optical Flow
I found projection matrixes for cameras.
Mat RT1;<br>
hconcat(R, T1, RT1);<br>
Mat P1 = C*RT1;<br>
R is 3x3 rotation matrix, T is 3x1 transform matrix (column), P1 - projection matrix.
I pass them to triangulatePoints function
triangulatePoints(P1, P2, leftPoints, rightPoints, out);
P1 and P2 is 3x4 projection matrix (Mat_<double>).
leftPoints and rightPoints is std::vector of Point2f.
What is out? It should be 1xN matrix of 4D coords. Is this Vec4f?
I am trying get coordinates
for (int i = 0; i < out.cols; i++)
{
Vec4f vec = out.at<Vec4f>(0, i);
float w = vec[3];
stream << "v " << vec[0] / w << " " << vec[1]/w << " " << vec[2]/w << "\n";
}
But I have two problems:
This cycle throw exception (works for small i, about 20% of out.cols)
OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 <
(unsigned)si ze.p[0] && (unsigned)(i1 * DataType<_Tp>::channels) <
(unsigned)(size.p1 * cha nnels()) &&
((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 <<
3) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file
c:\opencv\build\includ e\opencv2\core\mat.inl.hpp, line 89
I think this is some kind of Index Out Range Exception
Result is very strange:
Image
So, I am doing something wrong. How correctly work with this function and get 3D coordinates of points? I'll hope you can help me.
I don't understand exactly your approach in getting the coordinates.
As far as I see, you should not be accessing elements like
out.at<Vec4f>(0, i);
Instead, do it like this:
float x = out.at<float>(0, i);
float y = out.at<float>(1, i);
float z = out.at<float>(2, i);
float w = out.at<float>(3, i);
stream << "v " << x << " " << y << " " << z << "\n";
Or use double... depending whether you out is of type CV_32F or CV_64F.
Here is how I do it:
Mat points3DHomogeneous;
triangulatePoints(projectionMatrixL, projectionMatrixR, pointsL, pointsR, points3DHomogeneous);
projectionMatrixL:
projectionMatrixR:
pointsL:
700 250
200 300
600 350
400 400
500 450
600 500
700 550
800 600
150 650
1000 700
pointsR:
690 250
180 300
590 350
385 400
495 450
575 500
691 550
782 600
120 650
960 700
points3DHomogeneous is the result:
Related
I have a 2D array of greyscale pixel values that looks like
255 250 250 250 235 251 255 201
255 250 250 250 235 251 255 151
255 250 250 250 235 251 255 151
255 250 250 250 235 251 255 151
255 250 250 250 235 251 255 151
In implementations I have seen online and in other posts, the program will obtain neighboring pixels specifically in an 3x3 window area.
For example,
for (row = 1; row <= numRows; ++row)
{
for (col = 1; col <= numCols; ++col)
{
//neighbor pixel values are stored in window including this pixel
window[0] = imageArr[row - 1][col - 1];
window[1] = imageArr[row - 1][col];
window[2] = imageArr[row - 1][col + 1];
window[3] = imageArr[row][col - 1];
window[4] = imageArr[row][col];
window[5] = imageArr[row][col + 1];
window[6] = imageArr[row + 1][col - 1];
window[7] = imageArr[row + 1][col];
window[8] = imageArr[row + 1][col + 1];
// do something with window
}
}
I am trying to implement a more dynamic window size.
Ex. If the user wants to find neighboring pixels in an 4x4 area or an 5x5 area
I wasn't planning on answering this, but I may as well now that I've written extensively in comments.
General advice is to simplify your loop by treating row and col as the top-left corner of your window instead of the center. This makes the math straight-forward (and therefore clearer to anyone reading the code), especially for the case of an even-sized window dimension.
Assuming the window is square (dimension N), which appears to be your requirement, the outer loops become:
for (int row = 0; row < numRows - N; ++row)
{
for (int col = 0; col < numCols - N; ++col)
{
// TODO: copy window
// Your window's "center" if you need it
int cx = col + N/2;
int cy = row + N/2;
// TODO: Do something with window...
}
}
Now, let's do the "copy window" loops. This is a simple NxN image copy where the source position is [row + y][col + x]:
// Copy window
for (int y = 0; y < N; ++y)
{
for (int x = 0; x < N ++x)
{
window[y * N + x] = imageArr[row + y][col + x];
}
}
It's pretty simple to extend this to rectangular windows if you need, which would be a good exercise for you to try. Various optimizations are possible, but I think that's out of scope based on your current level, and I actually don't want to promote optimization to beginners. It's better to learn how to write simple, clear code.
So I'm trying to use a modified Bellman Ford algorithm to find the shortest path from the starting vertex to the ending vertex but I cannot go over a certain distance. So given a graph with edges:
0 1 100 30
0 4 125 50
1 2 50 250
1 2 150 50
4 2 100 40
2 3 90 60
4 3 125 150
Where the each line represents an edge and the first value is the starting vertex, the second value is the end vertex, the third is cost and the fourth is the distance.
With the code I have now when I try to find the cheapest path from 0 to 3 without going over 140 it yields 0 (default when no path is found) instead of 340 (the cost of the cheapest path). Any suggestions on how to alter my code.
Just gonna copy the code down below because this site is not letting me do anything else.
static void BellmanFord(struct Graph *graph, int source, int ending, int max){
int edges = graph->edgeCount;
int vertices = graph->verticesCount;
int* money = (int*)malloc(sizeof(int) * vertices);
int* distance = (int*)malloc(sizeof(int) * vertices);
for (int I = 0; I < vertices; I++){
distance[I] = INT_MAX;
money[I] = INT_MAX;
}
distance[source] = 0;
money[source] = 0;
for (int I = 1; I <= vertices - 1; ++I){
for int j = 0; j < edges; ++j){
int u = graph->edge[j].Source;
int v = graph->edge[j].Destination;
int Cost = graph->edge[j].cost;
int Duration = graph->edge[j].duration;
if ((money[u] != INT_MAX) && (money[u] + Cost < money[v])){
if (distance[u] + Duration <= max){
money[v] = money[u] + Cost;
distance[v] = distance[u] + Duration;
}
}
}
}
if (money[ending] == INT_MAX) cout << "0" << endl;
else cout << money[ending] << endl;
}
Please help! This is probably not that hard but finals are stressing me out
This problem, known as the "constrained shortest path" problem, is much harder to solve than this. The algorithm you provided does not solve it, it only might catch the solution, only by luck, according to the graph's structure.
When this algorithm is applied on the graph you provide, with max-distance = 140, it fails to find the solution, which is 0-->1-->2-->3 (using the edge 1 2 150 50) with total cost of 340 and a distance of 140.
We can observe the reason of failure by logging the updates to the nodes whenever they are updated, and here is the result:
from node toNode newCost newDistance
0 1 100 30
0 4 125 50
1 2 250 80
4 2 225 90
Here the algorithm is stuck and cannot go further, since any progress from this point will lead to paths that exceed the max distance (of 140). As you see, node 2 has found the path 0-->4--2 which is the lowest-cost from node 0 while respecting the max-distance constraint. But now, any progress from 2 to 3 will exceed the distance of 140 (it will be 150, because 2->3 has a distance of 60.)
Running again with max-distance=150 will find the path 0-->4->3 with cost 315 and distance 150.
from node toNode newCost newDistance
0 1 100 30
0 4 125 50
1 2 250 80
4 2 225 90
2 3 315 150
Obviously this is not the minimum cost path that respects the constraint of distance; the correct should be the same (that it failed to find) in the first example. This again proves the failure of the algorithm; this time it gives a solution but which is not the optimal one.
In conclusion, this is not a programming mistake or bug in the code, it is simply that the algorithm is not adequate to the stated problem.
Okay so right before the
if (money[ending] == INT_MAX) cout << "0" << endl;
I added some code that made it work but I'm wondering will this work for every case or does it need to be altered a little.
if (money[ending] == INT_MAX){
for (int j = 0; j < edges; ++j){
int u = graph->edge[j].Source;
int v = graph->edge[j].Destination;
int Cost = graph->edge[j].cost;
int Duration = graph->edge[j].duration;
if ((distance[u] != INT_MAX) && (distance[u] +Duration < distance[v])){
if (distance[u] + Duration <= max){
money[v] = money[u] + Cost;
distance[v] = distance[u] + Duration;
}
}
}
}
Im trying to build a simple input/output matrix (where you can calculate the multiplier effect in a simple economy if demand increases). But for some reason the final result is not adding up.
#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
void InputOutput(){
MatrixXf ProdA(5, 5);;
VectorXf Intd(5);
VectorXf Finald(5);
ProdA <<
10, 20, 0, 0, 5,
20, 30, 20, 10, 10,
10, 10, 0, 10, 10,
10, 40, 20, 5, 5,
20, 20, 30, 5, 5;
Intd << 55, 40, 20, 30, 10;
Finald << 0, 0, 0, 0, 0;
VectorXf ones(5);
ones << 1, 1, 1, 1, 1;
Finald = ProdA * ones + Intd;
MatrixXf AMatrix = MatrixXf::Zero(ProdA.rows(), ProdA.cols());
AMatrix = ProdA.array() / (Finald.replicate(1, ProdA.cols())).array();
cout << "Here is the Coefficient vector production needed:\n" << AMatrix << endl;
MatrixXf IminA(5, 5);;
IminA = MatrixXf::Identity(AMatrix.rows(), AMatrix.cols()) - AMatrix;
cout << "Here is the matrix of production:\n" << ProdA << endl;
cout << "Here is the vector Internal demand:\n" << Intd << endl;
cout << "Here is the vector Final demand:\n" << Finald << endl;
cout << "Here is the Coefficient vector production needed:\n" << AMatrix << endl;
MatrixXf IminAinv(5, 5);;
IminAinv = IminA.inverse();
cout << "The inverse of CoMatrix - Imatrix is:\n" << IminAinv << endl;
cout << "To check, final demand is:\n" << (IminAinv * Intd) << endl;
When I verify if the (I-A)inverse matrix (or IminAinv) is properly calculated it doesn't add up. By multiplying the IminAinv by Internal demand (int), I should get the same Intd. That is if Intd isn't changed. Instead I get a bigger number. Also if I calculate the inverse of the IminA matrix myself, I get something different then eigen.
So something goes wrong in getting the inverse of Identity matrix - Coefficient matrix. But what?
Thanks!
EDIT :
After some more digging into why there are some differences in the final results, I discovered that those "underlying mechanisms" mentioned in Case 2 were, in fact, my own mistake out of inadvertence while entering the matrices' values.
Here follows the original answer with these mistakes taken care of.
The actual problem does not lie in the inversion of the AMatrix but in a much more subtle detail.
You are using this command to perform the division in the definition of AMatrix:
AMatrix = ProdA.array() / (Finald.replicate(1, ProdA.cols())).array();
But if you check the results of this replicate operation on Finald you get:
...
cout << "Here is the replicated final demand vector:\n" << (Finald.replicate(1, ProdA.cols())).array() << endl;
...
>>
Here is the replicated final demand vector:
90 90 90 90 90
130 130 130 130 130
60 60 60 60 60
110 110 110 110 110
90 90 90 90 90
whereas the correct one should be:
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
You can transpose the replicated final demand vector like this:
MatrixXf Finaldrep(5,5);
Finaldrep = (Finald.replicate(1, ProdA.cols())).array().transpose();
and then of course:
AMatrix = ProdA.array() / Finaldrep.array();
which yields:
cout << "Here is the transposed replicated final demand vector:\n" << Finaldrep << endl;
...
>>
Here is the transposed replicated final demand vector:
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
90 130 60 110 90
So, let's see what are the differences in your intermediate and final results in both these cases:
Case 1
ie Your current approach
Here is the Coefficient vector production needed:
0.111111 0.222222 0 0 0.0555556
0.153846 0.230769 0.153846 0.0769231 0.0769231
0.166667 0.166667 0 0.166667 0.166667
0.0909091 0.363636 0.181818 0.0454545 0.0454545
0.222222 0.222222 0.333333 0.0555556 0.0555556
The determinant of IminA is: 0.420962
The inverse of CoMatrix - Imatrix is:
1.27266 0.468904 0.131153 0.0688064 0.13951
0.443909 1.68132 0.377871 0.215443 0.240105
0.451292 0.628205 1.25318 0.287633 0.312705
0.404225 0.841827 0.423093 1.20242 0.224877
0.586957 0.777174 0.586957 0.23913 1.27174
To check, final demand is:
94.8349
108.09
86.7689
102.689
95
I have also added the determinant of IminA
Case 2
ie using the reversed final demand vector
Here is the Coefficient vector production needed:
0.111111 0.153846 0 0 0.0555556
0.222222 0.230769 0.333333 0.0909091 0.111111
0.111111 0.0769231 0 0.0909091 0.111111
0.111111 0.307692 0.333333 0.0454545 0.0555556
0.222222 0.153846 0.5 0.0454545 0.0555556
The determinant of IminA is: 0.420962
The inverse of CoMatrix - Imatrix is:
1.27266 0.324626 0.196729 0.0562962 0.13951
0.641202 1.68132 0.818721 0.254615 0.346818
0.300861 0.289941 1.25318 0.156891 0.20847
0.494053 0.712316 0.77567 1.20242 0.27485
0.586957 0.538044 0.880435 0.195652 1.27174
To check, final demand is:
90
130
60
110
90
Now, I understand that the Finald check still does not produce the exact values of the originally defined Finald, but I believe that this has something to do with the precision or some other underlying mechanism. (see NOTE)
As a proof of concept here are some results obtained with MATLAB, using the second case (reversed) for the replicated Final Demand Vector (denom):
>> AMatrixcm = ProdA ./ Finaldfullcm
AMatrixcm =
0.1111 0.1538 0 0 0.0556
0.2222 0.2308 0.3333 0.0909 0.1111
0.1111 0.0769 0 0.0909 0.1111
0.1111 0.3077 0.3333 0.0455 0.0556
0.2222 0.1538 0.5000 0.0455 0.0556
>> IminAcm = eye(5) - AMatrixcm
IminAcm =
0.8889 -0.1538 0 0 -0.0556
-0.2222 0.7692 -0.3333 -0.0909 -0.1111
-0.1111 -0.0769 1.0000 -0.0909 -0.1111
-0.1111 -0.3077 -0.3333 0.9545 -0.0556
-0.2222 -0.1538 -0.5000 -0.0455 0.9444
>> det(IminAcm)
ans =
0.4210
>> IminAinvcm = inv(IminAcm)
IminAinvcm =
1.2727 0.3246 0.1967 0.0563 0.1395
0.6412 1.6813 0.8187 0.2546 0.3468
0.3009 0.2899 1.2532 0.1569 0.2085
0.4941 0.7123 0.7757 1.2024 0.2748
0.5870 0.5380 0.8804 0.1957 1.2717
>> Finaldcheckcm = IminAinvcm * Intdc
Finaldcheckcm =
90.0000
130.0000
60.0000
110.0000
90.0000
It is quite clear that the second case results are (almost) identical to the MATLAB ones.
NOTE: Here you can see that the MATLAB output is identical to the original Finald, however, if you perform the last matrix multiplication (the one in the validation of the Final Demand vector) by hand, you will see that in fact both MATLAB and Case 2 versions of IminAinv yield the same result as the final output of Case 2, ie [88.9219, 125.728, 59.5037, 105.543, 84.5808].
This is why I think that there is some other mechanism involved in these differences. (See EDIT on top of post)
So I'm trying to make a graphing application, and I'm using Desmos as a base for that.
The thing I'm struggling with is the way Desmos handles the subdivisions of the axes. When you zoom in or out the scales are always on "easy" simple numbers like 5, 100, 1000 etc. So my question is: how does one go about simplifying their scale with any level of zoom?
BTW: Using C++
I was going to write a description of how to do this in general, but then I realize that the code may be easier than explaining.
Most important step: define precisely what you mean by "easy simple" numbers.
Example #1: 1, 2, 4, 8, 16, 32, 64, 128, ... , 1073741824, ...
These are powers of two. So, a straightforward ceil(log(x)/log(2.0)) will solve it.
Example #2: 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, ...
There is a mixture of powers of two, and some multiples of it. Let's take a closer look.
A subset of these can be described as powers of ten.
Changing the formula to ceil(log(x)/log(10.0)) will solve it.
For each power-of-ten, its multiples by 2.0 and 5.0 are also "easy simple numbers".
Inside each iteration, after checking the power-of-ten value, also check the two multiples. If it fits inside one of the multiple, that value can be returned as result.
Code
The following code is only meant to explain the concept. It is not efficient - an efficient version should have used logarithm to get the result in O(1) time.
#include <iostream>
#include <vector>
#include <limits>
#include <stdexcept>
#include <algorithm>
using namespace std;
double getNiceAxisLength(double value, double baseLength, double step, const std::vector<double>& subSteps)
{
typedef std::vector<double>::const_iterator VecDoubleIter;
if (value < 0.0)
{
throw std::invalid_argument("Error: value must be non-negative. Take absolute value if necessary.");
}
if (baseLength <= 0.0)
{
throw std::invalid_argument("Error: baseLength must be positive.");
}
if (step <= 1.0)
{
throw std::invalid_argument("Error: step must be strictly greater than 1.");
}
for (VecDoubleIter iter = subSteps.begin(); iter != subSteps.end(); ++iter)
{
double subStep = *iter;
if (subStep <= 1.0 || subStep >= step)
{
throw std::invalid_argument("Error: each subStep must be strictly greater than 1, and strictly smaller than step.");
}
}
// make ascending.
std::vector<double> sortedSubSteps(subSteps.begin(), subSteps.end());
std::sort(sortedSubSteps.begin(), sortedSubSteps.end());
if (value <= baseLength)
{
return baseLength;
}
double length = baseLength;
double terminateLength = numeric_limits<double>::max() / step;
while (length < terminateLength)
{
for (VecDoubleIter iter = sortedSubSteps.begin(); iter != sortedSubSteps.end(); ++iter)
{
double subStep = *iter;
if (value <= length * subStep)
{
return (length * subStep);
}
}
double nextLength = length * step;
if (value <= nextLength)
{
return nextLength;
}
length = nextLength;
}
return baseLength;
}
int main()
{
double baseLength = 1.0;
double step = 10.0;
std::vector<double> subSteps;
subSteps.push_back(2.5);
subSteps.push_back(5);
for (int k = 0; k < 1000; k += ((k >> 2) + 1))
{
double value = k;
double result = getNiceAxisLength(value, baseLength, step, subSteps);
cout << "k: " << value << " result: " << result << endl;
}
cout << "Hello world!" << endl;
return 0;
}
Output
k: 0 result: 1
k: 1 result: 1
k: 2 result: 2.5
k: 3 result: 5
k: 4 result: 5
k: 6 result: 10
k: 8 result: 10
k: 11 result: 25
k: 14 result: 25
k: 18 result: 25
k: 23 result: 25
k: 29 result: 50
k: 37 result: 50
k: 47 result: 50
k: 59 result: 100
k: 74 result: 100
k: 93 result: 100
k: 117 result: 250
k: 147 result: 250
k: 184 result: 250
k: 231 result: 250
k: 289 result: 500
k: 362 result: 500
k: 453 result: 500
k: 567 result: 1000
k: 709 result: 1000
k: 887 result: 1000
Hello world!
Hello world!
I'm trying to calculate the covariance of a multichannel image patch (using cv::calcCovarMatrix), so I can in turn calculate the Mahalonobis distance of a pixel from that patch and I'm really struggling to find the right options to reshape the matrix into the right format.
For example if my matrix has 3 rows, 4 columns, and 2 channels:
// Channel 1:
1 2 3 4
5 6 7 8
9 0 1 2
// Channel 2:
99 98 97 96
95 94 93 92
91 90 89 88
What I believe I need is to reshape the image into a shape with 3x4=12 rows and 2 columns (or its transpose):
// Desired result:
1 2 3 4 5 6 7 8 9 0 1 2
99 98 97 96 95 94 93 92 91 90 89 88
Is this the correct format for cv::calcCovarMatrix?
What parameters do I need for .reshape() to achieve this?
An example in code:
#include <opencv2/opencv.hpp>
int main(int argc, char* argv[])
{
// Construct channel 1
cv::Mat_<float> channel1 = (cv::Mat_<float>(3, 4) << 1.0, 2.0, 3.0, 4.0,
5.0, 6.0, 7.0, 8.0,
9.0, 0.0, 1.0, 2.0);
std::cout << "Channel 1: " << std::endl;
std::cout << channel1 << std::endl;
// Construct channel 2
cv::Mat_<float> channel2 = (cv::Mat_<float>(3, 4) << 99.0, 98.0, 97.0, 96.0,
95.0, 94.0, 93.0, 92.0,
91.0, 90.0, 89.0, 88.0);
std::cout << "Channel 2: " << std::endl;
std::cout << channel2 << std::endl;
// Merge together
std::vector<cv::Mat> stack;
cv::Mat merged;
stack.push_back(channel1);
stack.push_back(channel2);
cv::merge(stack, merged);
std::cout << "Merged:" <<std::endl;
std::cout << merged << std::endl;
// Reshape
cv::Mat reshaped = merged.reshape(0,1).reshape(1); // <----Need help with this line
std::cout << "Reshaped:" <<std::endl;
std::cout << reshaped << std::endl;
return 0;
}
Not tested, but looking at the docs and the calcCovarMatrix() implementation, you should do something like
cv::Mat reshaped = merged.reshape(1,1);
or
cv::Mat reshaped = merged.reshape(1,3*4);
It seems that calcCovarMatrix() can process both column matrices and row-matrices.
You can take a look at the code in opencv/modules/core/src/matmul.cpp, line 2097