iis服务器助手广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++ OpenCV实现之实现红绿灯识别
  • 516
分享到

C++ OpenCV实现之实现红绿灯识别

C++ OpenCV红绿灯识别OpenCV红绿灯识别C++ OpenCV 识别 2022-11-13 13:11:50 516人浏览 薄情痞子
摘要

目录前言一、轮廓识别相关原理什么是轮廓检测轮廓提取函数findContours二、案例实现Step1:初始化配置Step2:进行帧处理Step3:膨胀腐蚀处理Step4:红绿灯提示判

前言

本文以实现行车过程当中的红绿灯识别为目标,核心的内容包括:OpenCV轮廓识别原理以及OpenCV红绿灯识别的实现具体步骤

一、轮廓识别相关原理

什么是轮廓检测

目前轮廓检测方法有两类,一类是利用传统的边缘检测算子检测目标轮廓,另一类是从人类视觉系统中提取可以使用的数学模型完成目标轮廓检测

轮廓提取函数findContours

函数原型: 

findContours( InputOutputArray image, OutputArrayOfArrays contours,
                              OutputArray hierarchy, int mode,
                              int method, Point offset=Point());

参数:

image:单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像

contours:  定义为“vector<vector<Point>> contours”,是一个向量,并且是一个双重向量,向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。有多少轮廓,向量contours就有多少元素

hierarchy:  也是一个向量,向量内每个元素保存了一个包含4个int整型的数组。向量内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同

int mode: 

取值一:CV_CHaiN_APPROX_NONE 保存物体边界上所有连续的轮廓点到 contours向量内

取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留

取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法

Point: Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point还可以是负值!

参数详解引用出处:findContours函数参数详解

二、案例实现

这是本案例所用到的素材,如下图所示: 

PS:视频的效果比较好,如果方便的话可以自行外出拍摄取材

Step1:初始化配置

做好准备工作,创建我们需要的内容,设置亮度参数,以及我们导入的视频路径

    int redCount = 0;
    int greenCount = 0;
 
    Mat frame;
    Mat img;
    Mat imgYCrCb;
    Mat imgGreen;
    Mat imgRed;
 
    // 亮度参数
    double a = 0.3;
    double b = (1 - a) * 125;
 
    VideoCapture capture("C:/Users/86177/Desktop/image/123.mp4");//导入视频的路径
    if (!capture.isOpened())
    {
        cout << "Start device failed!\n" << endl;//启动设备失败!
        return -1;
    }

Step2:进行帧处理

调整视频亮度,分解YCrCb的三个成分,拆分红色和绿色,方便对红绿两种颜色进行特征提取

    // 帧处理
    while (1)
    {
        capture >> frame;
        //调整亮度
        frame.convertTo(img, img.type(), a, b);
 
        //转换为YCrCb颜色空间
        cvtColor(img, imgYCrCb, CV_BGR2YCrCb);
 
        imgRed.create(imgYCrCb.rows, imgYCrCb.cols, CV_8UC1);
        imgGreen.create(imgYCrCb.rows, imgYCrCb.cols, CV_8UC1);
 
        //分解YCrCb的三个成分
        vector<Mat> planes;
        split(imgYCrCb, planes);
        // 遍历以根据Cr分量拆分红色和绿色
        MatIterator_<uchar> it_Cr = planes[1].begin<uchar>(),
                it_Cr_end = planes[1].end<uchar>();
        MatIterator_<uchar> it_Red = imgRed.begin<uchar>();
        MatIterator_<uchar> it_Green = imgGreen.begin<uchar>();
 
        for (; it_Cr != it_Cr_end; ++it_Cr, ++it_Red, ++it_Green)
        {
            // RED, 145<Cr<470 红色
            if (*it_Cr > 145 && *it_Cr < 470)
                *it_Red = 255;
            else
                *it_Red = 0;
 
            // GREEN 95<Cr<110 绿色
            if (*it_Cr > 95 && *it_Cr < 110)
                *it_Green = 255;
            else
                *it_Green = 0;
        }

Step3:膨胀腐蚀处理

去除其他噪点,提高我们需要的红绿灯的特征

        //膨胀和腐蚀
        dilate(imgRed, imgRed, Mat(15, 15, CV_8UC1), Point(-1, -1));
        erode(imgRed, imgRed, Mat(1, 1, CV_8UC1), Point(-1, -1));
        dilate(imgGreen, imgGreen, Mat(15, 15, CV_8UC1), Point(-1, -1));
        erode(imgGreen, imgGreen, Mat(1, 1, CV_8UC1), Point(-1, -1));
 
        redCount = processImgR(imgRed);
        greenCount = processImgG(imgGreen);
        cout << "red:" << redCount << ";  " << "green:" << greenCount << endl;

Step4:红绿灯提示判断

加入红绿灯识别结果显示,方便我们查看效果

        if(redCount == 0 && greenCount == 0)
        {
            cv::putText(frame, "lights out", Point(40, 150), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(255, 255, 255), 8, 8, 0);
        }else if(redCount > greenCount)
        {
            cv::putText(frame, "red light", Point(40, 150), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(0, 0, 255), 8, 8, 0);
        }else{
            cv::putText(frame, "green light", Point(40, 150), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(0, 255, 0), 8, 8, 0);
        }

Step5:轮廓提取

分别对红灯和绿灯进行轮廓特征提取,提高辨识度

int processImgR(Mat src)
{
    Mat tmp;
 
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    vector<Point> hull;
 
    CvPoint2D32f tempnode;
    CvMemStorage* storage = cvCreateMemStorage();
    CvSeq* pointSeq = cvCreateSeq(CV_32FC2, sizeof(CvSeq), sizeof(CvPoint2D32f), storage);
 
    Rect* trackBox;
    Rect* result;
    int resultNum = 0;
 
    int area = 0;
    src.copyTo(tmp);
 
    //提取轮廓
    findContours(tmp, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
 
    if (contours.size() > 0)
    {
        trackBox = new Rect[contours.size()];
        result = new Rect[contours.size()];
 
        //确定要跟踪的区域
        for (int i = 0; i < contours.size(); i++)
        {
            cvClearSeq(pointSeq);
            // 获取凸包的点集
            convexHull(Mat(contours[i]), hull, true);
            int hullcount = (int)hull.size();
            // 凸包的保存点
            for (int j = 0; j < hullcount - 1; j++)
            {
                tempNode.x = hull[j].x;
                tempNode.y = hull[j].y;
                cvSeqPush(pointSeq, &tempNode);
            }
 
            trackBox[i] = cvBoundingRect(pointSeq);
        }
 
        if (isFirstDetectedR)
        {
            lastTrackBoxR = new Rect[contours.size()];
            for (int i = 0; i < contours.size(); i++)
                lastTrackBoxR[i] = trackBox[i];
            lastTrackNumR = contours.size();
            isFirstDetectedR = false;
        }
        else
        {
            for (int i = 0; i < contours.size(); i++)
            {
                for (int j = 0; j < lastTrackNumR; j++)
                {
                    if (isIntersected(trackBox[i], lastTrackBoxR[j]))
                    {
                        result[resultNum] = trackBox[i];
                        break;
                    }
                }
                resultNum++;
            }
            delete[] lastTrackBoxR;
            lastTrackBoxR = new Rect[contours.size()];
            for (int i = 0; i < contours.size(); i++)
            {
                lastTrackBoxR[i] = trackBox[i];
            }
            lastTrackNumR = contours.size();
        }
 
        delete[] trackBox;
    }
    else
    {
        isFirstDetectedR = true;
        result = NULL;
    }
    cvReleaseMemStorage(&storage);
 
    if (result != NULL)
    {
        for (int i = 0; i < resultNum; i++)
        {
            area += result[i].area();
        }
    }
    delete[] result;
 
    return area;
}
 
int processImgG(Mat src)
{
    Mat tmp;
 
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    vector< Point > hull;
 
    CvPoint2D32f tempNode;
    CvMemStorage* storage = cvCreateMemStorage();
    CvSeq* pointSeq = cvCreateSeq(CV_32FC2, sizeof(CvSeq), sizeof(CvPoint2D32f), storage);
 
    Rect* trackBox;
    Rect* result;
    int resultNum = 0;
 
    int area = 0;
 
    src.copyTo(tmp);
    //提取轮廓
    findContours(tmp, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
 
    if (contours.size() > 0)
    {
        trackBox = new Rect[contours.size()];
        result = new Rect[contours.size()];
 
        // 确定要跟踪的区域
        for (int i = 0; i < contours.size(); i++)
        {
            cvClearSeq(pointSeq);
            // 获取凸包的点集
            convexHull(Mat(contours[i]), hull, true);
            int hullcount = (int)hull.size();
            // 保存凸包的点
            for (int j = 0; j < hullcount - 1; j++)
            {
                tempNode.x = hull[j].x;
                tempNode.y = hull[j].y;
                cvSeqPush(pointSeq, &tempNode);
            }
 
            trackBox[i] = cvBoundingRect(pointSeq);
        }
 
        if (isFirstDetectedG)
        {
            lastTrackBoxG = new Rect[contours.size()];
            for (int i = 0; i < contours.size(); i++)
                lastTrackBoxG[i] = trackBox[i];
            lastTrackNumG = contours.size();
            isFirstDetectedG = false;
        }
        else
        {
            for (int i = 0; i < contours.size(); i++)
            {
                for (int j = 0; j < lastTrackNumG; j++)
                {
                    if (isIntersected(trackBox[i], lastTrackBoxG[j]))
                    {
                        result[resultNum] = trackBox[i];
                        break;
                    }
                }
                resultNum++;
            }
            delete[] lastTrackBoxG;
            lastTrackBoxG = new Rect[contours.size()];
            for (int i = 0; i < contours.size(); i++)
            {
                lastTrackBoxG[i] = trackBox[i];
            }
            lastTrackNumG = contours.size();
        }
 
        delete[] trackBox;
    }
    else
    {
        isFirstDetectedG = true;
        result = NULL;
    }
    cvReleaseMemStorage(&storage);
 
    if (result != NULL)
    {
        for (int i = 0; i < resultNum; i++)
        {
            area += result[i].area();
        }
    }
    delete[] result;
 
    return area;
}

Step6:判断是否相交

//确定两个矩形区域是否相交
bool isIntersected(Rect r1, Rect r2)
{
    int minX = max(r1.x, r2.x);
    int minY = max(r1.y, r2.y);
    int maxX = min(r1.x + r1.width, r2.x + r2.width);
    int maxY = min(r1.y + r1.height, r2.y + r2.height);
 
    if (minX < maxX && minY < maxY)
        return true;
    else
        return false;
}

案例效果

完整代码

#include "OpenCV2/opencv.hpp"
#include "opencv2/imgproc.hpp"
#include <windows.h>
#include <iOStream>
 
using namespace std;
using namespace cv;
 
// Function headers
int processImgR(Mat);
int processImgG(Mat);
bool isIntersected(Rect, Rect);
 
// Global variables
bool isFirstDetectedR = true;
bool isFirstDetectedG = true;
Rect* lastTrackBoxR;
Rect* lastTrackBoxG;
int lastTrackNumR;
int lastTrackNumG;
 
//主函数
int main()
{
    int redCount = 0;
    int greenCount = 0;
 
    Mat frame;
    Mat img;
    Mat imgYCrCb;
    Mat imgGreen;
    Mat imgRed;
 
    // 亮度参数
    double a = 0.3;
    double b = (1 - a) * 125;
 
    VideoCapture capture("C:/Users/86177/Desktop/image/123.mp4");//导入视频的路径
    if (!capture.isOpened())
    {
        cout << "Start device failed!\n" << endl;//启动设备失败!
        return -1;
    }
 
    // 帧处理
    while (1)
    {
        capture >> frame;
        //调整亮度
        frame.convertTo(img, img.type(), a, b);
 
        //转换为YCrCb颜色空间
        cvtColor(img, imgYCrCb, CV_BGR2YCrCb);
 
        imgRed.create(imgYCrCb.rows, imgYCrCb.cols, CV_8UC1);
        imgGreen.create(imgYCrCb.rows, imgYCrCb.cols, CV_8UC1);
 
        //分解YCrCb的三个成分
        vector<Mat> planes;
        split(imgYCrCb, planes);
        // 遍历以根据Cr分量拆分红色和绿色
        MatIterator_<uchar> it_Cr = planes[1].begin<uchar>(),
                it_Cr_end = planes[1].end<uchar>();
        MatIterator_<uchar> it_Red = imgRed.begin<uchar>();
        MatIterator_<uchar> it_Green = imgGreen.begin<uchar>();
 
        for (; it_Cr != it_Cr_end; ++it_Cr, ++it_Red, ++it_Green)
        {
            // RED, 145<Cr<470 红色
            if (*it_Cr > 145 && *it_Cr < 470)
                *it_Red = 255;
            else
                *it_Red = 0;
 
            // GREEN 95<Cr<110 绿色
            if (*it_Cr > 95 && *it_Cr < 110)
                *it_Green = 255;
            else
                *it_Green = 0;
        }
 
        //膨胀和腐蚀
        dilate(imgRed, imgRed, Mat(15, 15, CV_8UC1), Point(-1, -1));
        erode(imgRed, imgRed, Mat(1, 1, CV_8UC1), Point(-1, -1));
        dilate(imgGreen, imgGreen, Mat(15, 15, CV_8UC1), Point(-1, -1));
        erode(imgGreen, imgGreen, Mat(1, 1, CV_8UC1), Point(-1, -1));
 
        redCount = processImgR(imgRed);
        greenCount = processImgG(imgGreen);
        cout << "red:" << redCount << ";  " << "green:" << greenCount << endl;
 
        if(redCount == 0 && greenCount == 0)
        {
            cv::putText(frame, "lights out", Point(40, 150), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(255, 255, 255), 8, 8, 0);
        }else if(redCount > greenCount)
        {
            cv::putText(frame, "red light", Point(40, 150), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(0, 0, 255), 8, 8, 0);
        }else{
            cv::putText(frame, "green light", Point(40, 150), cv::FONT_HERSHEY_SIMPLEX, 2, cv::Scalar(0, 255, 0), 8, 8, 0);
        }
 
        imshow("video", frame);
        imshow("Red", imgRed);
        imshow("Green", imgGreen);
 
        // Handle with the keyboard input
        if (cvWaiTKEy(20) == 'q')
            break;
    }
 
    return 0;
}
 
int processImgR(Mat src)
{
    Mat tmp;
 
    vector<vector<Point>> contours;
    vector<Vec4i> hierarchy;
    vector<Point> hull;
 
    CvPoint2D32f tempNode;
    CvMemStorage* storage = cvCreateMemStorage();
    CvSeq* pointSeq = cvCreateSeq(CV_32FC2, sizeof(CvSeq), sizeof(CvPoint2D32f), storage);
 
    Rect* trackBox;
    Rect* result;
    int resultNum = 0;
 
    int area = 0;
    src.copyTo(tmp);
 
    //提取轮廓
    findContours(tmp, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
 
    if (contours.size() > 0)
    {
        trackBox = new Rect[contours.size()];
        result = new Rect[contours.size()];
 
        //确定要跟踪的区域
        for (int i = 0; i < contours.size(); i++)
        {
            cvClearSeq(pointSeq);
            // 获取凸包的点集
            convexHull(Mat(contours[i]), hull, true);
            int hullcount = (int)hull.size();
            // 凸包的保存点
            for (int j = 0; j < hullcount - 1; j++)
            {
                tempNode.x = hull[j].x;
                tempNode.y = hull[j].y;
                cvSeqPush(pointSeq, &tempNode);
            }
 
            trackBox[i] = cvBoundingRect(pointSeq);
        }
 
        if (isFirstDetectedR)
        {
            lastTrackBoxR = new Rect[contours.size()];
            for (int i = 0; i < contours.size(); i++)
                lastTrackBoxR[i] = trackBox[i];
            lastTrackNumR = contours.size();
            isFirstDetectedR = false;
        }
        else
        {
            for (int i = 0; i < contours.size(); i++)
            {
                for (int j = 0; j < lastTrackNumR; j++)
                {
                    if (isIntersected(trackBox[i], lastTrackBoxR[j]))
                    {
                        result[resultNum] = trackBox[i];
                        break;
                    }
                }
                resultNum++;
            }
            delete[] lastTrackBoxR;
            lastTrackBoxR = new Rect[contours.size()];
            for (int i = 0; i < contours.size(); i++)
            {
                lastTrackBoxR[i] = trackBox[i];
            }
            lastTrackNumR = contours.size();
        }
 
        delete[] trackBox;
    }
    else
    {
        isFirstDetectedR = true;
        result = NULL;
    }
    cvReleaseMemStorage(&storage);
 
    if (result != NULL)
    {
        for (int i = 0; i < resultNum; i++)
        {
            area += result[i].area();
        }
    }
    delete[] result;
 
    return area;
}
 
int processImgG(Mat src)
{
    Mat tmp;
 
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    vector< Point > hull;
 
    CvPoint2D32f tempNode;
    CvMemStorage* storage = cvCreateMemStorage();
    CvSeq* pointSeq = cvCreateSeq(CV_32FC2, sizeof(CvSeq), sizeof(CvPoint2D32f), storage);
 
    Rect* trackBox;
    Rect* result;
    int resultNum = 0;
 
    int area = 0;
 
    src.copyTo(tmp);
    //提取轮廓
    findContours(tmp, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
 
    if (contours.size() > 0)
    {
        trackBox = new Rect[contours.size()];
        result = new Rect[contours.size()];
 
        // 确定要跟踪的区域
        for (int i = 0; i < contours.size(); i++)
        {
            cvClearSeq(pointSeq);
            // 获取凸包的点集
            convexHull(Mat(contours[i]), hull, true);
            int hullcount = (int)hull.size();
            // 保存凸包的点
            for (int j = 0; j < hullcount - 1; j++)
            {
                tempNode.x = hull[j].x;
                tempNode.y = hull[j].y;
                cvSeqPush(pointSeq, &tempNode);
            }
 
            trackBox[i] = cvBoundingRect(pointSeq);
        }
 
        if (isFirstDetectedG)
        {
            lastTrackBoxG = new Rect[contours.size()];
            for (int i = 0; i < contours.size(); i++)
                lastTrackBoxG[i] = trackBox[i];
            lastTrackNumG = contours.size();
            isFirstDetectedG = false;
        }
        else
        {
            for (int i = 0; i < contours.size(); i++)
            {
                for (int j = 0; j < lastTrackNumG; j++)
                {
                    if (isIntersected(trackBox[i], lastTrackBoxG[j]))
                    {
                        result[resultNum] = trackBox[i];
                        break;
                    }
                }
                resultNum++;
            }
            delete[] lastTrackBoxG;
            lastTrackBoxG = new Rect[contours.size()];
            for (int i = 0; i < contours.size(); i++)
            {
                lastTrackBoxG[i] = trackBox[i];
            }
            lastTrackNumG = contours.size();
        }
 
        delete[] trackBox;
    }
    else
    {
        isFirstDetectedG = true;
        result = NULL;
    }
    cvReleaseMemStorage(&storage);
 
    if (result != NULL)
    {
        for (int i = 0; i < resultNum; i++)
        {
            area += result[i].area();
        }
    }
    delete[] result;
 
    return area;
}
 
//确定两个矩形区域是否相交
bool isIntersected(Rect r1, Rect r2)
{
    int minX = max(r1.x, r2.x);
    int minY = max(r1.y, r2.y);
    int maxX = min(r1.x + r1.width, r2.x + r2.width);
    int maxY = min(r1.y + r1.height, r2.y + r2.height);
 
    if (minX < maxX && minY < maxY)
        return true;
    else
        return false;
}

三、总结

本文主要讲解OpenCV轮廓识别原理以及OpenCV红绿灯识别的实现具体步骤OpenCV还是有很多识别的库函数可以用,接下来继续探索,结合生活实际继续做一些有意思的案例

到此这篇关于c++ OpenCV实现之实现红绿灯识别的文章就介绍到这了,更多相关C++ OpenCV红绿灯识别内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++ OpenCV实现之实现红绿灯识别

本文链接: https://www.lsjlt.com/news/171464.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++ OpenCV实现之实现红绿灯识别
    目录前言一、轮廓识别相关原理什么是轮廓检测轮廓提取函数findContours二、案例实现Step1:初始化配置Step2:进行帧处理Step3:膨胀腐蚀处理Step4:红绿灯提示判...
    99+
    2022-11-13
    C++ OpenCV红绿灯识别 OpenCV红绿灯识别 C++ OpenCV 识别
  • javascript如何实现红绿灯
    本篇内容介绍了“javascript如何实现红绿灯”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! ...
    99+
    2024-04-02
  • react如何实现红绿灯
    本篇内容介绍了“react如何实现红绿灯”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!react实现红绿灯的方法:1、引入“import R...
    99+
    2023-07-05
  • 纯CSS如何实现红绿灯效果
    这篇文章主要介绍纯CSS如何实现红绿灯效果,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、下面的代码输出的内容是什么?function O(name){    th...
    99+
    2023-06-08
  • 基于OpenCV 差分法实现绿叶识别
    目录实现原理功能函数代码C++测试代码实现原理 物体识别是图像处理学在现实生活中较多的应用之一,目前最为流行的就是运用AI、机器学习等技术结合图像处理学,大量训练数据集,以实现智能且...
    99+
    2024-04-02
  • Vue 实现新国标红绿灯效果实例详解
    目录引言1 组件分析1.1 lamp1.2 lamp-group1.3 traffic-lamp2 全局文件定义2.1 样式变量2.2 常量定义2.3 导入资源3 组件开发3.1 实...
    99+
    2024-04-02
  • JS面试异步模拟红绿灯实现详解
    目录引言问题拆解代码设计引言 异步的问题是程序员绕不开的话题,无论在实际开发上还是在面试中,我们总会遇到各种头疼的问题,但是细细品味,其实这些问题总能拓展我们的思路,激发我们的思维能...
    99+
    2023-01-10
    JS面试异步模拟红绿灯 JS 异步面试
  • 人脸识别实战之Opencv+SVM实现人脸识别
    目录前言项目结构编码训练人脸识别模型识别图像中的人脸摄像头识别人脸前言 在本文中,您将学习如何使用 OpenCV 进行人脸识别。文章分三部分介绍: 第一,将首先执行人脸检测,使用深度...
    99+
    2024-04-02
  • C++OpenCV实战之形状识别
    目录前言一、图像预处理二、形状识别三、源码四、结果显示总结前言 本案例通过使用OpenCV中的approxPolyDP进行多边形近似,进而进行基础形状识别(圆、三角形、矩形、星形&h...
    99+
    2024-04-02
  • C++OpenCV实战之手势识别
    目录前言一、手部关键点检测1.1 功能源码1.2 功能效果二、手势识别2.1算法原理2.2功能源码三、结果显示3.1功能源码3.2效果显示四、源码总结前言 本文将使用OpenCV C...
    99+
    2024-04-02
  • opencv实现车牌识别
    本文实例为大家分享了opencv实现车牌识别的具体代码,供大家参考,具体内容如下 (1)提取车牌位置,将车牌从图中分割出来;(2)车牌字符的分割;(3)通过模版匹配识别字符;(4)将...
    99+
    2024-04-02
  • opencv实现答题卡识别
    本文实例为大家分享了opencv实现答题卡识别的具体代码,供大家参考,具体内容如下 """ 识别答题卡 """   import cv2 import numpy as np   d...
    99+
    2024-04-02
  • python+opencv 车牌识别实现
    识别思路: 1、通过摄像头采集图片 2、对图片进行去噪、对比度加强处理等操作 3、车牌位置的定位,采集到车牌信息 4、对车牌字母进行分割 5、通过卷积神经网络训练出来的模型,对采集车牌的各个字母进行识别 6、对结果进行组合,最后得到车牌...
    99+
    2023-01-31
    车牌 python opencv
  • C++ OpenCV怎么实现形状识别功能
    本篇内容主要讲解“C++ OpenCV怎么实现形状识别功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++ OpenCV怎么实现形状识别功能”吧!一、图像预处理原图如图所...
    99+
    2023-07-02
  • C++中怎么用OpenCV实现手势识别
    本篇内容介绍了“C++中怎么用OpenCV实现手势识别”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、手部关键点检测如图所示,为我们的手部...
    99+
    2023-06-29
  • C++OpenCV实现银行卡号识别功能
    目录前言一、获取模板图像1.1 功能效果1.2 功能源码二、银行卡号定位2.1 将银行卡号切割成四块2.2 字符切割三、字符识别3.1.读取文件3.2.字符匹配3.3.功能源码四、效...
    99+
    2024-04-02
  • C++OpenCV实战之手写数字识别
    目录前言一、准备数据集二、KNN训练三、模型预测及结果显示四、源码总结前言 本案例通过使用machine learning机器学习模块进行手写数字识别。源码注释也写得比较清楚啦,大家...
    99+
    2022-11-13
    C++ OpenCV手写数字识别 C++ OpenCV数字识别 OpenCV 数字识别
  • Python-OpenCV实现简单的颜色识别(对红色和蓝色识别并输出)
    摄像头识别红色和蓝色并框选,当该颜色为摄像头屏幕上大多数颜色时打印出该颜色的名称 新手学习笔记,第一次写博客,若有错误还请指出( ~`_` )~ 1.调包 import cv2import numpy as npfrom matpl...
    99+
    2023-09-08
    python opencv 计算机视觉
  • C++基于OpenCV实现手势识别的源码
    先给大家上效果图: 源码在下面 使用 RGB 值分割手部区域,即手部的 GB 值将与背景不同 或者使用边缘检测 或者 背景减法。  我这里使用了背景减法模型。OpenC...
    99+
    2024-04-02
  • C++ OpenCV如何实现身份证离线识别
    这篇文章将为大家详细讲解有关C++ OpenCV如何实现身份证离线识别,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。OpenCV身份证离线识别技术的主要技术就是通过OpenCV找到身份证号码区域...
    99+
    2023-06-22
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作