Skip to content

Commit

Permalink
update notebooks for recent changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Justin McAllister committed Apr 2, 2019
1 parent d81ee87 commit b4a28d9
Show file tree
Hide file tree
Showing 11 changed files with 114 additions and 86 deletions.
73 changes: 34 additions & 39 deletions Alignment-RigRelatives.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,35 @@
},
"outputs": [],
"source": [
"import os, glob, numpy as np\n",
"import micasense.capture\n",
"import os, glob\n",
"import micasense.capture as capture\n",
"%matplotlib inline\n",
"\n",
"panelNames = None\n",
"\n",
"# This is an altum image with RigRelatives and a thermal band\n",
"imagePath = os.path.join('.','data','ALTUM1SET','000')\n",
"panelPath = imagePath\n",
"imageNames = glob.glob(os.path.join(imagePath,'IMG_0008_*.tif'))\n",
"panelNames = glob.glob(os.path.join(panelPath,'IMG_0000_*.tif'))\n",
"panelNames = glob.glob(os.path.join(imagePath,'IMG_0000_*.tif'))\n",
"\n",
"capture = micasense.capture.Capture.from_filelist(imageNames)\n",
"panelCap = micasense.capture.Capture.from_filelist(panelNames)\n",
"if panelCap.panels_in_all_expected_images():\n",
" panel_irradiance = panelCap.panel_irradiance()\n",
"if panelNames is not None:\n",
" panelCap = capture.Capture.from_filelist(panelNames)\n",
"else:\n",
" raise ValueError(\"Panels not detected in all images\")\n",
"\n",
"panelCap.plot_panels()\n",
" panelCap = None\n",
"\n",
"# Plotting the reflectance images in the capture will ensure that a reflectance image has been\n",
"# calculated for all images in the capture. In this case we use the dls irradiance during panel capture\n",
"# to calibrate to the panel, and then scale future dls_irradiance values using that factor\n",
"capture = capture.Capture.from_filelist(imageNames)\n",
"\n",
"dls_factor = np.asarray(panel_irradiance) / np.asarray(panelCap.dls_irradiance()[0:5])\n",
"corrected_irradiance = capture.dls_irradiance()[0:5] * dls_factor\n",
"capture.plot_undistorted_reflectance(dls_factor)"
"if panelCap is not None:\n",
" if panelCap.panel_albedo() is not None:\n",
" panel_reflectance_by_band = panelCap.panel_albedo()\n",
" else:\n",
" panel_reflectance_by_band = [0.67, 0.69, 0.68, 0.61, 0.67] #RedEdge band_index order\n",
" panel_irradiance = panelCap.panel_irradiance(panel_reflectance_by_band) \n",
" img_type = \"reflectance\"\n",
" capture.plot_undistorted_reflectance(panel_irradiance)\n",
"else:\n",
" img_type = \"radiance\"\n",
" capture.plot_undistorted_radiance()"
]
},
{
Expand Down Expand Up @@ -88,7 +91,7 @@
"\n",
"warp_matrices = capture.get_warp_matrices()\n",
"cropped_dimensions,edges = imageutils.find_crop_bounds(capture,warp_matrices)\n",
"im_aligned = imageutils.aligned_capture(capture, warp_matrices, cv2.MOTION_HOMOGRAPHY, cropped_dimensions, None, img_type=\"reflectance\")\n",
"im_aligned = imageutils.aligned_capture(capture, warp_matrices, cv2.MOTION_HOMOGRAPHY, cropped_dimensions, None, img_type=img_type)\n",
"\n",
"for i,mat in enumerate(warp_matrices):\n",
" print(\"Band {}:\\n{}\".format(i,mat))"
Expand Down Expand Up @@ -177,15 +180,14 @@
"rows, cols, bands = im_display.shape\n",
"driver = gdal.GetDriverByName('GTiff')\n",
"outRaster = driver.Create(\"bgrnet.tiff\", cols, rows, 6, gdal.GDT_UInt16)\n",
"normalize = False\n",
"\n",
"normalize = panelCap is None\n",
"\n",
"# Output a 'stack' in the same band order as RedEdge/Alutm\n",
"# Blue,Green,Red,NIR,RedEdge[,Thermal]\n",
"\n",
"# NOTE: NIR and RedEdge are not in wavelength order!\n",
"\n",
"capture.compute_reflectance(panel_irradiance+[0])\n",
"\n",
"for i in range(0,5):\n",
" outband = outRaster.GetRasterBand(i+1)\n",
" if normalize:\n",
Expand Down Expand Up @@ -254,19 +256,12 @@
"ndvi = (im_aligned[:,:,3] - im_aligned[:,:,2]) / (im_aligned[:,:,3] + im_aligned[:,:,2])\n",
"\n",
"# remove shadowed areas (mask pixels with NIR reflectance < 20%))\n",
"ndvi[im_aligned[:,:,3] < 0.2] = 0 \n",
"\n",
"# plotutils.plotwithcolorbar(ndvi, \n",
"# figsize = (18,18), \n",
"# title = 'NDVI filtered to only plants over RGB base layer',\n",
"# vmin = 0,\n",
"# vmax = 1)\n",
"\n",
"\n",
"if img_type == 'reflectance':\n",
" ndvi = np.ma.masked_where(im_aligned[:,:,3] < 0.20, ndvi)\n",
"\n",
"# Compute and display a histogram\n",
"hist_min = np.min(ndvi[np.where(np.logical_and(ndvi > 0, ndvi < 1))])\n",
"hist_max = np.max(ndvi[np.where(np.logical_and(ndvi > 0, ndvi < 1))])\n",
"hist_min = np.min(ndvi)\n",
"hist_max = np.max(ndvi)\n",
"fig, axis = plt.subplots(1, 1, figsize=(10,4))\n",
"axis.hist(ndvi.ravel(), bins=512, range=(hist_min, hist_max))\n",
"plt.title(\"NDVI Histogram\")\n",
Expand Down Expand Up @@ -308,15 +303,15 @@
"masked_ndre = np.ma.masked_where(ndvi < 0.45, ndre)\n",
"\n",
"# Compute a histogram\n",
"hist_min = np.min(masked_ndre[np.where(np.logical_and(masked_ndre > 0, masked_ndre < 1))])\n",
"hist_max = np.max(masked_ndre[np.where(np.logical_and(masked_ndre > 0, masked_ndre < 1))])\n",
"hist_min = np.min(masked_ndre)\n",
"hist_max = np.max(masked_ndre)\n",
"fig, axis = plt.subplots(1, 1, figsize=(10,4))\n",
"axis.hist(masked_ndre.ravel(), bins=512, range=(hist_min, hist_max))\n",
"plt.title(\"NDRE Histogram (filtered to only plants)\")\n",
"plt.show()\n",
"\n",
"min_display_ndre = 0.2\n",
"max_display_ndre = 0.45\n",
"min_display_ndre = np.percentile(masked_ndre, 5)\n",
"max_display_ndre = np.percentile(masked_ndre, 99.5)\n",
"\n",
"fig, axis = plotutils.plot_overlay_withcolorbar(gamma_corr_rgb, \n",
" masked_ndre, \n",
Expand Down Expand Up @@ -375,9 +370,9 @@
" vmin=min_display_therm,vmax=max_display_therm,\n",
" overlay_alpha=0.25,\n",
" overlay_colormap='jet',\n",
" overlay_steps=8,\n",
" overlay_steps=16,\n",
" display_contours=True,\n",
" contour_steps=8,\n",
" contour_steps=16,\n",
" contour_alpha=.4,\n",
" contour_fmt=\"%.0fC\")\n",
" fig.savefig('thermal_over_rgb.png')"
Expand Down Expand Up @@ -408,7 +403,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
"version": "3.7.1"
},
"toc": {
"nav_menu": {},
Expand Down
61 changes: 37 additions & 24 deletions Alignment.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -41,33 +41,47 @@
"import micasense.capture as capture\n",
"%matplotlib inline\n",
"\n",
"## This is an older RedEdge image without RigRelatives\n",
"# imagePath = os.path.join(os.path.abspath('.'),'data','0000SET','000')\n",
"# imageNames = glob.glob(os.path.join(imagePath,'IMG_0001_*.tif'))\n",
"# panelNames = glob.glob(os.path.join(imagePath,'IMG_0000_*.tif'))\n",
"panelNames = None\n",
"\n",
"# This is an older RedEdge image without RigRelatives\n",
"imagePath = os.path.join(os.path.abspath('.'),'data','0000SET','000')\n",
"imageNames = glob.glob(os.path.join(imagePath,'IMG_0001_*.tif'))\n",
"panelNames = glob.glob(os.path.join(imagePath,'IMG_0000_*.tif'))\n",
"\n",
"# # Image from the example RedEdge imageSet (see the ImageSet notebook) without RigRelatives.\n",
"# imagePath = os.path.expanduser(os.path.join('~','Downloads','RedEdgeImageSet','0000SET'))\n",
"# imageNames = glob.glob(os.path.join(imagePath,'000','IMG_0013_*.tif'))\n",
"# panelNames = glob.glob(os.path.join(imagePath,'000','IMG_0000_*.tif'))\n",
"\n",
"# # This is an altum image with RigRelatives and a thermal band\n",
"# imagePath = os.path.join('.','data','ALTUM1SET','000')\n",
"# imageNames = glob.glob(os.path.join(imagePath,'IMG_0245_*.tif'))\n",
"# panelNames = glob.glob(os.path.join(imagePath,'IMG_0000_*.tif'))\n",
"\n",
"# This is the example RedEdge imageSet without RigRelatives.\n",
"imagePath = os.path.expanduser(os.path.join('~','Downloads','RedEdgeImageSet','0000SET'))\n",
"imageNames = glob.glob(os.path.join(imagePath,'000','IMG_0013_*.tif'))\n",
"panelNames = glob.glob(os.path.join(imagePath,'000','IMG_0000_*.tif'))\n",
"# Allow this code to align both radiance and reflectance images; bu excluding\n",
"# a definition for panelNames above, radiance images will be used\n",
"# For panel images, efforts will be made to automatically extract the panel information\n",
"# but if the panel/firmware is before Altum 1.3.5, RedEdge 5.1.7 the panel reflectance\n",
"# will need to be set in the panel_reflectance_by_band variable.\n",
"# Note: radiance images will not be used to properly create NDVI/NDRE images below.\n",
"if panelNames is not None:\n",
" panelCap = capture.Capture.from_filelist(panelNames)\n",
"else:\n",
" panelCap = None\n",
"\n",
"panelCap = capture.Capture.from_filelist(panelNames) \n",
"capture = capture.Capture.from_filelist(imageNames)\n",
"\n",
"if panelCap.panel_albedo() is not None:\n",
" panel_reflectance_by_band = panelCap.panel_albedo()\n",
"if panelCap is not None:\n",
" if panelCap.panel_albedo() is not None:\n",
" panel_reflectance_by_band = panelCap.panel_albedo()\n",
" else:\n",
" panel_reflectance_by_band = [0.67, 0.69, 0.68, 0.61, 0.67] #RedEdge band_index order\n",
" panel_irradiance = panelCap.panel_irradiance(panel_reflectance_by_band) \n",
" img_type = \"reflectance\"\n",
" capture.plot_undistorted_reflectance(panel_irradiance)\n",
"else:\n",
" panel_reflectance_by_band = [0.67, 0.69, 0.68, 0.61, 0.67] #RedEdge band_index order\n",
" \n",
"panel_irradiance = panelCap.panel_irradiance(panel_reflectance_by_band)\n",
"# Plotting the reflectance images in the capture will ensure that a reflectance image has been\n",
"# calculated for all images in the capture.\n",
"capture.plot_undistorted_reflectance(panel_irradiance)"
" img_type = \"radiance\"\n",
" capture.plot_undistorted_radiance() "
]
},
{
Expand Down Expand Up @@ -166,7 +180,7 @@
"rgb_band_indices = [2,1,0]\n",
"cir_band_indices = [3,2,1]\n",
"\n",
"im_aligned = imageutils.aligned_capture(capture, warp_matrices, warp_mode, cropped_dimensions, match_index, img_type=\"reflectance\")\n",
"im_aligned = imageutils.aligned_capture(capture, warp_matrices, warp_mode, cropped_dimensions, match_index, img_type=img_type)\n",
"\n",
"# Create a normalized stack for viewing\n",
"im_display = np.zeros((im_aligned.shape[0],im_aligned.shape[1],im_aligned.shape[2]), dtype=np.float32 )\n",
Expand Down Expand Up @@ -221,7 +235,7 @@
"# Apply a gamma correction to make the render appear closer to what our eyes would see\n",
"gamma = 1.4\n",
"gamma_corr_rgb = unsharp_rgb**(1.0/gamma)\n",
"fig = plt.figure(figsize=(18,18))\n",
"fig = plt.figure(figsize=(16,16))\n",
"plt.imshow(gamma_corr_rgb, aspect='equal')\n",
"plt.axis('off')\n",
"plt.show()"
Expand Down Expand Up @@ -271,15 +285,13 @@
"if im_aligned.shape[2] == 6:\n",
" filename = filename + \"t\" #thermal\n",
"outRaster = driver.Create(filename+\".tiff\", cols, rows, 6, gdal.GDT_UInt16)\n",
"normalize = False\n",
"normalize = panelCap is None\n",
"\n",
"# Output a 'stack' in the same band order as RedEdge/Alutm\n",
"# Blue,Green,Red,NIR,RedEdge[,Thermal]\n",
"\n",
"# NOTE: NIR and RedEdge are not in wavelength order!\n",
"\n",
"capture.compute_reflectance(panel_irradiance+[0])\n",
"\n",
"for i in range(0,5):\n",
" outband = outRaster.GetRasterBand(i+1)\n",
" if normalize:\n",
Expand Down Expand Up @@ -348,7 +360,8 @@
"ndvi = (im_aligned[:,:,3] - im_aligned[:,:,2]) / (im_aligned[:,:,3] + im_aligned[:,:,2])\n",
"\n",
"# remove shadowed areas (mask pixels with NIR reflectance < 20%))\n",
"ndvi[im_aligned[:,:,3] < 0.2] = 0 \n",
"if img_type == 'reflectance':\n",
" ndvi[im_aligned[:,:,3] < 0.2] = 0 \n",
"\n",
"# Compute and display a histogram\n",
"hist_min = np.min(ndvi[np.where(np.logical_and(ndvi > 0, ndvi < 1))])\n",
Expand Down Expand Up @@ -534,7 +547,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
"version": "3.7.1"
},
"toc": {
"nav_menu": {},
Expand Down
32 changes: 17 additions & 15 deletions Batch Processing.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
"import os, glob\n",
"import multiprocessing\n",
"\n",
"images_dir = os.path.expanduser(os.path.join('~','Downloads','RedEdgeImageSet','0000SET'))\n",
"panelNames = glob.glob(os.path.join(images_dir,'000','IMG_0000_*.tif'))\n",
"imagePath = os.path.expanduser(os.path.join('~','Documents','MicaSense','Micashare','sets','2019-02-26-Lettuce','raw'))\n",
"panelNames = glob.glob(os.path.join(imagePath,'0004SET','000','IMG_0000_*.tif'))\n",
"panelCap = micasense.capture.Capture.from_filelist(panelNames)\n",
"\n",
"# Make sure to update or replace this if using your own data.\n",
Expand All @@ -69,7 +69,7 @@
"def update_f(val):\n",
" f.value=val\n",
"\n",
"%time imgset = imageset.ImageSet.from_directory(images_dir, progress_callback=update_f)\n",
"%time imgset = imageset.ImageSet.from_directory(imagePath, progress_callback=update_f)\n",
"update_f(1.0)"
]
},
Expand All @@ -95,17 +95,19 @@
"from numpy import float32\n",
"\n",
"# Use the warp_matrices derived from the Alignment Tutorial for this RedEdge set without RigRelatives\n",
"warp_matrices = [array([[ 1.0022864e+00, -2.5218742e-03, -7.8897724e+00],\n",
" [ 2.3614613e-03, 1.0036647e+00, -1.3134360e+01],\n",
" [-1.7785960e-06, 1.1342933e-06, 1.0000000e+00]], dtype=float32), array([[1., 0., 0.],\n",
"warp_matrices = [array([[ 1.0040672e+00, -4.0104943e-03, -9.5216265e+00],\n",
" [ 2.2561555e-03, 1.0027155e+00, 4.2039639e+01],\n",
" [ 5.0572447e-07, -2.1989829e-06, 1.0000000e+00]], dtype=float32), array([[1., 0., 0.],\n",
" [0., 1., 0.],\n",
" [0., 0., 1.]], dtype=float32), array([[ 9.9724644e-01, -1.5535479e-03, 1.2301332e+00],\n",
" [ 8.6746749e-04, 9.9738181e-01, -1.6499146e+00],\n",
" [-8.2814904e-07, -3.4492047e-07, 1.0000000e+00]], dtype=float32), array([[ 1.0007139e+00, -8.4427306e-03, 1.6312788e+01],\n",
" [ 6.2834658e-03, 9.9977130e-01, -1.6011746e+00],\n",
" [-1.9520005e-06, -6.3761996e-07, 1.0000000e+00]], dtype=float32), array([[ 9.9284184e-01, 9.2153507e-04, 1.6069824e+01],\n",
" [-3.2895375e-03, 9.9262553e-01, -5.0334185e-01],\n",
" [-1.5845230e-06, -1.7681158e-06, 1.0000000e+00]], dtype=float32)]"
" [0., 0., 1.]], dtype=float32), array([[ 9.9754542e-01, -4.7137290e-03, -1.1499515e-02],\n",
" [ 4.0390319e-03, 9.9641830e-01, 3.2048538e+01],\n",
" [ 8.6146406e-07, -9.0479244e-07, 1.0000000e+00]], dtype=float32), array([[ 9.9953163e-01, -9.4728440e-04, -5.5923462e+00],\n",
" [ 3.1482654e-05, 1.0024158e+00, 4.9206558e+01],\n",
" [-1.0887084e-06, 1.2995536e-06, 1.0000000e+00]], dtype=float32), array([[ 1.0025666e+00, -2.9827280e-03, -9.4002628e+00],\n",
" [ 3.3366329e-03, 1.0009472e+00, 1.4802245e+01],\n",
" [ 1.5620793e-06, -8.3874954e-07, 1.0000000e+00]], dtype=float32), array([[ 6.35209892e-02, 1.17877689e-05, 1.40322785e+01],\n",
" [-4.56733969e-04, 6.35520044e-02, 1.15592432e+01],\n",
" [-4.15804231e-06, -2.63551964e-06, 1.00000000e+00]])]"
]
},
{
Expand Down Expand Up @@ -144,7 +146,7 @@
" outputFilename = capture.uuid+'.tif'\n",
" fullOutputPath = os.path.join(outputPath, outputFilename)\n",
" if (not os.path.exists(fullOutputPath)) or overwrite:\n",
" capture.save_capture_as_reflectance_stack(fullOutputPath, irradiance_list=irradiance, warp_matrices=warp_matrices)\n",
" capture.save_capture_as_stack(fullOutputPath, irradiance_list=irradiance, warp_matrices=warp_matrices)\n",
" capture.clear_image_data()\n",
" update_f2(float(i)/float(len(imgset.captures)))\n",
"update_f2(1.0)\n",
Expand Down Expand Up @@ -259,7 +261,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
"version": "3.7.1"
}
},
"nbformat": 4,
Expand Down
10 changes: 9 additions & 1 deletion Captures.ipynb
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Captures\n",
"A `micasense.capture.Capture` object holds a set of 5 (or in the case of Altum 6) images which are captured at the same moment together in a MicaSense camera. Files which meet this criteria will tend to have the same filename except for the suffix, but that is not required to load a captures. Captures can be loaded by starting with one image by calling Capture.from_file('file_name.tif') and adding others using the append_file, or by providing a list of filenames or images. See capture.py for more creation methods."
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -62,7 +70,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
"version": "3.7.1"
},
"toc": {
"nav_menu": {},
Expand Down
12 changes: 11 additions & 1 deletion ImageSets.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
"## Load a directory of images into an ImageSet"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%load_ext autoreload\n",
"%autoreload 2"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -232,7 +242,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
"version": "3.7.1"
},
"toc": {
"nav_menu": {},
Expand Down
2 changes: 1 addition & 1 deletion Images.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
"version": "3.7.1"
},
"toc": {
"nav_menu": {},
Expand Down
2 changes: 1 addition & 1 deletion MicaSense Image Processing Setup.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
"version": "3.7.1"
},
"toc": {
"nav_menu": {},
Expand Down
Loading

0 comments on commit b4a28d9

Please sign in to comment.