U-Matrix for Rectangular Maps - machine-learning

I have read about the U-Matrix in many places including this site. The best explanation of a U-Matrix is found here in this site with the explanation why there is so little correct information (the original paper is not at all useful) about how the U-Matrix is properly calculated.
The answer to the above question completely explains the concept for a hexagonal map. But the logic of calculating the U-matrix in the answer to the linked question do not hold when the map is rectangular.
For example consider 3 x 3 rectangular lattice as shown below.
Using the above lattice I can calculate the U-Matrix as shown below.
The yellow colored squares are the distances between the blue colored squares. I'm certain about the yellow colored squares. I'm also certain about the blue colored squares since we only need to take the average or the median of its surrounding.
So my question is : How to calculate the red squares?
I found a few sources including the ones mentioned in the previous question I have cited above. The best explanations I got for a rectangular U-Matrix is the following
Description 1 -> In this paper the authors does not completely explain how to calculate the red squares. Just explains the average of the surrounding needs to be taken. Which is not clear and in my opinion not proper (see below)
Description 2 -> In this paper the authors have clearly stated how to calculate the red squares but the logic they have presented seem flawed.
My explanation why the above might not be proper
If one takes the average of its surrounding to calculate the red squares as mentioned by description 1 the calculation of blue squares would be directly affected. For example consider calculating the value of blue square number 1 in U-Matrix. If we are to take the average of its surrounding we need distances (1,2) , (1,4) and (1,5). If we fill the corresponding red square with (1,5) the calculation for the blue square 4 is wrong since we did not calculate (2,4) and the same red square should be the place to have it. So the equation of dividing the addition of (1,5) and (2,4) by 2*(1.414...) will not work since there is a component which does not belong to the average. In the case of blue square 1 the distance portion of (2,4) do not belong there.
I programmed using the description in the second paper and the U-Matrix generated for a simple data set is not satisfactory. Whilst the average of distances around a given node performs better than the U-Matrix for the same data set as given below. (The images are U-Matrix followed by the average)

I didn't read the papers you mentioned and I have been working mostly with hexagonal maps, but it seems the most reasonable solution is to caclulate the red squares as averages of the yellow squares since these are their neighbors. When you use rectangular maps there are no diagonal connections since if they were then it would be more like a hexagonal map. So yellow squares are the ones you shound take into account. Think of the red squares as "fake" map units that fill in the gaps created by the interpolation of the nodes made in the U matrix.
By the way, hexagonal maps are considered better in capturing the topology of the underling dataset.

I really appreciate the question. I agree with the answer that thinking the red squares as "fake" map units and hence assigning the average values of yellow squares is a good solution. Further and simpler, we create a distance map with the identical size of the training grid and then we assign the average values of a square's neighbours to the square. I found this is the solution adopted by the minisom. See the following get_distance() function __doc__ for convenience.
def distance_map(self):
"""Returns the distance map of the weights.
Each cell is the normalised sum of the distances between
a neuron and its neighbours."""
um = zeros((self._weights.shape[0], self._weights.shape[1]))

Related

Fitting curved edges separated by sharp corners

EDIT: To further clarify if my question is not clear,
Input: The image below
Output: The points on edge 1, the points on edge 2, the points on edge 3, and the points on edge 4. (I do not have a problem finding contours. I am just unable to separate the points that lie on each of the four edges. I want to group those points into four separate edges so that I can fit four separate curves to them)
My problem here is to detect points and fit separate curves to each of the curved edges of objects like what is shown below (The image shown is one example. The actual shape of each object is different, but there will be either a sharp corner or change in slope from one edge to another):
One way to approach this is to separate out the points/pixels on each edge (the four lines in the above example) and fit polynomials on each of them. By searching a little bit, I learnt that Hough Transform is available for detecting straight edges in OpenCV, but not for curved edges. I also tried detecting contours, but it does not separate out edges of a closed shape. The main criterion for an edge to be considered separate from an adjacent one is that there is a sharp change in slope.
Could anyone give me ideas on how to achieve this? I prefer using C++ with OpenCV due to the other modules of my task.
What you are trying to do is essentially to find high curvature points in the outline. There are several methods for curvature estimation. Some are based on local derivatives of the intensity, and some are based on the arrangement of the pixels along the curve. This problem is very close to that of corner detection.
You may be interested by the following references: "A Comparative Study
on 2D Curvature Estimators, Simon Hermann and Reinhard Klette" or "Curvature estimation in noisy curves, Thanh Phuong Nguyen, Isabelle Debled-Rennesson". Notice that there is large litterature on the topic as curvature estimation in the digital domain is uneasy because it takes second order derivatives.

Algorithm for selecting outer points on a graph ("rich" convex hull)

I'm looking for an efficient way of selecting a relatively large portion of points (2D Euclidian graph) that are the furthest away from the center. This resembles the convex hull, but would include (many) more points. Further criteria:
The number of points in the selection / set ("K") must be within a specified range. Most likely it won't be very narrow, but it most work for different ranges (eg. 0.01*N < K < 0.05*N as well as 0.1*N < K < 0.2*N).
The algorithm must be able to balance distance from the center and "local density". If there are dense areas near the upper part of the graph range, but sparse areas near the lower part, then the algorithm must make sure to select some points from the lower part even if they are closer to the center than the points in the upper region. (See example below)
Bonus: rather than simple distance from center, taking into account distance to a specific point (or both a point and the center) would be perfect.
My attempts so far have focused on using "pigeon holing" (divide graph into CxR boxes, assign points to boxes based on coordinates) and selecting "outer" boxes until we have sufficient points in the set. However, I haven't been successful at balancing the selection (dense regions over-selected because of fixed box size) nor at using a selected point as reference instead of (only) the center.
I've (poorly) drawn an Example: The red dots are the points, the green shape is an example of what I want (outside the green = selected). For sparse regions, the bounding shape comes closer to the center to find suitable points (but doesn't necessarily find any, if they're too close to the center). The yellow box is an example of what my Pigeon Holing based algorithms does. Even when trying to adjust for sparser regions, it doesn't manage well.
Any and all ideas are welcome!
I don't think there are any standard algorithms that will give you what you want. You're going to have to get creative. Assuming your points are embedded in 2D Euclidean space here are some ideas:
Iteratively compute several convex hulls. For example, compute the convex hull, keep the points that are part of the convex hull, then compute another convex hull ignoring the points from the original convex hull. Continue to do this until you have a sufficient number of points, essentially plucking off points on the perimeter for each iteration. The only problem with this approach is that it will not work well for concavities in your data set (e.g., the one on the bottom of your sample you posted).
Fit a Gaussian to your data and keep everything > N standard
deviations away from the mean (where N is a value that you'd have to
choose). This should work pretty well if your data is Gaussian. If
it isn't, you could always model it with several Gaussians (instead
of one), and keep points with a joint probability less than some threshold. Using multiple Gaussians will probably handle concavities decently. References:
http://en.wikipedia.org/wiki/Gaussian_function
How to fit a gaussian to data in matlab/octave?\
Use Kernel Density Estimation - If you create a kernel density
surface, you could slice the surface at some height (e.g., turning
it into a plateau), giving you a perimeter shape (the shape of the
plateau) around the points. The trick would be to slice it at the
right location though, because you could end up getting no points
outside of the shape, but with the right selection you could easily
get the green shape you drew. This approach will work well and give you the green shape in your example if you choose the slice point wisely (which may be difficult to do). The big drawback of this approach is that it is very computationally expensive. More information:
http://en.wikipedia.org/wiki/Multivariate_kernel_density_estimation
Use alpha shapes to get a general shape the wraps tightly around
the outside perimeter of the point set. Then erode the shape a
little to force some points outside of the shape. I don't have a lot of experience with alpha shapes, but this approach will also be quite computationally expensive. More info:
http://doc.cgal.org/latest/Alpha_shapes_2/index.html

Color-based image segmentation method for detecting square or triangular shapes

Could you suggest an approach for color-based segmentation for square or triangular shapes? I'm working on an iOS app for recognizing road signs and have implemented it for round signs but that approach doesn't seem to work with other forms. For the circles we do the following:
Detect the colors we need, e.g. red and white, through HSV/B.
Detect circle through the method called Fast Circle Detection Using Gradient Pair Vectors based on analysis of gradient direction vectors (description and code: http://rnd.azoft.com/applied-use-of-m2m-tchnology-in-ios-apps/)
Triangles and squares demand differed approach and we've stuck a bit.
Assuming you're looking for red lines...
Threshold just the red component of the image
Compute hough lines and look for line segments of an estimated length (if you know the length of the sides of the triangle/square you're looking for).
Once you have this list, find combinations of lines that form triangles and squares.
Verify each candidate triangle/square by checking that their areas are within expected ranges.
If you follow this method, it is likely that you will find multiple shapes within close proximity of each other i.e. the same triangle/square in the real world will be found multiple times by the algorithm depending on the thickness of the lines. In this case, cluster them by distance and only retain one shape per cluster.
Another option is
Threshold the red component of the image.
Find contours.
Check for closed contours.
For every close contour, check if the shape resembles an equilateral triangle or a square by plotting histograms of slopes of individual points on the contour. The histogram for a square will have two highly populated bins, while that of a triangle will have three highly populated bins.
I have studied on a school project for road sign detection and for our segmentation part, we really benefited from this paper.
http://vc.cs.nthu.edu.tw/home/paper/codfiles/cmwang/201201100409/110104%20Goal%20evaluation%20of%20segmentation%20algorithms%20for%20traffic%20sign%20recognition.pdf
It compares performance of many color based segmentation techniques and some non-color based approaches. Tests compared with different signs.
Unlike some survey paper in this area it explains threshold values for different methods.
Good luck.

Detecting multiple shapes in a picture and calculate the middle

This question can be answered with any type of programming language, cause I would like some help with algorithms, but I prefer Delphi. I have a the task to detect and count multiple shapes (between 1 and N - mostly circular or a Elipse) of random pictures and calculate their middle and return them as coordinates of a picture. The middle of each shape can have a filling (but it doesn't matter). The shapes are at least 1+ pixel away from each other. None of the shapes will like blend in with another or the corner of a picture.
The background of the picture has always the same background color, which actually doesn't matter, cause the borders/frames of the shapes are always a different color compared to the background. This makes it easy to detect the shapes. I was thinking about going pixel by pixel and collect the coordinates and then draw like an invisible rectangle/square around every shape to calculate the middle. Then I also heard about scanline, but I don't think it would be faster in this case. So my question is, how can I calculate:
How many shapes are in the picture.
How can I calculate (more or less) the exact middle of them.
A few pictures to visualize the task:
This is a picture with random shapes (mostly close circles)
As you can see they are apart from each other just fine.
Then I could easily draw/calculate an imaginary rectangle/square around every shape and calculate the middle of it like that:
After I have the rectangles/squares. I can easily calculate the middle.
How do I start?
PS.: I've drawn some circles in mspaint. I have to add that all shapes are CLOSED, which makes it possible to flood fill EVERY shape in the picture with no problems!
Thank you for your help.
Calculate MSER (Maximally stable extremal regions) for the image. I can't explain that algorithm here. You can refer to the Maximally stable extremal regions article for more information about the algorithm.
That will give you centroid too.
This algorithm is implemented as inbuilt functions in OpenCv tool and Matlab 2012b.
Another method which i can think of and possibly simple than previous method is to apply connected components algorithm and count number of objects.More information of this can be found in book by Gonzalez and Woods on Digital Image Processing.

OpenCV: comparing simple images with small difference

I have a bunch of "simple" images and I want to compare if they are similar together. I compare them to each other using template matching (cv::matchTemplate) and results are quite good.
Now I want to fine tune my program and I face a problem. For example I have two images which look very much alike. Only differences they have is that another one has thicker line and the digit front of item is different. When both images are small, one pixell difference in line thickness makes big result differences when doing template matching. When line thicknesses are same and only difference is the front digit, I get template matching result something like 0.98 with CV_TM_CCORR_NORMED when match successful. When line thickness is different matching result is something like 0.95.
I cannot decrease my threshold value below 0.98 because some other similar images have same line thickness.
Here are example images:
So what options do I have?
I have tried:
dilate the original and template
erode also both
morphologyEx both
calculating keypoints and comparing them
finding corners
But no big success yet. Are those images too simple that detecting "good features" is hard?
Any help is very wellcome.
Thank you!
EDIT:
Here are some other example images. What my program consider as similar are put in same zip-folder.
ZIP
A possible way might be thinning the two images, so that every line is of one pixel width, since the differing thickness is causing you the main problem with similarity.
The procedure would be to first binarize/threshold the images, then apply a thinning operation on both images, so both are now having the same thickness of 1 px. Then use the usual template matching that you used before with good results.
In case you'd like more details on the thinning/skeletonization of binary images here are a few OpenCV implementations posted on various discussion forums and OpenCV groups:
OpenCV code for thinning (Guo and Hall algo, works with CvMat inputs)
The JR Parker implementation using OpenCV
Possibly more efficient code here (uses OpenCV optimized access methods a lot, however most of the page is in Japanese!)
And lastly a brief overview of thinning in case you're interested.
You need something more elementary here, there isn't much reason to go for fancy methods. Your figures are already binary ones, and their shapes are very similar overall.
One initial idea: consider the upper points and bottom points in a certain image and form a upper hull and a bottom hull (simply a hull, not a convex hull or anything else). A point is said to be an upper point (respec. bottom point) if, given a column i, it is the first point starting at the top (bottom) of the image that is not a background point in i. Also, your image is mostly one single connected component (in some cases there are vertical bars separated, but that is fine), so you can discard small components easily. This step is important for your situation because I saw there are some figures with some form of noise that is irrelevant to the rest of the image. Considering that a connected component with less than 100 points is small, these are the hulls you get for the respective images included in the question:
The blue line is indicating the upper hull, the green line the bottom hull. If it is not apparent, when we consider the regional maxima and regional minima of these hulls we obtain the same amount in both of them. Furthermore, they are all very close except for some displacement in the y axis. If we consider the mean x position of the extrema and plot the lines of both images together we get the following figure. In this case, the lines in blue and green are for the second image, and the lines in red and cyan for the first. Red dots are in the mean x coordinate of some regional minima, and blue dots the same but for regional maxima (these are our points of interest). (The following image has been resized for better visualization)
As you can see, you get many nearly overlapping points without doing anything. If we do even less, i.e. not even care about this overlapping, and proceed to classify your images in the trivial way: if an image a and another image b have the same amount of regional maxima in the upper hull, the same amount of regional minima in the upper hull, the same amount of regional maxima in the bottom hull, and the same amount of regional minima in the bottom hull, then a and b belong to the same class. Doing this for all your images, all images are correctly grouped except for the following situation:
In this case we have only 3 maxima and 3 minima for the upper hull in the first image, while there are 4 maxima and 4 minima for the second. Following you see the plots for the hulls and points of interest obtained:
As you can notice, in the second upper hull there are two extrema very close. Smoothing this curve eliminates both extrema, making the images match by the trivial method. Also, note that if you draw a rectangle around your images, then this method will tell they are all equal. In that case you will want to compare multiple hulls, discarding the points in the current hull and constructing other ones. Nevertheless, this method is able to group all your images correctly given they are all very simple and mostly noisy-free.
From as much as I can get, the difficulty is when the shape is the same, just size is different. A simple hack approach could be:
- subtract the images, then erode. If the shapes were the same but one slightly bigger, subtracting will leave only the edges, which will be thin an vanish with erosion as noise.
Somewhat more formal, would be to take the contours and then the approximate polygons and do a invariants comparison (Hu Moments etc.)

Resources