image thumbnail
from MATLAB codes for canopy image analysis by Lauri Korhonen
Codes for thresholding skyward-looking canopy images and calculating proportion of canopy pixels.

bin_cc_circ.m
%
%	A MATLAB program for analysis of thresholded (=binary) canopy images
%
% 	Authors: Jaakko Heikkinen & Lauri Korhonen 2006-2009			
%	Citation: Korhonen, L. & Heikkinen, J. 2009. Automated analysis of in situ canopy images for the estimation of forest canopy cover.
%		Forest Science 55(4): 323-334.
%	Here size reduction is done based on circular filter.

%Constants

filetype='bmp';	%Which type of files are read
elem_size=10	%Diameter of the circular structuring element used in painting
true_focal=6.5;	%Focal length of the camera, mm
ccd_hor=6.16;	%Horizontal size of the ccd sensor
ccd_ver=4.62;	%Vertical size of the ccd sensor
set_angle=40	%Angle of view that should be used, degrees. Larger than cameras diagonal AOV -> whole image is analyzed.

files=dir(['*.', filetype]); 	%Read all files of the specified type

results=cell(length(files),3);	%Create array for the results
results{1,1}='Image';
results{1,2}='C_Closure'; 
results{1,3}='C_Cover'; 



%%%%%%%%%%%%%%% START LOOP %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

for h=1:length(files) %Loop goes through all images h

	%%%%%%%%%%%%%%%%%% READ IMAGE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	fileid=files(h).name(1:length(files(h).name)-(length(filetype)+1));
	
	binim=imread(files(h).name); 		%Read RGB image
	[rows,cols,channels]=size(binim);	%Read image dimensions
	
	%%%%%% FIRST IMAGE: CIRCULAR MASK DETERMINATION %%%%%%%%%%
	if h==1
		centerx=round(cols/2);
		centery=round(rows/2);
		
		%Calculate AOVs in degrees
		hor_angle=2*atan(ccd_hor/(2*true_focal))*180/pi;
		ver_angle=2*atan(ccd_ver/(2*true_focal))*180/pi;
		
		%Pixel dimensions in degrees
		rowpix=ver_angle/rows;
		colpix=hor_angle/cols;
		
		mask=zeros(rows,cols);
		maskpixels=0;
		for r=1:rows
			for c=1:cols
				deltax=abs(centerx-c)*colpix;	%Horizontal angle for pixel (r,c)
				deltay=abs(centery-r)*rowpix;	%Vertical angle for pixel (r,c)
				
				d=sqrt(deltax^2+deltay^2);
				if d<=set_angle/2
					mask(r,c)=1;
					maskpixels=maskpixels+1;
				end
			end
		end
		disp('Analyzing image:');
	end %if
	disp(fileid);

	%%%%%%%%%%%%%%%%% PAINTING %%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	%Paint the crowns black using morphological opening and closing
	elem=strel('disk',elem_size);
	opeclo=imopen(binim,elem);	%Because objects are black, do the closing with opening operation
	opeclo=imclose(opeclo,elem);
	
	%%%%%%%%%%%%%%% CANOPY CLOSURE %%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	all=0;clos_black=0;cover_black=0;
	clos_black=sum(sum(binim & mask));
	cover_black=sum(sum(opeclo & mask));
	
	
	cclosure=100-clos_black/maskpixels*100;
	ccover=100-cover_black/maskpixels*100;
	
	%%%%%%%%%%%%%% SAVE PAINTED IMAGE AND SPREADSHEET %%%%%%%%%%%%%%%%%%%%%

	%Save painted images as bmp
	opeclo=opeclo>0;	%2-bit conversion
	imwrite(opeclo, ['painted_',fileid,'_',num2str(set_angle),'_circ.bmp'],'bmp')

    close all
	
	%Save results to array
	results{h+1,1}=files(h).name;
	results{h+1,2}=cclosure;
	results{h+1,3}=ccover;
	
end
results
xlswrite(['Circ_Bin_',num2str(set_angle),'.xls'],results);

clear all

Contact us at files@mathworks.com