calculating the distance between 2 points openCV c++ - c++

Basically i have to figure out whether the label on on object is straight. I have an edge image of the object. I would like to calculate the distance between the 2 edges on either side in a single row.
My algorithm involves iterating through a row until a white pixel is found. Then calculating the number of black pixels until the next white is found. However when i run the code the answer is always zero.
Code:
for(int i = 0; i < img.cols; i++)
{
int num = nms_result.at<int>(i,100);
//cout <<num<<endl;
if(num > 0) {
stage2 = true;
}
if (stage2 ==true)
counter4++;
{
int num2 = nms_result.at<int>(i,100);
;
if ((num2 < 1) && (counter4 >=1 )) {
counter2++;
}
else counter4 = 0;
}
}
I have tried a lot of things but none seem to work.

Problem number 1: If I'm reading your code right, 'num' and 'num2' are always the same, since they're in the same loop.
Problem number 2: What's the output here? a little hard to tell with your formatting. Consider using some indentations with your nested ifs.

Related

How to respond to a limitless possibility of outcomes?

So let's say that there is an imaginary 2 by 2 grid comprised for 4 numbers ...
1 2
3 4
You can either flip the grid horizontally or vertically down the middle by imputing either H or V respectively. You can also flip the grid as many times as you wish, with the previous choice affecting your future outcome.
For example, you could flip the grid horizontally down the middle, and then vertically.
While solving this problem, I got enough code written down so that the program works, except for the part where the "flipping" happens. Since you can enter as many H's and V's as you would like, I have some trouble writing code that would support this action.
Since the program input could contain as many horizontal or vertical flips as the user would prefer, that prevents me from manually using if-statements; in other words, I can't say "if the 1st letter is H, flip horizontally, if the 2nd letter is V, flip vertically, etc.".
This is just a short snippet of what I have figured out so far...
void flipGrid(string str, int letterPlace)
{
while (letterPlace < str.length())
{
if (str.at(letterPlace) == 'H')
{
// flip grid horizontally
}
else if (str.at(letterPlace) == 'V')
{
// flip grid vertically
}
letterPlace += 1;
}
}
int main()
{
int increment = 0;
string userInput;
cin >> userInput;
flipGrid(userInput, increment);
return 0;
}
As you can probably tell, I need help with the parts specified by the comments. If the code were to run as planned, it should look something like this...
Input (example 1)
H
Output
3 4
1 2
Input (example 2)
HVVH
Output (the two H's and the two V's cancel out, leaving us with the original)
1 2
3 4
I feel like there should be an easier way to solve this problem, or is the method I'm currently working on the right way to approach this problem? Please let me know if I'm on the right track or not. Thanks!
I would do a few things. First, I would simply count the H's and V's and, when done, modulo 2 each count. This will leave you flipCountH and flipCountV each having 0 or 1. There's no need to do multiple flips, right? Then you'll at most do each action once.
void flipCounts(string str, int &flipCountH, int &flipCountY)
{
for (char c: str) {
if (c == 'H')
{
++flipCountH;
}
else if (c == 'V')
{
++clipCountY
}
}
}
Use that method, then:
flipCountH %= 2;
flipCountY %= 2;
if (flipCountH > 0) {
performHorizontalFlip();
}
if (flipCountV > 0) {
performVerticalFlip();
}
Now, HOW you flip is based on how you store the data. For this very specific problem, I would store it in an int[2][2].
void performVerticalFlip() {
int[2] topLine;
topLine[0] = grid[0][0];
topLine[1] = grid[0][1];
grid[0][0] = grid[1][0];
grid[0][1] = grid[1][1];
grid[1][0] = topLine[0];
grid[1][1] = topLine[1];
}
Now, you can probably make use of C++ move semantics, but that's an advanced topic. You could also make a swap method that swaps two integers. That's not so advanced.
void swap(int &a, int &b) {
int tmp = a;
a = b;
b = tmp;
}
Then the code above is simpler:
swap(grid[0][0], grid[1][0]);
swap(grid[0][1], grid[1][1]);
Horizontal flip is similar.
From the comments:
I don't know how to flip it in each statement
So, flipping a 2x2 grid vertically is simple:
int tmp = grid[0][0];
grid[0][0] = grid[1][0];
grid[1][0] = tmp;
tmp = grid[0][1];
grid[0][1] = grid[1][1];
grid[1][1] = tmp;
If you have a grid bigger than a 2x2, this will work as well:
// for half the height of the grid
for(unsigned int i = 0;i<Height/2;i++) {
// for the width of the grid
for(unsigned int j =0; j<Width) {
// store a copy of the old value
int tmp = grid[i][j];
// put the new value in
grid[i][j] = grid[Height-1-i][j]; // note, we are flipping this vertically,
// so we want something an equal distance away
// from the other end as us
// replace the value we were grabbing from with the saved value
grid[Height-1-i][j] = tmp;
}
}
In case this is homework, I'm going to leave a horizontal flip for you to figure out (hint, it's the same thing, but with the width and height reversed).

How to group together 3D points that are all within a distance of each other

So I have a list of 3D points and I want to group together points that are within 1 unit or less from each other. So here's an example of what I'm talking about (I'll use 2D points for the example),
Say we have point 1: (0,0) and point 2: (0,1) which are 1 distance from each other. The program will store both in a vector. Now here's a third point (0,2). This point is 1 distance from point 2 but not from point 1 but the program will still store it since it is within 1 distance from at least 1 point in the vector.
So I want to gather 3D points in "blobs" and everything that is 1 unit or less from this "blob" will be added onto the "blob"
I've tried so many different functions these past few days, tried recursion but always crashes and nested tons of forloops but I can't make this work.
Here's my code (I added in comments next to the code to make it easier to understand)
void combinePoints(vector<Point>& allPoints, vector< vector<Cavity> >& allPointBlobs, vector<Point>& tempBlob)
{
float check;
if(allPoints.size() != 0) //if statement to stop recursion once all the points from "allPoints" vector is checked and removed
{
for(int i = 0; i < allPoints.size(); i++) //3d distance formula checking first point with all other points
{
check = sqrt((allPoints[0].getX() - allPoints[i].getX()) * (allPoints[0].getX() - allPoints[i].getX()) +
(allPoints[0].getY() - allPoints[i].getY()) * (allPoints[0].getY() - allPoints[i].getY()) +
(allPoints[0].getZ() - allPoints[i].getZ()) * (allPoints[0].getZ() - allPoints[i].getZ()));
if ((check <= 1.000) && (check != 0 )) //once a point is found that is 1 distance or less, it is added to tempBlob vector and removed from allPoints
{
tempBlob.push_back(allPoints[0]);
tempBlob.push_back(allPoints[i]);
allPoints.erase(allPoints.begin() + i);
allPoints.erase(connollyPoints.begin());
break;
}
}
if(check > 1.000) //However, if no points are nearby, then tempBlob is finished finding all nearby points and is added to a vector and cleared so it can start finding another blob.
{
allPointBlobs.push_back(tempBlob);
tempBlob.clear();
cout << "Blob Done" << endl;
combinePoints(allPoints, allPointBlobs, tempBlob);
}
else
{
combinePoints2(allPoints, allPointBlobs, tempBlob);
}
}
}
void combinePoints2(vector<Point>& allPoints, vector< vector<Point> >& allPointBlobs, vector<Point>& tempBlob) //combinePoints2 is almost the same as the first one, except I changed the first part where it doesnt have to initiate a vector with first two points. This function will then check all points in the temporary blob against all other points and find ones that are 1 distance or less
{
cout << tempBlob.size() << endl; //I use this just to check if function is working
float check = 0;
if(allPoints.size() != 0)
{
for(int j = 0; j < tempBlob.size(); j++)
{
for(int k = 0; k < allPoints.size(); k++)
{
check = sqrt((tempBlob[j].getX() - allPoints[k].getX()) * (tempBlob[j].getX() - allPoints[k].getX()) +
(tempBlob[j].getY() - allPoints[k].getY()) * (tempBlob[j].getY() - allPoints[k].getY()) +
(tempBlob[j].getZ() - allPoints[k].getZ()) * (tempBlob[j].getZ() - allPoints[k].getZ()));
if ((check <= 1.000) && (check != 0 ))
{
tempBlob.push_back(allPoints[k]);
allPoints.erase(allPoints.begin() + k);
break;
}
}
if ((check <= 1.000) && (check != 0 ))
{
break;
}
}
if(check > 1.000)
{
allPointBlobs.push_back(tempBlob);
tempBlob.clear();
cout << "Blob Done" << endl;
combinePoints(allPoints, allPointBlobs, tempBlob);
}
else
{
combinePoints2(allPoints, allPointBlobs, tempBlob);
}
}
}
I use all the breaks because when a point is deleted from allPoints, it messes up the forloops since I'm using .size() for the amount of times it runs. This makes the program really slow since it has to keep reinitiating the function when it finds 1 point. I'm hoping someone can help me find a simpler way to do this.
I've made many other functions but they crash, this is the only one that is working so far (or at least i hope its working lol, it just doesnt crash which is a good sign).
Write a function that gets two points as arguments and determines if they are within a certain distance or use a class "Point" with a method that checks if a point passed as argument is within distance x of this point.
Store all points within distance of 1 in a simple vector to represent your "blob".
A simple naive class could look like this:
class Point{
public:
bool withinDistance(const Point& other) const;
void addProxyPoint(const Point& other);
private:
double x_cord, y_cord, ...;
std::vector<Point> proximities;
};
Although you can do this in several other ways, especially if you don't want to store the blob on the point object itself.
Or you can write a method that checks if a point is within distance and also adds it to your blob vector.
Your choice of course.

Tallest tower with stacked boxes in the given order

Given N boxes. How can i find the tallest tower made with them in the given order ? (Given order means that the first box must be at the base of the tower and so on). All boxes must be used to make a valid tower.
It is possible to rotate the box on any axis in a way that any of its 6 faces gets parallel to the ground, however the perimeter of such face must be completely restrained inside the perimeter of the superior face of the box below it. In the case of the first box it is possible to choose any face, because the ground is big enough.
To solve this problem i've tried the following:
- Firstly the code generates the rotations for each rectangle (just a permutation of the dimensions)
- secondly constructing a dynamic programming solution for each box and each possible rotation
- finally search for the highest tower made (in the dp table)
But my algorithm is taking wrong answer in unknown test cases. What is wrong with it ? Dynamic programming is the best approach to solve this problem ?
Here is my code:
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstring>
struct rectangle{
int coords[3];
rectangle(){ coords[0] = coords[1] = coords[2] = 0; }
rectangle(int a, int b, int c){coords[0] = a; coords[1] = b; coords[2] = c; }
};
bool canStack(rectangle &current_rectangle, rectangle &last_rectangle){
for (int i = 0; i < 2; ++i)
if(current_rectangle.coords[i] > last_rectangle.coords[i])
return false;
return true;
}
//six is the number of rotations for each rectangle
int dp(std::vector< std::vector<rectangle> > &v){
int memoization[6][v.size()];
memset(memoization, -1, sizeof(memoization));
//all rotations of the first rectangle can be used
for (int i = 0; i < 6; ++i) {
memoization[i][0] = v[0][i].coords[2];
}
//for each rectangle
for (int i = 1; i < v.size(); ++i) {
//for each possible permutation of the current rectangle
for (int j = 0; j < 6; ++j) {
//for each permutation of the previous rectangle
for (int k = 0; k < 6; ++k) {
rectangle &prev = v[i - 1][k];
rectangle &curr = v[i][j];
//is possible to put the current rectangle with the previous rectangle ?
if( canStack(curr, prev) ) {
memoization[j][i] = std::max(memoization[j][i], curr.coords[2] + memoization[k][i-1]);
}
}
}
}
//what is the best solution ?
int ret = -1;
for (int i = 0; i < 6; ++i) {
ret = std::max(memoization[i][v.size()-1], ret);
}
return ret;
}
int main ( void ) {
int n;
scanf("%d", &n);
std::vector< std::vector<rectangle> > v(n);
for (int i = 0; i < n; ++i) {
rectangle r;
scanf("%d %d %d", &r.coords[0], &r.coords[1], &r.coords[2]);
//generate all rotations with the given rectangle (all combinations of the coordinates)
for (int j = 0; j < 3; ++j)
for (int k = 0; k < 3; ++k)
if(j != k) //micro optimization disease
for (int l = 0; l < 3; ++l)
if(l != j && l != k)
v[i].push_back( rectangle(r.coords[j], r.coords[k], r.coords[l]) );
}
printf("%d\n", dp(v));
}
Input Description
A test case starts with an integer N, representing the number of boxes (1 ≤ N ≤ 10^5).
Following there will be N rows, each containing three integers, A, B and C, representing the dimensions of the boxes (1 ≤ A, B, C ≤ 10^4).
Output Description
Print one row containing one integer, representing the maximum height of the stack if it’s possible to pile all the N boxes, or -1 otherwise.
Sample Input
2
5 2 2
1 3 4
Sample Output
6
Sample image for the given input and output.
Usually you're given the test case that made you fail. Otherwise, finding the problem is a lot harder.
You can always approach it from a different angle! I'm going to leave out the boring parts that are easily replicated.
struct Box { unsigned int dim[3]; };
Box will store the dimensions of each... box. When it comes time to read the dimensions, it needs to be sorted so that dim[0] >= dim[1] >= dim[2].
The idea is to loop and read the next box each iteration. It then compares the second largest dimension of the new box with the second largest dimension of the last box, and same with the third largest. If in either case the newer box is larger, it adjusts the older box to compare the first largest and third largest dimension. If that fails too, then the first and second largest. This way, it always prefers using a larger dimension as the vertical one.
If it had to rotate a box, it goes to the next box down and checks that the rotation doesn't need to be adjusted there too. It continues until there are no more boxes or it didn't need to rotate the next box. If at any time, all three rotations for a box failed to make it large enough, it stops because there is no solution.
Once all the boxes are in place, it just sums up each one's vertical dimension.
int main()
{
unsigned int size; //num boxes
std::cin >> size;
std::vector<Box> boxes(size); //all boxes
std::vector<unsigned char> pos(size, 0); //index of vertical dimension
//gets the index of dimension that isn't vertical
//largest indicates if it should pick the larger or smaller one
auto get = [](unsigned char x, bool largest) { if (largest) return x == 0 ? 1 : 0; return x == 2 ? 1 : 2; };
//check will compare the dimensions of two boxes and return true if the smaller one is under the larger one
auto check = [&boxes, &pos, &get](unsigned int x, bool largest) { return boxes[x - 1].dim[get(pos[x - 1], largest)] < boxes[x].dim[get(pos[x], largest)]; };
unsigned int x = 0, y; //indexing variables
unsigned char change; //detects box rotation change
bool fail = false; //if it cannot be solved
for (x = 0; x < size && !fail; ++x)
{
//read in the next three dimensions
//make sure dim[0] >= dim[1] >= dim[2]
//simple enough to write
//mine was too ugly and I didn't want to be embarrassed
y = x;
while (y && !fail) //when y == 0, no more boxes to check
{
change = pos[y - 1];
while (check(y, true) || check(y, false)) //while invalid rotation
{
if (++pos[y - 1] == 3) //rotate, when pos == 3, no solution
{
fail = true;
break;
}
}
if (change != pos[y - 1]) //if rotated box
--y;
else
break;
}
}
if (fail)
{
std::cout << -1;
}
else
{
unsigned long long max = 0;
for (x = 0; x < size; ++x)
max += boxes[x].dim[pos[x]];
std::cout << max;
}
return 0;
}
It works for the test cases I've written, but given that I don't know what caused yours to fail, I can't tell you what mine does differently (assuming it also doesn't fail your test conditions).
If you are allowed, this problem might benefit from a tree data structure.
First, define the three possible cases of block:
1) Cube - there is only one possible option for orientation, since every orientation results in the same height (applied toward total height) and the same footprint (applied to the restriction that the footprint of each block is completely contained by the block below it).
2) Square Rectangle - there are three possible orientations for this rectangle with two equal dimensions (for examples, a 4x4x1 or a 4x4x7 would both fit this).
3) All Different Dimensions - there are six possible orientations for this shape, where each side is different from the rest.
For the first box, choose how many orientations its shape allows, and create corresponding nodes at the first level (a root node with zero height will allow using simple binary trees, rather than requiring a more complicated type of tree that allows multiple elements within each node). Then, for each orientation, choose how many orientations the next box allows but only create nodes for those that are valid for the given orientation of the current box. If no orientations are possible given the orientation of the current box, remove that entire unique branch of orientations (the first parent node with multiple valid orientations will have one orientation removed by this pruning, but that parent node and all of its ancestors will be preserved otherwise).
By doing this, you can check for sets of boxes that have no solution by checking whether there are any elements below the root node, since an empty tree indicates that all possible orientations have been pruned away by invalid combinations.
If the tree is not empty, then just walk the tree to find the highest sum of heights within each branch of the tree, recursively up the tree to the root - the sum value is your maximum height, such as the following pseudocode:
std::size_t maximum_height() const{
if(leftnode == nullptr || rightnode == nullptr)
return this_node_box_height;
else{
auto leftheight = leftnode->maximum_height() + this_node_box_height;
auto rightheight = rightnode->maximum_height() + this_node_box_height;
if(leftheight >= rightheight)
return leftheight;
else
return rightheight;
}
}
The benefits of using a tree data structure are
1) You will greatly reduce the number of possible combinations you have to store and check, because in a tree, the invalid orientations will be eliminated at the earliest possible point - for example, using your 2x2x5 first box, with three possible orientations (as a Square Rectangle), only two orientations are possible because there is no possible way to orient it on its 2x2 end and still fit the 4x3x1 block on it. If on average only two orientations are possible for each block, you will need a much smaller number of nodes than if you compute every possible orientation and then filter them as a second step.
2) Detecting sets of blocks where there is no solution is much easier, because the data structure will only contain valid combinations.
3) Working with the finished tree will be much easier - for example, to find the sequence of orientations of the highest, rather than just the actual height, you could pass an empty std::vector to a modified highest() implementation, and let it append the actual orientation of each highest node as it walks the tree, in addition to returning the height.

Algorithm Trax Winning Condition

I tried to implement the game Trax in C++.
For those who do not know: http://www.traxgame.com/about_rules.php
I have built the board so far and created the rules where I can put my next Tile and which one I am allowed to set.
But now, I am struggling with the winning conditions.
As you can see, I need a line of at least 8 tiles..
My first solution attempt had included way to many if-conditions. That is simply not possible.
So i need to implement a proper algorithm..
My secong attempt using a bitboard is getting atm quite complicated, so my question would be if there is an easier way, I am simply missing at the moment.
Greets, MC
I can propose you to use recursion. I can misunderstand your, but anyway:
bool isWin(int i, int j, int length) {
if (length >= 8)
return true;
if (canMoveTo(i + 1, j)) {
if (isWin(i + 1, j, length + 1))
return true;
}
if (canMoveTo(i - 1, j)) {
if (isWin(i - 1, j, length + 1))
return true;
}
if (canMoveTo(i, j + 1)) {
if (isWin(i, j + 1, length + 1))
return true;
}
if (canMoveTo(i, j - 1)) {
if (isWin(i, j - 1, length + 1))
return true;
}
return false;
}
bool isWin(int i, int j) {
int length = 0;
isWin(i, j, length);
}
..
main() {
for (int i = 0; i < HEIGHT; ++i) {
for (int j = 0; j < WIDTH; ++j) {
if (isTilePresent(i, j)) {
if (isWin(i, j)) {
if (isRed(i, j))
std::cout << "Red is won!" << std::endl;
else
std::cout << "White is won!" << std::endl;
}
}
}
}
}
For this kind of game stuff To make things easy I would add a small bitmap to tile representation
create tile maps
smallest resolution able to represent all tiles like this
I think may be also 3x3 resolution will be doable. You need 4 colors:
Gray - wall
Red - path plr1
White - path plr2
Magenta - path plr1,plr2
after each turn
create board bitmap from tiles bitmaps and use A* start with last edited tile (and may be also 4 neighbors) and do path for each player/path start point (Yellow). When A* is done then analyze the map data (orange) so find the biggest number in map (green mid point). It is point where A* filling stops (no need to searching for it). Then reconstruct shortest path back to start point (brown) setting used map points as unusable. Then try to reconstruct path again if you can then closed loop is present
while reconstructing path
compute bounding box of used points so you will need min,max x,y coordinates x0,x1,y0,y1 (in tiles). From this if loop found you know:
columns = x1-x0+1
rows = y1-y0+1
so the win condition is just single if from this
Hope this helps, I developed this technique for closed loop path finding/counting in my Carcassonne game

Why am I getting "nan" values in C++?

I am making a Correlogram for an image. For each pixel, a correlogram finds the pixels of same color within a certain range of distance, d. Correlogram is a 2D matrix i.e. correlogram[color][distance]. The calculation of a Correlogram is somewhat similar to that of a Histogram.
My Code: I am posting some major part of the code in which all the calculations are going on. Rest of the code (which i didn't post) is used to fulfill other condtions and therefore is not necessary.
Problem: In my final correlogram[][] , some values are "nan". I have checked the code but i am not able to find where is the problem in my calculation/syntax.
int ColorBins = 180;
int DistanceRange = 5;
double calcCorrelogram(Mat hsvImage)
{
double correlogram[ColorBins][DistanceRange];
int pixelNum[ColorBins]; //Used to count the number of pixels of same color
Mat hsvPlanes[3];
split(hsvImage, hsvPlanes);
for(int pi=0; pi<hsvImage.rows; pi++)
{
for(int pj=0; pj<hsvImage.cols; pj++)
{
int pixelColor = (int)hsvPlanes[0].at<uchar>(pi,pj);
pixelNum[pixelColor]++;
for(int d=1; d<=DistanceRange; d++)
{
int sameColorNum=0; //* number of pixels with same color in the d-distance boundary */
int totalBoundaryNum=0; //* total number of pixels in the d-distance boundary */
for(int i= pi-d, j= pj-d; j<=pj+d; j++)
{
if(i<0)
break;
if(j<0 || j>=hsvImage.cols)
continue;
int neighbourColor = (int)hsvPlanes[0].at<uchar>(i,j);
if(pixelColor == neighbourColor)
{
sameColorNum++;
}
totalBoundaryNum++;
correlogram[pixelColor][d-1] = correlogram[pixelColor][d-1] + (double)sameColorNum / (double)totalBoundaryNum;
}
}
}
for(int c=0; c<ColorBins; c++)
{
for(int d=0; d<DistanceRange; d++)
{
if(pixelNum[c] != 0)
correlogram[c][d] = correlogram[c][d] / (double)pixelNum[c];
}
}
}
NaNs are generally created when you divide zero by zero or multiply zero by infinity. One easy way to check for abnormal numbers like NaN and infinity is to multiply by zero and check if the result is zero:
bool is_valid_double(double x)
{
return x*0.0==0.0;
}
This will return false if x is either NaN or infinity.
Then you can sprinkle your code with assertions to help find where things are going wrong:
assert(is_valid_double(correlogram[c][d]));
Once you get a crash due to an assertion failure, you can use the debugger to look at the state of the program to help determine what is going on.