Presentation on theme: "Creation of the Boundary Path Jonathan Misurda Math 1110 February 11, 2002."— Presentation transcript:
Creation of the Boundary Path Jonathan Misurda Math 1110 February 11, 2002
The Goal What we’d like: to have a way to represent the connections between the points that we generated last time. What we have: a list of the coordinates of the points on the boundary and the original matrix of those points derived from the image
How to get what we want from what we have Design an algorithm Ok, but how? Knowledge of similar algorithms Lots of creative thinking Creative thinking? Robert Sedgewick, a famous author of books on algorithms said that once you pick an appropriate way to represent your data, the algorithm will almost write itself
Beginning Our Algorithm Two things are quite useful to the process of actually designing an algorithm Defining terms Figuring out what information we have or can get So lets begin doing exactly these things, and see where our algorithm ends up
Algorithm – Step 1 We define a neighbor to be a point residing in the surrounding 8 squares of the point (i,j) in question. These are the locations of the neighbors of point (i,j) in our original matrix: (i-deltaX, j-deltaY)(i, j-deltaY)(i+deltaX, j-deltaY) (i-deltaX, j)(i,j)(i+deltaX, j) (i-deltaX, j+deltaY)(i, j+deltaY)(i+deltaX, j+deltaY)
Algorithm – Step 2 For each point (i,j) we can test to see if there is a 1 in each of those 8 matrix entries which would indicate that entry as being a neighboring point. Hint: We also must make sure that for edge points that we do not subscript the matrix with indices that are out of bounds. The number of neighbors is stored in two places, matrix m, which is the boundary matrix (a8) with the 1 entries replaced with the count of neighbors, and in our chosen data structure, the adjacency list.
Algorithm: An Interlude So when did we choose this data structure? I chose it after I saw what information we had and what we needed, and based it upon having used it before for similar problems. This requires some faith, but in the next few slides, I’ll prove this to be a good choice, and show you that it does, in fact, make it easy to write the algorithm
Algorithm – Step 2 (cont.) Adjacency list? What’s that? In graph traversal algorithms, we need to know who is a neighbor of whom, and there are 2 ways to store that information An Adjacency Matrix An Adjacency List Even though we are representing this with the fundamental type of Matlab (i.e. the matrix) we are actually choosing to store an adjacency list. It is defined as follows: For each point, store a pointer to the elements that are neighbors
Algorithm – Step 2 (cont.) Pointers? What is this, a CS class? No, we’re not going to deal with actual pointers here. What we’re going to do is take the list of points that we have, and for each one, generate a list of the indices of all the neighboring points Allow me to illustrate with the next slide.
Example: * ** * XY The List of Points: The Points: XYN1N2N The Adjacency List: (N - neighbor)
Algorithm – Step 3 Ok, we have an adjacency list, how does this help us to find the best traversal. Well, it turns out that if we record what nodes we’ve already visited, the best traversal of the nodes is to connect the current node to the one of its neighbors that has the least number of neighbors itself and has not yet been visited. The pseudocode is presented on the next slide
Algorithm – Step 3 (cont.) Current = some starting point; While there is an unvisited neighbor of current next = the minimum neighbored neighbor node; current.visited = true; path = path + current current = next; Return path;
Algorithm – Step 4 The minimum neighbored neighbor? This means that for the point we are currently looking at, we visit each of the neighbors and see how many neighbors those points have. How? Well, we have the list of neighbor indices, so just loop through that list, and look up the neighbors in the table. We could then count how many neighbors they have, but since we’ll be doing this for every point and since we already calculated it in Step 1, we could just store it with the list of neighbors
The Final Data Structure What we need to store: X Coordinate Y Coordinate Total Number of Neighbors The indices in the array of those neighbors Whether this point has been visited = 12 elements So this is how we store that in an array: XY|N|N1N2N3N4N5N6N7N8V
Algorithm – Step 5 Finding the minimum neighbored neighbor n = adjlist(current, 3); list = adjlist(current, 4:11); poss = ; possn = ; for i = 1:n p = list(i); if adjlist(p, 12) ~= 1 poss = [poss p]; possn = [possn adjlist(p,3)]; end [junk indx] = min(possn); if isempty(indx) return –1; end return poss(indx);
Algorithm Summary Taking the original matrix of points, and the generated list of points, we are able to find out how many neighbors every point has, and then using our algorithm, visit them in the appropriate order, storing them in the right order in a new array (z) We should now be able to plot the points and see our boundary with the command plot(z(:,1), z(:,2))
Plot of the returned list from our algorithm
That doesn’t look right! Well, no. It is almost correct though. You can notice that it is the correct shape, its just oriented incorrectly. How did that happen? Well it so happens that matrix indices start with zero at the top point, whereas Cartesian coordinates start at zero with the bottom point and that (row, column) is actually (y,x), so we need to correct for this. We can flip it by just swapping the columns in the plot command, but to reverse the order that its plotted in, we take the y coordinate and subtract it from ymax
Still some things wrong First, you might notice that the boundary isn’t closed. This is because z’s last element is joined to z’s first element, but plot doesn’t know that To get around that, just add z(1,:) to the end of z The second thing is that one of our trouble corners didn’t turn out exactly right. Let’s examine what happened and why.
Our problem corner ** *** * * How it looks: The number of neighbors: How we’d like it to be connected: How it’s actually connected:
So why did this happen? Since the algorithm picks the smallest neighbor, the point that has 4 neighbors will never get chosen. What can we do about it? Well, that node shouldn’t even really have 4 neighbors because the two nodes to its left are leaf nodes and should be pruned Unfortunately, I was unable to come up with a satisfactory way to prune these nodes programmatically Should you remove these nodes by hand, the algorithm might connect this region properly
Might? Yes, might. I didn’t implement an intelligent way to pick what node to go to in case of a tie, it just goes to the first node in the list. There is a possibility if it still didn’t work pruning the two nodes that you could just change the scanning algorithm from the last presentation so that it scanned back- and-forth instead of up-and-down. This would require some experimentation.
Conclusion We’ve now created the boundary for our region by coming up with a fairly simple algorithm that can take an arbitrary region described with a matrix and connect the points. It does this automatically without the need for much human interaction.