拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Opencv 快速使用(基础使用&手势识别)

Opencv 快速使用(基础使用&手势识别)

白鹭 - 2022-02-10 2076 0 0

文章目录

  • 环境准备
  • 资源读取
    • 读取图片
    • 读取视频
  • 资源操作
    • 修改图片
      • 绘制图形
      • 尺寸修改
    • 灰度处理图片
      • 图片保存
  • 使用模型
  • 模型训练
  • 训练模型加载
  • 手势识别
    • 纯opencv版本
    • mediapipe版本
      • HandTrackingModule.py
      • Main.py

环境准备

编辑器 pycharm
python 版本3.7x

pip3 install opencv-python
pip3 install opencv-contrib-python

基本要求:
熟练掌握 python3.x
懂得基本Pycahrm操作以及图片基本知识

资源读取

读取图片

import cv2.cv2 as cv

Image = cv.imread("Image/face1.jpg")
cv.imshow("Image",Image)
cv.waitKey(0)
cv.destroyAllWindows()

读取视频

import cv2

cap = cv2.VideoCapture(0)
# 0 表示读取摄像头
# 加入具体资源路径就表示直接读取路径对应的媒体资源

while True:
    flag,img = cap.read()
    cv2.imshow("Vido",img)
    if(cv2.waitKey(1)==ord("q")):
        #cv2.waitKey(0) 表示死回圈等待
        #cv2.waitKey(time)表示等待time ms 记录用户的输入获取对应的ASCII值
        #这里表示等待一ms并且如果用户输入 q 就退出
        break

资源操作

修改图片

绘制图形

这个在我们的图片框选当中是很有必要的

#绘制直线
cv2.line( img , (0,0),(511,511),( 255,0,0),5)
#绘制矩形
cv2.rectangle(img,(x,y,x+w,y+h),color=(0,0,255),thickness=1) # 方框颜色,粗细 -1表示实心
#绘制圆形
cv2.circle(img,center=(x+w,y+h),radius=100,color=(255,0,0),thickness=5)
#写字
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img , ' OpencV',(10,500), font,4,(255,255,255),2,cv.LINE_AA)
#在哪显示,显示字体,显示位置(开始),字体,大小,颜色,线条粗细,什么线条(实线,虚线...)

尺寸修改

Image_resize = cv.resize(Image,dsize=(200,200))

灰度处理图片

gary = cv.cvtColor(img,cv.COLOR_BGR2GRAY)

事实上

Image = cv.imread("Image/face1.jpg",0)

也可以,但是我们读取摄像头的时候是吧,有要处理的,
例如:

import cv2

cap = cv2.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)

while True:
    flag,img = cap.read()
    img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    cv2.imshow("Vido",img)
    if(cv2.waitKey(1)==ord("q")):
        #cv2.waitKey(0) 表示死回圈等待
        #cv2.waitKey(time)表示等待time ms 记录用户的输入获取对应的ASCII值
        #这里表示等待一ms并且如果用户输入 q 就退出
        break

图片保存

cv2.imwrite(filename,imgage)

使用模型

import cv2.cv2 as cv
import cv2.data as data

#读取影像
img = cv.imread('Image/face1.jpg')
gary = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
face_detect = cv.CascadeClassifier(data.haarcascades+"haarcascade_frontalface_alt2.xml")
face = face_detect.detectMultiScale(gary)
for x,y,w,h in face:
    cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
cv.imshow('result',img)

cv.waitKey(0)
#释放存储器
cv.destroyAllWindows()

CascadeClassifier()就是加载
在这里插入图片描述

例如:

import cv2.cv2 as cv
import cv2.data as data
cap = cv.VideoCapture(0)
cap.set(3,640)
cap.set(4,480)

while True:
    flag,img = cap.read()
    gary = cv.cvtColor(img,cv.COLOR_BGR2GRAY)

    face_detect = cv.CascadeClassifier(data.haarcascades + "haarcascade_frontalface_alt2.xml")
    face = face_detect.detectMultiScale(gary)
    for x, y, w, h in face:
        cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=2)

    cv.imshow("Vido",img)
    if(cv.waitKey(1)==ord("q")):
        #cv2.waitKey(0) 表示死回圈等待
        #cv2.waitKey(time)表示等待time ms 记录用户的输入获取对应的ASCII值
        #这里表示等待一ms并且如果用户输入 q 就退出
        break

cap.release()
#释放存储器
cv.destroyAllWindows()

模型训练

recognizer=cv.face.LBPHFaceRecognizer_create()
recognizer.train(faces,np.array(ids))
ids, confidence = recogizer.predict(gray[y:y + h, x:x + w])

加载预测模型

这个直接看例子吧:

import os
import cv2.cv2 as cv
import numpy as np
import cv2.data as data
def getImageIds(path):
    #函式作用是提取人脸然后回传人物的人脸和id
    faceseare=[] # 保存检测出的人脸
    ids=[] #
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
    #人脸检测
    face_detector = cv.CascadeClassifier(data.haarcascades+"haarcascade_frontalface_default.xml")
    if imagePaths:
        print('训练图片为:',imagePaths)
    else:
        print("请先录入人脸")
        return

    for imagePath in imagePaths:
        #二值化处理
        img = cv.imread(imagePath)
        img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
        img_numpy=np.array(img,'uint8')#获取图片矩阵

        faces = face_detector.detectMultiScale(img_numpy)

        id = int(os.path.split(imagePath)[1].split('.')[0])

        for x,y,w,h in faces:
            ids.append(id)
            faceseare.append(img_numpy[y:y+h,x:x+w])
        print('已获取id:', id)

    return faceseare,ids

if __name__ == '__main__':
    #图片路径
    path='Image/InPutImg'
    #获取影像阵列和id标签阵列和姓名
    faces,ids=getImageIds(path)
    #获取训练物件
    recognizer=cv.face.LBPHFaceRecognizer_create()
    recognizer.train(faces,np.array(ids)) #把对应的人脸和id联系起来训练
    #保存训练档案
    model_save = "trainer/"
    if not os.path.exists(model_save):
        os.makedirs(model_save)
    recognizer.write('trainer/trainer.yml')

完整的例子如下:
https://blog.csdn.net/futerox/article/details/120685898

训练模型加载

这个也是例子
使用
recogizer=cv.face.LBPHFaceRecognizer_create()#加载训练资料集档案
recogizer.read(‘trainer/trainer.yml’)

import cv2.cv2 as cv
import os
import cv2.data as data

recogizer=cv.face.LBPHFaceRecognizer_create()#加载训练资料集档案
recogizer.read('trainer/trainer.yml')
names=[]
warningtime = 0

#准备识别的图片
def face_detect_demo(img):
    global warningtime
    gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    face_detector=cv.CascadeClassifier(data.haarcascades+"haarcascade_frontalface_default.xm")
    face=face_detector.detectMultiScale(gray)
    for x,y,w,h in face:
        cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
        cv.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1)

        # 人脸识别
        ids, confidence = recogizer.predict(gray[y:y + h, x:x + w])

        if confidence > 80: #评分越大可信度越低
            warningtime += 1
            if warningtime > 100:
               warningtime = 0
               print("未识别出此人") #这块的话其实可以再搞一套对应的惩罚机制
            cv.putText(img, 'unkonw', (x + 10, y - 10), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
        else:
        #这里也对应一套识别后的机制
            cv.putText(img,str(names[ids-1]), (x + 10, y - 10), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
    cv.imshow('result',img)


def get_name(names):
    path = 'Image/InPutImg/'

    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
    for imagePath in imagePaths:
       name = str(os.path.split(imagePath)[1].split('.',2)[1])
       names.append(name)


cap=cv.VideoCapture(0)
get_name(names)
while True:
    flag,frame=cap.read()
    if not flag:
        break
    face_detect_demo(frame)
    if ord(' ') == cv.waitKey(10): #按下空格关了
        break
cap.release()
cv.destroyAllWindows()

手势识别

纯opencv版本

这个的话有点超纲了,在本篇博文,其实写这篇博文的目的还是翻笔记的时候找到了这篇笔记,顺便整理一下,其实就是那篇
分分钟自制人脸识别(如何快速识别心仪的小姐姐~)
的边角料
但是,突然想到最近那个手势识别比较火,那就来一下呗,识别你的手势是哪个数字,识别1~5
这个原理如下:

1.选择手势区域,我们这个比较那啥需要选定一个区域来放置我们的手势
2. 进行高斯滤波
3.之后我们就能够通过找到手的轮廓,之后找到凹凸位置,那么这样一来就能够判断你的手势是几

那么这个局限性也就很明显了,我们是通过凹凸点来确定你的手势是数字几的,这个就有点那啥了,只能说能用,
在这里插入图片描述

import cv2
import numpy as np
import math

cap = cv2.VideoCapture(0)

while (cap.isOpened()):
    ret, frame = cap.read()  # 读取摄像头每帧图片

    frame = cv2.flip(frame, 1)
    kernel = np.ones((2, 2), np.uint8)
    roi = frame[100:600, 100:600]  # 选取图片中固定位置作为手势输入

    cv2.rectangle(frame, (100, 100), (600, 600), (0, 0, 255), 0)  # 用红线画出手势识别框
    # 基于hsv的肤色检测
    hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
    lower_skin = np.array([0, 28, 70], dtype=np.uint8)
    upper_skin = np.array([20, 255, 255], dtype=np.uint8)

    # 进行高斯滤波
    mask = cv2.inRange(hsv, lower_skin, upper_skin)
    mask = cv2.dilate(mask, kernel, iterations=4)
    mask = cv2.GaussianBlur(mask, (5, 5), 100)

    # 找出轮廓
    contours, h = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnt = max(contours, key=lambda x: cv2.contourArea(x))
    epsilon = 0.0005 * cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, epsilon, True)
    hull = cv2.convexHull(cnt)
    areahull = cv2.contourArea(hull)
    areacnt = cv2.contourArea(cnt)
    arearatio = ((areahull - areacnt) / areacnt) * 100

    # 求出凹凸点
    hull = cv2.convexHull(approx, returnPoints=False)
    defects = cv2.convexityDefects(approx, hull)

    # 定义凹凸点个数初始值为0
    l = 0

    for i in range(defects.shape[0]):
        s, e, f, d, = defects[i, 0]
        start = tuple(approx[s][0])
        end = tuple(approx[e][0])
        far = tuple(approx[f][0])
        pt = (100, 100)

        a = math.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)
        b = math.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
        c = math.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)
        s = (a + b + c) / 2
        ar = math.sqrt(s * (s - a) * (s - b) * (s - c))

        # 手指间角度求取
        angle = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c)) * 57

        if angle <= 90 and d > 20:
            l += 1
            cv2.circle(roi, far, 3, [255, 0, 0], -1)
        cv2.line(roi, start, end, [0, 255, 0], 2)  # 画出包络线
    l += 1
    font = cv2.FONT_HERSHEY_SIMPLEX

    # 条件判断,知道手势后想实作的功能
    if l == 1:
        if areacnt < 2000:
            cv2.putText(frame, "put hand in the window", (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
        else:
            if arearatio < 12:
                cv2.putText(frame, '0', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
            elif arearatio < 17.5:
                cv2.putText(frame, "1", (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
            else:
                cv2.putText(frame, '1', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
    elif l == 2:
        cv2.putText(frame, '2', (0, 50), font, 2, (0, 0, 255), 3, cv2.LINE_AA)
							
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *