You want to segment the image into "grain" and "non-grain" areas.
Then you want to label the "grain" areas.
Segmentation is easy in principle: you process the image into a mask where all the "interesting" pixels are non-zero values (traditionally 1) and all the "non-interesting" pixels are zero.
Labeling is a matter of working through the segmented image and replacing each non-zero value with an ID for the cluster that it is in -- so the resulting image has zero-valued pixels (boring), and each cluster (in your case, each grain) with values 1, 2, 3, and so on.
I kinda like scikit-image; to label pixels with that you use skimage.morphology.label. Then if you want to operate on each individual grain (e.g., you want to find its centroid) you just mask the image on the label.
Segmentation is easy in principle, but difficult in practice. If you're really lucky, you can segment the image by comparing to some very dark but non-zero value, global to the image. "Objects" will be brighter than the threshold, "non-objects" will be darker. In the scikit-image environment, you should be able to use the code
binary = image > threshold -- then display
binary to see if it looks good.
If that doesn't work then start digging -- there are various ways to threshold an image. The simplest involve low-pass filtering the image, dividing that by some constant, and taking that as the threshold. This has the upside that gradual shading in the image (i.e., brighter on one side than the other) will be filtered out -- but it has the downside that large bright features, like your image has -- will suppress detection around them.
Ultimately, you need to experiment with your image(s) to find the best segmentation method. Find one that works, test it on some images, and run with it.