OpenCV - wrong results when accessing Mat - c++

Briefly, I would like to sum up values in a Mat matrix. For now I have a 256 by 1 Mat(which is actually a vector, but the Mat format will be important later on). In order to see what happens I'm trying to print it in the loop
`
calcFractile(Mat* in){
cout << "Input = " << *in << endl;
cout << "?!?! ";
for(int k = 0; k<in->rows; k++){
cout << static_cast<int>(in->at<uint8_t>(0,k)) << ", ";
sum += (int)in->at<uint8_t>(0,k);
}
cout <<endl;
}
`
I totally don't understand why, but the cout << "Input[...] line produces correct result, but the loop accessing individual elements fails giving different results
It's not just the value issue, but also positions in the array.
The Mat I'm passing is a histogram of an image, the histogram is single channel, 256 bins.

The problem came from type casting, or rather lack of it.
As soon as I wrote
static_cast(in->at(0,k)
and it worked.
Also just
(int)(in->at(0,k) seems to working fine as well.
Lesson I learned - *always check type casting * not that it's something new, but perhaps someone will benefit

Related

Cant send the whole vector through MPI_send

I have been trying to learn MPI. and when i try to run the following code i get the wrong output.
if (world_rank == 0){
vector<vector<double> > n(4,vector<double>(4));
srand(time(NULL));
for(int i=0; i<4 ;i++){
for(int j=0;j<4;j++){
n[i][j] = (double)rand()/RAND_MAX;
cout << n[i][j] << " ";
}
cout << endl;
}
MPI_Send((void*)&n[0][0],16*sizeof(double),MPI_BYTE,1,0,MPI_COMM_WORLD);
}else{
MPI_Status status;
vector<vector<double> > n(4,vector<double>(4));
MPI_Probe(0,0,MPI_COMM_WORLD,&status);
int size;
MPI_Get_count(&status,MPI_BYTE,&size);
cout << endl << size << endl;
MPI_Recv((void*)&n[0][0],16*sizeof(n[0][0]),MPI_BYTE,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);
cout.flush();
cout << endl;
for(int i=0; i<4 ;i++){
for(int j=0;j<4;j++){
cout << n[i][j] << " ";
}
cout << endl;
}
}
i get all the double values except the last 3.
like this.
0.824468 0.752417 0.757125 0.470763
0.251683 0.703306 0.157991 0.764423
0.815327 0.0402807 0.897109 0.313816
0.997203 0.796665 0.0522305 0.797733
128
0.824468 0.752417 0.757125 0.470763
0.251683 0.703306 0.157991 0.764423
0.815327 0.0402807 0.897109 0.313816
0.997203 0 0 0
can anyone tell me why this is happening?
i ran the same code around a hundred times and still get the same output (of course with different values) but the last three always are 0.
but when i changed the size from 16 to 19 i get all the values.
i also have another doubt.
some times the outputs (values from node 0 and 1) get overlapped. can anyone tell me how to stop that or at least explain why that happens. i mean even though send and recv are blocking functions. how can the node 1's output get printed before node 0's
Your definition of the 2D data n as vector<vector<double> > makes it non-contiguous in memory. Therefore, you cannot transmit it simply using MPI (there are ways for doing it, but you'd better just making the memory contiguous instead).
To have your memory contiguous, you can declare your n like this (not tested):
vector<double> ndata(4*4); //contiguous storage of the actual data
vector<double*> n(4); //vector of pointers to access the actual data
for (int i=1; i<4; i++) //initialisation of the pointers to the data
n[i] = &ndata[4*i];
Of course, there are better ways of defining a contiguous storage for multidimensional arrays in C++, but this is just a quick fix for your immediate problem. See for example this answer for a better structure.
And BTW, your MPI_Send() and MPI_Recv() calls should use 4*4 MPI_DOUBLE instead of 4*4*sizeof(double) MPI_BYTE.

A bug of using for loop to print out matrix in my program

I wrote the following code to test in int main()
int main() {
int *p1 = findmatrixsize("inputmatrix.txt","A");//A function gets matrix size
cout << p1[0] << endl << p1[1] << endl;
int *p2 = findmatrixsize("inputmatrix.txt","B");
cout << p2[0] << endl << p2[1] << endl;
double **C = normalmultiplication("inputmatrix.txt","A", "B");
cout << C[0][0] << endl;
ofstream fout;
const string s="outputmatrix.txt";
fout.open(s);
for(int i=0;i<p1[0];i++){
for(int j =0;j<p2[1];j++){
fout << C[i][j] << " ";
}
fout<< endl;
}
fout.close();
return 0;
}
Everything works except when I am executing the multiarray printing. Here is the problem:
1.If I comment out the printing part, p1[0],p1[1],p2[0],p2[1],C[i][j] gives me perfect and correct result that I want.
2.However, when I print by using normal loops it doesn't work. But, but,but, if I change the p1[0],p2[1] in the for loop to a concrete number like 3(when my matrix dimension is 3), it works again.
3.It compiles, but the for loop printing part is not written into the txt. When I changed it to the standard print cout(not only the single line, I mean the whole method), I couldn't see them in the terminal neither. But as I mentioned above, when I change p[0] p[1] to 3, it works, which means I can see them either in the txt or terminal
I have never met such weird situation in C++ before, so I hope someone can help me out!
FYI, I use Visual Studio 2010 as compiler.
Thanks for your help!
We don't know what findmatrixsize and normalmultiplication do.
But if they do what I think they do (and I think they return pointers to their local data), the objects referred to by p1, p2 and C share storage.
Check if p1 == p2.
The problem is in the way you get result from findmatrixsize and normalmultiplication functions: they keep the result of calculation in stack and return a pointer to it, but the stack is destroyed soon after these functions finish their work. Reimplement these functions so that the place in memory is valid outside of these functions. For example,
int p1[2];
findmatrixsize("inputmatrix.txt","A", p1)
and put the result inside of findmatrixsize into the last argument, eg.
void findmatrixsize(const char* fileName, const char* matrixName, int* result)
{
// routine
result[0] = someValue1;
result[1] = someValue2;
}

Trying to pass an array to a function and find the sum

I am newbie to programming and I am trying to pass an array into a function and add all the elements together and return the sum. The problem is that I am getting a garbage value for the sum. I have researched on how to pass arrays to functions and I do not know if I'm supposed to use a pointer to pass arrays. I am not good with pointers anyways.
Here is my code
#include <cmath>
#include <cstdlib>
using namespace std;
float mean(int);
int sum(int ARRZO[5]);
int total;
int main()
{
int ARRZ[5];
char *inname = "example.txt";
ifstream infile(inname);
if (!infile) {
cout << "There was a problem opening file " << inname << " for reading." << endl;
return 0;
}
cout << "Opened " << inname << " for reading." << endl;
for(int i=0; i<11; i++)
{
while (infile >> ARRZ[i])
{
cout << "Value from file is " << ARRZ[i] << endl;
}
}
total=sum(ARRZ);
cout<<"the sum of the elements in the array is"<<total<<endl;
system("PAUSE");
return 0;
}
int sum(int ARRZO[])
{
int sumz=0;
for (int i=0; i<5; i++)
{
sumz+=ARRZO[i];
cout<<ARRZO[i];
}
cout<<sumz<<endl;
return sumz;
}
You are actually reading all the values from the file in ARRZ[0] because of the inner loop. By the time you get to i=1, you are at the end of the file, and not reading anything.
Remove one loop, and increment i when you have read successfully a value.
I'm not sure what you think this pair of nested loops is supposed to do:
for(int i=0; i<11; i++)
{
while (infile >> ARRZ[i])
{
cout << "Value from file is " << ARRZ[i] << endl;
}
}
But (as #aliexisdm pointed out) the inner loop reads the entire content of the file. What he didn't (at least directly) point out is that you're reading every one of those values into the first element of your array. Then you're getting back to the outer loop, incrementing i, and trying to read the file again -- but since the stream's failbit has been set, all your subsequent attempts at reading are guaranteed to fail.
After that, you add up the 5 items in the array, but since you haven't read anything into 4 of them (and never initialized its contents) you end up with the last item you read from the file + 4 garbage values, giving still further garbage as the result (well, usually anyway -- you really have undefined behavior, so the program could crash and burn instead, but with most current computers, you'll just get some meaningless number).
I, however, would advise changing the program a bit more than just removing one loop and incrementing in the loop that's left. Instead, I'd remove all the (explicit) loops, and make some attempt at making real use of what the standard library provides.
You can read the numbers from the file in one fell swoop:
std::ifstream infile(inname);
std::vector<int> ARRZ ((std::istream_iterator<int>(infile)),
std::istream_iterator<int>());
Then you can sum them all with std::accumulate:
int sum = std::accumulate(ARRZ.begin(), ARRZ.end(), 0);
Finally, you can print out the result:
cout << "The sum of the elements in the array is: " << sum << "\n";
Since, however, you only read the values from the file to add them together, you don't really need to store them at all. You could just add them together and print out the result:
cout << "The sum of the elements in the file is: "
<< std::accumulate(std::istream_iterator<int>(infile),
std::istream_iterator<int>(), 0);
The whole job reduced to one step...

(C++) Specific values in an array

I'm not sure how to title my question, but here goes. I am testing some features, and I have hit a snag.
What I want to know is how can I set up a "for" or "if" statement to only put values in an array that meet a criteria? For example, find every divisor for a number, but only put factors in an array.
Any help would be loved, source code can be provided if needed :). Yes, I am new, so be gentle!
#include <iostream>
using namespace std;
int main(){
int n;
int counter = 1;
cout << "What number would you like to use? ";
cin >> n;
int DiviArray[n];
for (int k=0,j=1;k<n;k++,j++)
{
DiviArray[k] = n-k;
}
int k = 3;
int factn[n];
cout << "Factors of " << n << ": " << endl;
for (int i=0, j=1;i<n;i++,j++)
{
factn[i] = n/DiviArray[i];
if(factn[i]*DiviArray[i]==n)
{
cout << counter << ". " << factn[i] << " x " << DiviArray[i] << endl;
counter++;
}
}
return 0;
}
EDIT: Decided to go with vectors, not sure if I can get it to work, but thanks for the feedback guys :)
Since you don't know in advance how many values will meet the condition, you should use a std::vector.
As a benefit, it keeps track of how many elements you've already added, so push_back will always use the next available index.
This also fixes
cin >> n;
int DiviArray[n];
which isn't legal C++.
If you only want to put the values into the array that match the condition, then you should only put a number into the array when the condition is matched. To do that, the statement that puts a number into the array has to be inside the if-block for the condition. I hope I don't need to explain why :)
This is the only time in your program where you actually do want two indices: one that is incremented every time through the loop (to count how many times to run the process), and one that is incremented only when you put a number in the array (to figure out where the next number goes). Everywhere else, you've created a completely useless j variable (the uselessness should be apparent from the fact that there is no code that actually uses the value, only code to set it).

Referencing elements from two-dimensional array with a single value

I am probably missing something fundamental, but i cannot find a solution to the following issue.
I have a two-dimensional array of some float elements and i am trying to find a way to be able to reference them by using only a single value.
Example:
float test[5][50];
test[3][25] = 34.67;
cout << test[3][25] << endl;
int id = 25;
cout << *test[id*5+3] << endl;
I am hoping to get same result from both cout. Instead my output looks like this:
34.67
Segmentation fault
What am I doing wrong?
Thanks!
Without testing, I think something like this might work. Note that C++ arrays are major->minor from left dimension to right dimension.
float test[5][50];
test[3][25] = 34.67;
cout << test[3][25] << endl;
int id = 25;
float* test2 = &test[0][0]
cout << test2[(3 * 50) + id] << endl;
test is a float[][] with 5 elements (each of which is a float[] with 50 elements), and you are referring to test[128]. Hence the seg fault.You need to convert from single index to subscript using integer division and mod:
cout << test[id/50][id%50] << endl;
You should assert(id/50<5); to make sure your index is within bounds.
The crash is because you are trying to read the contents of the element as a memory address
*test[id*5+3] means int address = test[id*5+3]; then read memory at address.
If that address is 0 or memory you don't own then it will crash.
Accessing a two-dimensional bitmap (image) with a single reference is often useful.
Use:
int image2D[dim2][dim1];
int *image1D = &image2D[0][0];
Now
image2D[i][j] == image1d[i*dim1+j]
I agree with the first comment, that you really shouldn't do it, but I'll answer anyway.
I think that if you try:
cout << test[id*5+3] << endl;
it should work. There is no need to dereference with *.