OpenCV-python提取特征(批量处理数据)

一、提取特征

傅里叶描述子特征点进行提取
提取手部轮廓原理:

  • 加载图像(opencv,截图保存saveROI)
  • 肤色检测(YCrCb颜色空间的Cr分量+Otsu法阈值分割算法)
  • 图像去噪(numpy二值化处理)
  • 轮廓提取(canny检测,cv2.findContours->傅里叶描述子Laplacian)
  • 二次去噪(numpy二值化处理)
  • 绘制轮廓(cv2.drawContours)
    在这里插入图片描述

由视频中保存手势图像参考:python+opencv提取视频中手部轮廓
图片数据集增强参考:OpenCV-python增强数据集(几何变换原理)

现有手势库手势“1”测试图的147份图片:
在这里插入图片描述
目录:
在这里插入图片描述

fourierDesciptor.py

注:(此部分代码参考于:基于OpenCV的手势识别完整项目(Python3.7)

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

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

# 计算傅里叶描述子


def fourierDesciptor(res):
    # Laplacian算子进行八邻域检测
    gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
    dst = cv2.Laplacian(gray, cv2.CV_16S, ksize=3)
    Laplacian = cv2.convertScaleAbs(dst)
    contour = find_contours(Laplacian)  # 提取轮廓点坐标
    contour_array = contour[0][:, 0, :]  # 注意这里只保留区域面积最大的轮廓点坐标
    ret_np = np.ones(dst.shape, np.uint8)  # 创建黑色幕布
    ret = cv2.drawContours(
        ret_np, contour[0], -1, (255, 255, 255), 1)  # 绘制白色轮廓
    contours_complex = np.empty(contour_array.shape[:-1], dtype=complex)
    contours_complex.real = contour_array[:, 0]  # 横坐标作为实数部分
    contours_complex.imag = contour_array[:, 1]  # 纵坐标作为虚数部分
    fourier_result = np.fft.fft(contours_complex)  # 进行傅里叶变换
    #fourier_result = np.fft.fftshift(fourier_result)
    descirptor_in_use = truncate_descriptor(fourier_result)  # 截短傅里叶描述子
    #reconstruct(ret, descirptor_in_use)
    return ret, descirptor_in_use


def find_contours(Laplacian):
    # binaryimg = cv2.Canny(res, 50, 200) #二值化,canny检测
    h = cv2.findContours(Laplacian, cv2.RETR_EXTERNAL,
                         cv2.CHAIN_APPROX_NONE)  # 寻找轮廓
    contour = h[1]
    contour = sorted(contour, key=cv2.contourArea,
                     reverse=True)  # 对一系列轮廓点坐标按它们围成的区域面积进行排序
    return contour

# 截短傅里叶描述子


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

    # 取中间的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

# 由傅里叶描述子重建轮廓图


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.imag])
    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)  # 创建黑色幕布
    black = cv2.drawContours(
        black_np, contour_reconstruct, -1, (255, 255, 255), 3)  # 绘制白色轮廓
    #cv2.imshow("contour_reconstruct", black)
    # cv2.imwrite('recover.png',black)
    return black

二、保存特征点

第一种方式:txt文本格式保存,命名格式为x_i
在这里插入图片描述

feature.py 特征提取,内容:

  • 图片路径
  • 描述子个数
  • 取每张图的第二个点为参考描述子点
  • 其余31个各描述子点与参考描述点的比值
    在这里插入图片描述
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):
    os.mkdir(path)
list = os.listdir(path_img)

if __name__ == "__main__":
    for i in range(1, 2):  # 手势1
        # 将文件夹中照片的特征值提取出来,写入csv
        for j in range(0, len(list)):  # 图片147张
            out_path = os.path.join(path_img, list[j])
            print("Image url is:" + out_path)
            roi = cv2.imread(out_path)
            # 返回单张图的特征值
            # 第一个参数为图像,第二个参数为傅里叶描述子(32位)
            ret, descirptor_in_use = fd.fourierDesciptor(roi)
            # 计算欧式距离
            descirptor_in_use = abs(descirptor_in_use)
            # 设置参考点
            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)):
                    # 计算特征值比
                    x_record = int(100 * descirptor_in_use[k] / temp)
                    print(x_record, end=" ")
                    f.write(str(x_record))
                    f.write(' ')
                f.write('\n')
            print('\n', i, '_', j, 'success')
            print('--------------------------------------')

其中,添加噪声的扩展图像明显差值比较大。(扩展模型时,选择性剔除)
在这里插入图片描述
另一种方式是:
求取32个特征点的平均值保存到csv中:
(有两个手势集,即保存为2行32列的表格)
在这里插入图片描述在这里插入图片描述

import fourierDescriptor as fd  # 提取函数
import cv2
import numpy as np
import os
import csv

path = './feature/'
path_img = './image/data_augmention/'#图片集目录

if not os.path.exists(path):
    os.mkdir(path)


# 返回单张图像的 32D 特征


def return_32d_features(path_img):
    roi = cv2.imread(path_img)
    # 第一个参数为图像,第二个参数为傅里叶描述子(32位)
    ret, descirptor_in_use = fd.fourierDesciptor(roi)
    # 计算欧式距离
    descirptor_in_use = abs(descirptor_in_use)

    return descirptor_in_use


# 将文件夹中照片特征提取出来, 写入 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)):
            # 调用return_32d_features()得到32d特征
            print("%-40s %-20s" % ("正在读的手势图像 / image to read:",
                                   path_hands_gestureX + "/" + photos_list[i]))  # 每个手势
            features_32d = return_32d_features(
                path_hands_gestureX + "/" + photos_list[i])
            #  print(features_32d)
            # 遇到没有检测出手势的图片跳过
            if all(features_32d == 0):
                i += 1
            else:
                features_list_gestureX.append(features_32d)
    else:
        print("文件夹内图像文件为空 / Warning: No images in " +
              path_hands_gestureX + '/', '\n')

    # 计算 32D 特征的均值
    # N x 32D -> 1 x 32D
    if features_list_gestureX:
        features_mean_gestureX = np.array(features_list_gestureX).mean(axis=0)
    else:
        features_mean_gestureX = '0'

    return features_mean_gestureX


def write_in_csv():
    # 读取某手势所有的手势图像数据
    handslist = os.listdir(path_img)
    handslist.sort()
    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)
            writer.writerow(features_mean_gestureX)
            print("特征均值 / The mean of features:", list(features_mean_gestureX))
            print('\n')
        print("写入成功!保存位置:" + path + "features_all.csv")


if __name__ == "__main__":
    write_in_csv()

总结,每次图像识别的过程都是:

  • 准备过程:
    导入图像、图像处理、提取特征值、特征值处理、模型训练(制定判别参数)
  • 识别:
    导入图像、图像处理、提取特征值、特征值与判别参数对比、输出结果

接下来就是:对模型训练的思路:

  1. 构建CNN神经网络创建handpose_Keras.h5模型

    参考学习:10分钟教会你搭建CNN模型破解网站验证码

  2. 构建SVM分类训练创建handpose_model.m模型

    Day 14:SVM案例

  3. 计算特征数据集的欧氏距离作对比

    Dlib模型人脸特征检测原理及demo

这里另起一文说明,关于此部分OpenCV-python手语识别项目的相关代码后面都会放在gitee上。

### 回答1: 使用OpenCV进行批量处理图片的Python代码如下: ``` python import cv2 import os # 图片所在的文件夹路径 image_folder = 'path/to/folder' # 待处理的图片文件格式 image_format = '.jpg' # 处理后保存的文件夹路径 output_folder = 'path/to/output/folder' # 遍历文件夹中所有的图片 for filename in os.listdir(image_folder): if filename.endswith(image_format): # 读取图片 image = cv2.imread(os.path.join(image_folder, filename)) # 在这里进行对图片的处理 # 保存处理后的图片 output_filename = os.path.splitext(filename)[0] + '_processed' + image_format output_path = os.path.join(output_folder, output_filename) cv2.imwrite(output_path, image) ``` 你可以根据需要修改image_folder、image_format和output_folder的值,以及在循环中添加你需要对图片进行的操作。最后将处理后的图片保存到指定的文件夹中。 ### 回答2: 要使用OpenCV进行批量处理图片,可以按照以下步骤进行: 1. 导入OpenCV库:在Python程序中导入OpenCV库,可以使用`import cv2`语句。 2. 获取图片路径:使用Python的文件操作函数(例如os模块或glob模块),获取待处理图片的路径。可以是一个文件夹中的多张图片,或者一个包含图片路径的列表。 3. 循环处理每张图片:使用循环语句遍历每张图片的路径。 4. 读取图片:使用`cv2.imread()`函数读取图片。该函数接受图片路径作为参数,并返回一个表示图片的numpy数组。 5. 执行图像处理操作:对读取的图片进行各种处理操作。可以使用OpenCV提供的函数和方法,如图像缩放、图像旋转、颜色转换等。 6. 保存处理后的图片:使用`cv2.imwrite()`函数将处理后的图片保存到指定路径。该函数接受保存路径和处理后的图片数组作为参数。 7. 释放资源:在循环结束后,使用`cv2.destroyAllWindows()`函数关闭窗口及释放资源。 下面是一个示例代码片段,演示了如何使用OpenCV进行批量处理图片: ```python import cv2 import glob # 获取图片路径 image_paths = glob.glob("path/to/images/*.jpg") # 循环处理每张图片 for image_path in image_paths: # 读取图片 image = cv2.imread(image_path) # 执行图像处理操作,例如缩放为指定大小 resized_image = cv2.resize(image, (300, 300)) # 保存处理后的图片 save_path = "path/to/save/processed_images/" + image_path.split("/")[-1] cv2.imwrite(save_path, resized_image) # 释放资源 cv2.destroyAllWindows() ``` 这是一个简单的示例,你可以根据具体需求和处理操作进行更多定制和扩展。 ### 回答3: 使用OpenCV库可以方便地批量处理图片,特别是在Python使用。 首先,我们需要导入OpenCV库和其他相关的库,如numpy等。 接下来,我们可以使用cv2.imread()函数读取要处理的图片文件。这个函数可以读取多种图片格式,如bmp、jpg、png等。读取的图片数据会存储在一个numpy数组中。 然后,我们可以对图片进行各种处理操作,如调整大小、裁剪、旋转、灰度化、二值化等。这些操作可以通过调用OpenCV提供的相应函数来实现。 例如,我们可以通过cv2.resize()函数调整图片的尺寸,通过cv2.cvtColor()函数将图片转换为灰度图像,通过cv2.threshold()函数进行图像二值化等。 如果要对多张图片进行批量处理,可以使用循环来遍历每一张图片,对每张图片进行相同或不同的操作。 最后,我们可以使用cv2.imwrite()函数将处理后的图片保存到指定的位置。 综上所述,通过OpenCV以及Python的强大功能,我们可以轻松地对多张图片进行批量处理,实现各种各样的操作,如调整尺寸、颜色转换、特征提取等。这对于进行图像处理、机器视觉、深度学习等应用非常有用。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值