Making developers awesome at machine learning
Making developers awesome at machine learning
The Random Forest algorithm forms part of a family of ensemble machine learning algorithms and is a popular variation of bagged decision trees. It also comes implemented in the OpenCV library.
In this tutorial, you will learn how to apply OpenCV’s Random Forest algorithm for image classification, starting with a relatively easier banknote dataset and then testing the algorithm on OpenCV’s digits dataset.
After completing this tutorial, you will know:
Kick-start your project with my bookMachine Learning in OpenCV. It providesself-study tutorials withworking code.

Random Forest for Image Classification Using OpenCV
Photo byJeremy Bishop, some rights reserved.
This tutorial is divided into two parts; they are:
The topic surrounding the Random Forest algorithm has already been explained well in these tutorials by Jason Brownlee [1,2], but let’s first start with brushing up on some of the most important points:
We’ll first use the banknote dataset used inthis tutorial.
The banknote dataset is a relatively simple one that involves predicting a given banknote’s authenticity. The dataset contains 1,372 rows, with each row representing a feature vector comprising four different measures extracted from a banknote photograph, plus its corresponding class label (authentic or not).
The values in each feature vector correspond to the following:
The dataset may be downloaded from theUCI Machine Learning Repository.
Take my free email crash course now (with sample code).
Click to sign-up and also get a free PDF Ebook version of the course.
As in Jason’s tutorial, we shall load the dataset, convert its string numbers to floats, and partition it into training and testing sets:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # Function to load the dataset defload_csv(filename): file=open(filename,"rt") lines=reader(file) dataset=list(lines) returndataset # Function to convert a string column to float defstr_column_to_float(dataset,column): forrowindataset: row[column]=float32(row[column].strip()) # Load the dataset from text file data=load_csv('Data/data_banknote_authentication.txt') # Convert the dataset string numbers to float foriinrange(len(data[0])): str_column_to_float(data,i) # Convert list to array data=array(data) # Separate the dataset samples from the ground truth samples=data[:,:4] target=data[:,-1,newaxis].astype(int32) # Split the data into training and testing sets x_train,x_test,y_train,y_test=ms.train_test_split(samples,target,test_size=0.2,random_state=10) |
The OpenCV library implements theRTrees_create function in theml module, which will allow us to create an empty decision tree:
1 2 | # Create an empty decision tree rtree=ml.RTrees_create() |
All the trees in the forest will be trained with the same parameter values, albeit on different subsets of the training dataset. The default parameter values can be customized, but let’s first work with the default implementation. We will return to customizing these parameter values shortly in the next section:
1 2 3 4 5 6 7 8 9 | # Train the decision tree rtree.train(x_train,ml.ROW_SAMPLE,y_train) # Predict the target labels of the testing data _,y_pred=rtree.predict(x_test) # Compute and print the achieved accuracy accuracy=(sum(y_pred.astype(int32)==y_test)/y_test.size)*100 print('Accuracy:',accuracy[0],'%') |
1 | Accuracy: 96.72727272727273 % |
We have already obtained a high accuracy of around 96.73% using the default implementation of the Random Forest algorithm on the banknote dataset.
The complete code listing is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | fromcsvimportreader fromnumpyimportarray,float32,int32,newaxis fromcv2importml fromsklearnimportmodel_selectionasms # Function to load the dataset defload_csv(filename): file=open(filename,"rt") lines=reader(file) dataset=list(lines) returndataset # Function to convert a string column to float defstr_column_to_float(dataset,column): forrowindataset: row[column]=float32(row[column].strip()) # Load the dataset from text file data=load_csv('Data/data_banknote_authentication.txt') # Convert the dataset string numbers to float foriinrange(len(data[0])): str_column_to_float(data,i) # Convert list to array data=array(data) # Separate the dataset samples from the ground truth samples=data[:,:4] target=data[:,-1,newaxis].astype(int32) # Split the data into training and testing sets x_train,x_test,y_train,y_test=ms.train_test_split(samples,target,test_size=0.2,random_state=10) # Create an empty decision tree rtree=ml.RTrees_create() # Train the decision tree rtree.train(x_train,ml.ROW_SAMPLE,y_train) # Predict the target labels of the testing data _,y_pred=rtree.predict(x_test) # Compute and print the achieved accuracy accuracy=(sum(y_pred.astype(int32)==y_test)/y_test.size)*100 print('Accuracy:',accuracy[0],'%') |
Consider applying the Random Forest to images from OpenCV’s digits dataset.
The digits dataset is still relatively simple. However, the feature vectors we will extract from its images using the HOG method will have higher dimensionality (81 features) than those in the banknote dataset. For this reason, we can consider the digits dataset to be relatively more challenging to work with than the banknote dataset.
We will first investigate how the default implementation of the Random Forest algorithm copes with higher-dimensional data:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | fromdigits_datasetimportsplit_images,split_data fromfeature_extractionimporthog_descriptors fromnumpyimportarray,float32 fromcv2importml # Load the digits image img,sub_imgs=split_images('Images/digits.png',20) # Obtain training and testing datasets from the digits image digits_train_imgs,digits_train_labels,digits_test_imgs,digits_test_labels=split_data(20,sub_imgs,0.8) # Convert the image data into HOG descriptors digits_train_hog=hog_descriptors(digits_train_imgs) digits_test_hog=hog_descriptors(digits_test_imgs) # Create an empty decision tree rtree_digits=ml.RTrees_create() # Predict the target labels of the testing data _,digits_test_pred=rtree_digits.predict(digits_test_hog) # Compute and print the achieved accuracy accuracy_digits=(sum(digits_test_pred.astype(int)==digits_test_labels)/digits_test_labels.size)*100 print('Accuracy:',accuracy_digits[0],'%') |
1 | Accuracy: 81.0 % |
We find that the default implementation returns an accuracy of 81%.
This drop in accuracy from that achieved on the banknote dataset may indicate that the capacity of the default implementation of the model may not be enough to learn the complexity of the higher-dimensional data that we are now working with.
Let’s investigate whether we may obtain an improvement in the accuracy by changing:
getTermCriteria method and set using thesetTermCriteria method. When using the latter, the number of trees may be set through theTERM_CRITERIA_MAX_ITER parameter, whereas the desired accuracy may be specified using theTERM_CRITERIA_EPS parameter. getMaxDepth method, and set using thesetMaxDepth method. The specified tree depth may not be reached if the above termination criteria are met first.When tweaking the above parameters, remember that increasing the number of trees can increase the model’s capacity to capture more intricate detail in the training data; it will also increase the prediction time linearly and make the model more susceptible to overfitting. Hence, tweak the parameters judiciously.
If we add in the following lines following the creation of an empty decision tree, we may find the default values of the tree depth as well as the termination criteria:
1 2 | print('Default tree depth:',rtree_digits.getMaxDepth()) print('Default termination criteria:',rtree_digits.getTermCriteria()) |
1 2 | Default tree depth: 5 Default termination criteria: (3, 50, 0.1) |
In this manner, we can see that, by default, each tree in the forest has a depth (or number of levels) equal to 5, while the number of trees and desired accuracy are set to 50 and 0.1, respectively. The first value returned by thegetTermCriteria method refers to thetype of termination criteria under consideration, where a value of 3 specifies termination based on bothTERM_CRITERIA_MAX_ITER andTERM_CRITERIA_EPS.
Let’s now try changing the values mentioned above to investigate their effect on the prediction accuracy. The code listing is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | fromdigits_datasetimportsplit_images,split_data fromfeature_extractionimporthog_descriptors fromnumpyimportarray,float32 fromcv2importml,TERM_CRITERIA_MAX_ITER,TERM_CRITERIA_EPS # Load the digits image img,sub_imgs=split_images('Images/digits.png',20) # Obtain training and testing datasets from the digits image digits_train_imgs,digits_train_labels,digits_test_imgs,digits_test_labels=split_data(20,sub_imgs,0.8) # Convert the image data into HOG descriptors digits_train_hog=hog_descriptors(digits_train_imgs) digits_test_hog=hog_descriptors(digits_test_imgs) # Create an empty decision tree rtree_digits=ml.RTrees_create() # Read the default parameter values print('Default tree depth:',rtree_digits.getMaxDepth()) print('Default termination criteria:',rtree_digits.getTermCriteria()) # Change the default parameter values rtree_digits.setMaxDepth(15) rtree_digits.setTermCriteria((TERM_CRITERIA_MAX_ITER+TERM_CRITERIA_EPS,100,0.01)) # Train the decision tree rtree_digits.train(digits_train_hog.astype(float32),ml.ROW_SAMPLE,digits_train_labels) # Predict the target labels of the testing data _,digits_test_pred=rtree_digits.predict(digits_test_hog) # Compute and print the achieved accuracy accuracy_digits=(sum(digits_test_pred.astype(int)==digits_test_labels)/digits_test_labels.size)*100 print('Accuracy:',accuracy_digits[0],‘%') |
1 | Accuracy: 94.1 % |
We may see that the newly set parameter values bump the prediction accuracy to 94.1%.
These parameter values are being set arbitrarily here to illustrate this example. Still, it is always advised to take a more systematic approach to tweaking the parameters of a model and investigating how each affects its performance.
This section provides more resources on the topic if you want to go deeper.
In this tutorial, you learned how to apply OpenCV’s Random Forest algorithm for image classification, starting with a relativelyeasier banknote dataset and then testing the algorithm on OpenCV’s digits dataset.
Specifically, you learned:
Do you have any questions?
Ask your questions in the comments below, and I will do my best to answer.

...using OpenCV in advanced ways and work beyond pixels
Discover how in my new Ebook:
Machine Learing in OpenCV
It providesself-study tutorials withall working code in Python to turn you from a novice to expert. It equips you with
logistic regression,random forest,SVM,k-means clustering,neural networks, and much more...all using the machine learning module in OpenCV







Welcome!
I'mJason Brownlee PhD
and Ihelp developers get results withmachine learning.
Read more
TheMachine Learning in Open CV EBook
is where you'll find theReally Good stuff.