Image Processing: Concrete test blocks

Background

Concrete is mixture of aggregates and cement. Aggregates are composed of different sizes and colors. Core samples are taken by drilling in order to test the strength of concrete . They are usually in cylindrical form. See the image below. I want to detect the circle of the cylinder and aggregates as well as calculate the areas.

Question

I have many images similar to this one.

May Questions are :

1. How can I remove the background and detect the circle?
2. How can I find the shape of aggregates calculate the areas?

PS: I'm well aware of related Questions on this site but most of them end up with failure.

Edit 1 Thank you shrx for the first part of the Q

Code

img= Import["http://i.stack.imgur.com/tNcYK.jpg"]

circles = SelectComponents[MorphologicalComponents[
LaplacianGaussianFilter[
ColorNegate@DeleteSmallComponents@Closing[EdgeDetect[i, 3], 11],
2], 0.0056],
"Count", # > 600 &];
cm = ComponentMeasurements[circles, "MeanCentroidDistance"]
ct = 1 /. ComponentMeasurements[FillingTransform@i1, "Centroid"];
Show[i, Graphics[{Thick, Red, Circle[ct, cm[[1, 2]]]}]]


Here's a possible approach for the aggregates.

I've used a scaled down image (it was faster to experiment with) and adjusted the gamma to try to bring out the colour variations. I've also masked out the background (I estimated the circular region by eye but you could of course use your ComponentMeasurements code)

i = Import["C:\\Users\\Simon\\Desktop\\tNcYK.jpg"];
i2 = ImageResize[i, Scaled[0.3]] ~ImageAdjust~ {0, 0, 1.5};
i2 = Image[ImageData[i2] RotateLeft[DiskMatrix[190, Reverse@ImageDimensions@i2], {0, 3}]]


I used ImageForestingComponents to try to identify the different regions:

Colorize[c = ImageForestingComponents[i2, Automatic, 1]]


I keep only the large components, and apply a CommonestFilter to smooth the edges a bit:

Colorize[c = DeleteSmallComponents[c, 300] ~CommonestFilter~ 1]


Now compute the "Mask" and "Area" of each component (sorted by area)

cm = SortBy[ComponentMeasurements[c, {"Mask", "Area"}][[All, 2]], Last] // Reverse;

Grid[{ImageCrop[i2 ~ImageMultiply~ Image[#1]], #2} & @@@ Rest@cm]


This shows the component outlines superimposed on the image:

ImageSubtract[i2, Image@Total[GradientFilter[#1, 1] & @@@ cm]]


• Thank you for the nice answer! It was quite OK. I'm now testing with other images... A side note: usually there is no need for deleting small components. It is also useful information for modelling. – s.s.o Jun 19 '13 at 22:12

Applying

Closing[EdgeDetect[image, 3], 5]


Produces a well defined image:

edit: another option:

Binarize[ImageAdjust[TopHatTransform[image, DiskMatrix[20]]]]


After this, it's the same procedure as in the related examples you've found.

One way to approach the segmentation of images like this is to make use of the different colorspace representations. For example, applying the LAB colorspace to the original image allows separating the image into three pieces

ImageAdjust /@ ColorSeparate[img, "LAB"]
`

Observe that the third image is almost a mask for the circle. Likely, you could process this image to find the circle more easily than the raw image. But the others also have some interesting features. Notice the dark shape below the center in the left hand image, about halfway to the edge of the object. With luck, this could be segmented out from the rest. Similarly, the whitish shape in the middle, just below the center can be separated from its surround more easily here than in the others.

So -- it might be worthwhile in a problem like this to look through the various colorspace representations and see if they bring out features that might be of interest. A variety are easy to use: "LAB", "LUV", "XYZ" and the ever popular "HSB".