精华内容
下载资源
问答
  • 用于opencv的水果识别的图像样本,有苹果、香蕉、梨子。
  • 因为需要做opencv苹果识别 ,发现网上并没有相关资源 ,所以花了两天时间整理了2000多个分类器正样本以及其解释文件(解释文件太难弄了)
  • 使用OpenCV中的分类器和颜色识别苹果位置识别环境配置和安装拍摄并处理样本生成正样本的描述文件pos.vec开始训练分类器单目测距完成分类器与颜色识别,轮廓提取算法的结合运行结果图片展示我的代码,训练分类器的...

    这是我本科毕业设计中的软件项目,看到目前本博客中还暂无既使用OpenCV级联分类器又使用颜色是被边缘检测的项目,本来想对目标水果——苹果做实例分割的,迫于硬件条件唯数不多的计算资源被研究生占用了,无奈只好使用OpenCV级联分类器和颜色识别边缘检测来模拟实例分割并输出苹果的坐标。

    废话少说让我们开始吧。
    .
    .

    环境配置和安装

    .
    .
    OpenCV :需要安装文件夹中有 训练样本.exe和 训练级联分类器.exe两个文件的版本,我安装的 OpenCV 4.5.2版本有这两个文件,此版本在https://opencv.org/releases/网站去下载
    编译器使用 Pycharm 2021.1.1 (Pycharm的版本影响不大,Jetbrain官网下最新的就行)
    在Pycharm中Package中安装必要的Python包,进入Pycharm中Python Interpreter,安装下图中的包:在这里插入图片描述

    去官网下载到opencv-3.4.14-xxxxxx.exe后安装到D://opecv即可,随后在D目录下新建一个文件夹用于后续训练分类器的样本存储,模型存储等,我的训练文件夹命名为train_example,随后将D:/opencv/build/x64/vc15/bin文件夹中的
    opencv_createsamples.txt和 opencv_traincascade.exe文件拷贝到D:/train_example文件夹内,
    并在该文件夹中新建3个空文件夹:posdata , negdata ,xml
    分别用来存储训练的正样本图片集,负样本图片集和训练出来的模型。
    在这里插入图片描述

    准备工作到此结束。
    .

    拍摄并处理样本

    .
    Opencv中自带的级联分类器是opencv自带的一个训练好的,用于识别人脸的模型。但是opencv留了两个.exe文件用于给用户训练自己的识别模型。

    1)正样本的拍摄:我的项目是识别苹果,所以需要拍摄大约1000张各个场景下的苹果的照片
    使用QQ影音,图片工厂,或者Python脚本来处理样本图片为40*40,灰度化,并从1开始命名。
    在这里插入图片描述
    在文件夹内运行cmd,输入dir /b>pos.txt,生成所有文件的目录索引。
    新建一个Python脚本,给生成的pos.txt文件每一行后面加上 1 0 0 40 40,意义为:1代表文件,0 0 40 40代表从(0,0)到(40,40)读取图片,处理文件的Python脚本如下:

    import os
    import numpy as np
    
    with open("D:\\train_example\\posdata\\pos.txt") as txt:
        content = txt.readlines()  # 读全部行
        txt.close()
    lines = np.array(content)  # 转换成array 类型
    num_of_instances = lines.size  # 整个txt的行数
    print("number of instances: ", num_of_instances)
    list = []
    for i in range(0, num_of_instances):
        name, label = lines[i].split("\n")
        list.append(name + " 1 0 0 40 40\n" + label)  # 统一每行加字符串"_aligned.
    with open("D:\\train_example\\posdata\\pos1.txt", 'w')as F:
        F.writelines(list)  # 写入到另一个txt文件中
        F.close()
    
    

    2)负样本的拍摄训练:任何画面中不包含识别物体的图片都可以作为训练的负样本。
    我业余爱好摄影,直接从相机卡里考出大约3000张图片即可作为负样本,使用图片工厂,QQ图像等软件把图片分辨率降为500*500以下
    在这里插入图片描述
    同样,在该文件夹内使用dir /s/b >neg.txt,生成负样本中每个图片的路径
    在这里插入图片描述

    .

    生成正样本的描述文件pos.vec

    .
    在项目文件夹(即D:/train_example目录下)运行cmd

    opencv_createsamples.exe -vec pos.vec -info posdata\pos.txt -bg negdata\neg.txt -w 40 -h 40 -num 1000
    

    将会在项目文件夹目录内生成pos.vec描述文件,并且告诉系统正样本集的目录和负样本的目录文件 posdata.txt与negdata.txt, 图片尺寸40*40像素,数量1000

    .
    .

    开始训练分类器

    .
    .
    在项目文件夹中(D://train_example文件夹下)运行cmd
    输入

    opencv_traincascade.exe -data xml -vec pos.vec -bg negdata\neg.txt -numPos 900 -numNeg 3000 -numStages 20 -w 40 -h 40 -minHitRate 0.9999 -maxFalseAlarmRate 0.5 -mode ALL
    

    接下里就等着运行结果吧,别待机电脑
    在这里插入图片描述
    训练完成,接下来可以试试训练的结果如何,在Pycharm中新建一个train_test.py文件
    用以下代码测试下分类器的分类效果:

    import cv2
    # 加载训练好的分类器
    faceCascade = cv2.CascadeClassifier("cascade.xml")
    faceCascade.load('D:\\train_example\\xml\\cascade.xml')
     
    cap = cv2.VideoCapture(0)
    while True:
        ret, frame = cap.read()
        img = frame.copy()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        rect = faceCascade.detectMultiScale(
            gray,
            scaleFactor=1.15,
            minNeighbors=3,
            minSize=(3,3),
            flags = cv2.IMREAD_GRAYSCALE
        )
        for (x, y, w, h) in rect:
            cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
     
        cv2.imshow('frame', frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()
    

    正常的话,对视频内的目标结果如下:
    在这里插入图片描述
    .
    .

    单目测距

    .
    .
    由于本毕设项目需要获得苹果的三维坐标,还差一个苹果到摄像头的距离,由于使用了单相机,无法通过视差获取深度,原理为小孔成像的相似三角形,即需要知道自己使用的相机单个像素大小,详情可以见本CSDN博客:

    https://blog.csdn.net/ikoiiii/article/details/85219059?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162616414516780265454688%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162616414516780265454688&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_v2~rank_v29-2-85219059.pc_search_result_cache&utm_term=opencv%E5%8D%95%E7%9B%AE%E6%B5%8B%E8%B7%9D&spm=1018.2226.3001.4187

    那么我的相机是1/2.3的底,查上述博客的表中得到单个像素是0.0008厘米,焦距写在相机外壳上为6mm,苹果的大小(直径)大约为60mm-80mm,我计算距离时取得是70mm。
    .
    .

    完成分类器与颜色识别,轮廓提取算法的结合

    .
    .
    对于复杂的画面,直接使用颜色识别,轮廓识别,会出现很多错误的目标,不妨使用分类器先将目标区域识别出来,再对目标区域进行颜色过滤,轮廓识别,获取到多个目标的轮廓再使用Circle()函数把获取到的目标框起来获得圆心的坐标。

    import cv2
    import numpy as np
    faceCascade = cv2.CascadeClassifier("cascade.xml")# 加载训练好的分类器
    faceCascade.load('D:\\train_example\\xml\\cascade.xml')
    unit_pixel=0.0008
    f=0.6
    red_lower = np.array([0, 10, 50])
    red_upper = np.array([20, 255, 255]) #设置过滤出苹果颜色的两个阈值,色彩模型是HSV 不是RGB
    cap = cv2.VideoCapture(1) #外接相机为1,电脑自带相机为0,多接几个相机数字可以自己调
    while True:
        ret, frame = cap.read()
        ROI = np.zeros(frame.shape, np.uint8)
        img = frame.copy()
        data = np.array([[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],])
    
        # cv2.putText(draw2, 'biggest_apple_distance:', (0, 20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        rect = faceCascade.detectMultiScale(
            gray,
            scaleFactor=1.15,
            minNeighbors=3,
            minSize=(3, 3),
            flags=cv2.IMREAD_GRAYSCALE
        )
        for (x, y, w, h) in rect:
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
            cv2.rectangle(ROI, (x,y), (x+w,y+h), (255, 255, 255), thickness=-1)
        imgroi = ROI & img #将分类器获取到的目标的矩形框内容保留,画面中剩下的
        # cv2.putText(frame, 'Target', (target_x, target_y), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 0), 2)
        hsv = cv2.cvtColor(imgroi, cv2.COLOR_BGR2HSV)
        # 设置阈值,去除背景 保留所设置的颜色
        mask = cv2.inRange(hsv, red_lower, red_upper)
        # ret, thresh = cv2.threshold(dilation, 150, 255, cv2.THRESH_BINARY)  # 阈值处理 二值化 用150不用255是因为有些细胞就直接变白
        thresh1 = cv2.GaussianBlur(mask, (3, 3), 0)  # 高斯滤波
        contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        contours1=[]
        for i in contours:
            # area.append(cv2.contourArea(i))
            # print(area)
            if cv2.contourArea(i) > 10000:  # 计算面积 去除面积小的 连通域
                contours1.append(i)
            # 以上使用面积去除小面积连通域, 参考CSDN中显微镜细胞项目
            
            # 以下是使用线条长度进行筛选
        min_size = 200
    
        delete_list = []
    
        for i in range(len(contours1)):
            if (cv2.arcLength(contours1[i], True) < min_size):
                delete_list.append(i)
    
        k=0
        for cont in contours1:
    
            (x,y), radius = cv2.minEnclosingCircle(cont)
    
            data[0][k]=radius
            data[1][k]=int(x)
            data[2][k]=int(y)
            cv2.circle(imgroi,(int(x),int(y)),int(radius),(0,255,255),10)
            k=k+1
        data.T[np.lexsort(data[::-1, :])].T
    
    
        # print("最大的苹果的距离为:%d" % banjin[0])
        width=data[0][0]*unit_pixel
        distance=7*f/width
        target_x=data[1][0]
        target_y=data[2][0]
    
        # for i, j in zip(contours, range(len(contours))):
        #     M = cv2.moments(i)
        #     cX = int(M["m10"] / M["m00"])
        #     cY = int(M["m01"] / M["m00"])
        #     draw = cv2.putText(imgroi, str(j + 1), (cX, cY), 5, 5, (255, 0, 255), 5)
    
        draw2 = cv2.circle(imgroi.copy(), (target_x, target_y), data[0][0], (255, 255, 255), -1)
        cv2.line(draw2, (0, target_y), (target_x, target_y), (255, 0, 0), 3)
        cv2.line(draw2, (target_x, 0), (target_x, target_y), (255, 0, 0), 3)
        cv2.line(draw2, (target_x, target_y), (640, target_y), (255, 0, 0), 3)
        cv2.line(draw2, (target_x, target_y), (target_x, 480), (255, 0, 0), 3)
        cv2.putText(draw2, 'biggest_apple_distance:', (0, 20), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
        cv2.putText(draw2, 'And_its_coordinate_is::', (0, 90), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2)
        cv2.putText(draw2, 'Target', (target_x, target_y), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 0), 2)
        distance_display = "% .2f cm" % distance
        target_x_display = "% .0f , " % target_x
        target_y_display = "% .0f " % target_y
        cv2.putText(draw2, distance_display, (40, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
        cv2.putText(draw2, target_x_display, (40, 120), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
        cv2.putText(draw2, target_y_display, (120, 120), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
        # cv2.putText(draw2, target_x_display, (half_target_x, target_y), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
        # cv2.putText(draw2, target_y_display, (target_x, half_target_y), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
        draw2 = cv2.putText(draw2, target_x_display, (int(target_x / 2), int(target_y)), cv2.FONT_HERSHEY_SIMPLEX, 0.75,
                            (255, 0, 0), 2)
        draw2 = cv2.putText(draw2, target_y_display, (int(target_x), int(target_y / 2)), cv2.FONT_HERSHEY_SIMPLEX, 0.75,
                            (255, 0, 0), 2)
    
    
    
        cv2.imshow('ROI_image', imgroi)
        cv2.imshow('frame_with_rectangle', frame)
        cv2.imshow('Original_from_camera', img)
        cv2.imshow('target', draw2)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()
    

    .
    .

    运行结果图片展示

    .
    .
    最终运行结果如下:

    在这里插入图片描述
    .
    .

    我的代码,训练分类器的文件夹下载

    .
    .

    已上传百度网盘

    链接:https://pan.baidu.com/s/1S7wXacR8qolPSqACd3wosA
    提取码:0000

    .
    .


    展开全文
  • OpenCV人脸识别

    千次阅读 2017-05-15 10:35:13
    OpenCV学习 144 作者 星光社的戴铭 关注 2015.09.06 18:07 字数 1747 阅读 2336评论 2喜欢 21 介绍OpenCV是开源计算机视觉和机器学习库。包含成千上万优化过的算法。项目地址:http://opencv.org/about.html。...

    【C++】基于 OpenCV 的人脸识别(强烈推荐)
    2016-01-23 14:18 17718人阅读 评论(4) 收藏 举报
    分类: 人工智能(2)
    目录(?)[+]
    原文网址:http://www.jianshu.com/p/96be2417cc98
    一点背景知识
    OpenCV 是一个开源的计算机视觉和机器学习库。它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包。根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从谷歌街景的图片拼接,到交互艺术展览的技术实现中,都有 OpenCV 的身影。

    OpenCV 起始于 1999 年 Intel 的一个内部研究项目。从那时起,它的开发就一直很活跃。进化到现在,它已支持如 OpenCL 和 OpenGL 等现代技术,也支持如 iOS 和 Android 等平台。

    1999 年,半条命发布后大红大热。Intel 奔腾 3 处理器是当时最高级的 CPU,400-500 MHZ 的时钟频率已被认为是相当快。2006 年 OpenCV 1.0 版本发布的时候,当时主流 CPU 的性能也只和 iPhone 5 的 A6 处理器相当。尽管计算机视觉从传统上被认为是计算密集型应用,但我们的移动设备性能已明显地超出能够执行有用的计算机视觉任务的阈值,带着摄像头的移动设备可以在计算机视觉平台上大有所为。

    在本文中,我会从一个 iOS 开发者的视角概述一下 OpenCV,并介绍一点基础的类和概念。随后,会讲到如何集成 OpenCV 到你的 iOS 项目中以及一些 Objective-C++ 基础知识。最后,我们会看一个 demo 项目,看看如何在 iOS 设备上使用 OpenCV 实现人脸检测与人脸识别。

    OpenCV 概述
    概念
    OpenCV 的 API 是 C++ 的。它由不同的模块组成,这些模块中包含范围极为广泛的各种方法,从底层的图像颜色空间转换到高层的机器学习工具。

    使用 C++ API 并不是绝大多数 iOS 开发者每天都做的事,你需要使用 Objective-C++ 文件来调用 OpenCV 的函数。 也就是说,你不能在 Swift 或者 Objective-C 语言内调用 OpenCV 的函数。 这篇 OpenCV 的iOS 教程告诉你只要把所有用到 OpenCV 的类的文件后缀名改为 .mm 就行了,包括视图控制器类也是如此。这么干或许能行得通,却不是什么好主意。正确的方式是给所有你要在 app 中使用到的 OpenCV 功能写一层 Objective-C++ 封装。这些 Objective-C++ 封装把 OpenCV 的 C++ API 转化为安全的 Objective-C API,以方便地在所有 Objective-C 类中使用。走封装的路子,你的工程中就可以只在这些封装中调用 C++ 代码,从而避免掉很多让人头痛的问题,比如直接改文件后缀名会因为在错误的文件中引用了一个 C++ 头文件而产生难以追踪的编译错误。

    OpenCV 声明了命名空间 cv,因此 OpenCV 的类的前面会有个 cv:: 前缀,就像 cv::Mat、 cv::Algorithm 等等。你也可以在 .mm 文件中使用 using namespace cv 来避免在一堆类名前使用 cv:: 前缀。但是,在某些类名前你必须使用命名空间前缀,比如cv::Rect 和cv::Point,因为它们会跟定义在 MacTypes.h 中的Rect 和 Point 相冲突。尽管这只是个人偏好问题,我还是偏向在任何地方都使用 cv:: 以保持一致性。

    模块
    下面是在官方文档中列出的最重要的模块。

    core:简洁的核心模块,定义了基本的数据结构,包括稠密多维数组 Mat 和其他模块需要的基本函数。
    imgproc:图像处理模块,包括线性和非线性图像滤波、几何图像转换 (缩放、仿射与透视变换、一般性基于表的重映射)、颜色空间转换、直方图等等。
    video:视频分析模块,包括运动估计、背景消除、物体跟踪算法。
    calib3d:包括基本的多视角几何算法、单体和立体相机的标定、对象姿态估计、双目立体匹配算法和元素的三维重建。
    features2d:包含了显著特征检测算法、描述算子和算子匹配算法。
    objdetect:物体检测和一些预定义的物体的检测 (如人脸、眼睛、杯子、人、汽车等)。
    ml:多种机器学习算法,如 K 均值、支持向量机和神经网络。
    highgui:一个简单易用的接口,提供视频捕捉、图像和视频编码等功能,还有简单的 UI 接口 (iOS 上可用的仅是其一个子集)。
    gpu:OpenCV 中不同模块的 GPU 加速算法 (iOS 上不可用)。
    ocl:使用 OpenCL 实现的通用算法 (iOS 上不可用)。
    一些其它辅助模块,如 Python 绑定和用户贡献的算法。
    基础类和操作
    OpenCV 包含几百个类。为简便起见,我们只看几个基础的类和操作,进一步阅读请参考全部文档。过一遍这几个核心类应该足以对这个库的机理产生一些感觉认识。

    cv::Mat
    cv::Mat 是 OpenCV 的核心数据结构,用来表示任意 N 维矩阵。因为图像只是 2 维矩阵的一个特殊场景,所以也是使用 cv::Mat 来表示的。也就是说,cv::Mat 将是你在 OpenCV 中用到最多的类。

    一个 cv::Mat 实例的作用就像是图像数据的头,其中包含着描述图像格式的信息。图像数据只是被引用,并能为多个 cv::Mat 实例共享。OpenCV 使用类似于 ARC 的引用计数方法,以保证当最后一个来自cv::Mat 的引用也消失的时候,图像数据会被释放。图像数据本身是图像连续的行的数组 (对 N 维矩阵来说,这个数据是由连续的 N-1 维数据组成的数组)。使用step[] 数组中包含的值,图像的任一像素地址都可通过下面的指针运算得到:

    uchar pixelPtr = cvMat.data + rowIndex cvMat.step[0] + colIndex * cvMat.step[1]
    每个像素的数据格式可以通过 type() 方法获得。除了常用的每通道 8 位无符号整数的灰度图 (1 通道,CV_8UC1) 和彩色图 (3 通道,CV_8UC3),OpenCV 还支持很多不常用的格式,例如CV_16SC3 (每像素 3 通道,每通道使用 16 位有符号整数),甚至CV_64FC4 (每像素 4 通道,每通道使用 64 位浮点数)。

    cv::Algorithm
    Algorithm 是 OpenCV 中实现的很多算法的抽象基类,包括将在我们的 demo 工程中用到的 FaceRecognizer。它提供的 API 与苹果的 Core Image 框架中的CIFilter 有些相似之处。创建一个Algorithm 的时候使用算法的名字来调用 Algorithm::create(),并且可以通过get() 和set()方法来获取和设置各个参数,这有点像是键值编码。另外,Algorithm 从底层就支持从/向 XML 或 YAML 文件加载/保存参数的功能。

    在 iOS 上使用 OpenCV
    添加 OpenCV 到你的工程中
    集成 OpenCV 到你的工程中有三种方法:

    使用 CocoaPods 就好: pod “OpenCV”。
    下载官方 iOS 框架发行包,并把它添加到工程里。
    从 GitHub 拉下代码,并根据教程自己编译 OpenCV 库。
    Objective-C++
    如前面所说,OpenCV 是一个 C++ 的 API,因此不能直接在 Swift 和 Objective-C 代码中使用,但能在 Objective-C++ 文件中使用。

    Objective-C++ 是 Objective-C 和 C++ 的混合物,让你可以在 Objective-C 类中使用 C++ 对象。clang 编译器会把所有后缀名为.mm 的文件都当做是 Objective-C++。一般来说,它会如你所期望的那样运行,但还是有一些使用 Objective-C++ 的注意事项。内存管理是你最应该格外注意的点,因为 ARC 只对 Objective-C 对象有效。当你使用一个 C++ 对象作为类属性的时候,其唯一有效的属性就是assign。因此,你的dealloc 函数应确保 C++ 对象被正确地释放了。

    第二重要的点就是,如果你在 Objective-C++ 头文件中引入了 C++ 头文件,当你在工程中使用该 Objective-C++ 文件的时候就泄露了 C++ 的依赖。任何引入你的 Objective-C++ 类的 Objective-C 类也会引入该 C++ 类,因此该 Objective-C 文件也要被声明为 Objective-C++ 的文件。这会像森林大火一样在工程中迅速蔓延。所以,应该把你引入 C++ 文件的地方都用#ifdef __cplusplus 包起来,并且只要可能,就尽量只在.mm 实现文件中引入 C++ 头文件。

    要获得更多如何混用 C++ 和 Objective-C 的细节,请查看 Matt Galloway 写的这篇教程。

    Demo:人脸检测与识别
    现在,我们对 OpenCV 及如何把它集成到我们的应用中有了大概认识,那让我们来做一个小 demo 应用:从 iPhone 的摄像头获取视频流,对它持续进行人脸检测,并在屏幕上标出来。当用户点击一个脸孔时,应用会尝试识别这个人。如果识别结果正确,用户必须点击 “Correct”。如果识别错误,用户必须选择正确的人名来纠正错误。我们的人脸识别器就会从错误中学习,变得越来越好。

    demo 应用中人脸检测与识别系统线框图

    本 demo 应用的源码可从 GitHub 获得。

    视频拍摄
    OpenCV 的 highgui 模块中有个类,CvVideoCamera,它把 iPhone 的摄像机抽象出来,让我们的 app 通过一个代理函数- (void)processImage:(cv::Mat&)image 来获得视频流。CvVideoCamera 实例可像下面这样进行设置:

    CvVideoCamera *videoCamera = [[CvVideoCamera alloc] initWithParentView:view];
    videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionFront;
    videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480;
    videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
    videoCamera.defaultFPS = 30;
    videoCamera.grayscaleMode = NO;
    videoCamera.delegate = self;
    摄像头的帧率被设置为 30 帧每秒, 我们实现的 processImage 函数将每秒被调用 30 次。因为我们的 app 要持续不断地检测人脸,所以我们应该在这个函数里实现人脸的检测。要注意的是,如果对某一帧进行人脸检测的时间超过 1/30 秒,就会产生掉帧现象。

    人脸检测
    其实你并不需要使用 OpenCV 来做人脸检测,因为 Core Image 已经提供了 CIDetector 类。用它来做人脸检测已经相当好了,并且它已经被优化过,使用起来也很容易:

    CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:context options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}];

    NSArray *faces = [faceDetector featuresInImage:image];
    从该图片中检测到的每一张面孔都在数组 faces 中保存着一个 CIFaceFeature 实例。这个实例中保存着这张面孔的所处的位置和宽高,除此之外,眼睛和嘴的位置也是可选的。

    另一方面,OpenCV 也提供了一套物体检测功能,经过训练后能够检测出任何你需要的物体。该库为多个场景自带了可以直接拿来用的检测参数,如人脸、眼睛、嘴、身体、上半身、下半身和笑脸。检测引擎由一些非常简单的检测器的级联组成。这些检测器被称为 Haar 特征检测器,它们各自具有不同的尺度和权重。在训练阶段,决策树会通过已知的正确和错误的图片进行优化。关于训练与检测过程的详情可参考此原始论文。当正确的特征级联及其尺度与权重通过训练确立以后,这些参数就可被加载并初始化级联分类器了:

    // 正面人脸检测器训练参数的文件路径
    NSString *faceCascadePath = [[NSBundle mainBundle] pathForResource:@”haarcascade_frontalface_alt2”
    ofType:@”xml”];

    const CFIndex CASCADE_NAME_LEN = 2048;
    char CASCADE_NAME = (char ) malloc(CASCADE_NAME_LEN);
    CFStringGetFileSystemRepresentation( (CFStringRef)faceCascadePath, CASCADE_NAME, CASCADE_NAME_LEN);

    CascadeClassifier faceDetector;
    faceDetector.load(CASCADE_NAME);
    这些参数文件可在 OpenCV 发行包里的 data/haarcascades 文件夹中找到。

    在使用所需要的参数对人脸检测器进行初始化后,就可以用它进行人脸检测了:

    cv::Mat img;
    vector faceRects;
    double scalingFactor = 1.1;
    int minNeighbors = 2;
    int flags = 0;
    cv::Size minimumSize(30,30);
    faceDetector.detectMultiScale(img, faceRects,
    scalingFactor, minNeighbors, flags
    cv::Size(30, 30) );
    检测过程中,已训练好的分类器会用不同的尺度遍历输入图像的每一个像素,以检测不同大小的人脸。参数 scalingFactor 决定每次遍历分类器后尺度会变大多少倍。参数minNeighbors 指定一个符合条件的人脸区域应该有多少个符合条件的邻居像素才被认为是一个可能的人脸区域;如果一个符合条件的人脸区域只移动了一个像素就不再触发分类器,那么这个区域非常可能并不是我们想要的结果。拥有少于minNeighbors 个符合条件的邻居像素的人脸区域会被拒绝掉。如果minNeighbors 被设置为 0,所有可能的人脸区域都会被返回回来。参数flags 是 OpenCV 1.x 版本 API 的遗留物,应该始终把它设置为 0。最后,参数minimumSize 指定我们所寻找的人脸区域大小的最小值。faceRects 向量中将会包含对img 进行人脸识别获得的所有人脸区域。识别的人脸图像可以通过cv::Mat 的 () 运算符提取出来,调用方式很简单:cv::Mat faceImg = img(aFaceRect)。

    不管是使用 CIDetector 还是 OpenCV 的 CascadeClassifier,只要我们获得了至少一个人脸区域,我们就可以对图像中的人进行识别了。

    人脸识别
    OpenCV 自带了三个人脸识别算法:Eigenfaces,Fisherfaces 和局部二值模式直方图 (LBPH)。如果你想知道它们的工作原理及相互之间的区别,请阅读 OpenCV 的详细文档。

    针对于我们的 demo app,我们将采用 LBPH 算法。因为它会根据用户的输入自动更新,而不需要在每添加一个人或纠正一次出错的判断的时候都要重新进行一次彻底的训练。

    要使用 LBPH 识别器,我们也用 Objective-C++ 把它封装起来。这个封装中暴露以下函数:

    • (FJFaceRecognizer )faceRecognizerWithFile:(NSString )path;
    • (NSString )predict:(UIImage)img confidence:(double *)confidence;
    • (void)updateWithFace:(UIImage )img name:(NSString )name;
      像下面这样用工厂方法来创建一个 LBPH 实例:

    • (FJFaceRecognizer )faceRecognizerWithFile:(NSString )path {
      FJFaceRecognizer *fr = [FJFaceRecognizer new];
      fr->_faceClassifier = createLBPHFaceRecognizer();
      fr->_faceClassifier->load(path.UTF8String);
      return fr;
      }
      预测函数可以像下面这样实现:

    • (NSString )predict:(UIImage)img confidence:(double *)confidence {
      cv::Mat src = [img cvMatRepresentationGray];
      int label;
      self->_faceClassifier->predict(src, label, *confidence);
      return _labelsArray[label];
      }
      请注意,我们要使用一个类别方法把 UIImage 转化为 cv::Mat。此转换本身倒是相当简单直接:使用CGBitmapContextCreate 创建一个指向cv::Image 中的 data 指针所指向的数据的CGContextRef。当我们在此图形上下文中绘制此UIImage 的时候,cv::Image 的data 指针所指就是所需要的数据。更有趣的是,我们能对一个 Objective-C 类创建一个 Objective-C++ 的类别,并且确实管用。

    另外,OpenCV 的人脸识别器仅支持整数标签,但是我们想使用人的名字作标签,所以我们得通过一个 NSArray 属性来对二者实现简单的转换。

    一旦识别器给了我们一个识别出来的标签,我们把此标签给用户看,这时候就需要用户给识别器一个反馈。用户可以选择,“是的,识别正确”,也可以选择,“不,这是 Y,不是 X”。在这两种情况下,我们都可以通过人脸图像和正确的标签来更新 LBPH 模型,以提高未来识别的性能。使用用户的反馈来更新人脸识别器的方式如下:

    • (void)updateWithFace:(UIImage )img name:(NSString )name {
      cv::Mat src = [img cvMatRepresentationGray];
      NSInteger label = [_labelsArray indexOfObject:name];
      if (label == NSNotFound) {
      [_labelsArray addObject:name];
      label = [_labelsArray indexOfObject:name];
      }
      vector images = vector();
      images.push_back(src);
      vector labels = vector();
      labels.push_back((int)label);
      self->_faceClassifier->update(images, labels);
      }
      这里,我们又做了一次了从 UIImage 到 cv::Mat、int 到 NSString 标签的转换。我们还得如 OpenCV 的 FaceRecognizer::update API所期望的那样,把我们的参数放到std::vector 实例中去。

    如此“预测,获得反馈,更新循环”,就是文献上所说的监督式学习。

    结论
    OpenCV 是一个强大而用途广泛的库,覆盖了很多现如今仍在活跃的研究领域。想在一篇文章中给出详细的使用说明只会是让人徒劳的事情。因此,本文仅意在从较高层次对 OpenCV 库做一个概述。同时,还试图就如何集成 OpenCV 库到你的 iOS 工程中给出一些实用建议,并通过一个人脸识别的例子来向你展示如何在一个真正的项目中使用 OpenCV。如果你觉得 OpenCV 对你的项目有用, OpenCV 的官方文档写得非常好非常详细,请继续前行,创造出下一个伟大的 app!

    展开全文
  • opencv 3.0 ; 直接上效果图 注意:右下角的水印把中心点挡住了,要仔细看才能看到 下面是代码: #include #include<opencv2> #include <opencv2> #include <opencv2> #define PI 3.1415926 using namespace cv; ...
  • opencv 人脸识别

    2019-09-24 12:10:08
    根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从谷歌街景的图片拼接,到交互艺术展览的技术实现中,都有 OpenCV 的身影。 OpenCV 起始于 1999 年 Intel 的一个内部研究项目。从那时起,它的开发就...
     

    背景知识

    OpenCV 是一个开源的计算机视觉和机器学习库。它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包。根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从谷歌街景的图片拼接,到交互艺术展览的技术实现中,都有 OpenCV 的身影。

    OpenCV 起始于 1999 年 Intel 的一个内部研究项目。从那时起,它的开发就一直很活跃。进化到现在,它已支持如 OpenCL 和 OpenGL 等现代技术,也支持如 iOS 和 Android 等平台。

    1999 年,半条命发布后大红大热。Intel 奔腾 3 处理器是当时最高级的 CPU,400-500 MHZ 的时钟频率已被认为是相当快。2006 年 OpenCV 1.0 版本发布的时候,当时主流 CPU 的性能也只和 iPhone 5 的 A6 处理器相当。尽管计算机视觉从传统上被认为是计算密集型应用,但我们的移动设备性能已明显地超出能够执行有用的计算机视觉任务的阈值,带着摄像头的移动设备可以在计算机视觉平台上大有所为。

    在本文中,我会从一个 iOS 开发者的视角概述一下 OpenCV,并介绍一点基础的类和概念。随后,会讲到如何集成 OpenCV 到你的 iOS 项目中以及一些 Objective-C++ 基础知识。最后,我们会看一个 demo 项目,看看如何在 iOS 设备上使用 OpenCV 实现人脸检测与人脸识别。

    OpenCV 概述

    概念

    OpenCV 的 API 是 Chttps://objccn.io/issue-21-9/++ 的。它由不同的模块组成,这些模块中包含范围极为广泛的各种方法,从底层的图像颜色空间转换到高层的机器学习工具。

    使用 C++ API 并不是绝大多数 iOS 开发者每天都做的事,你需要使用 Objective-C++ 文件来调用 OpenCV 的函数。 也就是说,你不能在 Swift 或者 Objective-C 语言内调用 OpenCV 的函数。 这篇 OpenCV 的 iOS 教程告诉你只要把所有用到 OpenCV 的类的文件后缀名改为 .mm 就行了,包括视图控制器类也是如此。这么干或许能行得通,却不是什么好主意。正确的方式是给所有你要在 app 中使用到的 OpenCV 功能写一层 Objective-C++ 封装。这些 Objective-C++ 封装把 OpenCV 的 C++ API 转化为安全的 Objective-C API,以方便地在所有 Objective-C 类中使用。走封装的路子,你的工程中就可以只在这些封装中调用 C++ 代码,从而避免掉很多让人头痛的问题,比如直接改文件后缀名会因为在错误的文件中引用了一个 C++ 头文件而产生难以追踪的编译错误。

    OpenCV 声明了命名空间 cv,因此 OpenCV 的类的前面会有个 cv:: 前缀,就像 cv::Mat、 cv::Algorithm 等等。你也可以在 .mm 文件中使用 using namespace cv 来避免在一堆类名前使用 cv::前缀。但是,在某些类名前你必须使用命名空间前缀,比如 cv::Rect 和 cv::Point,因为它们会跟定义在 MacTypes.h 中的 Rect 和 Point 相冲突。尽管这只是个人偏好问题,我还是偏向在任何地方都使用 cv::以保持一致性。

    模块

    下面是在官方文档中列出的最重要的模块。

    • core:简洁的核心模块,定义了基本的数据结构,包括稠密多维数组 Mat 和其他模块需要的基本函数。
    • imgproc:图像处理模块,包括线性和非线性图像滤波、几何图像转换 (缩放、仿射与透视变换、一般性基于表的重映射)、颜色空间转换、直方图等等。
    • video:视频分析模块,包括运动估计、背景消除、物体跟踪算法。
    • calib3d:包括基本的多视角几何算法、单体和立体相机的标定、对象姿态估计、双目立体匹配算法和元素的三维重建。
    • features2d:包含了显著特征检测算法、描述算子和算子匹配算法。
    • objdetect:物体检测和一些预定义的物体的检测 (如人脸、眼睛、杯子、人、汽车等)。
    • ml:多种机器学习算法,如 K 均值、支持向量机和神经网络。
    • highgui:一个简单易用的接口,提供视频捕捉、图像和视频编码等功能,还有简单的 UI 接口 (iOS 上可用的仅是其一个子集)。
    • gpu:OpenCV 中不同模块的 GPU 加速算法 (iOS 上不可用)。
    • ocl:使用 OpenCL 实现的通用算法 (iOS 上不可用)。
    • 一些其它辅助模块,如 Python 绑定和用户贡献的算法。

    基础类和操作

    OpenCV 包含几百个类。为简便起见,我们只看几个基础的类和操作,进一步阅读请参考全部文档。过一遍这几个核心类应该足以对这个库的机理产生一些感觉认识。

    cv::Mat

    cv::Mat 是 OpenCV 的核心数据结构,用来表示任意 N 维矩阵。因为图像只是 2 维矩阵的一个特殊场景,所以也是使用 cv::Mat 来表示的。也就是说,cv::Mat 将是你在 OpenCV 中用到最多的类。

    一个 cv::Mat 实例的作用就像是图像数据的头,其中包含着描述图像格式的信息。图像数据只是被引用,并能为多个 cv::Mat 实例共享。OpenCV 使用类似于 ARC 的引用计数方法,以保证当最后一个来自 cv::Mat 的引用也消失的时候,图像数据会被释放。图像数据本身是图像连续的行的数组 (对 N 维矩阵来说,这个数据是由连续的 N-1 维数据组成的数组)。使用 step[] 数组中包含的值,图像的任一像素地址都可通过下面的指针运算得到:

    uchar *pixelPtr = cvMat.data + rowIndex * cvMat.step[0] + colIndex * cvMat.step[1]
    

    每个像素的数据格式可以通过 type() 方法获得。除了常用的每通道 8 位无符号整数的灰度图 (1 通道,CV_8UC1) 和彩色图 (3 通道,CV_8UC3),OpenCV 还支持很多不常用的格式,例如 CV_16SC3 (每像素 3 通道,每通道使用 16 位有符号整数),甚至 CV_64FC4 (每像素 4 通道,每通道使用 64 位浮点数)。

    cv::Algorithm

    Algorithm 是 OpenCV 中实现的很多算法的抽象基类,包括将在我们的 demo 工程中用到的 FaceRecognizer。它提供的 API 与苹果的 Core Image 框架中的 CIFilter 有些相似之处。创建一个 Algorithm 的时候使用算法的名字来调用 Algorithm::create(),并且可以通过 get() 和 set()方法来获取和设置各个参数,这有点像是键值编码。另外,Algorithm 从底层就支持从/向 XML 或 YAML 文件加载/保存参数的功能。

    在 iOS 上使用 OpenCV

    添加 OpenCV 到你的工程中

    集成 OpenCV 到你的工程中有三种方法:

    • 使用 CocoaPods 就好: pod "OpenCV"
    • 下载官方 iOS 框架发行包,并把它添加到工程里。
    • 从 GitHub 拉下代码,并根据教程自己编译 OpenCV 库。

    Objective-C++

    如前面所说,OpenCV 是一个 C++ 的 API,因此不能直接在 Swift 和 Objective-C 代码中使用,但能在 Objective-C++ 文件中使用。

    Objective-C++ 是 Objective-C 和 C++ 的混合物,让你可以在 Objective-C 类中使用 C++ 对象。clang 编译器会把所有后缀名为 .mm 的文件都当做是 Objective-C++。一般来说,它会如你所期望的那样运行,但还是有一些使用 Objective-C++ 的注意事项。内存管理是你最应该格外注意的点,因为 ARC 只对 Objective-C 对象有效。当你使用一个 C++ 对象作为类属性的时候,其唯一有效的属性就是 assign。因此,你的 dealloc 函数应确保 C++ 对象被正确地释放了。

    第二重要的点就是,如果你在 Objective-C++ 头文件中引入了 C++ 头文件,当你在工程中使用该 Objective-C++ 文件的时候就泄露了 C++ 的依赖。任何引入你的 Objective-C++ 类的 Objective-C 类也会引入该 C++ 类,因此该 Objective-C 文件也要被声明为 Objective-C++ 的文件。这会像森林大火一样在工程中迅速蔓延。所以,应该把你引入 C++ 文件的地方都用 #ifdef __cplusplus 包起来,并且只要可能,就尽量只在 .mm实现文件中引入 C++ 头文件。

    要获得更多如何混用 C++ 和 Objective-C 的细节,请查看 Matt Galloway 写的这篇教程

    Demo:人脸检测与识别

    现在,我们对 OpenCV 及如何把它集成到我们的应用中有了大概认识,那让我们来做一个小 demo 应用:从 iPhone 的摄像头获取视频流,对它持续进行人脸检测,并在屏幕上标出来。当用户点击一个脸孔时,应用会尝试识别这个人。如果识别结果正确,用户必须点击 “Correct”。如果识别错误,用户必须选择正确的人名来纠正错误。我们的人脸识别器就会从错误中学习,变得越来越好。

    demo 应用中人脸检测与识别系统线框图

    本 demo 应用的源码可从 GitHub 获得。

    视频拍摄

    OpenCV 的 highgui 模块中有个类,CvVideoCamera,它把 iPhone 的摄像机抽象出来,让我们的 app 通过一个代理函数 - (void)processImage:(cv::Mat&)image 来获得视频流。CvVideoCamera 实例可像下面这样进行设置:

    CvVideoCamera *videoCamera = [[CvVideoCamera alloc] initWithParentView:view];
    videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionFront;
    videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPreset640x480;
    videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
    videoCamera.defaultFPS = 30; videoCamera.grayscaleMode = NO; videoCamera.delegate = self; 

    摄像头的帧率被设置为 30 帧每秒, 我们实现的 processImage 函数将每秒被调用 30 次。因为我们的 app 要持续不断地检测人脸,所以我们应该在这个函数里实现人脸的检测。要注意的是,如果对某一帧进行人脸检测的时间超过 1/30 秒,就会产生掉帧现象。

    人脸检测

    其实你并不需要使用 OpenCV 来做人脸检测,因为 Core Image 已经提供了 CIDetector 类。用它来做人脸检测已经相当好了,并且它已经被优化过,使用起来也很容易:

    CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:context options:@{CIDetectorAccuracy: CIDetectorAccuracyHigh}]; NSArray *faces = [faceDetector featuresInImage:image]; 

    从该图片中检测到的每一张面孔都在数组 faces 中保存着一个 CIFaceFeature 实例。这个实例中保存着这张面孔的所处的位置和宽高,除此之外,眼睛和嘴的位置也是可选的。

    另一方面,OpenCV 也提供了一套物体检测功能,经过训练后能够检测出任何你需要的物体。该库为多个场景自带了可以直接拿来用的检测参数,如人脸、眼睛、嘴、身体、上半身、下半身和笑脸。检测引擎由一些非常简单的检测器的级联组成。这些检测器被称为 Haar 特征检测器,它们各自具有不同的尺度和权重。在训练阶段,决策树会通过已知的正确和错误的图片进行优化。关于训练与检测过程的详情可参考此原始论文。当正确的特征级联及其尺度与权重通过训练确立以后,这些参数就可被加载并初始化级联分类器了:

    // 正面人脸检测器训练参数的文件路径
    NSString *faceCascadePath = [[NSBundle mainBundle] pathForResource:@"haarcascade_frontalface_alt2" ofType:@"xml"];  const CFIndex CASCADE_NAME_LEN = 2048; char *CASCADE_NAME = (char *) malloc(CASCADE_NAME_LEN); CFStringGetFileSystemRepresentation( (CFStringRef)faceCascadePath, CASCADE_NAME, CASCADE_NAME_LEN); CascadeClassifier faceDetector; faceDetector.load(CASCADE_NAME); 

    这些参数文件可在 OpenCV 发行包里的 data/haarcascades 文件夹中找到。

    在使用所需要的参数对人脸检测器进行初始化后,就可以用它进行人脸检测了:

    cv::Mat img;
    vector<cv::Rect> faceRects;
    double scalingFactor = 1.1;
    int minNeighbors = 2; int flags = 0; cv::Size minimumSize(30,30); faceDetector.detectMultiScale(img, faceRects, scalingFactor, minNeighbors, flags cv::Size(30, 30) ); 

    检测过程中,已训练好的分类器会用不同的尺度遍历输入图像的每一个像素,以检测不同大小的人脸。参数 scalingFactor 决定每次遍历分类器后尺度会变大多少倍。参数 minNeighbors 指定一个符合条件的人脸区域应该有多少个符合条件的邻居像素才被认为是一个可能的人脸区域;如果一个符合条件的人脸区域只移动了一个像素就不再触发分类器,那么这个区域非常可能并不是我们想要的结果。拥有少于 minNeighbors 个符合条件的邻居像素的人脸区域会被拒绝掉。如果 minNeighbors 被设置为 0,所有可能的人脸区域都会被返回回来。参数 flags 是 OpenCV 1.x 版本 API 的遗留物,应该始终把它设置为 0。最后,参数 minimumSize 指定我们所寻找的人脸区域大小的最小值。faceRects 向量中将会包含对 img 进行人脸识别获得的所有人脸区域。识别的人脸图像可以通过 cv::Mat 的 () 运算符提取出来,调用方式很简单:cv::Mat faceImg = img(aFaceRect)

    不管是使用 CIDetector 还是 OpenCV 的 CascadeClassifier,只要我们获得了至少一个人脸区域,我们就可以对图像中的人进行识别了。

    人脸识别

    OpenCV 自带了三个人脸识别算法:Eigenfaces,Fisherfaces 和局部二值模式直方图 (LBPH)。如果你想知道它们的工作原理及相互之间的区别,请阅读 OpenCV 的详细文档

    针对于我们的 demo app,我们将采用 LBPH 算法。因为它会根据用户的输入自动更新,而不需要在每添加一个人或纠正一次出错的判断的时候都要重新进行一次彻底的训练。

    要使用 LBPH 识别器,我们也用 Objective-C++ 把它封装起来。这个封装中暴露以下函数:

    + (FJFaceRecognizer *)faceRecognizerWithFile:(NSString *)path;
    - (NSString *)predict:(UIImage*)img confidence:(double *)confidence; - (void)updateWithFace:(UIImage *)img name:(NSString *)name; 

    像下面这样用工厂方法来创建一个 LBPH 实例:

    + (FJFaceRecognizer *)faceRecognizerWithFile:(NSString *)path {
        FJFaceRecognizer *fr = [FJFaceRecognizer new];
        fr->_faceClassifier = createLBPHFaceRecognizer();
        fr->_faceClassifier->load(path.UTF8String);
        return fr;
    }
    

    预测函数可以像下面这样实现:

    - (NSString *)predict:(UIImage*)img confidence:(double *)confidence {
        cv::Mat src = [img cvMatRepresentationGray];
        int label; self->_faceClassifier->predict(src, label, *confidence); return _labelsArray[label]; } 

    请注意,我们要使用一个类别方法把 UIImage 转化为 cv::Mat。此转换本身倒是相当简单直接:使用 CGBitmapContextCreate 创建一个指向 cv::Image 中的 data 指针所指向的数据的 CGContextRef。当我们在此图形上下文中绘制此 UIImage 的时候,cv::Image 的 data 指针所指就是所需要的数据。更有趣的是,我们能对一个 Objective-C 类创建一个 Objective-C++ 的类别,并且确实管用。

    另外,OpenCV 的人脸识别器仅支持整数标签,但是我们想使用人的名字作标签,所以我们得通过一个 NSArray 属性来对二者实现简单的转换。

    一旦识别器给了我们一个识别出来的标签,我们把此标签给用户看,这时候就需要用户给识别器一个反馈。用户可以选择,“是的,识别正确”,也可以选择,“不,这是 Y,不是 X”。在这两种情况下,我们都可以通过人脸图像和正确的标签来更新 LBPH 模型,以提高未来识别的性能。使用用户的反馈来更新人脸识别器的方式如下:

    - (void)updateWithFace:(UIImage *)img name:(NSString *)name {
        cv::Mat src = [img cvMatRepresentationGray];
        NSInteger label = [_labelsArray indexOfObject:name]; if (label == NSNotFound) { [_labelsArray addObject:name]; label = [_labelsArray indexOfObject:name]; } vector<cv::Mat> images = vector<cv::Mat>(); images.push_back(src); vector<int> labels = vector<int>(); labels.push_back((int)label); self->_faceClassifier->update(images, labels); } 

    这里,我们又做了一次了从 UIImage 到 cv::Matint 到 NSString 标签的转换。我们还得如 OpenCV 的 FaceRecognizer::update API所期望的那样,把我们的参数放到 std::vector 实例中去。

    如此“预测,获得反馈,更新循环”,就是文献上所说的监督式学习

    结论

    OpenCV 是一个强大而用途广泛的库,覆盖了很多现如今仍在活跃的研究领域。想在一篇文章中给出详细的使用说明只会是让人徒劳的事情。因此,本文仅意在从较高层次对 OpenCV 库做一个概述。同时,还试图就如何集成 OpenCV 库到你的 iOS 工程中给出一些实用建议,并通过一个人脸识别的例子来向你展示如何在一个真正的项目中使用 OpenCV。如果你觉得 OpenCV 对你的项目有用, OpenCV 的官方文档写得非常好非常详细,请继续前行,创造出下一个伟大的 app!


    原文 Face Recognition with OpenCV

    来自:https://objccn.io/issue-21-9/

    转载于:https://www.cnblogs.com/CityPe/p/6180228.html

    展开全文
  • 准备工作:python3.7, pycharm,opencv-python模块。(不懂的话,网上有许多资料可供查询) 全部代码如下(直接可运行,需将图片路径换成自己电脑的图片路径) import cv2 as cv import numpy as np # canny边缘...
  • 苹果标识符 一个使用OpenCV库的图像处理微型项目,旨在识别果园中的苹果
  • # https://blog.csdn.net/lovebyz/article/details/83276435 openCV获取图像特征点的方法NBNBN #!usr/env/bin python3 # 本文链接:https://blog.csdn.net/qq_36699423/article/details/84728238 from math...
  • 基于Android的苹果损坏程度的检测,用opencv怎么实现啊?
  • 我是OpenCV和图像处理的新手.直到现在我都尝试过以下方法,但我相信必须采用更好的方法.1). Finding color range (HSV) manually using GColor2/Gimp tool/trackbar manually from a reference image which contains ...

    嗨!我是OpenCV和图像处理的新手.直到现在我都尝试过以下方法,但我相信必须采用更好的方法.

    1). Finding color range (HSV) manually using GColor2/Gimp tool/trackbar manually from a reference image which contains a single fruit (banana)

    with a white background. Then I used inRange(), findContour(),

    drawContour() on both reference banana image & target

    image(fruit-platter) and matchShapes() to compare the contours in the

    end.

    只要选择的颜色范围合适,它就可以正常工作. (见第2张图片).但由于这些水果没有均匀的纯色,这种方法对我来说似乎不是一个理想的方法.我不想硬编码inRange()中的颜色范围(标量值).

    2). Manual thresholding and contour matching.

    与(1)相同的问题.不想硬编码阈值.

    3). OTSU thresholding and canny edge detection.

    不适用于香蕉,苹果和柠檬.

    4). Dynamically finding colors. I used the cropped banana reference

    image. Calculated the mean & standard deviation of the image.

    不知道如何忽略我的mean / std-dev计算中的白色背景像素而不循环遍历每个x,y像素.对此有任何建议都是受欢迎的.

    5). Haar Cascade training gives inaccurate results. (See the image below). I believe proper training might give better results. But not interested in this for now.

    我正在考虑的其他方法:

    6). Using floodfill to find all the connected pixels and

    calculating

    the average and standard deviation of the same.

    在这方面没有成功.不知道如何获得所有连接的像素.我倾倒了面具(imwrite)并将香蕉(来自参考香蕉图像)放入黑色&白色的形式.对此有任何建议都是受欢迎的.

    7). Hist backprojection:- not sure how it would help me.

    8). K-Means , not tried yet. Let me know, if it’s better than step

    (4).

    9). meanshift/camshift → not sure whether it will help. Suggestions are welcome.

    10). feature detection — SIFT/SURF — not tried yet.

    任何帮助,提示或建议将受到高度赞赏.

    展开全文
  • 基于 OpenCV 的人脸识别

    千次阅读 2016-06-04 20:50:23
    OpenCV 是一个开源的计算机视觉和机器学习库。它包含成千上万优化过的算法,为各种计算机视觉应用提供了一个通用工具包。根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从谷歌街景的图片拼接,到交互...
  • 但是最近一直想在树莓派和OpenCV的环境下进行某种物体的识别,所以要训练特定的分类器,过程不难,相对繁杂,跟着走就OK,以下用苹果识别为例。 在Linux环境下进行Opencv分类器的训练(基于树莓派和OpenCV的物体识别...
  • 可以说识别任意的物品,前提是需要训练模型 使用opencv 训练http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/user_guide/ug_traincascade.html 正样本:包含特征(苹果)的图片,灰度图。 正样本大小:统一大小...
  • iOS中基于OpenCV的人脸识别

    千次阅读 2016-11-28 10:18:01
    title: iOS中基于OpenCV的人脸识别 type: categories date: 2016-11-28 09:45:27 categories: OCtags: [OpenCV, 人脸识别] OpenCV 是一个开源的计算机视觉和机器学习库。 与iOS系统自带的识别库一样,对于侧...
  • opencv果实分割与识别

    2018-04-25 09:37:19
    实现对猕猴桃果实的图像处理,包含二值化、滤波、提取果实目标、图像相与、边缘化过程。
  • 使用OpenCV和Python进行人脸识别 (Face Recognition With OpenCV and Python)What is face recognition? Or what is recognition? When you look at an apple fruit, your mind immediately tells you that this is ...
  • ios学习之基于 OpenCV的人脸识别

    千次阅读 2017-10-10 13:19:33
    根据这个项目的关于页面,OpenCV 已被广泛运用在各种项目上,从谷歌街景的图片拼接,到交互艺术展览的技术实现中,都有 OpenCV 的身影。 OpenCV 起始于 1999 年 Intel 的一个内部研究项目。从那时起,它的开发就...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,538
精华内容 615
关键字:

opencv识别苹果