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?
Use Focal Statistics weighted kernel file to omit the central cell with the format:
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:
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."
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
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
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
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.
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.)