Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I have land cover data that I would like to clean using some generalization tools. Majority filter does almost exactly what I want, but is missing one key option. Majority filter allows you to change cells where 5 out of 8 of the neighbors are a different class. The problem is that in my data there are many instances when 5 out of 8 is too aggressive. I would like to only target those cells that are surrounded by 7 or 8 different neighbors. Is there a way to do this in Arc?

share|improve this question
Focal variety in an annular neighborhood that omits the central cell would be a key ingredient in any efficient solution. The details depend on whether "different neighbors" must also differ from the central cell or not. –  whuber Oct 22 '12 at 20:27
Thanks for the feedback, I hadn't tried focal variety yet. In this case, the 7 or 8 neighbors must be different than the central cell. This is making it difficult to distinguish from cells in contiguous blocks which also have a focal variety of '1'. –  Ryan Oct 24 '12 at 19:50
add comment

2 Answers

Use Focal Statistics weighted kernel file to omit the central cell with the format:

3 3
1 1 1
1 0 1
1 1 1

See example of ASCII weighted kernel file in the help topic How Focal Statistics works. Save as *.txt.

The only statistics available with this neighborhood are mean, std, and in this case sum (useful on binary rasters of each landcover value - so you will have to reclassify each value into a separate raster of 1s and 0s). Unfortunately, no majority statistic so see below for all steps.

To complete the generalization* by omitting the center cell in the filter:

  1. reclassify each value of the original_landcover into separate rasters of 1s and 0s (automate with batch processing OR ModelBuilder iterator with the Con tool OR a script tool such as 2.2.3 Binary Class Conversions)
  2. input each binary raster into the Focal Statistics weighted kernel sum (automate as in step 1)
  3. then you can input all the focal weighted sum rasters into the Raster Calculator with the conditional expression: Con("f1" >= 7,1,0) + Con("f2" >= 7,2,0) + Con("f3" >= 7,3,0) + ...Con("fn" >= 7,n,0)
  4. use Raster Calculator to compare the summed_conditions from step 3 with the original_landcover: Con("summed_conditions" == 0, "original_landcover", "summed_conditions") (Note: this could effectively be incorporated into step 3)

Be sure to use the exact same integers as the original_landcover class values in all file names and raster values (except the binary raster values in step 1).

Save each set of rasters (i.e. steps 1 and 2) into separate folders for easy deleting later.

All steps may be incorporated into a reusable Model Builder tool or a Python script (with possible alternative in-memory computations with arcpy.sa). Iteration on the value field to help generate the raster calculator expression helps make this more generally applicable.

Alternatively, you can input everything into Raster Calculator all at one time, but that may sometimes be unreliable for huge nested expressions, so breaking it into smaller components to check along the way is often the way to go.

*This method ensures that any cell that is surrounded by 7 to 8 contiguous cells - all having the same value but different from the center cell - will get replaced with that majority value. It sure would be helpful if the built-in Majority Filter tool would allow one to select the number of cells for the rule instead of using the default "five out of eight connected cells must have the same value."

share|improve this answer
add comment

It is a challenge to solve this one without creating (possibly a great number of) indicator grids, one per classification, and then carrying out a lot of expensive reclassifications and conditional calculations. Here's one way.

I interpret the question as asking to identify cells in which at most one of their eight neighbors has the same value as the cell itself. To do this we can inspect each neighbor for equality using tiny custom (but unweighted) neighborhoods. To minimize the amount of computation, we could (for instance) compute eight focal variety grids for the eight neighborhoods with shapes

1 0 0    0 1 0
0 1 0    0 1 0
0 0 0    0 0 0

and their four rotated equivalents.

For instance, here is a land cover image coded by color:


The eight focal variety grids (in grayscale, with white indicating higher values) look like

Focal varieties

Recall that the output of a focal variety operation replaces each cell's value with the count of distinct values found in its neighborhood. We would therefore like to find cells where all, or all but one, of these focal variety counts equals 2. Such cells can readily be found by summing all eight focal variety results and comparing that sum to 8*2 - 1 = 15: when the sum equals or exceeds 15, we have found cells with too many different neighbors. (This procedure easily generalizes to identifying cells having at most k neighbors of their own type. The value of k can even vary, being specified on another grid.) This is the sum, shown on a "temperature" scale with orange representing high values:


The cells where the sum equals or exceeds 15 are shown in white in this indicator grid resulting from the comparison:


Handle border cells and any other occurrences of NoData by including NoData as if it were just another cell classification (if necessary by first reclassifying NoData to some unique non-null value).

To inspect the example more closely, let's zoom in to the upper left corner. I have recolored the classes to make them more distinguishable. The indicator is at the right: its white cells correspond to the original cells that have at most one neighbor with a value in common with them.

Close up

The total work involved is an optional reclassification of NoData, eight (tiny) focal variety calculations, a single local sum of eight grids, and a comparison. That is all sufficiently fast and simple that it should be preferable in any situation with more than about four different categories. It is nice, too, that the amount of work is independent of the categories: neither the number of different categories nor the individual category codes need to be known at all. That makes this solution available as a general-purpose, reusable tool.

Incidentally, if it is desired only to find cells all of whose neighbors have other values, there is a more expedient solution. Compute two focal varieties: one for the 3 by 3 neighborhood and another for the annular neighborhood in which the central cell is omitted. Select all cells where the former exceeds the latter: this is where including the central cell's value increases the number of distinct values found, showing that the central cell's value differs from those of all its neighbors. (How you deal with NoData values in this case is immaterial.)

share|improve this answer
add comment

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.