Reverse image searching - c#

Is there any ways to reverse the image search? Instead of scanning from top-left to bottom-right, start from bottom-left to top-right ?
That's how I scan the image
for (int y = 0; y < matches.GetLength(0); y++)
{
for (int x = 0; x < matches.GetLength(1); x++)
{
double matchScore = matches[y, x, 0];
if (matchScore > threshold)
{
Console.WriteLine("There is a Match");
Console.WriteLine($"Coords: {x},{y}");
return new Point(x, y);
}
}
}
return new Point(-1, -1);
I just scan a screenshot and find matches on it using emgu.cv
Can I reverse the scan, starting from the bottom instead of top?
Let say, there is 2 matches at X100, Y100 and X350, Y350
it should scan from X350 -> X100, instead of X100 -> X350 and thus return X350, Y350

You can write:
for ( int y = matches.GetLength(0) - 1; y >= 0; y-- )
for ( int x = matches.GetLength(1) - 1; x >= 0; x-- )
if ( matches[y, x, 0] > threshold )
{
Console.WriteLine("There is a Match");
Console.WriteLine($"Coords: {x},{y}");
return new Point(x, y);
}
Because you return the first searched element found, it is possible that this loop and yours do not find the same result, if for example your finds a first element at the top, and this one at the bottom, so your returns the top element and this one returns the bottom element...
Choosing a loop direction depends of what you want to return first, from top to bottom or bottom to top, and from left to right or right to left.

Related

C# Shifting items in an array down and skip spaces

I am trying to work out a method by which I can shift items in an array of objects, but keep some items in the array exactly where they are, having all items above dropping bellow the fixed items. Think in terms of a Gem Matching game, where gems can be matched. Here are the rules:
Board can be of any X,Y size
Board is filled with Gems (that can break and therefore be destroyed) and Rocks that cannot break (and therefore cannot be destroyed)
Rocks are stationary in their position and cannot move.
When user matches gems, they get destroyed and all the remaining gems drop down to the next available space.
If gems that are matched are below a Rock, then gems above the rock should skip the rock position and fill the bottom most open position.
Rocks can be stacked n deep, vertically or horizontally.
My code works, but only if there is one rock. Please note, this is written in C# for Unity, but the solution is not Unity specific (or even c#). If there are two Rocks stacked on top each other, like this:
[Gem_1]
[Rock_1]
[Rock_2]
[Gem_2]
[Gem_3]
[Gem_4]
And Gems 2,3 and 4 are destroyed, then the gems should all fall and look like this:
[Gem_7]
[Rock_1]
[Rock_2]
[Gem_6]
[Gem_5]
[Gem_1]
But, with my code, when they fall, they look like this:
[Gem_7]
[Rock_1]
[Rock_2]
[Gem_1]
[Gem_6]
[Gem_5]
Here is my Updated code:
private gem_script NextGem(Vector2Int currentGem)
{
for (int y = 0; y < board_height; y++ )
{
if(allGems[currentGem.x, y] != null && isGem(layoutStore[currentGem.x, y]) && y > 0){
return allGems[currentGem.x, y].GetComponent<gem_script>();
}
}
return null;
}
private IEnumerator ScrollNewGems()
{
for (int x = 0; x < board_width; x++)
{
for (int y = 0; y < board_height; y++)
{
if (layoutStore[x, y] != Gem_Type.empty)
{
if (allGems[x, y] == null)
{
Vector2Int current_gem_pos = new Vector2Int(x, y);
gem_script next_gem = NextGem(current_gem_pos);
if(next_gem != null)
{
Vector2Int next_gem_pos = next_gem.GetGemPos();
next_gem.SetGemXYPos(new Vector2Int(current_gem_pos.x, current_gem_pos.y));
allGems[x, y] = allGems[next_gem_pos.x, next_gem_pos.y];
allGems[next_gem_pos.x, next_gem_pos.y] = null;
}
}
}
}
}
}
Edit
I updated my code, but this only works if there is one Gem to drop down. If there are more than one gems, then they stay on the top
There was a typo in my edited script. The nextGem function should not start a y=0 but instead at currentGem.y. Otherwise, it starts from the beginning. Complete working code is:
private gem_script NextGem(Vector2Int currentGem)
{
for (int y = currentGem.y; y < board_height; y++ )
{
if(allGems[currentGem.x, y] != null && isGem(layoutStore[currentGem.x, y])){
return allGems[currentGem.x, y].GetComponent<gem_script>();
}
}
return null;
}
private IEnumerator ScrollNewGems()
{
gameState = GameState.Wait;
yield return new WaitForSeconds(.2f);
for (int x = 0; x < board_width; x++)
{
for (int y = 0; y < board_height; y++)
{
if (layoutStore[x, y] != Gem_Type.empty)
{
if (allGems[x, y] == null)
{
Vector2Int current_gem_pos = new Vector2Int(x, y);
gem_script next_gem = NextGem(current_gem_pos);
if(next_gem != null)
{
Vector2Int next_gem_pos = next_gem.GetGemPos();
next_gem.SetGemXYPos(new Vector2Int(current_gem_pos.x, current_gem_pos.y));
allGems[x, y] = allGems[next_gem_pos.x, next_gem_pos.y];
allGems[next_gem_pos.x, next_gem_pos.y] = null;
}
}
}
}
}
}

grahams scan to implement polygon partition in c#

I am trying to solve polygon partition problem using graham scan
below is the problem statement and input and expected output
I have implemented graham scan logic but i need to display output
according to the sets formed and display all the points with indexes;
The first line will contain a single integer ().
The next lines will contain two integers (), denoting a point with coordinates . Note that points are not guaranteed to be distinct.
SAMPLE INPUT
3
0 0
0 1
1 0
On the first line, output a single integer (), the number of sets in your partition.
On the next lines, print the elements of the partition. On the -th of these lines, first print the integer (), and then indices of points forming the -th set. Points are numbered starting from . Each index from to must appear in exactly one set.
SAMPLE OUTPUT
1
3 1 2 3
below is the code implemented according to the output mentioned above,
how to print for more sets?
private static void convexHull(Point[] points, int N, int set)
{
int index = 0;
List<int> result = new List<int>();
// There must be at least 3 points
if (N < 3) return;
// Initialize Result
MyStack<Point> hull = new MyStack<Point>(N);
// Find the leftmost point
int l = 0;
for (int i = 1; i < N; i++)
if (points[i].x < points[l].x)
l = i;
// Start from leftmost point, keep moving
// counterclockwise until reach the start point
// again. This loop runs O(h) times where h is
// number of points in result or output.
int p = l, q;
do
{
// Add current point to result
hull.push(points[p]);
// Search for a point 'q' such that
// orientation(p, x, q) is counterclockwise
// for all points 'x'. The idea is to keep
// track of last visited most counterclock-
// wise point in q. If any point 'i' is more
// counterclock-wise than q, then update q.
q = (p + 1) % N;
for (int i = 0; i < N; i++)
{
// If i is more counterclockwise than
// current q, then update q
if (orientation(points[p], points[i], points[q])
== 2)
q = i;
}
// Now q is the most counterclockwise with
// respect to p. Set p as q for next iteration,
// so that q is added to result 'hull'
p = q;
} while (p != l); // While we don't come to first
set += 1;
var ele = hull.GetAllStackElements();
foreach (Point pt in ele)
{
index += 1;
}
Console.WriteLine(set);
Console.Write(string.Format("{0} ", index));
for (int s = 1; s <= index; s++)
{
Console.Write(string.Format("{0} ", s));
}
Console.Write(Environment.NewLine);
}

Pathfinding - Index out of Bounds

Good day everyone, I'm writing my own pathfinding script, first had it on paper then started coding and let me tell you, it's much harder in practice than in theory. So, I've ran into a problem, which I of course can't solve.
The problem presents itself in the following images:1) In this shot, the waypoint is set to (6,6) and returns no errors.
2) Note the 2 points in the upper right corner, one shows no direction the other shows up. Error is the node that points upwards. In this shot, the waypoint is moved to (7,5) at which point it starts throwing errors starting from the last index. The more I move the waypoint closer to the bottom-right corner, the more points at X=13 down the Y axis throws exceptions.
Relevant code:
for (int x = 0; x < map.sizeX; x++)
{
for (int y = 0; y < map.sizeY; y++)
{
if (!(x == pVal.x && y == pVal.y) && map.grid[x, y].passable )
{
float dot = 1;
var heading = (grid[x, y].position - t.position).normalized;
heading.y = 0;
foreach (Vector3 direction in map.GetDirections())
{
var dot2 = Vector3.Dot(heading, direction.normalized);
if (dot > dot2 )
{
if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)
{ // Error thrown when it reaches this if-statement \\
grid[x, y].direction = direction;
dot = dot2;
}
}
}
}
}
}
This Index out of Bounds error is only thrown when I add the check to see if the point towards the direction is passable or not. Another thing to note is that I use direction.y where the directions are actually stored in x and z. For some reason if I use the z instead of y, it stops working completely.
When in doubt, try walking through a test case to see what goes wrong.
Let's say we're in the second image, x = 13, y = 12
if (!(x == pVal.x && y == pVal.y) && map.grid[x, y].passable )
(13, 12) is not our target point, and is passable, so we pass this test and proceed to the next line...
float dot = 1;
var heading = (grid[x, y].position - t.position).normalized;
heading.y = 0;
heading ends up being something like (0.659, 0, 0.753) here, though if you have some y offsets it might be shorter since you normalize it before zeroing the y.
foreach (Vector3 direction in map.GetDirections())
I don't know what order your directions are stored in, so I'll just guess here:
{(0, 0, 1), (1, 0, 1), (1, 0, 0), (1, 0, -1)...}
Starting with (0, 0, 1) then...
var dot2 = Vector3.Dot(heading, direction.normalized);
if (dot > dot2 )
dot is still 1, and dot2 is 0.753 so we pass this test, check that the cell above is passable (even though that points wildly away from the direction we want to go! More on that soon), set dot = dot2 and try the next direction:
(1, 0, 1) normalizes to (0.707, 0, 0.707). dot is 0.753 and dot2 is 0.466 + 0.532 = 0.998 so we fail the dot > dot2 test and skip this one.
Here's the killer: (1, 0, 0)
dot is still 0.753 and dot2 is 0.659, so we pass the dot > dot2 test, and proceed to check the cell in that direction:
if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)
{ // Error thrown when it reaches this if-statement \\
No kidding an error is thrown! We were already at x = 13 (ie. map.sizeX - 1) and we added 1, so we're off the edge of the board!
So, this error is easy to detect just by walking through the problem case.
Possible fixes (from most to least hacky):
Do bounds checking whenever you try to access an adjacent cell, and skip it if it would lead off the map.
Add a border of unused grid cells around your map, so checking one cell off the edge never poses a problem.
Consider switching to a more conventional, well-studied pathfinding algorithm, like Breadth-first search (all moves cost the same) or Djikstra's algorithm (distinct move costs) if you want to populate the entire grid with pathing information, or A* if you want the shortest point-to-point path.
Make a simple function that checks if you are within the bounds of the map.grid 2D array before doing if (map.grid[x + (int)direction.x, y + (int)direction.y].passable).
Check if map.grid[x + (int)direction.x is less than map.sizeX-1
then check if map.grid[ y + (int)direction.y] is less than map.sizeY-1.
If both conditions are met, go ahead with the if (map.grid[x + (int)direction.x, y + (int)direction.y].passable).
Here is a simple function to simplify that:
bool isWithinBound(Vector3 direction, int sizeX, int sizeY, int x, int y)
{
return ((x + (int)direction.x < sizeX - 1) && (y + (int)direction.y < sizeY - 1));
}
Now you can just do:
for (int x = 0; x < map.sizeX; x++)
{
for (int y = 0; y < map.sizeY; y++)
{
if (!(x == pVal.x && y == pVal.y) && map.grid[x, y].passable)
{
float dot = 1;
var heading = (grid[x, y].position - t.position).normalized;
heading.y = 0;
foreach (Vector3 direction in map.GetDirections())
{
var dot2 = Vector3.Dot(heading, direction.normalized);
if (dot > dot2)
{
//Check if we are within bounds
if (isWithinBound(direction, map.sizeX, map.sizeY, x, y))
{
if (map.grid[x + (int)direction.x, y + (int)direction.y].passable)
{ // Error thrown when it reaches this if-statement \\
grid[x, y].direction = direction;
dot = dot2;
}
}
}
}
}
}
}

A way to list to array of bytes pixels values of bricks

Sorry I had no idea how set a topic which could express what help I need.
I have in an array of bytes, values for each pixel from a bitmap. It is a one dimensional array, from left to right. It takes each row and add it to the end of array's index.
I would like to split a bitmap to 225(=15*15) pieces. Each brick has for example dimension 34x34 and the length of array is then 260100(=225*34*34). So as you see now we will need 15 bricks on width and on height.
Few months ago I was using two loops starting from 0 - 14. I wrote own long code to get all that 34x34 bricks. However I didn't used any array which was storing all values.
Now I have a one dimensional array because marshal copy and bitmapdata with bitlocks were the best way to fast copy all pixels' values to array.
But I stand face to face with problem how to get 34 elements then one row lower and another one knowing that on 35 level will be another brick with its own starting value..
PS. edit my post if something is not good.
Few people could say "first make any your test code". I tried that but what I got was just trash and I really don't know how to do that.
This method was used to crop image to smaller images containing bricks. But I don't want store small images of brick. I need values storing in array of bytes.
Under, there is a proof.
private void OCropImage(int ii, int jj, int p, int p2)
{
////We took letter and save value to binnary, then we search in dictionary by value
this.rect = new Rectangle();
this.newBitmap = new Bitmap(this.bitmap);
for (ii = 0; ii < p; ii++)
{
for (jj = 0; jj < p2; jj++)
{
////New bitmap
this.newBitmap = new Bitmap(this.bitmap);
////Set rectangle working area with letters
this.rect = new Rectangle(jj * this.miniszerokosc, ii * this.miniwysokosc, this.miniszerokosc, this.miniwysokosc);
////Cut single rectangle with letter
this.newBitmap = this.newBitmap.Clone(this.rect, this.newBitmap.PixelFormat);
////Add frame to rectangle to delet bad noise
this.OAddFrameToCropImage(this.newBitmap, this.rect.Width, this.rect.Height);
this.frm1.SetIm3 = (System.Drawing.Image)this.newBitmap;
////Create image with letter which constains less background
this.newBitmap = this.newBitmap.Clone(this.GetAreaLetter(this.newBitmap), this.newBitmap.PixelFormat);
////Count pixels in bitmap
this.workingArea = this.GetBinnary(this.newBitmap);
var keysWithMatchingValues = this.alphabetLetters.Where(x => x.Value == this.workingArea).Select(x => x.Key);
foreach (var key in keysWithMatchingValues)
{
this.chesswords += key.ToString();
}
}
this.chesswords += Environment.NewLine;
var ordered = this.alphabetLetters.OrderBy(x => x.Value);
}
}
PS2. sorry for my English, please correct it if it is needed.
If I get you right, then if you have an image like this
p00|p01|p02|...
---+---+-------
p10|p11|p12|...
---+---+-------
p20|p21|p22|...
---+---+---+---
...|...|...|...
Which is stored in an array in left-to-right row scan like this:
p00,p01,...,p0n, p10,p11,...,p1n, p20,p21, ...
If I understand you correctly, what you want to be able to do, is to take a given rectangle (from a certain x and y with a certain width and height) from the image. Here is code to do this, with explanations:
byte[] crop_area (byte[] source_image, int image_width, int image_height,
int start_x, int start_y, int result_width, int result_height)
{
byte[] result = new byte[result_width * result_height];
int endX = x + result_width;
int endY = y + result_height;
int pos = 0;
for (int y = startY; y < endY; y++)
for (int x = startX; x < endX; x++)
{
/* To get to the pixel in the row I (starting from I=1), we need
* to skip I-1 rows. Since our y indexes start from row 0 (not 1),
* then we don't need to subtract 1.
*
* So, the offset of the pixel at (x,y) is:
*
* y * image_width + x
* |-----------------------| |-----------------|
* Skip pixels of y rows Offset inside row
*/
result[pos] = source_image[y * image_width + x];
/* Advance to the next pixel in the result image */
pos++;
}
return result;
}
Then, to take the block in the row I and column J (I,J=0,...,14) do:
crop_area (source_image, image_width, image_height, J*image_width/15, I*image_height/15, image_width/15, image_height/15)

C# - Recursive Function Issue

Here's my function:
static Map AddFormation(Map _map, Tile tile, int x, int y, int length,
Random rand, Tile endTile = (Tile)Int32.MaxValue)
{
//so a call to AddFormation without the endTile will work, if I don't want a border.
if ((int)endTile == Int32.MaxValue) endTile = tile;
if (x >= 0 && x < _map.Data.GetLength(0) && y >= 0 && y < _map.Data.GetLength(1))
{
if (_map.Data[x, y].Tile != tile)
{
if (length > 0)
{
_map.Data[x, y].Tile = tile;
int newlength = length - 1;
AddFormation(_map, tile, x, y - 1, newlength, rand, endTile); // ^
AddFormation(_map, tile, x, y + 1, newlength, rand, endTile); // v
AddFormation(_map, tile, x - 1, y, newlength, rand, endTile); // <-
AddFormation(_map, tile, x + 1, y, newlength, rand, endTile); // ->
}
else
{
_map.Data[x, y].Tile = endTile;
}
}
}
return _map;
}
I have a Tile enum which is to make my life easier when working with the tiles.
I have a Cell class which contains a Tile enum called "Tile" and other info (unimportant to this)
The Map class contains a Cell[,] group called Data.
What I am trying to achieve is to create a block of the specific tile at a specific point, I will later incorporate Randomisation into this (so it wouldn't be just a diamond) but I took it out to see if that was the cause of my issue.
The problem is a call to this function always produces blocks taller than they are wide and I can't for the life of me see why..
I created a test function to see what happens if I use something like:
public static int[,] Add(int[,] grid, int x, int y, int length, int value)
{
if (x >= 0 && y >= 0 && x < grid.GetLength(0) && y < grid.GetLength(1))
{
if(grid[x,y] != value)
{
if(length > 0)
{
grid[x, y] = value;
Add(grid, x - 1, y, length - 1, value);
Add(grid, x + 1, y, length - 1, value);
Add(grid, x, y - 1, length - 1, value);
Add(grid, x, y + 1, length - 1, value);
}
}
}
return grid;
}
Which seems to suffer from the same problem if you go big enough (5 produces a perfect diamond, 6 produces a strange shape and something like 11 even stranger)
Ok, after spending a long time on this (I do like recursion), here is partway to the solution (it may be hard to explain):
The problem is that you are allowing the "path" to backtrack along the cells that have already been allocated as endTiles. If you take a look at your first method, you make the search point go down straight after it has searched up. You simply need to remove that.
This is the code I am using (notice that it calls AddFormationAlt twice, once for going up, once for going down):
class Program
{
static string left;
static string right;
static void Main(string[] args)
{
int size = 20;
int sizem = size*2 + 1;
Map m = new Map(new int[sizem,sizem]);
AddFormationAlt(m, 1, size, size, size-1, 2);
var l = left;
var r = right;
}
private class Map
{
public int[,] Data { get; set; }
public Map(int[,] data)
{
Data = data;
}
public string Print()
{
StringBuilder sb = new StringBuilder();
for (int x = 0; x < Data.GetLength(0); x++)
{
for (int y = 0; y < Data.GetLength(1); y++)
sb.Append(Data[y, x] == 0 ? " " : Data[y,x] == 1 ? "." : "#");
sb.AppendLine();
}
return sb.ToString();
}
}
static void AddFormationAlt(Map _map, int tile, int x, int y, int length, int endTile)
{
// You may need to change the cloning method when you change the tiles from ints
Map m1 = new Map((int[,])_map.Data.Clone());
Map m2 = new Map((int[,])_map.Data.Clone());
// Contains the left and right half of the Map you want, you need to join these together.
Map aleft = AddFormationAlt(m1, true, tile, x, y, length, endTile);
Map aright = AddFormationAlt(m2, false, tile, x, y + 1, length, endTile);
left = aleft.Print();
right = aright.Print();
}
static Map AddFormationAlt(Map _map, bool up, int tile, int x, int y, int length, int endTile)
{
if (x >= 0 && x < _map.Data.GetLength(0) && y >= 0 && y < _map.Data.GetLength(1))
{
if (_map.Data[y, x] != tile)
{
if (length > 0)
{
_map.Data[y, x] = tile;
int newlength = length - 1;
// Either go 'up' or 'down'
if(up)
AddFormationAlt(_map, true, tile, x, y - 1, newlength, endTile); // ^
else
AddFormationAlt(_map, false, tile, x, y + 1, newlength, endTile); // v
AddFormationAlt(_map, up, tile, x - 1, y, newlength, endTile); // <-
AddFormationAlt(_map, up, tile, x + 1, y, newlength, endTile); // ->
}
else
_map.Data[y, x] = endTile;
}
}
return _map;
}
}
I changed all your Data[x, y] to Data[y, x] because that's how I usually store them and then it worked xD.
In aleft and aright you have the left half and the right half of the diamond you want in separate Maps, you need to join them together somehow (shouldn't be too hard for a clever guy like you :). left and right show the textual representation of Maps (note the overlap in the centre):
left:
#
#.
#..
#...
#....
#.....
#......
#.......
#........
#.........
#..........
#...........
#............
#.............
#............
#...........
#..........
#.........
#........
#.......
#......
#.....
#....
#...
#..
#.
#
right:
#
.#
..#
...#
....#
.....#
......#
.......#
........#
.........#
..........#
...........#
............#
.............#
............#
...........#
..........#
.........#
........#
.......#
......#
.....#
....#
...#
..#
.#
#
You need to clean this up and change all the classes back to your own ones. I hope this helps!
When you say:
if(grid[x,y] != value)
You're telling it to only continue down this "leg" if you don't run into any blocks that have already been set to this value. The problem is that once you get a long enough length, the "leg" going out the top of the starting point "spirals around" to the left and right, and so when the recursion finally comes back to the point where it starts trying to go out the left or right, there is already a square there and you return immediately.
It looks like you want to take the if(length > 0) and put it after the if(grid[x,y] != value) block, rather than inside of it. That way, you only "set" the value if it hasn't already been set, but you will continue until you reach the appropriate length.
Of course, since "branches" (i.e. if statements) take longer than "assignments" (i.e. setting a value in an array), you might as well just remove the if(grid[x,y] != value) entirely, and risk setting spots to the same value multiple times, because it's cheaper than comparing the current value.
if (x >= 0 && y >= 0 && x < grid.GetLength(0) && y < grid.GetLength(1))
{
grid[x, y] = value;
if(length > 0)
{
Add(grid, x - 1, y, length - 1, value);
Add(grid, x + 1, y, length - 1, value);
Add(grid, x, y - 1, length - 1, value);
Add(grid, x, y + 1, length - 1, value);
}
}
return grid;
Don't you want something like
if(grid[x,y] != 0) // or whatever the initial value is
instead of
if(grid[x,y] != value)
Otherwise, when you grow out, it will grow back to the seed point.

Categories