access single element in vec3d

I have this code that store 3d coordinates in vec3d.
Now I am trying to find the average of max & min value in first column (which is c in my vec3d)
then let the z (third column in my vec3d), z = current x - (avg found)

I am having error with the following code to find max and min values.
E0349 no operator "<" matches these operands
C2678 binary '<': no operator found which takes a left-hand operand of type 'const cv::Vec3d' (or there is no acceptable conversion)
I tried to search to resolve the error but nothing helps.
I learn how to access 3 elements like, myVec.at(100), but I am having trouble to access a single element out from 3 values because it only making sense to me that now the vec3d comes in three.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "iostream"
#include <vector>
#include <direct.h>
#include <algorithm> // for copy
#include <iterator> // for ostream_iterator

using namespace cv;
using namespace std;

Mat pic, gray, bw;
int rows, cols;

string path_in = "C:/Users/Dell/Desktop/";
string path_out = "C:/Users/Dell/Desktop/New Folder/";

/*bool sortcol(const myVec& v1,
const myVec& v2,
const myVec& v3)
{
return v1[1] < v2[1] < v3[1];
}*/

bool sortcol(const vector<Vec3d>& v1,
	const vector<Vec3d>& v2,
	const vector<Vec3d>& v3)
{
	return v1[1] < v2[1] < v3[1];
}

int main(int argc, char** argv)
{
	vector<cv::String> fn;
	vector<cv::String> fo;
	glob(path_in + "*.jpg", fn, false);
	glob(path_out + "*.jpg", fo, false);

	size_t count = fn.size();
	for (size_t i = 0; i < 1; i++) //try for an image first, if works, then try for all images in folder
	{
		pic = imread(fn[i], CV_LOAD_IMAGE_COLOR);
		cout << fn[i] << endl;

		cvtColor(pic, gray, CV_BGR2GRAY);
		//Canny(gray, gray, 50, 150, 3);

		threshold(gray, bw, 128.0, 255.0, THRESH_BINARY);

		std::vector<Vec3d> myVec;
		for (int r = 0; r < bw.rows; r++)
		{
			for (int c = 0; c < bw.cols; c++)
			{
				if (bw.at<uchar>(r, c) > 0) // white pixels
				{
					double z = 3.1209;
					//myVec.push_back(Point(r, c));
					myVec.push_back(Vec3d(c, r, z)); //add them to vector3d

					//cout << " : " << myVec.at<Vec3d>myVec.r << " , " << myVec.at<Vec3d>myVec.c << " , " << z << endl;
				}
			}
		}


		std::copy(myVec.begin(), myVec.end(), std::ostream_iterator<Vec3d>(std::cout << " " << std::endl));
		std::cout << "size: " << myVec.size() << '\n';
		//std::cout <<  myVec.at(myVec.size() - 1);
		//std::cout << ' ' << myVec.at(100) << '\n';

		//sort(myVec.begin(), myVec.end(), sortcol);
		auto min = std::min_element(myVec.begin(), myVec.end(), sortcol);
		auto max = std::max_element(myVec.begin(), myVec.end(), sortcol);


		waitKey(0);
	}

	system("PAUSE");
	//return 0;
}



Thank you .
Your sortcol is wrong. It isn't going to be passed three vectors. It's going to be passed two elements, which are Vec3d objects. So maybe something like this:
1
2
3
4
bool sortcol(const Vec3d& v, const Vec3d& w)
{
    return v[1] < w[1];
}

It was complaining about the < sign because you were trying to compare two vectors instead of two doubles.
Last edited on
Hi @tpb,

Thank you!

Is that mean 'v' and 'w' here are not vector?
Correct me if I am wrong, is v[1] < w[1] means that sort first column by comparing 1st element and second element, then second element with third element in the single column?

May I know how do i get single element from the first column ?
because they seems like come in three, i do not know how to get a single value?

or would you have any recommend reading materials you figured i shall go through to get that?
I think I might overlooked, or i just do not know the right keyword to look for.

Thanks again
Last edited on
Glacous, Vec3d appears to be a custom container of three doubles, as per the OpenCV documentation that I linked in the last post. v[1] is the second element in the v, likely equal to "y" coordinate.

Now I am trying to find the average of max & min value in first column

Not sure exactly what you're looking for. Here is an example which may give you some ideas:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include <iostream>
#include <array>
#include <vector>
#include <algorithm>

using namespace std;

// Similar to Vec3d
typedef array<double,3> Vec3d;

// From a collection of points, finds average coordinate value
//  i=0 - average X value
//  i=1 - average Y value
//  i=2 - average Z value
double AverageCoordinate(const vector<Vec3d>& v, int i)
{
    double sum = 0.0;
    for (auto& v3d : v)
        sum += v3d[i];
    return sum/v.size();
}

Vec3d AveragePoint(const Vec3d& a, const Vec3d& b)
{
    Vec3d avg;
    avg[0] = (a[0]+b[0])/2.0;
    avg[1] = (a[1]+b[1])/2.0;
    avg[2] = (a[2]+b[2])/2.0;
    return avg;
}

// From a collection of points, compare based on X, then Y, then Z
bool PointComparer(const Vec3d& a, const Vec3d& b)
{
    if (a[0] < b[0]) return true;
    if (a[0] > b[0]) return false;
    
    if (a[1] < b[1]) return true;
    if (a[1] > b[1]) return false;
    
    return a[2] < b[2];
}

void ShowPoint(const Vec3d& p)
{
    cout << "[" << p[0] << ", " << p[1] << ", " << p[2] << "]\n";
}

void Show(const vector<Vec3d>& v)
{
    for(auto& p : v)
        ShowPoint(p);
}

int main() 
{
    vector<Vec3d> points = 
    {
        {0.0, 0.4, 0.7},
        {0.2, 0.3, 0.0},
        {0.1, 0.7, 0.2},
        {0.7, 0.3, 0.5},
        {0.7, 0.2, 0.6},
        {0.9, 0.5, 0.4},
        {0.3, 0.2, 0.7},
        {0.8, 0.2, 0.2},
        {1.0, 0.8, 0.7},
        {0.8, 0.5, 0.0},
        {0.4, 0.7, 0.4},
        {0.0, 1.0, 0.0},
        {0.6, 0.8, 0.4},
        {0.4, 0.9, 0.6},
        {0.8, 0.0, 0.2},
        {0.6, 1.0, 0.1},
        {0.9, 0.3, 0.3},
        {0.9, 0.9, 0.0},
        {0.6, 0.5, 0.0},
        {0.9, 0.6, 0.3},
        {0.4, 0.2, 0.4},
        {0.9, 0.3, 0.6},
        {0.3, 0.6, 0.5},
        {0.8, 0.9, 0.7},
        {0.0, 0.6, 0.2},
        {0.1, 0.8, 0.3},
        {0.7, 0.8, 0.7},
        {0.7, 0.6, 0.0},
        {0.6, 0.5, 0.3},
        {0.4, 0.6, 0.0},
        {0.9, 0.5, 0.9},
        {0.2, 1.0, 0.6},
        {1.0, 0.2, 0.0},
        {0.1, 0.8, 0.8},
        {0.1, 0.8, 0.7},
        {0.3, 0.2, 0.4},
        {0.4, 0.0, 0.4},
        {0.9, 0.5, 0.0},
        {0.4, 0.4, 0.4},
        {0.9, 0.2, 0.3},
        {0.6, 0.6, 0.1},
        {0.7, 0.7, 0.2},
        {0.9, 0.8, 0.2},
        {0.2, 0.7, 0.2},
        {0.3, 0.1, 0.6},
        {1.0, 0.7, 0.0},
        {0.0, 0.2, 0.4},
        {0.1, 0.7, 0.0},
        {0.0, 1.0, 0.1},
        {0.8, 0.3, 0.2},
        {0.0, 0.3, 1.0},
        {0.2, 0.5, 1.0},
        {0.7, 0.1, 0.1},
        {0.3, 1.0, 0.9},
        {0.0, 0.0, 0.6},
        {0.9, 0.0, 0.3},
        {0.3, 0.3, 0.3},
        {0.1, 0.6, 0.3},
        {0.0, 0.9, 0.7},
        {1.0, 0.1, 0.5},
        {0.0, 1.0, 1.0},
        {0.4, 0.6, 0.9},
        {0.9, 0.8, 0.0},
        {0.3, 0.9, 0.9},
        {0.4, 0.4, 0.1},
        {0.9, 0.3, 0.7},
        {0.4, 0.7, 0.5},
        {0.1, 1.0, 0.8},
        {0.2, 0.2, 0.7},
        {0.8, 1.0, 0.6},
        {0.6, 0.1, 0.5},
        {0.8, 0.7, 1.0},
        {0.9, 0.9, 0.0},
        {0.1, 0.7, 0.7},
        {0.8, 1.0, 0.5},
        {0.0, 0.6, 0.8},
        {0.6, 1.0, 0.1},
        {0.6, 0.7, 0.2},
        {0.7, 0.6, 0.1},
        {0.5, 0.9, 0.3},
        {0.1, 1.0, 1.0},
        {0.4, 0.5, 0.3},
        {0.8, 0.9, 0.8},
        {0.6, 0.9, 0.1},
        {0.3, 0.7, 0.3},
        {0.2, 0.1, 0.8},
        {0.9, 0.3, 0.9},
        {0.6, 0.0, 0.3},
        {0.8, 0.4, 0.2},
        {0.9, 0.1, 0.6},
        {0.3, 0.5, 0.0},
        {0.5, 0.5, 0.1},
        {0.4, 0.6, 0.2},
        {1.0, 0.5, 0.0},
        {0.2, 1.0, 0.8},
        {0.8, 0.8, 0.9},
        {0.3, 0.2, 0.7},
        {0.8, 0.6, 0.3},
        {0.1, 0.0, 1.0},
        {0.8, 0.7, 0.9}
    };
    
    cout << "Before:" << endl;
    Show(points);
    cout << endl;
    
    cout << "After:" << endl;
    sort(points.begin(), points.end(), PointComparer);
    Show(points);
    
    cout << endl;
    cout << "AveragePoint of points[0] and points["<<points.size()-1<<"]:" << endl;
    ShowPoint(AveragePoint(points[0], points[points.size()-1]));
    
    cout << endl;
    cout << "AverageCoordinate from all points." << endl;
    cout << "  X: " << AverageCoordinate(points, 0) << endl;
    cout << "  Y: " << AverageCoordinate(points, 1) << endl;
    cout << "  Z: " << AverageCoordinate(points, 2) << endl;
    
    return 0;
}


can test at https://repl.it/repls/MeanGigaClosedsource
Last edited on
Thank you so much icy1 ! below is my modified code referring your advised code

I have a doubt, may I know is the storing container now a vector or an array?
I am sorry, I am a little confused.
Sorry for the long-winded post. I have a few questions.

1. As I go through some sites, I figured tydef is like..
typedef existing_dataType<userDefined_dataType, numberInOneElement> storage_name;
is it correct??
typedef array<double, 3> cvVec3d;

2. I have a few comments listed in my code based on my weak assumptions.
Would you have a look and point it out if it is wrong?
Thank you so much.
It was so lovely wake up to this helpful code.

3. since 3 points together is An Element.
This is the first element in your code, [0, 0.4, 0.7],
If I were to refer 0.4, should I call it a point?
like "pointY in first element of Point (array/vector)" ?

4. Is it possible to have hundred of vector?
Like one vector per image? because sometimes i have up to 400 images.
I tried to make it like the below, but it seems that it doesn't work this way,
std::vector<Vec3d> myVec[i]; //i is the integer in image loop
but it says 'the value in variable i cannot be used as a constant'.

5. last question,
Am I able to retrieve single point out from an element?
[0, 0.4, 0.7], I want to get 0, so it is supposed to be a[0] or p[0],
so I tried to do the below, but it says, a and p are undefined?
cout << a[0] << endl;
cout << p[0] << endl;

I tried to change 'return avg' to 'return avg[0]' since I am only concern about the average of X.
but instead of getting 0.5, I got [0.5, 0, 0] :(

*p/s : I am actually need to generate z (third column value) from it respective x value. **with hope


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "iostream"
#include <array>
#include <vector>
#include <direct.h>
#include <algorithm> // for copy
#include <iterator> // for ostream_iterator

using namespace cv;
using namespace std;

//if I put 'Vec3d' instead of 'cvVec3d', 
//it makes the rest of the Vec3d ambiguous.
// I know it has to do with the 'using namespace cv' above, 
//but I couldn't figured out why it's affected tho
//typedef existing_dataType<userDefined_dataType, numberInOneElement> storage_name;
typedef array<double, 3> cvVec3d; 

Mat pic, gray, bw;
int rows, cols;

//string path_in = "C:/Users/Dell/Desktop/";
//string path_out = "C:/Users/Dell/Desktop/New Folder/";

Vec3d AveragePoint(const Vec3d& a, const Vec3d& b) //comparing 2 elements
{
	Vec3d avg;

	//XYZ = 0,1,2 ; a=first entry in col, b=last entry in col
	avg[0] = (a[0] + b[0]) / 2.0; //X avg of max+min = first + last entry in the column
	avg[1] = (a[1] + b[1]) / 2.0; //Y avg of max+min
	avg[2] = (a[2] + b[2]) / 2.0; //Z avg of max+min
	return avg;
}

bool PointComparer(const Vec3d& a, const Vec3d& b) //comparing each value in column
{
	if (a[0] < b[0]) return true;  //sort from first to last point in X? true, if it is in ascending order
	if (a[0] > b[0]) return false;  //else

	if (a[1] < b[1]) return true;  //sort from first to last point in Y?
	if (a[1] > b[1]) return false;  //

	return a[2] <= b[2];  //compare first and last point in Z?
	//wonder why in this condition <= is used unlike the previous comparison with only < or > ?
}

void ShowPoint(const Vec3d& p) //show all points of particular element in array/vector
{
	cout << "[" << p[0] << ", " << p[1] << ", " << p[2] << "]\n"; 
}

void Show(const vector<Vec3d>& v)//show all points of all elements in array/vector
{
	//auto& modify values in sequence
	
	for (auto& p : v) //loop each element in v(vector in code)? while v is the total number in array/vector
		ShowPoint(p);
}

//attempts
/*bool sortcol(const myVec& v1,
const myVec& v2,
const myVec& v3)
{
return v1[1] < v2[1] < v3[1];
}*/

/*
bool sortcol(const Vec3d& v1,
	const Vec3d& v2)
{
	return v1[1] < v2[1];
}
*/

int main(int argc, char** argv)
{
	vector<cv::String> fn;
	vector<cv::String> fo;
	glob(path_in + "*.jpg", fn, false);
	glob(path_out + "*.jpg", fo, false);

	size_t count = fn.size();
	for (size_t i = 1; i < 2; i++) //try for an image first, if works, then try for all images in folder
	{
		pic = imread(fn[i], CV_LOAD_IMAGE_COLOR);
		cout << fn[i] << endl;

		cvtColor(pic, gray, CV_BGR2GRAY);
		//Canny(gray, gray, 50, 150, 3);

		threshold(gray, bw, 128.0, 255.0, THRESH_BINARY);

		std::vector<Vec3d> myVec;
		for (int c = 0; c < bw.cols; c++)
		{
			for (int r = 0; r < bw.rows; r++)
			{
				if (bw.at<uchar>(r, c) > 0) // white pixels
				{
					double z = 3.1209;
					//myVec.push_back(Point(r, c));
					myVec.push_back(Vec3d(c, r, z)); //add them to vector3d

					//cout << " : " << myVec.at<Vec3d>myVec.r << " , " << myVec.at<Vec3d>myVec.c << " , " << z << endl;
				}
			}
		}
		
		//std::copy(myVec.begin(), myVec.end(), std::ostream_iterator<Vec3d>(std::cout << " " << std::endl));
		//std::cout << "size: " << myVec.size() << '\n';
		//std::cout <<  myVec.at(myVec.size() - 1);
		//std::cout << ' ' << myVec.at(100) << '\n';


		//failed attempt
		/*std::vector<Vec3d> myVec;
		for (int l = 0; l<3; l++)
		{
			for (int m = 0; m<3; m++)
			{
				for (int n = 0; n < 3; n++)
				{
					cout << myVec[l][m][n] << "\t";
				}
			}
			cout << endl;
		}*/
		//myVec[c][r][z] = [492, 477, 3.1209];
		//double getX();
		//cout << myVec.getX(1846) << '\n';
		//sort(myVec.begin(), myVec.end(), sortcol);
		//auto min = std::min_element(myVec.begin(), myVec.end(), sortcol);
		//auto max = std::max_element(myVec.begin(), myVec.end(), sortcol);
		//std::cout << min << '\n';
		//std::cout << max << '\n';

		//cout << "Before:" << endl;
		//Show(myVec);
		//cout << endl;

		//cout << "After:" << endl;
		sort(myVec.begin(), myVec.end(), PointComparer);
		std::copy(myVec.begin(), myVec.end(), std::ostream_iterator<Vec3d>(std::cout << " " << std::endl));
		//Show(myVec);

		//cout << endl;
		cout << "AveragePoint of points[0] and points[" << myVec.size() - 1 << "]:" << endl;
		ShowPoint(AveragePoint(myVec[0], myVec[myVec.size() - 1]));

		//cout << a[0] << endl;
		//cout << p[0] << endl;
	}

	system("PAUSE");
	//return 0;
}
Last edited on
Hi Glacous,

1. I only did the typedef because I didn't want to include opencv and to make the example runnable online. typedef is used for aliasing. In my example, typedef array<double,3> Vec3d; , from then on anywhere I used Vec3d can and will be replaced by array<double,3> at compile time. It's used when there are especially long namespaces just to shorten the code and hopefully make it more readable. In the OpenCV documentation, as I had linked somewhere (your last forum post?), their Vec3d looks very similar to that. Use their original structure; you don't need to typedef. It's like a vector in the mathematical sense; I doubt it has, for example, a push_back() method defined.

2. AveragePoint just averages any two points you give it. Doesn't iterate over anything. I just demo'd its usage on the first and last points of the sorted collection.
PointComparer -- so the classic comparator functions usually just return a<b and are done. When sorting based on multiple criteria, you isolate each criterion. In this case, I preferred to sort by point[0] first, then by point[1], then point[2]. If it gets by the first two if statements, that means a[0]==b[0] and so we examine the next index. So indirectly the equals cases are accounted for. The last line would probably work with a[2]<b[2] as well; it just might perform a swap if all coordinates are equal.
Show() function -- for(auto& : v) and for(auto : v) is the difference between references and value copies during the iteration, as each element in turn is assigned to auto. Prefer references; can also qualify with const.

3. I think the whole thing together (that is, one Vec3d) represents a point in an image.
I could be wrong; maybe it's the colors that the pixel consists of, and it's r,g,b instead of x,y,z. Again, you should prob read their docs.

4. You can have as many std::vector s as you want. For each image, you're writing to "pic", then to "gray", then to "bw", and creating a new vector to store points that meet some criteria. You could make multiple vectors here to store different things as you iterate through rows/cols of your cv::Mat, sure.

5. If you want the average X of all the points in your std::vector<Vec3d> , just use AverageCoordinate function. To get X you'd need the index in your vector first... myVec[i][0].

Good luck in your project. You may need to look more carefully to see what it is exactly you're working with; maybe they're not coordinates after all.
Thank you icy1 for the useful input.

I was caught up with the old project, finally back to this.
I understand that if {0.0, 0.4, 0.7} is the first entry,
then myVec[i][0] get 0.0, myVec[i][0] = 0.4, and so forth.

But here I have one last concern with this multidimensional array thingy.

1. I want to get z before I proceed with other steps, but i am stuck here, hard.
z = x.midpoint - respective x

in the code, i went like below to get the value of x.
I am dazed that it is not working. the line 'int g = myVec[i][t];'
is where some exception thrown comes in. I checked it online, but I couldn't see how it helps. *sweating
Then I tried myVec[c][0] or myVec[c][1], with hope that it gives the value of first x and second x, but no luck.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
		int t = 0;
		
		std::vector<Vec3d> myVec;
		for (int c = 0; c < bw.cols; c++)
		{
			for (int r = 0; r < bw.rows; r++)
			{
				if (bw.at<uchar>(r, c) > 0) // white pixels
				{
					

					t += 3;
					int g = myVec[i][t]; //fail attempt: using avg[0]-x

					myVec.push_back(Vec3d(c, r, g));
				}
			}
		}



2. To get accurate results, I realised that I have to find the largest x and smallest x with same y.
So I am thinking to get lowest y or y = someValue, then with the same y, take (largestX+lowestX)/2.
Is it possible to do that?
I tried to google, usually they are using max element to get the largest without concerning about the value of y.
I could get int smallY = myVec[i][1], but what about get all x from same y?

3. https://www.geeksforgeeks.org/multidimensional-arrays-c-cpp/
It stated that x[i][j][k] to get the value in the location. then , I am a bit curious how did in this case myVec[i][0] can already get first element in first row?
How is it different ?
If you think that I might have overlooked some important fact, I dont mind reading to figure out. I am just stuck.

Thank you and have a great day .
And yes, I'll see what I am getting, if i dont try i wouldnt know if they are coordinates or something else for me. ;)
1. Looks like you didn't add it to myVec yet but are already trying to access it? Spend time conditionally adding to myVec and in a completely separate loop you should iterate over myVec and do stuff with it.

2. So make a comparator to sort based on Y, then X, then Z. After sorting, you'll have chunks of equal Y that start with minX and end with maxX.

Edit: On the topic of '<=' in comparators -- after I did some more research, you should just use '<' throughout since that conforms to 'strict weak ordering'. I've corrected my comparators to now have '<' everywhere.

3. Idk, confirm the contents of your bw or myVec or w/e are what you expect them to be.
Last edited on
Thanks icy1 !

1. ouch ! what a silly mistake i made ! Thank you for noticing.
I have got all the x values now. I have one more question . Sorry and thank you..

2. Below is the code I wrote for
- storing all x and y values of 1st image in 2d vector when y is smallest in myVector
- get the average x point, (big x-small x)/2 from 1st column in the 2d vector, newVector
- I can't figure this out yet. Do you have slight idea on how to decide the y is smallest? only when it has at least 5 entries of x with same y values.
- eg. y = 0, has this order of x and y values : [1, 0] [2, 0] [3, 0].
- y = 1 has [1, 1] [5, 1] [33, 1] [33, 1] [49, 1]
- so deciding y = 1 is the small y.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//myVec[row][column]
int small = myVec[0][1];
		
std::vector<Vec2d> newVec;
if (i == 0) { //in 1st image ONLY
cout << fn[i] << endl;		
for (int t = 1; t < myVec.size(); t++)
	if (myVec[t][1] < small)
		{
			small = myVec[t][1];
			newVec.push_back(Vec2d(t, 1)); //so newVec only store all x and y values when y is lowest 
		}
}

double avg = AveragePoint(newVec[0], newVec[newVec.size() - 1]) / 2.0; //this line
cout << avg << endl; //get only single avg 'x' value from 1st column

//I am having this error in code, on 'this line' no suitable conversion function from "cv::Vec<double, 3>" to "double" exists
//even after I changed the function in AveragePoint to
//	avg = (a[0] + b[0]) / 2.0;
//	return avg;



Thank you for being so helpful.
Last edited on
I made some correction to the code,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//myVec[row][column]
double small = myVec[0][1];
		
std::vector<Vec2d> newVec;
if (i == 0) { //in 1st image ONLY		
for (int t = 1; t < myVec.size() -1; t++)
	if (myVec[t][1] < small)
		{
			small = myVec[t][1];
			newVec.push_back(Vec2d(myVec[t][0], myVec[t][1])); //so newVec only store all x and y values when y is lowest 
		}
}

double avg = AveragePoint(newVec[0], newVec[newVec.size() - 1]) / 2.0; //this line
cout << avg << endl; //get only single avg 'x' value from 1st column

//I am having this error in code, on 'this line' no suitable conversion function from "cv::Vec<double, 3>" to "double" exists
//even after I changed the function in AveragePoint to
//	avg = (a[0] + b[0]) / 2.0;
//	return avg;


Still when I run this line, I get nothing but an empty vector
std::copy(newVec.begin(), newVec.end(), std::ostream_iterator<Vec2d>(std::cout << " " << std::endl));
Last edited on
Can anybody help?

I can't figure this out yet. Does anyone have slight idea on how to decide the y is smallest only when it has at least 5 entries of x with same y values?

- eg. y = 0, has this order of x and y values : [1, 0] [2, 0] [3, 0].
- y = 1 has [1, 1] [5, 1] [33, 1] [33, 1] [49, 1]
- so deciding y = 1 is the small y.

The code that I now have only finds the smallest y values, and save those xyz in new vector. Also able get the average of biggest x + smallest x divide by 2.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//myVec[row][column]
double small = myVec[0][1];

		std::vector<Vec3d> newVec;
		if (i == 0) //in 1st image ONLY
		{
			for (int t = 1; t < myVec.size(); t++)
			{
				if (myVec[t][1] < small)
				{
					small = myVec[t][1];
				}
			}

			for (int s = 0; s < myVec.size() - 1; s++)
			{
				if (myVec[s][1] == small)
				{
					newVec.push_back(Vec3d(myVec[s][0], myVec[s][1], myVec[s][2]));
					//so newVec only store all x and y values when y is lowest 
				}

			}

			a = newVec[0][0];
			b = newVec[newVec.size() - 1][0];

		}

		double avg = (a + b) / 2; //get only single avg 'x' value from 1st column
		//cout << avg << endl;



Thank you very much.
Last edited on
Didn't just want to make a comparator to sort based on Y, then X, then Z and afterwards examine those chunks?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <array>
#include <vector>
#include <algorithm>

using namespace std;

// Similar to Vec3d
typedef array<double,3> Vec3d;

// From a collection of points, compare based on Y, then X, then Z
bool YPointComparer(const Vec3d& a, const Vec3d& b)
{
    if (a[1] < b[1]) return true;
    if (a[1] > b[1]) return false;
    
    if (a[0] < b[0]) return true;
    if (a[0] > b[0]) return false;
    
    return a[2] < b[2];
}

void ShowPoint(const Vec3d& p)
{
    cout << "[" << p[0] << ", " << p[1] << ", " << p[2] << "]\n";
}

void Show(const vector<Vec3d>& v)
{
    for(auto& p : v)
        ShowPoint(p);
}

// From set of points sorted by Y, find 
//   min Y with at least <required> points with that Y, >= 2.
// If nothing satisfies, returns -1.0
double MinY(const vector<Vec3d>& a, int required=2)
{
    double best_y;
    int chunk_size;
    for (int i=0; ; )
    {
        best_y = a[i][1];
        chunk_size = 1;
        if (++i == a.size())
            return -1;
            
        while (a[i][1]==best_y)
        {
            if (++chunk_size == required)
                return best_y;
            
            if (++i == a.size())
                return -1;
        }
    }
    return best_y;
}


int main() 
{
    vector<Vec3d> points = 
    {
        {33, 1, 196},
        {3, 0, 224},
        {33, 1, 117},
        {4, 2, 114},
        {2, 0, 116},
        {5, 3, 255},
        {1, 0, 44},
        {1, 1, 190},
        {5, 1, 21},
        {16, 3, 29},
        {49, 1, 69},
        {4, 4, 4},
        {4, 3, 3}
    };
    
    cout << "Before:" << endl;
    Show(points);
    cout << endl;
    
    cout << "Sort by Y, then X, then Z:" << endl;
    sort(points.begin(), points.end(), YPointComparer);
    Show(points);

    cout << endl;
    int req = 2;
    cout << "Min Y with at least "<<req<<" of the same" << endl;
    cout << MinY(points, req) << endl;
    req = 5;
    cout << "Min Y with at least "<<req<<" of the same" << endl;
    cout << MinY(points, req) << endl;
    req = 6;
    cout << "Min Y with at least "<<req<<" of the same" << endl;
    cout << MinY(points, req) << endl;

    return 0;
}


https://repl.it/repls/SoulfulShinyCad

Before:
[33, 1, 196]
[3, 0, 224]
[33, 1, 117]
[4, 2, 114]
[2, 0, 116]
[5, 3, 255]
[1, 0, 44]
[1, 1, 190]
[5, 1, 21]
[16, 3, 29]
[49, 1, 69]
[4, 4, 4]
[4, 3, 3]

Sort by Y, then X, then Z:
[1, 0, 44]
[2, 0, 116]
[3, 0, 224]
[1, 1, 190]
[5, 1, 21]
[33, 1, 117]
[33, 1, 196]
[49, 1, 69]
[4, 2, 114]
[4, 3, 3]
[5, 3, 255]
[16, 3, 29]
[4, 4, 4]

Min Y with at least 2 of the same
0
Min Y with at least 5 of the same
1
Min Y with at least 6 of the same
-1
Topic archived. No new replies allowed.