“悉灵杯”课题研究-基于opecv的集成RGB_D相机SDK的基础小样物品颜色检测及人脸识别
本文主要介绍使用opencv,对RGB_D相机采集的图像中小型物品进行基本的颜色检测和基础的人脸识别。

    OpenCV是一个基于Apache2.0许可(开源)发行的跨平台计算机视觉机器学习软件库。它轻量级而且高效,同时提供了许多语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。基于与本次海康sdk的数据结合,本文接下来介绍如何使用SDK读取RGB图像帧,并用其进行简单的检测和识别操作。


一. 本文环境介绍


1. opencv 4.3.0

2. visual studio 2019

2. 悉灵相机MV-EB435i
3. SDK_Mv3dRgbd_V1.0.0_Win



二. 海康RGB_D相机SDK图像结构解析和RGB图像提取


    在RGB_D相机采集的图像中,SDK给出图像帧格式:MV3D_RGBD_FRAME_DATA,其中具体代码定义如下:

typedef struct _MV3D_RGBD_FRAME_DATA_
{
    uint32_t                    nImageCount;                                    // 图像个数,表示stImage数组的有效个数
    MV3D_RGBD_IMAGE_DATA        stImageData[MV3D_RGBD_MAX_IMAGE_COUNT];         // 图像数组,每一个代表一种类型的图像    
       
    uint8_t                     nReserved[16];                                  // 保留字节  
} MV3D_RGBD_FRAME_DATA;

    可看出,每一帧产生的图像是由一个 stImageData 图像数组包容的,其中图像含有多种图像类型,具体定义如下:

typedef enum Mv3dRgbdImageType
{
    ImageType_Undefined         = MV3D_RGBD_UNDEFINED,
    ImageType_Mono8             = (MV3D_RGBD_PIXEL_MONO  | MV3D_RGBD_PIXEL_BIT_COUNT(8)  | 0x0001),   //0x01080001
    ImageType_Depth             = (MV3D_RGBD_PIXEL_MONO  | MV3D_RGBD_PIXEL_BIT_COUNT(16) | 0x00B8),   //0x011000B8
    ImageType_YUV422            = (MV3D_RGBD_PIXEL_COLOR | MV3D_RGBD_PIXEL_BIT_COUNT(16) | 0x0032),   //0x02100032
    ImageType_YUV420SP_NV12     = (MV3D_RGBD_PIXEL_COLOR | MV3D_RGBD_PIXEL_BIT_COUNT(12) | 0x8001),   //0x020C8001
    ImageType_YUV420SP_NV21     = (MV3D_RGBD_PIXEL_COLOR | MV3D_RGBD_PIXEL_BIT_COUNT(12) | 0x8002),   //0x020C8002
    ImageType_RGB8_Planar       = (MV3D_RGBD_PIXEL_COLOR | MV3D_RGBD_PIXEL_BIT_COUNT(24) | 0x0021),   //0x02180021
    ImageType_PointCloud        = (MV3D_RGBD_PIXEL_COLOR | MV3D_RGBD_PIXEL_BIT_COUNT(96) | 0x00C0),   //0x026000C0,
    ImageType_Jpeg              = (MV3D_RGBD_PIXEL_CUSTOM| MV3D_RGBD_PIXEL_BIT_COUNT(24) | 0x0001)    //0x80180001, 自定义的图片格式
} Mv3dRgbdImageType;

    每帧中 stImageData 图像数组包含了 ImageType_DepthImageType_YUV422 ImageType_Mono8 三种图像类型。

    而 stImageData 代表的图像数据 MV3D_RGBD_IMAGE_DATA 定义如下:

typedef struct _MV3D_RGBD_IMAGE_DATA_
{
    Mv3dRgbdImageType           enImageType;                        // 图像格式
    uint32_t                    nWidth;                             // 图像宽
    uint32_t                    nHeight;                            // 图像高
    uint8_t*                    pData;                              // 相机输出的图像数据
    uint32_t                    nDataLen;                           // 图像数据长度(字节)
    uint32_t                    nFrameNum;                          // 帧号,代表第几帧图像
    int64_t                     nTimeStamp;                         // 设备上报的时间戳 (设备上电从0开始,规则详见设备手册)

    uint8_t                     nReserved[16];                      // 保留字节
} MV3D_RGBD_IMAGE_DATA;

    stImageData 数组中每一副图像的数据以 pdata 存储和表现。 

    此三种图像类型对应图像数据解释如下:
        ImageType_Depth :体现深度图的图像深度信息;

        ImageType_YUV422 : 以YUV 4:2:2 格式存储图像信息,体现图像亮度信息Y与色彩信息UV。

        ImageType_Mono8 : 以Mono 格式存储图像信息,储存单色,一般以灰度图展示。

    在本文中,需要提取RGB图像,即上述代码中 ImageType_RGB8_Planar 类型。


    由于需要提取的是 ImageType_RGB8_Planar 类型,而 stImageData 数组的输出的主要部分是 ImageType_Depth 和 ImageType_YUV422 两个类型。 需要对采集的帧数据进行格式分析转换才能输出成我们能读懂的图像,刚好在SDK中 parseframe(MV3D_RGBD_FRAME_DATA* , RIFrameInfo* ,RIFrameInfo* ) 的静态函数中可将帧数据分别转换成 RIFrameInfo类型的 深度图格式和RGB格式(RIFrameInfo 类型定义与上述 MV3D_RGBD_IMAGE_DATA 基本相同)。

    但是,此处的RGB图像其实在R(红色)、B(蓝色)通道表现相反,即相机采集图像转换时更类似于BGR图像, 这里可用 cv::cvtColor 的函数中 COLOR_BGR2RGB 的图像转换类型进行转换。



三. 实现基础人脸识别和小样物体的颜色检测


 (1)基础人脸识别

    在opencv中 Objdetect 模块中可检测特定的目标,其中包含 Cascade Classification(级联分类)的检测识别模式,主要是通过 CascadeClassifier 级联分类器类型定义的变量,读取opencv 自带的人脸识别haar面部特征文件 "haarcascade_frontalface_default.xml" ,对灰度图进行多尺度特征提取和检测,以下是主要源代码部分:

   while (1)
    {
        // 获取图像数据
        int nRet = MV3D_RGBD_FetchFrame(handle, &stFrameData, 5000);
        if (MV3D_RGBD_OK == nRet)
        {
            LOGD("MV3D_RGBD_FetchFrame success.");

            //分析获取每帧数据
            parseFrame(&stFrameData, &depth, &rgb);
            Mat rgb_frame(rgb.nHeight, rgb.nWidth, CV_8UC3, rgb.pData);

            LOGD("rgb: FrameNum(%d), height(%d), width(%d)。", rgb.nFrameNum, rgb.nHeight, rgb.nWidth);

            //B、R通道交换,显示正常彩色图像
            Mat frame, gray_frame;
            cvtColor(rgb_frame, frame, COLOR_BGR2RGB);
            cvtColor(rgb_frame, gray_frame, COLOR_BGR2GRAY);

            //以下进行人脸识别
            faceCascade.load("haarcascade_frontalface_default.xml");

            if (faceCascade.empty())
            {
                LOGD("xml not found!");
            }

            //进行直方图均衡化
            equalizeHist(gray_frame, gray_frame);

            //执行多尺度特征检测
            vector<Rect> faces;
            faceCascade.detectMultiScale(gray_frame, faces, 1.1, 5, 0, Size(24, 24));

            for (int i = 0; i < faces.size(); i++)
            {
                LOGD("catch_face: x(%d), y(%d)", faces[i].x, faces[i].y);
                rectangle(frame, faces[i].tl(), faces[i].br(), Scalar(255, 255, 255), 4);
            }

            namedWindow("HIK_face", 0);
            resizeWindow("HIK_face", 640, 360);
            imshow("HIK_face", frame);
            waitKey(1);
        }
    }

    其中,发现由于在光线强度大的白天,图像采集的泛白部分过大,可能对面部显示并没有很精细,这里采用直方图均衡化 equalizeHist 函数,让灰度图中泛白的部分,在均衡化之后能够合并一些像素灰度, 从而增强对比度。最后在 detectMultiScale 多尺度特征检测函数中能够更为准确的进行面部识别。

    下图是代码运行结果:



(2)基础小样物体的颜色检测(HSV格式的颜色向量范围预设)

    对物体检测主要是通过同一线程轮询分析出的RGB图像分成两个方面的过程:

    1. 其一RGB图像进行图像变换、处理,再将处理后的图像查找轮廓向量,得到该轮廓的外部矩形边界点。

    2. 另一RGB图像用上述得到外部矩形边界点进行绘图。

    在这里,首先简要介绍 HSV格式, HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法。HSV即色相(Hue)、饱和度(Saturation)、明度(Value)。色相是色彩的基本属性,表现出是何种颜色。饱和度(S)是指色彩的纯度。明度(V)即色彩的亮暗。在本项目中,将RGB图像帧转换成HSV格式,能够更有利的得到色彩的明暗,色调,以及鲜艳程度,方便进行提取不同的颜色。以下是 getcolor 色彩转换函数代码:

void getcolor(Mat ero_frame)
{
    Mat hsv_frame;
    cvtColor(ero_frame, hsv_frame, COLOR_BGR2HSV);

    for (int i = 0; i < ColorValues.size(); i++)
    {
        Mat mask;
        Scalar lower(ColorValues[i][0], ColorValues[i][1], ColorValues[i][2]);
        Scalar upper(ColorValues[i][3], ColorValues[i][4], ColorValues[i][5]);
        
        //二值化图像
        inRange(hsv_frame, lower, upper, mask);

        Point po = getcontours(mask);

        if (po.x != 0)
        {
            LOGD("findPoint: x(%d), y(%d)", po.x, po.y);

            String t_color = coltypes(i);
            putText(after_frame, t_color, {po.x -5, po.y }, FONT_HERSHEY_PLAIN, 2, Scalar(0, 0, 255), 2);
        }
    }
}

    传入函数之前已经对图像进行高斯滤波和膨胀腐蚀的形态学滤波的操作。这里用 inRange 函数控制 HSV格式图像在预设范围的二值化输出,能够更好的界定接下来寻找轮廓的点集位置。以下是寻找轮廓和矩阵点向量的 getcontours 函数代码:

Point getcontours(Mat image)
{
    //轮廓点向量contours
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;

    findContours(image, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    //矩形点向量和矩形向量
    vector<vector<Point>> conpoly(contours.size());
    vector<Rect> boundirect(contours.size());

    Point myPoint(0, 0);

    for (int i = 0; i < contours.size(); i++)
    {
        int area = contourArea(contours[i]);

        //控制检测像素面积大小
        if (area> 3000 && area < 10000)
        {
            //多边形曲线拟合
            float peri = arcLength(contours[i], true);
            approxPolyDP(contours[i], conpoly[i], 0.03 * peri, true);

            LOGD("contours: area(%d);  conpoly[%d]: size(%d)", area, i, conpoly[i].size());

            boundirect[i] = boundingRect(conpoly[i]);

            //图框的左上角
            myPoint.x = boundirect[i].x;
            myPoint.y = boundirect[i].y;

            //图像绘图
            //drawContours(frame, conpoly, i, Scalar(255, 0, 255), 2);
            rectangle(after_frame, boundirect[i].tl(), boundirect[i].br(), Scalar(0, 0, 255), 2);  
            LOGD("draw finish!");
        }
    }

    return myPoint;
}

    用轮廓面积的大小确定小型物体的大致图像面积范围,有效的避免了大型图像颜色的泛查,由于对轮廓线长的曲线拟合,较好得到邻近的矩形框点。

    以下是代码运行结果:



四. 总结


    本文基础的检测功能能够实现初步的人脸识别和颜色识别,但需要进一步优化,类似颜色检测,对颜色的精细界定和对无关事物和图像背景的误差检测也是需要考究的方面。


开源代码:https://github.com/JiaHao-YU03/HIKROBOT_opencv/tree/master

来自 南京工程学院-丁可可团队

版权声明:本文为V社区用户原创内容,转载时必须标注文章的来源(V社区),文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:v-club@hikrobotics.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
上一篇

悉灵杯”课题研究-LabVIEW集成及示例代码开发

下一篇

“悉灵杯”课题研究-MV-EB435i立体相机图像处理UI界面开发

评论请先登录 登录
全部评论 1
优秀!
2022-08-16 00:17:08
回复
  • 1
Lv.0
1
创作
1
粉丝
9
获赞
相关阅读
  • 3C行业|字符缺陷检测及字符识别
    2022-11-11
  • VM常见定位场景与方案设计
    2022-11-11
  • VM模块-相机映射
    2022-11-11
  • AI训练平台V2.1上线公测啦
    2022-11-05
  • V社区一周年“心仪祝福”揭晓
    2022-11-08

请升级浏览器版本

您正在使用的浏览器版本过低,请升级最新版本以获得更好的体验。

推荐使用以下浏览器