OpenCV训练级联分类器

新建文件夹,在该文件夹当中新建neg(存放负样本)、pos(存放正样本)这两个文件夹。

训练分类器-1

在该文件夹当中新建1.py,填入如下代码以生成灰度文件,注意要以管理员权限打开powershell执行python代码!


# 图像转换代码,负责处理正样本
import cv2
import os

# 指定目录路径
directory_path = r'C:\Users\20414\Desktop\opencv341_bin-master\pos'

# 获取目录下所有文件
file_list = os.listdir(directory_path)

# 遍历每个文件并转换为灰度图
for filename in file_list:
    file_path = os.path.join(directory_path, filename)
    img = cv2.imread(file_path, cv2.IMREAD_GRAYSCALE)  # 读取为灰度图
    resized_img = cv2.resize(img, (60, 60))  # 调整像素为 60x60
    # 保存灰度图;此处如果不改文件名,会覆盖原先的文件
    cv2.imwrite(f'GRAY_{filename}', resized_img)

print("已将所有图片转换为灰度图并调整像素。")

新建2.py,填入如下代码以生成两个txt文件,同样以管理员权限打开powershell执行python代码!

import os

def create_pos_n_neg():
    for file_type in ['pos', 'neg']: #此处修改neg或pos即可
        if not os.path.exists(file_type):
            continue
        for img in os.listdir(file_type):
            if (file_type.startswith('neg')):
                line = 'C:/Users/20414/Desktop/opencv341_bin-master/'+ file_type + '/' + img + '\n'
                with open('bg.txt', 'a') as f:
                    f.write(line)
            elif (file_type.startswith('pos')):
                line = 'C:/Users/20414/Desktop/opencv341_bin-master/'+ file_type + '/' + img + ' 1 0 0 50 50\n'
                with open('info.txt', 'a') as f:
                    f.write(line)

if __name__ == '__main__':
    create_pos_n_neg()
    print('描述文件已生成!')

生成的代码会在根目录下生成两个txt文档

训练分类器-2

将这两个txt复制到opencv_annotation.exe的所在目录,并在该目录下执行以下指令,以生成.vec文件

.\opencv_createsamples.exe -vec info.vec -info info.txt -bg bg.txt -num 105 -w 50 -h 50

或:

opencv_createsamples.exe -vec info.vec -info info.txt -bg bg.txt -num 1200 -w 50 -h 50

生成完成后,终端继续执行以下指令,生成最终的xml文件

.\opencv_traincascade.exe -data C:\Users\20414\Desktop\opencv\build\x64\vc14\bin\data -vec C:\Users\20414\Desktop\opencv\build\x64\vc14\bin\info.vec -bg C:\Users\20414\Desktop\opencv\build\x64\vc14\bin\bg.txt -numPos 4 -numNeg 100 -numStages 5 -featureType LBP -w 50 -h 50

或:

opencv_traincascade.exe -data data -vec info.vec -bg bg.txt -numPos 1000 -numNeg 2000 -numStages 5 -featureType LBP -w 50 -h 50

参考链接:

OpenCV编程:OpenCV3.X训练自己的分类器_7月月更_DS小龙哥_InfoQ写作社区

Windows环境下训练OpenCV分类器_positives.vec-CSDN博客

Windows使用opencv训练模型过程记录(提供样本)_windows环境下训练opencv分类器-CSDN博客

OpenCV 级联分类器之样本处理、训练、测试_opencv如何获得负样本数据-CSDN博客

加载分类器并在指定区域匹配:

只检测画面正中央的指定区域作为检测区域,如果检测到特定物体,则将该物体用绿色方框框出

import cv2

# 加载级联分类器
object_cascade = cv2.CascadeClassifier("./data/testdata/cascade.xml")

# 打开摄像头
cap = cv2.VideoCapture(0)

# 获取画面宽度和高度
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# 计算画面中间矩形区域的左上角坐标
roi_x = (frame_width - 20) // 2
roi_y = (frame_height - 20) // 2

while True:
    # 读取摄像头帧
    ret, frame = cap.read()

    # 将帧转换为灰度图像
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 获取画面中间 20x20 区域
    roi_gray = gray[roi_y:roi_y + 150, roi_x:roi_x + 150]

    # 检测物体
    objects = object_cascade.detectMultiScale(roi_gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

    # 在原始图像上绘制矩形框
    for (x, y, w, h) in objects:
        cv2.rectangle(frame, (roi_x + x, roi_y + y), (roi_x + x + w, roi_y + y + h), (0, 255, 0), 2)

    # 显示结果
    cv2.imshow("Object Detection", frame)

    # 按下 'q' 键退出循环
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

# 释放摄像头和窗口
cap.release()
cv2.destroyAllWindows()