no match for 'operator =' for 3d vector - c++

I am trying to convert a vector of coordinates std::vector surface into a 3D array, setting all entries of the 3d array that are contained in surface to 0;
however I am getting a no match for operator array.
I looked up the error several times but did not find my case....
std::vector<coordinates> surface is global.
the coordiantes simply look like
struct coords{
int xvalue;
int yvalue;
int zvalue;
coords(int x1, int y1, int z1) : xvalue(x1),yvalue(y1),zvalue(z1){}
~coords(){}
};
typedef struct coords coordinates;
and my method is:
(doubleBox is a typedef for a 3D double vector)
doubleBox levelset::putIntoBox( vector<coordinates> surface){
int xMaxs, yMaxs,zMaxs;
for (vector<coordinates>::iterator it = surface.begin() ; it != surface.end(); ++it){
if (it->xvalue > xMaxs)
xMaxs = it->xvalue;
if (it->yvalue > yMaxs)
yMaxs = it->yvalue;
if (it->zvalue > zMaxs)
zMaxs = it->zvalue;
//check invalid surface
if (it->xvalue < 0 || it->yvalue <0 || it->zvalue<0)
cout << "invalid surface with point coordinates below 0 !" << endl;
}
doubleBox surfaceBox[xMaxs+1][yMaxs+1][zMaxs+1];
int max = std::ceil(sqrt(xMaxs*xMaxs + yMaxs*yMaxs + zMaxs*zMaxs));
std::fill(&surfaceBox[0][0][0],&surfaceBox[0][0][0] + sizeof(surfaceBox)*sizeof(surfaceBox[0])/ sizeof(surfaceBox[0][0]) / sizeof(surfaceBox[0][0]), max);
for (vector<coordinates>::iterator it = surface.begin() ; it != surface.end(); it++){
surfaceBox[it->xvalue][it->yvalue][it->zvalue] = 0.0;
}
return surfaceBox;
}
the output is (declaring that the error lies in the second for-loop)
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\vector.tcc:160:5: note: std::vector<_Tp, _Alloc>& std::vector<_Tp, _Alloc>::operator=(const std::vector<_Tp, _Alloc>&) [with _Tp = std::vector<std::vector<double> >; _Alloc = std::allocator<std::vector<std::vector<double> > >]
vector<_Tp, _Alloc>::
^
c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\vector.tcc:160:5: note: no known conversion for argument 1 from 'const int' to 'const std::vector<std::vector<std::vector<double> > >&'
..\src\Levelset.cpp: In member function 'doubleBox levelset::putIntoBox(std::vector<coords>)':
..\src\Levelset.cpp:295:1: warning: control reaches end of non-void function [-Wreturn-type]
Maybe this problem is caused by the fact that std::fill is used inappropriately??

Since doubleBox is defined as std::vector<std::vector<std::vector<double>, why do you define doubleBox surfaceBox[xMaxs+1][yMaxs+1][zMaxs+1]; in this way?
What you defined is a 3 dimensional array whose element type is doubleBox, which means that every element is of type std::vector<std::vector<std::vector<double>, which is not what you want.
You may need something like doubleBox surfaceBox(xMaxs + 1, std::vector<std::vector<double>>(yMaxs + 1, std::vector<double>(zMaxs + 1)));

Related

Slicing Eigen tensor: Error accessing matrices from tensors

I am new to tensor in Eigen and just trying to run simple examples here. This is the code I have it's to access the first matrix in a tensor. Let's say I have a tensor with size ((nz+1),ny,nx), where each matrix in this tensor should have the shape or size of (nz+1)-by-ny. The thing is I can only extract a matrix that returns size ny-by-nz.
The code:
static const int nx = 10;
static const int ny = 10;
static const int nz = 10;
Eigen::Tensor<double, 3> epsilon((nz+1),ny,nx);
epsilon.setZero();
//slicing test: access first matrix in tensor
std::array<long,3> offset = {0,0,0}; //Starting point
std::array<long,3> extent = {1,ny,nx}; //Finish point
std::array<long,2> shape2 = {(ny),(nx)};
std::cout << epsilon.slice(offset, extent).reshape(shape2) << std::endl;
The answer is a matrix with a 10-by-10 size. How can I change this to extract slice and reshape it into a 11x10 matrix instead (11 rows and 10 columns). I tried changing last line to std::array<long,2> shape2 = {(nz+1),(nx)}; but this returns the error:
Eigen::TensorEvaluator<const Eigen::TensorReshapingOp<NewDimensions, XprType>, Device>::TensorEvaluator(const XprType&, const Device&) [with NewDimensions = const std::array<long int, 2>; ArgType = Eigen::TensorSlicingOp<const std::array<long int, 3>, const std::array<long int, 3>, Eigen::Tensor<double, 3> >; Device = Eigen::DefaultDevice; Eigen::TensorEvaluator<const Eigen::TensorReshapingOp<NewDimensions, XprType>, Device>::XprType = Eigen::TensorReshapingOp<const std::array<long int, 2>, Eigen::TensorSlicingOp<const std::array<long int, 3>, const std::array<long int, 3>, Eigen::Tensor<double, 3> > >]: Assertion `internal::array_prod(m_impl.dimensions()) == internal::array_prod(op.dimensions())' failed.
Aborted
How can I change the number of rows in this matrix? Thanks
I was able to fix:
std::array<long,3> offset = {0,0,0}; //Starting point
std::array<long,3> extent = {(nz+1),nx,1}; //Finish point:(row,column,matrix)
std::array<long,2> shape = {(nz+1),(nx)};
std::cout << epsilon.slice(offset, extent).reshape(shape) << std::endl;

why I cannot multiply an op result by the constant eigen tensor array

Why it's not legal to do multiplication of the tensor op(sqrt()) and the linear.constant()
Eigen::Tensor<float, 1> linear(2);
linear.setValues({3,4});
auto linear_square = linear * linear;
auto linear_square_sum = linear_square.sum().sqrt();
std::cout<<linear_square_sum<<std::endl; // 5
auto new_linear = linear_square_sum * linear.constant(5); //no compiling error but aborted when executing
error info
tensor2matrix:
/usr/local/include/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h:380:
Eigen::TensorEvaluator, Device>::TensorEvaluator(const XprType&,
const Device&) [with BinaryOp =
Eigen::internal::scalar_product_op; LeftArgType = const
Eigen::TensorCwiseUnaryOp,
const Eigen::TensorReductionOp,
const Eigen::DimensionList, const
Eigen::TensorCwiseBinaryOp, const Eigen::Tensor, const Eigen::Tensor
, Eigen::MakePointer> >; RightArgType = const Eigen::TensorCwiseNullaryOp,
const Eigen::Tensor >; Device = Eigen::DefaultDevice;
Eigen::TensorEvaluator, Device>::XprType =
Eigen::TensorCwiseBinaryOp, const
Eigen::TensorCwiseUnaryOp,
const Eigen::TensorReductionOp,
const Eigen::DimensionList, const
Eigen::TensorCwiseBinaryOp, const Eigen::Tensor, const Eigen::Tensor
, Eigen::MakePointer> >, const Eigen::TensorCwiseNullaryOp,
const Eigen::Tensor > >]: Assertion
`dimensions_match(m_leftImpl.dimensions(), m_rightImpl.dimensions())'
failed. Aborted
I'm pretty sure people already linked to you the documentation saying that using auto with expression templates is not a good idea. Evaluating one expression template multiple times seems like an even worse idea.
If you don't want/can't explicitly mention the types you can base them on the original values you put in.
Eigen::Tensor<float, 1> linear(2);
linear.setValues({ 3,4 });
decltype(linear) linear_square = linear * linear;
Eigen::Tensor<decltype(linear)::Scalar, 0> linear_square_sum = linear_square.sum().sqrt();
std::cout << linear_square_sum << std::endl; // 5
// Don't forget to convert to an actual scalar
// |
// v
decltype(linear) new_linear = linear_square_sum() * linear.constant(5);
std::cout << new_linear;
return 0;

simple multiplication or operator issue

I am trying to run this simple code. But I am missing something. I tried to look at operator overloading. Could someone explain what I am missing here.
#include <iostream>
#include <vector>
#include <cstdlib>
int main(){
std::vector < std::vector<double> > tm;
std::vector<int> dfg;
// Creating a simple matrix
double ta1[]={0.5,0.5,0};
std::vector <double> tv1 (ta1, ta1+3);
tm.push_back(tv1);
double ta2[]={0.5,0,0};
std::vector <double> tv2 (ta2, ta2+3);
tm.push_back(tv2);
double ta3[]={0,0.5,0};
std::vector <double> tv3 (ta3, ta3+3);
tm.push_back(tv3);
double d_load =0.5;
// doing some simple calculations
for (int destinationID = 1; destinationID <= tm.size(); destinationID++){
float randomNum = ((double) rand())/((double) RAND_MAX);
if (randomNum <= d_load * tm[destinationID - 1])
dfg.push_back(destinationID);
}
return 0;
}
I get the following error.
error: no match for ‘operator*’ in ‘d_load * tm.std::vector<_Tp, _Alloc>::operator[] [with _Tp = std::vector<double>, _Alloc = std::allocator<std::vector<double> >, std::vector<_Tp, _Alloc>::reference = std::vector<double>&, std::vector<_Tp, _Alloc>::size_type = long unsigned int](((long unsigned int)(destinationID + -0x00000000000000001)))’
The tm is a std::vector<std::vector<double>>, thus effectively it is a 2-dimensional dynamic array of double. This means that to access the individual double elements in tm, you would use something like this:
double value = tm[destinationID - 1][theValueIndex];
It is the [theValueIndex] part of the loop that you're missing.
Since we don't know your exact intentions on how you want to traverse the array, I leave it to you to fill in this gap.
The following line is invalid:
d_load * tm[destinationID - 1]
Since tm is a std::vector<std::vector<double>>, The elements of tm are std::vector<double>, not double. If you want to multiply each number or check that each number matches the condition, you have to iterate the element you're getting out of tm[]

Eigen passing Quaternionf, discards qualifiers

i am trying to use Eigen::Quaternionf. But i am getting when i just want to asign one Quaternion an error.
oldQuat = pos;
both are Eigen::Quaternionf, the following error is given. Is must be because the Methods are declared as constant (see: http://eigen.tuxfamily.org/dox/classEigen_1_1Quaternion.html)
Fehler: passing 'const Quaternionf {aka const Eigen::Quaternion<float>}' as 'this' argument of 'Eigen::Quaternion<Scalar, Options>& Eigen::Quaternion<Scalar, Options>::operator=(const Eigen::Quaternion<Scalar, Options>&) [with _Scalar = float, int _Options = 0, Eigen::Quaternion<Scalar, Options> = Eigen::Quaternion<float>]' discards qualifiers [-fpermissive]
I have to idea on how to get past this error. Thanks in advance
edit:
for (itCanon = canonicalValues.begin(), itTraj = exampleTraj.begin(); itCanon != canonicalValues.end(); ++itCanon, itTraj++)
{
const SampledTrajectoryV2::TrajData& state = *itTraj;
Eigen::Vector3f axis;
axis << itTraj->getPosition(1), itTraj->getPosition(2), itTraj->getPosition(3);
Eigen::AngleAxisf angleAxis(itTraj->getPosition(0), axis);
Eigen::Quaternionf pos(angleAxis);
pos.normalize();
//Error in both these lines! Same error both times.
Eigen::Vector3f vecVel = calcAngularVelocity(oldQuat, pos);
oldQuat = pos;
// D0 element R3x3 nicht kompatibel mit quat
result[*itCanon] = - A_Z*(B_Z*2*log(pos) - TAU * vecVel);
}
oldQuat is declared in the header. as are A_z, B_Z and TAU.
Eigen::Quaternionf<S, O>::operator= is declared as non const, but oldQuat is a const object (I suspect). Change it to non-const.

"no matching function for call to min_element" when using a vector of CvPoints (opencv)

Here's my function to retrieve the corners of a rectangle, the input is a thresholded image (with a numberplate on it) and I want the output to be a vector (within a vector) with the cornerpoints of the plate. Ordered: left_up, right_up, right_bottom, left_bottom.
I use openCV to find the contours (which works fine); after some filters, I use approxPoly to find rectangles. I find four points, which is great, but I want to order them. I thought the following would work:
put all the point in a vector
find min_element specified by compare function Left and erase from vector
find another left element and erase, then determine which is up and which is down.
the remaining two points are the right points.
bool left(CvPoint &pt1, CvPoint &pt2) {
return pt1.x < pt2.x;
}
bool up(CvPoint &pt1, CvPoint &pt2) {
return pt1.y < pt2.y;
}
std::vector<std::vector<CvPoint> > findNumberPlate(IplImage* img) {
vector<CvPoint> numberplate;
vector<vector<CvPoint> > numberplates_output;
CvMemStorage* storage = cvCreateMemStorage(0);
CvMemStorage* storage2 = cvCreateMemStorage(0);
CvSeq* contour = 0;
cvFindContours(img, storage, &contour, sizeof (CvContour), CV_RETR_EXTERNAL);
CvSeq* result = 0;
for (CvSeq* c = contour; c != NULL; c = c->h_next) {
double area_contour = cvContourArea(c, CV_WHOLE_SEQ);
CvBox2D c_box = cvMinAreaRect2(c);
double area_box = c_box.size.height * c_box.size.width;
if (area_contour / area_box > 0.83 && area_contour > 2000) {
if (!storage2 == 0) cvClearMemStorage(storage2);
else storage2 = cvCreateMemStorage(0);
result = cvApproxPoly(c, sizeof (CvContour), storage2, CV_POLY_APPROX_DP, cvContourPerimeter(c)*0.03, 0);
if (result->total == 4) {
//find up/bottom & left/right
vector<CvPoint> points;
for (int i = 0; i < 4; i++) {
CvPoint* tempPoint = (CvPoint*) cvGetSeqElem(result, i);
points.push_back(cvPoint(tempPoint->x,tempPoint->y));
}
vector<CvPoint>::iterator itLeft1 = std::min_element(points.begin(), points.end(), left);
points.erase(itLeft1);
vector<CvPoint>::iterator itLeft2 = std::min_element(points.begin(), points.end(), left);
points.erase(itLeft2);
vector<CvPoint>::iterator itLeftUp = std::min(itLeft1, itLeft2, left);
vector<CvPoint>::iterator itLeftBottom = std::max(itLeft1, itLeft2, left);
CvPoint left_up = *itLeftUp;
CvPoint left_bottom = *itLeftBottom;
vector<CvPoint>::iterator itRightUp = std::min(points.begin(), points.end(), up);
vector<CvPoint>::iterator itRightBottom = std::max(points.begin(), points.end(), up);
CvPoint right_up = *itRightUp;
CvPoint right_bottom = *itRightBottom;
//etc
}
However, when using the function min_element & max_element I get several errors I don't understand.
findNumberPlate.cpp:57: error: no matching function for call to ‘min_element(__gnu_cxx::__normal_iterator<CvPoint*, std::vector<CvPoint, std::allocator<CvPoint> > >, __gnu_cxx::__normal_iterator<CvPoint*, std::vector<CvPoint, std::allocator<CvPoint> > >, <unresolved overloaded function type>)’
findNumberPlate.cpp:59: error: no matching function for call to ‘min_element(__gnu_cxx::__normal_iterator<CvPoint*, std::vector<CvPoint, std::allocator<CvPoint> > >, __gnu_cxx::__normal_iterator<CvPoint*, std::vector<CvPoint, std::allocator<CvPoint> > >, <unresolved overloaded function type>)’
findNumberPlate.cpp:62: error: no matching function for call to ‘min(__gnu_cxx::__normal_iterator<CvPoint*, std::vector<CvPoint, std::allocator<CvPoint> > >&, __gnu_cxx::__normal_iterator<CvPoint*, std::vector<CvPoint, std::allocator<CvPoint> > >&, <unresolved overloaded function type>)’
findNumberPlate.cpp:63: error: no matching function for call to ‘max(__gnu_cxx::__normal_iterator<CvPoint*, std::vector<CvPoint, std::allocator<CvPoint> > >&, __gnu_cxx::__normal_iterator<CvPoint*, std::vector<CvPoint, std::allocator<CvPoint> > >&, <unresolved overloaded function type>)’
Can't I use CvPoints with min_element? Or... Can anyone help me?
Thanks!
From the error message, it becomes very clear that there is another overloaded function with same name left, hence the compiler is unable to resolve which one you mean when you pass left as third argument to std::min_element.
So the solution is to help the compiler to disambiguate the situation as:
auto min = std::min_element(points.begin(),
points.end(),
static_cast<bool(*)(CvPoint&,CvPoint&)>(left) );
Well that looks cumbersome, so you can simplify it as:
bool (*leftptr)(CvPoint&,CvPoint&) = left; //compiler chooses the correct overload
auto min = std::min_element(points.begin(), points.end(), leftptr);
Or, this:
typedef bool (*left_type)(CvPoint&,CvPoint&);
left_type leftptr = left; //compiler chooses the correct overload
auto min = std::min_element(points.begin(), points.end(), leftptr);
In all these cases, the compiler chooses the correct overload based on the target type, be it in the static_cast, or in the leftptr declaration.