# Coloring a map of India

Below is a map of India (img).

and I can visualize it in the following way:

imgbin = Binarize@img;
MorphologicalComponents[imgbin] // Colorize


and the result is:

### Edit

Following a manual approach, I can isolate the small components:

sc = SelectComponents[imgbin, #Count < 60 &];


However, this gives me

Now I find the coordinates of the centroids:

centroids = ComponentMeasurements[sc, "Centroid"];


This gives me

{1 -> {523.425, 182.274}, 2 -> {545.125, 182.563}, 3 -> {521.089, 154.518},
4 -> {96.2778, 154.722}, 5 -> {101.5, 150.625}, 6 -> {285.375, 146.667},
7 -> {111.7, 136.}, 8 -> {517.868, 133.947}, 9 -> {91.8846, 134.885},
10 -> {99.3889, 135.167}, 11 -> {95.0882, 122.382}, 12 -> {531.136, 105.409},
13 -> {535.5, 94.}, 14 -> {541.4, 92.6}, 15 -> {551.833, 93.8333},
16 -> {540.333, 86.5833}, 17 -> {564., 63.5}, 18 -> {557.929, 61.5},
19 -> {558.833, 55.8333}, 20 -> {567.5, 27.}, 21 -> {575.689, 20.3491}}


From this information, I think, the grouping can be done. I need to choose two thresholds for the X coordinates of the centroids. Manually, I can set the thresholds as 100 and 200. Then, the components having centroids with x < 100 will be grouped into one, the component having the centroid with 100 < x < 200 will be grouped into another one (this component should be discarded as it is already considered as a component earlier) and finally the components having centroids with x > 200 will be grouped into the second one.

However, I wish to group some of the components as shown below:

That is, the components inside the circle at the bottom left should be grouped into a single component and visualized with a single color and the components inside the ellipse at the bottom right should be grouped into another single component and visualized with another unique color while keeping the rest of the map unchanged.

How can I do so?

Edit 2: I can now group the components desired in a very manual way as follows:

scleft = SelectComponents[
imgbin, #Count < 80 && #Centroid[[1]] < 130 &];
scright =
SelectComponents[imgbin, #Count < 80 && #Centroid[[1]] > 350 &];


and the components for the rest of the parts

mc = MorphologicalComponents[


Now how can I join these components - scleft, scright and mc and get the desired result?

Edit 3: Both the answers by @kglr and @Chip Hurst are acceptable to me. However, I don't like the way they have colorized scleft and scright. I would prefer to append these two components into mc so that I can have all the components together and then visualize using simply Colorize.

• What have you tried so far ? Understand your original attempts will help us get started in helping you.
– ktm
Commented Oct 12, 2018 at 13:43
• @user6014 I am not sure. Maybe group them by the components' centroid coordinates. Commented Oct 12, 2018 at 13:51
• If you post code examples of your best attempt so far it will be a good starting point for someone to build off of and hopefully get you to the next step.
– ktm
Commented Oct 12, 2018 at 13:52
• @user6014 see my edit. Commented Oct 12, 2018 at 14:27
• Majis, may i suggest you re-visit your previous questions and check if any of the answers is worth accepting?
– kglr
Commented Oct 12, 2018 at 15:53

A manual way (since OP has suggested that this question is not about clustering, more about how to deal with groups of labels) to do this would be to right click on the image, then get indices. Select the upper left corner and the bottom right corner of the bounding box of a group of components and then use ctrl+c to copy the indices. Paste it into the notebook. Do this for both groups. Then rearrange the indices for use in Part, in the following way:

img = Import["https://i.sstatic.net/6wQT9.jpg"];
comps = MorphologicalComponents[Binarize[img]];
comps[[492 ;; 549, 76 ;; 125]] = comps[[492 ;; 549, 76 ;; 125]] /. Except[0, _Integer] -> 1000;
comps[[459 ;; 648, 498 ;; 593]] = comps[[459 ;; 648, 498 ;; 593]] /. Except[0, _Integer] -> 1001;
comps = ArrayComponents[comps];
Colorize[comps]


This code works also without ArrayComponents. What ArrayComponents does is that it reindexes the components so that they are consecutive integers rather than the 1000 and 1001 that we arbitrarily used in the code.

comps // Flatten // DeleteDuplicates


{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, \ 19, 20, 21, 22, 23, 24, 25, 26, 27}

If I were to finish what OP started, I'd do it similarly:

binimg = Binarize[img];
scleft = SelectComponents[binimg, #Count < 80 && #Centroid[[1]] < 130 &];
scright = SelectComponents[binimg, #Count < 80 && #Centroid[[1]] > 350 &];
mc += 1000 ImageData[scleft];
mc += 1001 ImageData[scright];
Colorize[
mc,
ColorRules -> Join[
Table[i -> Green, {i, 25}], {
1000 -> Blue,
1001 -> Red
}]
]


• This is also a very good approach. However, I am having a problem with all the three answers. I don't want to colorize the map with the default color scheme. I have my own set of colors and I want to render the map with my colors. However, ColorFunction is not an option for Image. Is it possible to do so in any other way? Commented Oct 12, 2018 at 21:13
• @CE Secondly, I don't understand what are the purposes of using the values 1000 and 1001. Can you please explain this to me? Commented Oct 12, 2018 at 21:16
• @Majis The colors should be specified as an option to Colorize, not Image. Colorize accepts both ColorRules and ColorFunction. Those are arbitrary labels. We have to give them some labels, right? So we can give them the labels 235 and 367, or 10323023 and 29301490. It doesn't matter which, but they must be unique. For this particular image, since we have 25 other components, the label number must be larger than 25. Commented Oct 12, 2018 at 21:24
• @CE This means I can use ColorRules or ColorFunction with Colorize. Yes, I understand that they are just labels. Then how can I use it to apply custom colors? Commented Oct 12, 2018 at 21:35
• @Majis I updated the last example to demonstrate this. Is it more understandable now? Commented Oct 12, 2018 at 21:46

Another idea is to dilate the image slightly to find 'connected' components.

img = Import["https://i.sstatic.net/6wQT9.jpg"];

{chain2, chain1, mainland} = SortBy[Table[
Binarize[img*Image[1 - Unitize[comps - i]]], {i, 3}], Total];

Colorize[MorphologicalComponents[mainland, CornerNeighbors -> False]] +
ImageMultiply[chain1, Green] +
ImageMultiply[chain2, Red]


### Edit

To color the island chains from within Colorize:

mcomp = MorphologicalComponents[mainland, CornerNeighbors -> False];
max = Max[mcomp];

Colorize[mcomp + (max + 1)ImageData[chain1] + (max + 2)ImageData[chain2]]


• It's not what I need. mc is a list of components while, scleft and scright are images. I want to convert scleft and scright into components and append them to mc and then apply Colorize[mc]. Commented Oct 12, 2018 at 17:51
• @Majis see my edit. Commented Oct 12, 2018 at 18:12
• Yes, Now this is very straightforward. Thanks a lot. Commented Oct 12, 2018 at 18:40

Update 2: have all the components together and then visualize using simply Colorize:

Modify the MorphologicalComponents matrix to assign the same label to members of a cluster:

replace = Thread[Alternatives @@ # -> First[#]] & /@ clusters;
MorphologicalComponents[imgbin] /. replace // Colorize


Update:

clusters = FindClusters[#[[2, 1]] -> # & /@
ComponentMeasurements[MorphologicalComponents[imgbin],
{"Centroid", "Count"}, #2 < 80 && (#[[1]] < 130 || #[[1]] > 350) &], 2][[All, All, 1]];

Colorize[MorphologicalComponents[imgbin],


clusters = FindClusters[#[[2, 1]] -> # & /@
ComponentMeasurements[imgbin, {"Centroid", "Count"}, #2 < 65 &], 2][[All, All, 1]];
Colorize[MorphologicalComponents[imgbin],

• Don't worry, (#[[1]] < 130 || #[[1]] > 250) gives me the desired result. Thanks a lot. Commented Oct 12, 2018 at 18:07