ld2daps/Notebooks/Attribute Profiles Classifier.ipynb
2018-07-06 11:55:11 +02:00

412 lines
9.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Attribute Profiles Classification Prototype\n",
"\n",
"Ground classification (2D) of LiDAR data with Attribute Profiles (APs) on pre-calculated rasters from LiDAR point cloud processing (DEMs, intensity maps...).\n",
"\n",
"We will use the LD2DAPs package to compute profiles and try to generalize the process to automatise the classification."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup\n",
"\n",
"### Packages"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"from pathlib import Path\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"sys.path.append(str(Path('..').resolve()))\n",
"import ld2dap\n",
"\n",
"sys.path.append(str(Path('../triskele/').resolve()))\n",
"import triskele"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Fuctions and constants"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"figsize=np.array([16,9]) * 1."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## List of raster files"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"layers_files = [\n",
" '../Data/phase1_rasters/DEM+B_C123/UH17_GEM051_TR.tif',\n",
" '../Data/phase1_rasters/DEM_C123_3msr/UH17_GEG051_TR.tif',\n",
" '../Data/phase1_rasters/DEM_C123_TLI/UH17_GEG05_TR.tif',\n",
" '../Data/phase1_rasters/DSM_C12/UH17c_GEF051_TR.tif',\n",
" '../Data/phase1_rasters/Intensity_C1/UH17_GI1F051_TR.tif',\n",
" '../Data/phase1_rasters/Intensity_C2/UH17_GI2F051_TR.tif',\n",
" '../Data/phase1_rasters/Intensity_C3/UH17_GI3F051_TR.tif',\n",
" #'../Data/ground_truth/2018_IEEE_GRSS_DFC_GT_TR.tif',\n",
" #'../Res/HVR/C123_num_returns_0_5_nearest.tif',\n",
" '../Res/HVR noisy/C123_num_returns_0_5_nearest.tif'\n",
"\n",
"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**IDEA:** We could try to combinate rasters into new ones (e.g. $R_{DSM} - R_{DTM}$ to obtain trees and building height map)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Create the Profiles Pattern"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Basic APs classification flow:\n",
"\n",
"- Load rasters\n",
"- Filter input rasters with a treshold value: for reasons DFC rasters are noisy with very high values\n",
"- Construct filtered rasters with basic attributes profiles\n",
" + Area: [10, 100, 1e3, ..., 1e4]\n",
" + ...\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Load and filter rasters"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"loader = ld2dap.LoadTIFF(layers_files)\n",
"dfc_filter = ld2dap.Treshold(1e4)\n",
"rasters_disp = ld2dap.ShowFig('all')\n",
"\n",
"dfc_filter.input = loader\n",
"rasters_disp.input = dfc_filter\n",
"\n",
"loader.run()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Compute APs\n",
"\n",
"Choose area filter tresholds."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"areas = [10., 100.]\n",
"areas.extend([x * 1e3 for x in range(1,100,2)])\n",
"plt.plot(areas, '.')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Disable previous display then add the APs node and the vectors output to the flow ."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rasters_disp.input = None\n",
"\n",
"aps = ld2dap.AttributeProfiles(area=areas)\n",
"aps.input = dfc_filter\n",
"\n",
"out_vectors = ld2dap.RawOutput()\n",
"out_vectors.input = aps\n",
"\n",
"out_vectors.run()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"out_vectors.data.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Classification"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- Concatenate filtered rasters into pixel description vector\n",
"- Split the vectors in train and test sets for cross validation with a spatial approach: random sampling is not good for spatial descriptors!\n",
"- Random forests"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Vectors"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"X = attributes.reshape(-1, attributes.shape[2])\n",
"\n",
"(attributes[0,0] == X[0]).all()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"labels_file = Path('../Data/ground_truth/2018_IEEE_GRSS_DFC_GT_TR.tif')\n",
"labels = triskele.read(labels_file)\n",
"display(labels.shape)\n",
"\n",
"plt.figure(figsize=(16*2,3*2))\n",
"plt.imshow(labels)\n",
"plt.colorbar()\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"Y = labels.reshape(-1)\n",
"\n",
"X.shape, Y.shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Random Forest Classifier"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import importlib\n",
"from sklearn import metrics\n",
"from sklearn.ensemble import RandomForestClassifier\n",
"import pickle\n",
"sys.path.insert(0, '..')\n",
"import CrossValidationGenerator as cvg"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"importlib.reload(cvg)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from sklearn import metrics\n",
"import pandas as pd\n",
"\n",
"\n",
"def scores(actual, prediction):\n",
" ct = pd.crosstab(prediction, actual,\n",
" rownames=['Prediction'], colnames=['Reference'],\n",
" margins=True, margins_name='Total',\n",
" normalize=False # all, index, columns\n",
" )\n",
" display(ct)\n",
" \n",
" scores = metrics.precision_recall_fscore_support(actual, prediction)\n",
" print(metrics.classification_report(actual, prediction)) "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"cv_labels = np.zeros(labels[:].shape)\n",
"\n",
"for xtrain, xtest, ytrain, ytest, train_index in cvg.CVG(attributes[:], labels[:], 10, 1): \n",
" rfc = RandomForestClassifier(n_jobs=-1, random_state=0, n_estimators=100, verbose=True)\n",
" rfc.fit(xtrain, ytrain)\n",
" \n",
" ypred = rfc.predict(xtest)\n",
" \n",
" display(ytest.shape, ypred.shape)\n",
" \n",
" scores(ytest, ypred)\n",
" \n",
" cv_labels[:,train_index == False] = ypred.reshape(cv_labels.shape[0], -1)\n",
" "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"show(labels)\n",
"show(cv_labels)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.imsave('../Res/labels.png', labels)\n",
"plt.imsave('../Res/prediction.png', cv_labels)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Scores"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"scores(actual=labels.reshape(-1), prediction=cv_labels.reshape(-1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Labels\n",
"\n",
"\n",
" 0 Unclassified\n",
" 1 Healthy grass\n",
" 2 Stressed grass\n",
" 3 Artificial turf\n",
" 4 Evergreen trees\n",
" 5 Deciduous trees\n",
" 6 Bare earth\n",
" 7 Water\n",
" 8 Residential buildings\n",
" 9 Non-residential buildings\n",
" 10 Roads\n",
" 11 Sidewalks\n",
" 12 Crosswalks\n",
" 13 Major thoroughfares\n",
" 14 Highways\n",
" 15 Railways\n",
" 16 Paved parking lots\n",
" 17 Unpaved parking lots\n",
" 18 Cars\n",
" 19 Trains\n",
" 20 Stadium seats\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}