element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Pi IoT
  • Challenges & Projects
  • Design Challenges
  • Pi IoT
  • More
  • Cancel
Pi IoT
Blog [Pi IoT] Plant Health Camera #11 - Finalization
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Events
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: gpolder
  • Date Created: 27 Aug 2016 9:05 PM Date Created
  • Views 4181 views
  • Likes 6 likes
  • Comments 25 comments
  • pi camera noir v2
  • ndvi
  • pi-iot
  • pi camera v2
  • gardens
  • winners
  • pi iot design challenge
  • plant health camera
Related
Recommended

[Pi IoT] Plant Health Camera #11 - Finalization

gpolder
gpolder
27 Aug 2016

After quite a bit of hard work during the last days, the project reached its end. Of course many improvements can be made, and other features can be added, but that is for later, after the challenge. I had the plan to add humidity, pressure and temperature measurements with the SenseHat, but unfortunately SenseHat, Wi-Pi and PiFace digital were missing from my kit. I this post I will briefly explain the ndvicam.py python code which mainly does all the work. I will finish with a number of example images.

 

Previous posts:

[Pi IoT] Plant Health Camera #10 - connecting the Master and Slave Pi

[Pi IoT] Plant Health Camera #9 - calculating BNDVI and GNDVI

[Pi IoT] Plant Health Camera #8 - Aligning the images

[Pi IoT] Plant Health Camera #7 - Synchronizing the cameras

[Pi IoT] Plant Health Camera #6 - Putting the slave Pi to work

[Pi IoT] Plant Health Camera #5 - OpenCV

[Pi IoT] Plant Health Camera #4 - Putting the parts together

[Pi IoT] Plant Health Camera #3 - First steps

[Pi IoT] Plant Health Camera #2 - Unboxing

[Pi IoT] Plant Health Camera #1 - Application

 

Software to capture the NDVI image

Below is the source code of ndvicam.py. I added comments for each step so the code is self explaining. After some initializations  an endless loop is started

While True:

in which first a live image is shown until a key is pressed. There are five options:

  • q: Quit
  • c: Show Color Image
  • o: Show NoIR Image
  • n: Show NDVI Image
  • g: Show GNDVI Image
  • b: Show BNDVI Image

After pressing q the program terminates, after pressing any other key, an image is captured from the camera and a trigger is send to the slave so that this also captures an image, see [Pi IoT] Plant Health Camera #7 - Synchronizing the cameras for details.

Then also this image is loaded from the share which was mounted from the slave pi (details can be found in [Pi IoT] Plant Health Camera #6 - Putting the slave Pi to work). Then the images of the two cameras are aligned, as described in [Pi IoT] Plant Health Camera #8 - Aligning the images. I tested the options TRANSLATION, AFFINE and HOMOGRAPHY, by commenting out the specific setting. After the images are aligned, the NVDI, GNDVI and BNDVI are calculated, and depending on which key was pressed, one of them is displayed. After a key is pressed, or after ten seconds all images (noir, color, nevi, gndvi and bndvi) are saved, with a timestamp in the filename.

 

ndvicam.py

 

# import the necessary packages
from picamera.array import PiRGBArray
from picamera import PiCamera
import RPi.GPIO as GPIO
import time
import numpy
import readchar
import datetime
import cv2


# initialize the camera and grab a reference to the raw camera capture
camera = PiCamera()
camera.ISO = 100
camera.resolution = (800, 480)
rawCapture = PiRGBArray(camera)


# Define the motion model
warp_mode = cv2.MOTION_TRANSLATION
#warp_mode = cv2.MOTION_AFFINE
#warp_mode = cv2.MOTION_HOMOGRAPHY
# Define 2x3 or 3x3 matrices and initialize the matrix to identity
if warp_mode == cv2.MOTION_HOMOGRAPHY : 
  warp_matrix = numpy.eye(3, 3, dtype=numpy.float32)
else :
  warp_matrix = numpy.eye(2, 3, dtype=numpy.float32)
# Specify the number of iterations.
number_of_iterations = 5000;
# Specify the threshold of the increment
# in the correlation coefficient between two iterations 
termination_eps = 1e-10;
# Define termination criteria
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps)


# allow the camera to warmup
time.sleep(0.1)


# GPIO Setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
GPIO.output(18, 0)




while True:
  print("Usage:")
  print(" q: Quit")
  print(" c: Show Color Image")
  print(" o: Show NoIR Image")
  print(" n: Show NDVI Image")
  print(" g: Show GNDVI Image")
  print(" b: Show BNDVI Image")

  camera.start_preview()
  c = readchar.readchar()
  camera.stop_preview()


  if c=='q':
  print('quit ndvicam.py')
  break


  # grab an image from the camera
  camera.capture(rawCapture, format="bgr")
  noir_image = rawCapture.array

  # trigger camera on slave and load
  GPIO.output(18, 1)
  time.sleep(1)
  GPIO.output(18, 0)
  time.sleep(1)
  color_image = cv2.imread('pi1iot_share/slave_image.jpg',cv2.IMREAD_COLOR)


  # extract nir, red green and blue channel
  nir_channel = noir_image[:,:,0]/256.0
  green_channel = noir_image[:,:,1]/256.0
  blue_channel = noir_image[:,:,2]/256.0
  red_channel = color_image[:,:,0]/256.0

  # align the images
  # Run the ECC algorithm. The results are stored in warp_matrix.
  # Find size of image1
  sz = color_image.shape
  (cc, warp_matrix) = cv2.findTransformECC (color_image[:,:,1],noir_image[:,:,1],warp_matrix, warp_mode, criteria)
  if warp_mode == cv2.MOTION_HOMOGRAPHY :
  # Use warpPerspective for Homography 
  nir_aligned = cv2.warpPerspective (nir_channel, warp_matrix, (sz[1],sz[0]), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)
  else :
  # Use warpAffine for nit_channel, Euclidean and Affine
  nir_aligned = cv2.warpAffine(nir_channel, warp_matrix, (sz[1],sz[0]), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP);

  # calculate ndvi
  ndvi_image = (nir_aligned - red_channel)/(nir_aligned + red_channel)
  ndvi_image = (ndvi_image+1)/2
  ndvi_image = cv2.convertScaleAbs(ndvi_image*255)
  ndvi_image = cv2.applyColorMap(ndvi_image, cv2.COLORMAP_JET)

  # calculate gndvi_image
  gndvi_image = (nir_channel - green_channel)/(nir_channel + green_channel)
  gndvi_image = (gndvi_image+1)/2
  gndvi_image = cv2.convertScaleAbs(gndvi_image*255)
  gndvi_image = cv2.applyColorMap(gndvi_image, cv2.COLORMAP_JET)


  # calculate bndvi_image
  bndvi_image = (nir_channel - blue_channel)/(nir_channel + blue_channel)
  bndvi_image = (bndvi_image+1)/2
  bndvi_image = cv2.convertScaleAbs(bndvi_image*255)
  bndvi_image = cv2.applyColorMap(bndvi_image, cv2.COLORMAP_JET)


  # display the image based on key pressed on screen
  if c == 'o':
  cv2.imshow("Image", noir_image)
  elif c == 'c':
  cv2.imshow("Image", color_image)
  elif c == 'n':
  cv2.imshow("Image", ndvi_image)
  elif c == 'b':
  cv2.imshow("Image", bndvi_image)
  elif c == 'g':
  cv2.imshow("Image", gndvi_image)

  # wait at most 10 seconds for a keypress
  cv2.waitKey(10000)

  # cleanup
  cv2.destroyAllWindows()
  rawCapture.truncate(0)

  # get current date and time to add to the filenames
  d = datetime.datetime.now()
  datestr = d.strftime("%Y%m%d%H%M%S")


  # save all images
  cv2.imwrite("./images/" + datestr + "_noir.jpg",noir_image)
  cv2.imwrite("./images/" + datestr + "_color.jpg",color_image)
  cv2.imwrite("./images/" + datestr + "_ndvi.jpg",ndvi_image)
  cv2.imwrite("./images/" + datestr + "_gndvi.jpg",gndvi_image)
  cv2.imwrite("./images/" + datestr + "_bndvi.jpg",bndvi_image)

 

 

The prove of the pudding

The prove of the pudding is the eating, so here are the images you have been waiting for so long.

Here is a video of the setup. In front of the camera are a hydrangea plant and two roses.

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

This results in the following images:

The color image.

image

The NoIR image, which is the NoIR camera with the infra-blue filter attached. Note the different perspective on this small distance.

image

The two images are aligned using the HOMOGRAPHY algorithm, which you can clearly see in the blue border below.

A drawback of the HOMOGRAPHY is that it is quite time consuming. In this case, the ECC algorithm took almost 15 minutes image.

The NDVI image clearly shows healthy plant parts in read, while other stuff is in the blue-green range.

Note that the roses looks like very unhealthy! This is true, because they are fake.

image

The BNDVI and GNDVI doesn't look very promising, I will investigate in this later.

imageimage

 

I also took my camera outside, powered by a USB power bank.

 

imageimage

 

With the following results:

 

imageimageimage

Here I used TRANSLATION for the alignment which works pretty well for objects at larger distance from the camera. It also is much faster, less than 30 s computation time in this case.

 

This finalizes more or less my project. I will try to make a summary blog on Monday, but yet I'm not sure I will have time for that.

I hope you enjoyed my posts and it inspired you to use the Pi for agricultural applications and plant phenotyping.

Feel free to comment or ask questions, I will try to answer them all.

  • Sign in to reply

Top Comments

  • gpolder
    gpolder over 9 years ago in reply to element14Dave +3
    Thanks Dave, just finishing my summary video. (7 more hours to go, but a lot of other duties) Gerrit.
  • element14Dave
    element14Dave over 9 years ago +2
    Congrats on completing the project, it is no small feat. Great project! Dave
  • gpolder
    gpolder over 8 years ago in reply to davidbale +2
    David, To extract the color channel, for example nir channel from noir image, why need to divide by 256? and the captured image is 8 bit per channel, 2^8 = 256. OpenCV works with float images, ranging…
  • cjnsario
    cjnsario over 5 years ago in reply to gpolder

    Thank you sir! Your reply was very helpful for a newbie like me.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • gpolder
    gpolder over 5 years ago in reply to stuksdara

    Hi stuksdara that looks great, nice to see my project still makes sense, thanks for sharing.

    I know GNDVI is not optimal. to improve you can try to use the sum of G and B in stead of G only.

    A better 'infra blue' filter might work as well, if you can find one. I don't have experience with that.

     

    If you have mor budget, you can switch to a multispectral camera, there are plenty of them available on the market.

     

    best,

    Gerrit.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • gpolder
    gpolder over 5 years ago in reply to cjnsario

    Sure, note that an image is just a whole bunch of numbers. You can average them out to one average NDVI value.

    If you want to focus on just the plant material in your image, you can first make a threshold and then average the remaining pixels.

    Needs some openCV magic to do this.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • stuksdara
    stuksdara over 5 years ago

    Really helpful tutorial! Thank you, Gerrit!

     

    We do plant monitoring in greenhouse with 60-sec interval to determine unfavourable climate conditions and this set up helps us a lot

     

    I did camera with NoIR camera, and used GNDVI, result was somewhat usable, but not fully satisfactory. https://www.youtube.com/watch?v=0FWwieqPmKk

     

    In last 2 days I have built this project, so now we will have clear understanding in plant responses to climate. Still we have struggle to make camera work o 64-bit OS, but this is not topic of this post.

    image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • cjnsario
    cjnsario over 5 years ago

    Good day sir! Is there a way to get the NDVI values of the captured images in terms of numbers? For example image1 got a 0.7 ndvi value.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube