views:

476

answers:

4

alt text

Hello, I have an image as shown above. Is it possible for me to detect the center point of the cross and output the result using Matlab? Thanks.

A: 

I would start by using the grayscale image map. The darkest points are on the cross, so discriminating on the highest values is a starting point. After discrimination, set all the lower points to white and leave the rest as they are. This would maximize the contrast between points on the cross and points in the image. Next up is to come up with a filter for determining the position with the highest average values. I would step through the entire image with a NxM array and take the mean value at the center point. Create a new array of these means and you should have the highest mean at the intersection. I'm curious to see how someone else may try this!

Jeff
The NxM array stepping... are you referring to convolution by a structural element?
kigurai
Technically yes. It's just a quick to code method for feature extraction in the case where there is a extreme value landmark, in this case the black of the X. I had a problem with this a few years ago. In verifying the positioning of CT scans, a metal ball in placed at certain points that causes streaks in the reconstructed image. Locating the position of these is simply enough to find the extreme value. So instead of a rectangle, a circle can be used to determine both the positioning and the scale of the image.
Jeff
+5  A: 

Here you go. I'm assuming that you have the image toolbox because if you don't then you probably shouldn't be trying to do this sort of thing. However, all of these functions can be implemented with convolutions I believe. I did this process on the image you presented above and obtained the point (139,286) where 138 is the row and 268 is the column.

1.Convert the image to a binary image:

bw = bw2im(img, .25);

where img is the original image. Depending on the image you might have to adjust the second parameters (which ranges from 0 to 1) so that you only get the cross. Don't worry about the cross not being fully connected because we'll remedy that in the next step.

2.Dilate the image to join the parts. I had to do this twice because I had to set the threshold so low on the binary image conversion (some parts of your image were pretty dark). Dilation essentially just adds pixels around existing white pixels (I'll also be inverting the binary image as I send it into bwmorph because the operations are made to act on white pixels which are the ones that have a value of 1).

bw2 = bwmorph(~bw, 'dilate', 2);

The last parameter says how many times to do the dilation operation.

3.Shrink the image to a point.

bw3 = bwmorph(bw2, 'shrink',Inf);

Again, the last parameter says how many times to perform the operation. In this case I put in Inf which shrinks until there is only one pixel that is white (in other words a 1).

4.Find the pixel that is still a 1.

[i,j] = find(bw3);

Here, i is the row and j is the column of the pixel in bw3 such that bw3(i,j) is equal to 1. All the other pixels should be 0 in bw3.

There might be other ways to do this with bwmorph, but I think that this way works pretty well. You might have to adjust it depending on the picture too. I can include images of each step if desired.

Justin Peel
If you are interested in sub-pixel accuracy for determining the center, this would only be the first step. Using the determined center, you can collect x and y for the two lines. Now, you can use polyfit to calculate slope and intersection of each line. From that, you can calculate the intersection.
sjchoi
Sometimes I get more than a pixel. Is there a way to reduce the number until I get 1 result? Thanks.
Veronica
@Veronica are you getting two pixels remaining or more than two pixels remaining?
Justin Peel
Sometimes I get 2 and sometimes 3. Thanks.
Veronica
@Veronica are the 2 or 3 pixels adjacent to each other?
Justin Peel
Nope, they're not adjacent to each other.
Veronica
@veronica Then you need to adjust the threshold in `bw = bw2im(img, .25);`. You need to lower it to something like 0.2. The problem is that you have very dark regions away from the cross.
Justin Peel
As the 10 images I have are taken with just a slight movement of the cross, is there a way to compare the pixel of the 1st cross point so that the other extra pixels that I get can be eliminated giving me only 1 result for the other 9 images? Using the pixel from the 1st image to compare with the 2nd image and using the pixel from the 2nd image to compare with the 3rd image etc. Is this possible? Thanks.
Veronica
@Veronica You should probably just post a new question about this. I'm not completely sure what you are asking. I would link back to this question though in your new question.
Justin Peel
+1  A: 

I think that there is a far simpler way of solving this. The lines which form the cross-hair are of equal length. Therefore it in will be symmetric in all orientations. So if we do a simple line scan horizontally as well as vertically, to find the extremities of the lines forming the cross-hair. the median of these values will give the x and y co-ordinates of the center. Simple geometry.

Egon
I think that this is a good idea, but you would want to convert it to a binary map first. After converting, you can do it with a single pass through the whole image row by row. Just keep track of the furthest up, down, left and right points that have a 1 in them. Then at the end find the average of the four points. Good idea.
Justin Peel
A: 

I just love these discussions of how to find something without defining first what that something is! But, if I had to guess, I’d suggest the center of mass of the original gray scale image.

Peter Saveliev
I think the OP means the point where the two lines of the cross meet.
Justin Peel