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
Forget Me Not Design Challenge
  • Challenges & Projects
  • Design Challenges
  • Forget Me Not Design Challenge
  • More
  • Cancel
Forget Me Not Design Challenge
Blog Cam-e-lot - Round 13 - Man vs NDVI
  • Blog
  • Forum
  • Documents
  • Files
  • Events
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: amgalbu
  • Date Created: 2 Oct 2014 2:01 PM Date Created
  • Views 486 views
  • Likes 0 likes
  • Comments 2 comments
  • forget_me_not
  • iot_cam-e-lot
Related
Recommended

Cam-e-lot - Round 13 - Man vs NDVI

amgalbu
amgalbu
2 Oct 2014

In this post, I will face a difficult challenge: detect whether a plant is flourishing or not. At this moment in time, this feature requires some more experiments and works to make a reliable solution, but I think the solution is promising

NDVI

Vegetation is green because plant leaves reflect green light -- they don't use much of it for photosynthesis (see Figure 1).

  image

Instead they use lots of the blue and red wavelengths in sunlight. The pigments in leaves absorb this light to power photosynthesis which converts CO2, water, and nutrients into carbohydrates (food). In general, you can estimate the productivity or vigor of vegetation by how much blue and red light it is absorbing. Photosynthetic pigments do not use the longer, invisible wavelengths of near infrared light and reflect almost all of it away (this helps prevent the leaves from overheating).

Shortly after the launch of the first Landsat satellite in 1972, scientists began using the data from its sensors to estimate the productivity of vegetation by comparing the amount of red light reflected (there is not much from healthy plants) to the amount of near infrared light reflected (there is a lot). The amount of infrared light reflected from vegetation is a good indicator of how bright the sunlight was at any moment (leaves reflect almost all IR). Comparing that to the amount of reflected red light can suggest what proportion of the sunlight was being absorbed by the plants.

That relationship is a good measure of the amount of photosynthetically active biomass. They quickly settled on an index of plant productivity called NDVI for Normalized Difference Vegetation Index defined as

            N - R / N + R

 

where N is the amount of radiation in the near-infrared spectrum and R is the amount of radiation in the red spectrum.

It is possible to capture all the information needed to compute NDVI in just one camera using a so-called "superblue" filter. Spectral transmission of a "superblue" filter is shown in the image below. Most red light (600 to 700 nm) is blocked, but other visible light and most near infrared light (> 700 nm) passes through. This type of filter can replace the IR block filter to allow NDVI to be produced from a single camera. The red channel in the image file will record mostly infrared light, and the blue channel will record light that plants use for photosynthesis.


image
 

After some theory, nothing is better than some coding...

 

NDVI Implementation

 

First of all, I need to split the original RGB image (actually an NGB, because R channel is replaces by the Near-infrared radiation) into its three components

    CvSize imgSize = cvGetSize(image);

    IplImage* n = cvCreateImage(imgSize, image->depth, 1);

    IplImage* g = cvCreateImage(imgSize, image->depth, 1);

    IplImage* b = cvCreateImage(imgSize, image->depth, 1);

cvSplit(image, b, g, n, NULL);            

 

Then I created the image where the NDVI will be shown. This has only 1 channel

    IplImage* imgNDVI = cvCreateImage(imgSize, image->depth, 1);

 

I will also map the NDVI range of values (from -1 to 1) to RGB colors. The resulting image will have three channels.

    IplImage* imgOut = cvCreateImage(imgSize, image->depth, 3);

 

Next I need some pointer arithmetic to make image pixels access faster

    unsigned int stepIn = n->widthStep / (n->depth / 8);

    unsigned int stepOut = imgOut->widthStep / (imgOut->depth / 8);

    unsigned int imgIn_width = n->width;

    unsigned int imgIn_height = n->height;

    unsigned int imgIn_offset = 0;

    unsigned int imgOut_width = imgOut->width;

    unsigned int imgOut_height = imgOut->height;

    unsigned int imgOut_offset = 0;

if(n->roi)

    {

      imgIn_width = n->roi->width;

imgIn_height = n->roi->height;

imgIn_offset = n->roi->xOffset + (n->roi->yOffset * stepIn);

    }

if(imgOut->roi)

    {

      imgOut_width = imgOut->roi->width;

      imgOut_height = imgOut->roi->height;

      imgOut_offset = imgOut->roi->xOffset + (imgOut->roi->yOffset * stepOut);

    }

 

    unsigned char *imgDataN = (unsigned char *)n->imageData + imgIn_offset;

    unsigned char *imgDataB = (unsigned char *)b->imageData + imgIn_offset;

    unsigned char *imgDataOut = (unsigned char *)imgOut->imageData + imgOut_offset;

    unsigned char *imgDataNDVI = (unsigned char *)imgNDVI->imageData + imgIn_offset;

 

#define imageN(X, Y) imgDataN[(X) + (Y)*stepIn]

#define imageB(X, Y) imgDataB[(X) + (Y)*stepIn]

#define imageOut(X, Y, ch) imgDataOut[(X)*3 + (Y)*stepOut + ch]

#define imageNDVI(X, Y) imgDataNDVI[(X) + (Y)*stepIn]

 

All the above stuff is just to compute the number of bytes for row in each image involved in the NDVI calculation. The three macro imageN, imageB and imageOut make it easy to access the image pixels. Thanks to this macros, I can write code like

       imageN(10, 100)

to access the pixel value at position (10, 100). Note that the imageOut has an extra parameter (ch) which is the channel. Because OpenCV uses the BGR pixel format, ch's permitted values are 0 (for B channel), 1 (for G channel) and 2 (for R channel)

To compute NDVI, I just loop on each pixel and convert the NDVI value to the corresponding RGB color

 

#define NVDI_MIN -1

#define NVDI_MAX +1

#define PIXEL_MIN 0

#define PIXEL_MAX 255

 

    // for each pixel, compute (N-B) / (N+B)

    for (unsigned int y=0; y<imgIn_height; y++)

    {

      for (unsigned int x=0; x<imgIn_width; x++)

      {

        double N = imageN(x, y);

        double B = imageB(x, y);

        double NVDI = (N-B) / (N+B);

 

        double px = (NVDI - NVDI_MIN) * (PIXEL_MAX-PIXEL_MIN) / (NVDI_MAX-NVDI_MIN) + PIXEL_MIN;

imageNDVI(x,y) = (unsigned char)px;

       

        uint8_t r, g, b;

ValueToColor(NVDI, -1, +1, &r, &g, &b);

       

imageOut(x,y, 0) = b;

imageOut(x,y, 1) = g;

imageOut(x,y, 2) = r;       

      }

    }

 

The imgNDVI is then searched for blobs that represents flourishing plants

 

    IplImage* frame = cvCreateImage(imgSize, imgOut->depth, imgOut->nChannels);

cvConvertScale(imgOut, frame, 1, 0);

 

    double threshold = (0.05 - NVDI_MIN) * (PIXEL_MAX-PIXEL_MIN) / (NVDI_MAX-NVDI_MIN) + PIXEL_MIN;

   

    IplImage* segmentated = cvCreateImage(imgSize, 8, 1);

cvInRangeS(imgNDVI, CV_RGB((uint8_t)threshold, (uint8_t)threshold, (uint8_t)threshold),

CV_RGB(255, 255, 255), segmentated);

 

    IplImage* labelImg = cvCreateImage(cvGetSize(image), IPL_DEPTH_LABEL, 1);

 

    CvBlobs blobs;

cvLabel(segmentated, labelImg, blobs);

 

cvFilterByArea(blobs, 200, 1000000);

    result = blobs.size();

 

 

Results and videos in my next post...

  • Sign in to reply
Parents
  • DAB
    DAB over 10 years ago

    Ah yes, multispectral analysis.  Know it well.

     

    The NVDI will get you a reasonable indication of plant health.

    RGB is a reasonable start, especially if you can get the Ir component with the red.

     

    Have you looked into MULTISPEC?  It is a free software package from Purdue University.  They also have a lot of data and papers on using various light bands for getting good crop data correlation.

     

    Are you going to set up a passive monitoring system or an active one?

     

    You might need to do multiple readings to get a rough data confidence set over various lighting conditions.

     

    Should be a fun project though,

     

    DAB

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • amgalbu
    amgalbu over 10 years ago in reply to DAB

    Hi DAB   

    I'm new to NDVI, so thank you very much for your suggestions... Multispec is actually awesome an for sure I will explore it in more depth as soon as possible

     

    Ambrogio

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • amgalbu
    amgalbu over 10 years ago in reply to DAB

    Hi DAB   

    I'm new to NDVI, so thank you very much for your suggestions... Multispec is actually awesome an for sure I will explore it in more depth as soon as possible

     

    Ambrogio

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
No Data
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