This article is your ultimate guide to becoming a pro at image feature extraction and classification using OpenCV and Python. We'll kick things off with an overview of how OpenCV plays a role in feature extraction, and we'll go through the setup process for the OpenCV environment. You'll get to learn all about different feature extraction techniques and algorithms, with a focus on the ones specific to OpenCV.
Feature extraction is a crucial process in machine learning and data analysis. It focuses on identifying and extracting relevant features from raw data, transforming it into numerical features that machine learning algorithms can work with. This process helps convert raw data into a format suitable for machine learning models and plays a role in dimensionality reduction, simplifying large datasets into manageable groups. The goal is to reduce data complexity while retaining as much relevant information as possible.
Step 1: Install OpenCV
Ensure you have OpenCV installed. You can install it using pip if you haven't already:
pip install opencv-python
Step 2: Import Libraries
Python
import cv2
import numpy as np
import matplotlib.pyplot as plt
Step 3: Load an Image
Input Image
Python
image = cv2.imread('GeeksForGeeks.jpg')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
Step 4: Use Edge Detection
One of the common feature extraction techniques is edge detection using the Canny algorithm.
The Canny edge detection algorithm smooths the image to reduce noise, calculates the gradient to find edge strength and direction, applies non-maximum suppression to thin edges, and uses hysteresis for final edge tracking, resulting in a black and white image with edges in white. This makes it highly effective for object detection and image segmentation.
Python
edges = cv2.Canny(gray_image, 100, 200)
plt.imshow(edges, cmap='gray')
plt.title('Edge Image')
plt.show()
Output:
outputStep 5: Use Feature Detectors
OpenCV provides several feature detectors. Two commonly used ones are SIFT (Scale-Invariant Feature Transform) and ORB (Oriented FAST and Rotated BRIEF).
First, we are going to implement SIFT, SIFT can find specific points in an image by looking at their size, orientation, and local details.
Python
sift = cv2.SIFT_create()
keypoints, descriptors = sift.detectAndCompute(gray_image, None)
image_with_sift = cv2.drawKeypoints(image, keypoints, None)
plt.imshow(cv2.cvtColor(image_with_sift, cv2.COLOR_BGR2RGB))
plt.title('SIFT Features')
plt.show()
Output:
SIFT Output
Now, we will be implementing ORB and ORB is a faster alternative to SIFT, suitable for real-time applications.
Python
orb = cv2.ORB_create()
keypoints, descriptors = orb.detectAndCompute(gray_image, None)
image_with_orb = cv2.drawKeypoints(image, keypoints, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
plt.imshow(cv2.cvtColor(image_with_orb, cv2.COLOR_BGR2RGB))
plt.title('ORB Features')
plt.show()
Output:
ORB Output
In a nutshell, OpenCV offers feature extraction methods like SIFT and ORB that are crucial for identifying important features in images. SIFT is super robust, but it can be a bit of a computer hog. On the other hand, ORB is a faster option that performs just as well. By using these methods, you can easily extract features from images and unlock a whole world of possibilities in image processing and computer vision.
Implementing Image Classification with OpenCV
Step 1: Install the necessary libraries
pip install PyWavelets
pip install opencv-python
Step 2: Importing Necessary Libraries
Importing necessary libraries like NumPy for numerical operations, OpenCV for image processing, and Matplotlib for plotting images.
Python
import numpy as np
import cv2
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
We have used the Indian Cricketer Dataset and the directory structure is discussed below.
Directory StructureStep 2: Loading and Displaying the Image
Python
img = cv2.imread('images\ms_dhoni\dhoni.jpg')
plt.imshow(img)
Output:
outputStep 4: Converting Image to Grayscale
Converting the loaded image to grayscale using cv2.cvtColor and displaying the grayscale image. The shape of the grayscale image is also printed.
Python
#Converting the image to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray.shape
plt.imshow(gray)
Output:
Output
Python
plt.imshow(gray, cmap='gray')
Output:
OutputStep 5: Loading Haar Cascades for Face and Eye Detection
The code initializes face and eye classifiers using pre-trained Haar cascade models and applies the face classifier to a grayscale image to detect faces. The results are stored in the faces variable, which contains a list of rectangles representing detected faces. This setup enables the identification of facial regions within the image, allowing for further processing or feature extraction.
Python
face_cascade = cv2.CascadeClassifier('./opencv/haarcascades/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('./opencv/haarcascades/haarcascade_eye.xml')
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
faces
Output:
array([[172, 55, 268, 268]])
The code extracts the coordinates and dimensions of the first detected face from the faces variable. Specifically, x and y represent the top-left corner coordinates of the face, while w and h represent the width and height of the bounding box around the face. This step isolates the region of interest for further processing, such as drawing rectangles around the detected face or performing additional analyses
Python
(x,y,w,h) = faces[0]
x,y,w,h
Output:
(172, 55, 268, 268)
Step 6: Detecting Faces and Drawing Rectangles Around Them
Detecting faces in the grayscale image using detectMultiScale. The first detected face's coordinates are used to draw a rectangle around it on the original image. The resulting image is displayed.
Python
face_img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
plt.imshow(face_img)
Output:
OutputStep 7: Detecting Faces , eyes and Drawing Rectangles Around Them
The code detects faces and eyes in an image and visualizes the results. It first closes any open OpenCV windows, then loops through the detected faces to draw red rectangles around them. For each detected face, it defines regions of interest (ROI) in both grayscale and color images. Within each face ROI, it detects eyes and draws green rectangles around them. Finally, it displays the image with the detected faces and eyes, showing the rectangles in grayscale. This provides a clear visual representation of the detected features..
Python
cv2.destroyAllWindows()
for (x,y,w,h) in faces:
face_img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray = gray[y:y+h, x:x+w]
roi_color = face_img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
for (ex,ey,ew,eh) in eyes:
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
plt.figure()
plt.imshow(face_img, cmap='gray')
plt.show()
Output:
Output
Python
#Plotting the cropped Image
%matplotlib inline
plt.imshow(roi_color, cmap='gray')
plt.show()
Output:
output
Python
cropped_img = np.array(roi_color)
cropped_img.shape
Output:
(268, 268, 3)
The purpose of this code is to apply a 2D wavelet transform to an input image, which can be useful in various image processing tasks, including denoising, compression, and feature extraction. The specific wavelet used and the level of decomposition can be adjusted according to the requirements of the task.
Python
import numpy as np
import pywt
import cv2
def w2d(img, mode='haar', level=1):
imArray = img
#Datatype conversions
#convert to grayscale
imArray = cv2.cvtColor( imArray,cv2.COLOR_RGB2GRAY )
#convert to float
imArray = np.float32(imArray)
imArray /= 255;
# compute coefficients
coeffs=pywt.wavedec2(imArray, mode, level=level)
#Process Coefficients
coeffs_H=list(coeffs)
coeffs_H[0] *= 0;
# reconstruction
imArray_H=pywt.waverec2(coeffs_H, mode);
imArray_H *= 255;
imArray_H = np.uint8(imArray_H)
return imArray_H
Step 9: Function to Get Cropped Image with Two Eyes
Python
im_har = w2d(cropped_img,'db1',5)
plt.imshow(im_har, cmap='gray')
Output:
OutputStep 10: Preprocessing: Load image, detect face. If eyes >=2, then save and crop the face region
Lets write a python function that can take input image and returns cropped image (if face and eyes >=2 are detected)
Python
def get_cropped_image_if_2_eyes(image_path):
img = cv2.imread(image_path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
eyes = eye_cascade.detectMultiScale(roi_gray)
if len(eyes) >= 2:
return roi_color
original_image = cv2.imread('images\ms_dhoni\dhoni.jpg')
plt.imshow(original_image)
Output:
Output
Python
cropped_image = get_cropped_image_if_2_eyes('images\ms_dhoni\dhoni.jpg')
plt.imshow(cropped_image)
Output:
OutputStep 9: Preparing and Organizing the Dataset
Python
path_to_data = "./images/"
path_to_cr_data = "./images/cropped/"
import os
img_dirs = []
for entry in os.scandir(path_to_data):
if entry.is_dir():
img_dirs.append(entry.path)
img_dirs
Output:
['./images/bhuvneshwar_kumar',
'./images/dinesh_karthik',
'./images/hardik_pandya',
'./images/jasprit_bumrah',
'./images/k._l._rahul',
'./images/kedar_jadhav',
'./images/kuldeep_yadav',
'./images/mohammed_shami',
'./images/ms_dhoni',
'./images/ravindra_jadeja',
'./images/rohit_sharma',
'./images/shikhar_dhawan',
'./images/vijay_shankar',
'./images/virat_kohli',
'./images/yuzvendra_chahal']
Go through all images in dataset folder and create cropped images for them. There will be cropped folder inside dataset folder after you run this code.
Python
import shutil
if os.path.exists(path_to_cr_data):
shutil.rmtree(path_to_cr_data)
os.mkdir(path_to_cr_data)
- Initialization: Begin by initializing an empty list cropped_image_dirs to store paths to directories containing cropped images, and an empty dictionary celebrity_file_names_dict to store file paths for each celebrity.
- Iterate through Directories: Iterate through each directory (img_dirs) containing images of different celebrities.
- Detect and Crop Faces: For each image in the directory, attempt to detect and crop the face if both eyes are visible using the get_cropped_image_if_2_eyes function.
- Create and Save Cropped Images:
- If a valid face is detected, create a folder (if it doesn't already exist) to store cropped images for that celebrity.
- Save the cropped image to the appropriate folder with a unique file name.
- Update the celebrity_file_names_dict with the file path of the cropped image.
- Use a count variable to ensure each saved image has a unique name within its respective celebrity's folder.
- Repeat for Each Celebrity: Repeat steps 2-4 for each directory containing images of different celebrities.
Python
cropped_image_dirs = []
celebrity_file_names_dict = {}
for img_dir in img_dirs:
count = 1
celebrity_name = img_dir.split('/')[-1]
print(celebrity_name)
celebrity_file_names_dict[celebrity_name] = []
for entry in os.scandir(img_dir):
roi_color = get_cropped_image_if_2_eyes(entry.path)
if roi_color is not None:
cropped_folder = path_to_cr_data + celebrity_name
if not os.path.exists(cropped_folder):
os.makedirs(cropped_folder)
cropped_image_dirs.append(cropped_folder)
print("Generating cropped images in folder: ",cropped_folder)
cropped_file_name = celebrity_name + str(count) + ".png"
cropped_file_path = cropped_folder + "/" + cropped_file_name
cv2.imwrite(cropped_file_path, roi_color)
celebrity_file_names_dict[celebrity_name].append(cropped_file_path)
count += 1
Output:
bhuvneshwar_kumar
Generating cropped images in folder: ./images/cropped/bhuvneshwar_kumar
dinesh_karthik
Generating cropped images in folder: ./images/cropped/dinesh_karthik
hardik_pandya
Generating cropped images in folder: ./images/cropped/hardik_pandya
jasprit_bumrah
Generating cropped images in folder: ./images/cropped/jasprit_bumrah
k._l._rahul
Generating cropped images in folder: ./images/cropped/k._l._rahul
kedar_jadhav
Generating cropped images in folder: ./images/cropped/kedar_jadhav
kuldeep_yadav
Generating cropped images in folder: ./images/cropped/kuldeep_yadav
mohammed_shami
.....
yuzvendra_chahal
Generating cropped images in folder: ./images/cropped/yuzvendra_chahal
Now you should have cropped folder under datasets folder that contains cropped images ,Manually examine cropped folder and delete any unwanted images
Step 10: Creating a Dictionary for Training Files
Python
celebrity_file_names_dict = {}
for img_dir in cropped_image_dirs:
celebrity_name = img_dir.split('/')[-1]
file_list = []
for entry in os.scandir(img_dir):
file_list.append(entry.path)
celebrity_file_names_dict[celebrity_name] = file_list
celebrity_file_names_dict
Output:
{'bhuvneshwar_kumar': ['./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar1.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar10.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar11.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar12.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar13.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar14.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar2.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar3.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar4.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar5.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar6.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar7.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar8.png',
'./images/cropped/bhuvneshwar_kumar\\bhuvneshwar_kumar9.png'],
Step 11: Creating a Class Dictionary
Python
class_dict = {}
count = 0
for celebrity_name in celebrity_file_names_dict.keys():
class_dict[celebrity_name] = count
count = count + 1
class_dict
Output:
{'bhuvneshwar_kumar': 0,
'dinesh_karthik': 1,
'hardik_pandya': 2,
'jasprit_bumrah': 3,
'k._l._rahul': 4,
'kedar_jadhav': 5,
'kuldeep_yadav': 6,
'mohammed_shami': 7,
'ms_dhoni': 8,
'ravindra_jadeja': 9,
'rohit_sharma': 10,
'shikhar_dhawan': 11,
'vijay_shankar': 12,
'virat_kohli': 13,
'yuzvendra_chahal': 14}
Images in cropped folder can be used for model training. We will use these raw images along with wavelet transformed images to train our classifier. Let's prepare X and y now
Step 12: Preparing the Feature Vectors
We're getting everything ready to train an image classifier. First, we go through each celebrity's pictures, making sure they're all the same size. Then, we use the Wavelet Transform to pull out the high-frequency parts from the images.
After that, we stack all these processed images together and add them to our list of features, which we call X. At the same time, we also add the corresponding labels to a separate list called y. This step is important because it ensures our dataset is set up correctly for training the classifier. Each image is represented by its features and has an associated label.
Python
X, y = [], []
for celebrity_name, training_files in celebrity_file_names_dict.items():
for training_image in training_files:
img = cv2.imread(training_image)
if img is None:
continue
scalled_raw_img = cv2.resize(img, (32, 32))
img_har = w2d(img,'db1',5)
scalled_img_har = cv2.resize(img_har, (32, 32))
combined_img = np.vstack((scalled_raw_img.reshape(32*32*3,1),scalled_img_har.reshape(32*32,1)))
X.append(combined_img)
y.append(class_dict[celebrity_name])
Step 13: Training the SVM Classifier
We will use SVM with rbf kernel tuned with heuristic finetuning
Python
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.metrics import classification_report
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
pipe = Pipeline([('scaler', StandardScaler()), ('svc', SVC(kernel = 'rbf', C = 10))])
pipe.fit(X_train, y_train)
pipe.score(X_test, y_test)
Output:
0.5166666666666667
Now let's evaluate the model.
Python
print(classification_report(y_test, pipe.predict(X_test)))
Output:
precision recall f1-score support
0 0.50 0.25 0.33 4
1 0.00 0.00 0.00 3
2 0.33 0.50 0.40 2
3 0.00 0.00 0.00 0
4 0.40 0.40 0.40 5
5 0.00 0.00 0.00 3
6 1.00 0.33 0.50 3
7 1.00 1.00 1.00 2
8 0.47 0.78 0.58 9
9 0.00 0.00 0.00 2
10 0.56 0.75 0.64 12
11 0.00 0.00 0.00 3
12 0.00 0.00 0.00 3
13 0.73 0.89 0.80 9
accuracy 0.52 60
macro avg 0.36 0.35 0.33 60
weighted avg 0.45 0.52 0.46 60
Conclusion
In conclusion, becoming a pro at extracting and classifying image features using OpenCV and Python involves really understanding image processing, being super careful with feature extraction, and using top-notch classifiers. Throughout this journey, we learned the crucial steps of setting up the OpenCV environment, exploring different feature extraction techniques, and creating a powerful image classifier.
Similar Reads
Random Forest for Image Classification Using OpenCV
Random Forest is a machine learning algorithm that uses multiple decision trees to achieve precise results in classification and regression tasks. It resembles the process of choosing the best path amidst multiple options. OpenCV, an open-source library for computer vision and machine learning tasks
8 min read
Feature Extraction in Image Processing: Techniques and Applications
Feature extraction is a critical step in image processing and computer vision, involving the identification and representation of distinctive structures within an image. This process transforms raw image data into numerical features that can be processed while preserving the essential information. T
15+ min read
Image Feature Extraction Using Python
An essential method in computer vision and image processing is picture feature extraction. It entails locating and removing different characteristics or patterns from an image in order to make analysis and comprehension easier. These characteristics, which are essential for tasks like object detecti
9 min read
An introduction to MultiLabel classification
One of the most used capabilities of supervised machine learning techniques is for classifying content, employed in many contexts like telling if a given restaurant review is positive or negative or inferring if there is a cat or a dog on an image. This task may be divided into three domains, binary
7 min read
Face Detection using Cascade Classifier using OpenCV - Python
Face detection is a important task in computer vision and Haar Cascade classifiers play an important role in making this process fast and efficient. Haar Cascades are used for detecting faces and other objects by training a classifier on positive and negative images. Positive Images: These images co
3 min read
Dog Breed Classification using Transfer Learning
In this tutorial, we will demonstrate how to build a dog breed classifier using transfer learning. This method allows us to use a pre-trained deep learning model and fine-tune it to classify images of different dog breeds. Why to use Transfer Learning for Dog Breed ClassificationTransfer learning is
9 min read
Feature detection and matching with OpenCV-Python
In this article, we are going to see about feature detection in computer vision with OpenCV in Python. Feature detection is the process of checking the important features of the image in this case features of the image can be edges, corners, ridges, and blobs in the images. In OpenCV, there are a nu
5 min read
Age Detection using Deep Learning in OpenCV
The task of age prediction might sound simple at first but it's quite challenging in real-world applications. While predicting age is typically seen as a regression problem this approach faces many uncertainties like camera quality, brightness, climate condition, background, etc. In this article we'
5 min read
Dataset for Image Classification
The field of computer vision has witnessed remarkable progress in recent years, largely driven by the availability of large-scale datasets for image classification tasks. These datasets play a pivotal role in training and evaluating machine learning models, enabling them to recognize and categorize
12 min read
Python | Detect corner of an image using OpenCV
OpenCV (Open Source Computer Vision) is a computer vision library that contains various functions to perform operations on Images or videos. OpenCV library can be used to perform multiple operations on videos. Let's see how to detect the corner in the image. cv2.goodFeaturesToTrack() method finds N
2 min read