I'll recommend PDAL the point data abstratction library. I've had good success using PDAL for a similar filtering problem. I like PDAL because it is open source, provides Python support, and makes it easy for me to reproduce the processing and keep track of my filtering parameters. I also like it because it has 'pipelines' where you can chain together several steps (e.g. crop then filter then export) and execute them at once. Note that if you have really, really large point clouds PDAL might not be as speedy as some other solutions (LASTools, QTM, etc.).
You could address the issue of outlying points with a PDAL pipeline similar to the following:
{
"pipeline": [
"input_utm.las",
{
"type":"filters.crop",
"bounds":"([401900,415650],[7609100,7620200])"
},
{
"type":"filters.outlier",
"method":"statistical",
"mean_k":12,
"multiplier":2.0
},
{
"type":"filters.range",
"limits":"Classification![7:7]"
},
{
"filename":"output.tif",
"resolution":1.0,
"output_type":"mean",
"radius":3.0,
"bounds":"([401900,415650],[7609100,7620200])",
"type": "writers.gdal"
}
]
}
This pipeline reads in an LAS, crops it to a specified UTM extent, then performs a filter which flags all outlying points, then performs a second filter which retains only non-outlying points (i.e. the Classification flag != 7), then exports to a 1 m resolution GeoTIFF. The statistical filter is performing a nearest neighbor mean distance computation to test whether or not a point is 'too far' from its neighbors and therefore an outlier.
From the documentation: