Opencv Python feature extraction (batch data processing)

Article directory

1, Extract features

Extracting feature points from Fourier descriptors
Principle of hand contour extraction:

  • Load image (opencv, screenshot save saveROI)
  • Skin color detection (threshold segmentation algorithm of Cr component + Otsu method in YCrCb color space)
  • Image denoising (numpy binarization)
  • Contour extraction (canny detection, CV2. Findcontours - > Fourier descriptor Laplacian)
  • Secondary denoising (numpy binarization)
  • Draw contours (cv2.drawContours)

Save gesture image reference in video: Extracting hand contour from video by python+opencv
Picture dataset enhanced reference: Opencv Python enhanced dataset (principle of geometric transformation)

147 pictures of "1" test picture of existing gesture Library:


Note: (this part of the code refers to: OpenCV based gesture recognition complete project (Python 3.7))

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import cv2
import numpy as np

MIN_DESCRIPTOR = 32  # surprisingly enough, 2 descriptors are already enough

# Computed Fourier descriptors

def fourierDesciptor(res):
    # Eight neighborhood detection by Laplacian operator
    gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
    dst = cv2.Laplacian(gray, cv2.CV_16S, ksize=3)
    Laplacian = cv2.convertScaleAbs(dst)
    contour = find_contours(Laplacian)  # Extract contour point coordinates
    contour_array = contour[0][:, 0, :]  # Note that only the coordinates of contour points with the largest area of the area are reserved here
    ret_np = np.ones(dst.shape, np.uint8)  # Create a black screen
    ret = cv2.drawContours(
        ret_np, contour[0], -1, (255, 255, 255), 1)  # Draw a white outline
    contours_complex = np.empty(contour_array.shape[:-1], dtype=complex)
    contours_complex.real = contour_array[:, 0]  # Abscissa as real part
    contours_complex.imag = contour_array[:, 1]  # Ordinate as imaginary part
    fourier_result = np.fft.fft(contours_complex)  # Fourier transform
    #fourier_result = np.fft.fftshift(fourier_result)
    descirptor_in_use = truncate_descriptor(fourier_result)  # Truncated Fourier descriptor
    #reconstruct(ret, descirptor_in_use)
    return ret, descirptor_in_use

def find_contours(Laplacian):
    # binaryimg = cv2.Canny(res, 50, 200) #Binarization, canny detection
    h = cv2.findContours(Laplacian, cv2.RETR_EXTERNAL,
                         cv2.CHAIN_APPROX_NONE)  # Looking for outline
    contour = h[1]
    contour = sorted(contour, key=cv2.contourArea,
                     reverse=True)  # The coordinates of a series of contour points are sorted according to the area they enclose
    return contour

# Truncate Fu Liye Miao Shuzi

def truncate_descriptor(fourier_result):
    descriptors_in_use = np.fft.fftshift(fourier_result)

    # Take the middle min descriptor
    center_index = int(len(descriptors_in_use) / 2)
    low, high = center_index - \
        int(MIN_DESCRIPTOR / 2), center_index + int(MIN_DESCRIPTOR / 2)
    descriptors_in_use = descriptors_in_use[low:high]

    descriptors_in_use = np.fft.ifftshift(descriptors_in_use)
    return descriptors_in_use

# Reconstruction of contour from Fourier descriptors

def reconstruct(img, descirptor_in_use):
    #descirptor_in_use = truncate_descriptor(fourier_result, degree)
    #descirptor_in_use = np.fft.ifftshift(fourier_result)
    #descirptor_in_use = truncate_descriptor(fourier_result)
    # print(descirptor_in_use)
    contour_reconstruct = np.fft.ifft(descirptor_in_use)
    contour_reconstruct = np.array([contour_reconstruct.real,
    contour_reconstruct = np.transpose(contour_reconstruct)
    contour_reconstruct = np.expand_dims(contour_reconstruct, axis=1)
    if contour_reconstruct.min() < 0:
        contour_reconstruct -= contour_reconstruct.min()
    contour_reconstruct *= img.shape[0] / contour_reconstruct.max()
    contour_reconstruct = contour_reconstruct.astype(np.int32, copy=False)

    black_np = np.ones(img.shape, np.uint8)  # Create a black screen
    black = cv2.drawContours(
        black_np, contour_reconstruct, -1, (255, 255, 255), 3)  # Draw a white outline
    #cv2.imshow("contour_reconstruct", black)
    # cv2.imwrite('recover.png',black)
    return black

2, Save feature points

The first way is to save the text in the format of txt, and name it in the format of X feature extraction, content:

  • Picture path
  • Number of descriptors
  • Take the second point of each graph as the reference description sub point
  • The ratio of the other 31 descriptors to the reference descriptors
import fourierDescriptor as fd
import cv2
import numpy as np
import os

path = './feature/'
path_img = './image/1_test/'

if not os.path.exists(path):
list = os.listdir(path_img)

if __name__ == "__main__":
    for i in range(1, 2):  # Gesture 1
        # Extract the characteristic value of photos in the folder and write it to csv
        for j in range(0, len(list)):  # Picture 147
            out_path = os.path.join(path_img, list[j])
            print("Image url is:" + out_path)
            roi = cv2.imread(out_path)
            # Returns the eigenvalue of a single graph
            # The first parameter is image, the second parameter is Fourier descriptor (32 bits)
            ret, descirptor_in_use = fd.fourierDesciptor(roi)
            # Calculate Euclidean distance
            descirptor_in_use = abs(descirptor_in_use)
            # Set reference point
            temp = descirptor_in_use[1]
            print("Descirptor length is:" + str(len(descirptor_in_use)))
            print("Reference point is:" + str(temp))
            print("Eigenvalue division is:")
            fd_name = path + str(i) + '_' + str(j) + '.txt'
            with open(fd_name, 'w', encoding='utf-8') as f:
                for k in range(1, len(descirptor_in_use)):
                    # Calculate the ratio of eigenvalues
                    x_record = int(100 * descirptor_in_use[k] / temp)
                    print(x_record, end=" ")
                    f.write(' ')
            print('\n', i, '_', j, 'success')

Among them, the difference of the extended image with noise is large. (selective culling when extending the model)

Another way is to:
Calculate the average value of 32 feature points and save it in csv:
(there are two gesture sets, a table saved as 2 rows and 32 columns)

import fourierDescriptor as fd  # Extraction function
import cv2
import numpy as np
import os
import csv

path = './feature/'
path_img = './image/data_augmention/'#Picture set catalog

if not os.path.exists(path):

# Return 32D features of a single image

def return_32d_features(path_img):
    roi = cv2.imread(path_img)
    # The first parameter is image, the second parameter is Fourier descriptor (32 bits)
    ret, descirptor_in_use = fd.fourierDesciptor(roi)
    # Calculate Euclidean distance
    descirptor_in_use = abs(descirptor_in_use)

    return descirptor_in_use

# Extract the photo features in the folder and write them to CSV

def return_features_mean_gestrueX(path_hands_gestureX):
    features_list_gestureX = []
    photos_list = os.listdir(path_hands_gestureX)
    if photos_list:
        for i in range(len(photos_list)):
            # Call return ﹣ 32d ﹣ features() to get 32d features
            print("%-40s %-20s" % ("Gesture image being read / image to read:",
                                   path_hands_gestureX + "/" + photos_list[i]))  # Each gesture
            features_32d = return_32d_features(
                path_hands_gestureX + "/" + photos_list[i])
            #  print(features_32d)
            # Picture skipping without gesture detected
            if all(features_32d == 0):
                i += 1
        print("The image file in the folder is empty / Warning: No images in " +
              path_hands_gestureX + '/', '\n')

    # Calculating the mean value of 32D features
    # N x 32D -> 1 x 32D
    if features_list_gestureX:
        features_mean_gestureX = np.array(features_list_gestureX).mean(axis=0)
        features_mean_gestureX = '0'

    return features_mean_gestureX

def write_in_csv():
    # Read all gesture image data of a gesture
    handslist = os.listdir(path_img)
    with open(path + "features_all.csv", "w", newline="") as csvfile:
        writer = csv.writer(csvfile)
        for gesture in handslist:
            print("##### " + gesture + " #####")
            # Get the mean/average features of gestureX, it will be a list with
            # a length of 32D
            features_mean_gestureX = return_features_mean_gestrueX(
                path_img + gesture)
            print("Characteristic mean / The mean of features:", list(features_mean_gestureX))
        print("Write succeeded! Save in:" + path + "features_all.csv")

if __name__ == "__main__":

In summary, each image recognition process is:

  • Preparation process:
    Import image, image processing, extract eigenvalue, eigenvalue processing, model training (develop discrimination parameters)
  • Distinguish:
    Import image, image processing, extract eigenvalue, comparison of eigenvalue and discrimination parameter, output result

Next, the train of thought of model training:

  1. Building CNN neural network to create handpost_keras.h5 model
  2. Construct SVM classification training and create handpost ﹣ model. M model
  3. Euclidean distance of feature data set for comparison

Here's another article to show that the code related to this part of OpenCV Python sign language recognition project will be put on gitee.

195 original articles published, praised 335, visited 120000+
Private letter follow

Tags: OpenCV Python encoding network

Posted on Fri, 07 Feb 2020 01:09:03 -0500 by xcandiottix