how can i split an image based on longest horizontal edge? - matlab

For example , how can i split the two row of books of this shelf based on horizontal edge? I have used sobel edge detector to detect the edges but i don't know how to or what condition to use to split the image.

I can recommend you two different approach to solve this problem.
1) Machine learning approach. This requires some labeled data, indicating the y coordinate of the edge position, then HOG feature plus a random forest classifier will do the job.
2) Image processing approach. First, let's see the output of what i have done:
the blue color indicating the score of being the desired y position of the separation edge.
Such approach always relies on some assumptions on your data, here we suppose that the target horizontal edge separating books, which contains a lot of vertical lines. Namely, we are looking for y coordinate where locate long horizontal lines which are not cut by vertical lines.
Once define our objective, the rest begin very easy.
First we need a straight line detector, hough transform will do.
Secondly, we vote for each y coordinates for being the best separator using two scores:
1) 1st score describes how many long horizontal lines (found previously) are located in the neighborhood. Let's call it s_h.
2) 2nd score describes how many long vertical lines are located in the neighborhood. Let's call it s_v.
Finally, we only need to combine s_v and s_h to make a final score. For example,
s = s_h / (s_v + 1)
Using this, we get the first scoring map posted at the beginning. Some further post processing need to be done, but should not be difficult.
Here is just one possibility to solve it, here you find my code presented in a notebook.

Related

How to perform matching of markers from two images which are taken from different perspective?

I have a markered robot with circular markers and two images from different perspective as shown: (Circular white rings are the markers)
I want to match the markers in the two images, by matching I mean the bottommost marker of 1st image should be treated as correspondence point of bottom most marker of 2nd image and so on.
The finger-like robot given in the image can bend in any direction given in space (can also bend in a U-like manner).
If it helps, the camera geometry is fixed and known beforehand.
I am lost, as simple correspondence algorithm would not work, since the perspectives are very different. How should I go about matching the two images?
You can start like this:
You know the position of the mounting point on the base panel for each perspective.
You know the positions of the white rings for each perspective as discussed here.
You can derive the direction of the arm at each ring by its tilt.
So you can easily determine the sequence of the positions starting with the mounting point stepping from ring to ring even if the arm is bent. With this you can match the rings from both images. If you have any situation where this fails, please add an according example to your question!
Unfortunately, you don't have matching points but matching curves. You might try to fit ellipses on the rings and take the ellipse centers for points to be matched.
This is an approximation, as the center of a circle does not exactly project as the center of the ellipse, but I don't think that this will be the major source of error: as you only see half circles, the fitting will not be that accurate.
If all nine circles remain visible and are ordered vertically, the matching of the centers is trivial. If they are not ordered but don't form a loop, you can probably start from the lowest and follow the chain of nearest neighbors.

Grid based dungeon with random room sizes

I'm making a game, where levels are grid based.
At first, I have rectangle MxM cells. Then within this rectangle I have to put rooms. Room is another rectangle which is AxB cells, where 2 <= A, B <= 4. Besides, It's necessary to put N rooms in each row and N ones in each column. They should fill all the space, there can't be empty space between them. In other words, I have to feel rectangle with other rectangles the way that there will no be empty space between them and they will form a grid with N rows and N columns.
What I did:
I store information about rooms in form of their left-top corner, calculate it and then put rooms based on their and neighbor's corners. To do that:
Divide grid on rooms 3x3
In each of 3x3 rooms define area which is obligatory floor (2x2 square, let's call it red area)
In loop for each room count it's neighbor x and y corner position the way that it doesn't cross none of the obligatory floor ares. For that:
a. Get red area of current room and it's neighbors. Set corner somewhere between them, making sure the dimensions of the room are within range above.
b. Resolve collisions, when it's not possible to set random corner. For instance, if x position of room above isn't equal to our room, then we can't put horizontal wall between to rooms righter them in random y position, because in that case these rooms will overlap each other.
Some other stuff with converting information about corners to rooms themselves
So, what's the problem? My code with a lot of if-statements and crutches became so unreadable and huge that it almost impossible to test and find bugs. Approach I used seems to work but it's impossible to control the way it's working or not working.
Another issue is that I want to have more control on how it looks like. Grid must be interesting, which means that neighbor rooms are preferably not of the same size. There's an example (grid) of such a grid (with red areas that are gray there), which is not bad.
Is there some alternative to solve this? In other questions I saw a lot of similar solutions, but all of them doesn't assume that there's fixed amount of rows and columns.
Recommend me some articles I haven't managed to find, probably, literature devoted to this topic, or point the direction where to move and find a working solution.
A traditional method of generating grids containing rooms is to use Binary-Space-Partition trees.
One thing about that method is that it often produces grids that are less densely populated than your example. You might be able to modify some BSP example code and make the map more dense though.
Another possible approach would be to generate the rectangles first, (perhaps with a border along two edges for the gap) then try to pack them using a rectangle packing algorithm. This previous answer has several potential packing algorithms.

DITMatlab: How to calculate hysteresis for experimental data set?

I got an experimental data set that looks more or less like this.
I need to determine how big the hysteresis loop is, aka if I look at two points with the same capacity (Y axis), whats the maximum distance between said points (X axis).
The issue is, data points arent located on the same Y value, aka I cant just find max X and min X for every Y and subtract them - that'd be too easy :^)
I figured I can use convex hull (convhull) to calculate the outer envelope of the set, but then I realised, it will only work for the convex part, not the concaved part, but I guess I can divide my data set into smaller subsets and find a sum of them... or something.
And then, assuming I have the data set thats only the outer outline of the data set, I need to calculate distances between left and right border (as shown here), but then again, thats just data set of X and Y, and Id need to find the point where green line crosses outer rim
So here are the questions:
Is there a matlab procedure that calculates the outer outline of data set, that works with the concaved part - kinda like convhull, but better?
Assuming I have the outline data set, is there an easy way to calculate secant line of data set, like shown on second picture??
Thanks for any advice, hope I made what I have in mind clear enough - english isnt my first language
Benji
EDIT 1: Or perhaps there is an easier (?) way to determine, which points form biggest outline? Like... group points into (duh) groups, lets say, those near 20%, 30%, 40%... and then pick two randomly (or brute force pick all possible pairs), one for top boundary, other for bot boundary, and then calculate area of polygon formed this way? Then, select set of points resulting in polygon with biggest area?
EDIT 2: Ooor I could group them like I thought I would before, and then work on only two groups at a time. Find convex hull for two groups, then for two next groups, and when Im done with all the groups, Id only need to find points common to all the group, and find a global hull :D Yeah, that might work :D

An algorithm for merging matched lines?

I've designed an algorithm that matches correspondent lines seen from different positions of a robot.
Now I want to merge correspondent lines into one.
Does anyone know an algorithm for this purpose?
It seems like what you're trying to do is a mosaic but restricted to 2D. Or at least something similar considering only extracted features. I'll go through the basic idea of how to do it (as I remember it anyway).
You extract useful features in both images (your lines)
You do feature matching (your matching)
You extract relative positional information about your cameras from the matched features. This allows to determining a transform between the two.
You transform one image into the other's perspective or both to a different perspective
Since you say you're working in a 2D plane that's where you will want to transform to. If your scans can be considered to not add any 3D distortion (always from the same hight facing perpendicular to the plane) then you need only deal with 2D transformations.
To do what you call the merging of the lines you need to perform step 3 and 4 of the mosaic algorithm.
For step 3 you will need to use a robust approach to calculate your 2D Transformation (rotation and translation) from one picture/scan to the other. Probably something like least mean squares (or other approaches for estimating parameters from multiple values).
For step 4 you use the calculated 2D transform and possibly a previous transformation that was calculated for the previous picture (not needed if you're matching from the composed image, a.k.a moasic, to a new image instead of sequetial images) use it on the image it would apply to. In your case probably just your 2D lines from the new scan (and not a full image) will need to be transformed by this global 2D transform to take their position and orientation to the global map reference.
Hope this helps. Good Luck!

Kink detection in drawn polylines

Users can sketch in my app using a very simple tool (move mouse while holding LMB). This results in a series of mousemove events and I record the cursor location at each event. The resulting polyline curve tends to be rather dense, with recorded points almost every other pixel. I'd like to smooth this pixelated polyline, but I don't want to smooth intended kinks. So how do I figure out where the kinks are?
The image shows the recorded trail (red pixels) and the 'implied' shape as a human would understand it. People tend to slow down near corners, so there is usually even more noise here than on the straight bits.
Polyline tracker http://www.freeimagehosting.net/uploads/c83c6b462a.png
What you're describing may be related to gesture recognition techniques, so you could search on them for ideas.
The obvious approach is to apply a curve fit, but that will have the effect of smoothing away all the interesting details and kinks. Another approach suggested is to look at speeds and accelerations, but that can get hairy (direction changes can be very fast or very slow and deliberate)
A fairly basic but effective approach is to simplify the samples directly into a polyline.
For example, work your way through the samples (e.g.) from sample 1 to sample 4, and check if all 4 samples lie within a reasonable error of the straight line between 1 & 4. If they do, then extend this to points 1..5 and repeat until such a time as the straight line from the start point to the end point no longer provides a resonable approximation to the curve defined by those samples. Create a line segment up to the previous sample point and start accumulating a new line segment.
You have to be careful about your thresholds when the samples are too close to each other, so you might want to adjust the sensitivity when regarding samples fewer than 4-5 pixels away from each other.
This will give you a set of straight lines that will follow the original path fairly accurately.
If you require additional smoothing, or want to create a scalable vector graphic, then you can then curve-fit from the polyline. First, identify the kinks (the places in your polyline where the angle between one line and the next is sharp - e.g. anything over 140 degrees is considered a smooth curve, anything less than that is considered a kink) and break the polyline at those discontinuities. Then curve-fit each of these sub-sections of the original gesture to smooth them. This will have the effect of smoothing the smooth stuff and sharpening the kinks. (You could go further and insert small smooth corner fillets instead of these sharp joints to reduce the sharpness of the joins)
Brute force, but it may just achieve what you want.
Rather than trying to do this from the resultant data, have you considered looking at the timing of the data as it comes in? If the mouse stops or slows noticably, you use the trend since the last 'kink' (the last time the mouse slowed) to establish the direction of travel. If the user goes off in a new direction, you call it a kink, otherwise, you ignore the current slowing trend and start waiting for the next one.
Well, one way would be to use a true curve-fitting algorithm. Generate a bezier curve (with exact endpoints, using Catmull-Rom or something similar), then optimize & recursively subdivide (using distance from actual line points as a cost metric). This may be too complicated for your use-case, though.
Record the order the pixels are drawn in. Then, compute the slope between pixels that are "near" but not "close". I'm guessing a graph of the slope between pixel(i) and pixel(i+7) might exhibit easily identifable "jumps" around kinks in the curve.