I guess I would try something like the following.
Suppose the image has 8-bit pixels with values from 0 to 255 where higher value means higher tissue density.
1. Experimentally determine two threshold values: A - the value below which the pixel is definitely not a bone, B - the value above which the pixel is definitely a bone.
2. Set all pixels with value below A to 0, and with values above B to 255.
Then execute something like this.
boolean changed= true;
while(changed) {
changed = false;
for(x=0;x<sizeX; ++x) {
for(y=0; y<sizeY; ++y) {
pixel = image[x][y];
if(pixel!=0 && pixel!=255) {
nA = calculateNumberOfNeighboursWithValue(x,y,0);
nB = calculateNumberOfNeighboursWithValue(x,y,255);
/* maximum 8 neighbours */
if(nA>4) { image[x][y]=0; changed = true; }
else
if(nB>4) { image[x][y]=255; changed = true; }
}
}
}
}
When this finishes, most of the bone area will probably be 255 values, while most non-bone area should be 0 values. The rest is gray area, but from viewpoint of finding the bone axis it is not relevant -- the 255 values will form enough of a picture to represent the bone shape.
I have one more idea... There is a system called ArcGIS. It is a geographic information system, and it allows to do calculations on rasters and see results immediately. It has a lot of useful raster functions to play with, like pixel classification based on different criteria... If I were you, I would get some system like this and play with different raster conversion functions to form an idea of what works and what doesn't.