[19] Opencv_CUDA应用之 基于形状的对象检测与跟踪

Opencv_CUDA应用之 基于形状的对象检测与跟踪

  • 形状可以用作全局特征检测具有不同形状的物体,可以是直线、多边形、圆形或者任何其他不规则形状
  • 利用对象边界、边缘和轮廓可以检测具有特定形状的对象
  • 本文将使用Canny边缘检测算法和Hough变换来检测两个规则形状,即线和圆

1. Canny 边缘检测

  • Canny 结合了高斯滤波、梯度寻找、非极大值抑制和滞后阈值处理

  • 高通滤波器对噪声非常敏感,在Canny边缘检测中,检测边缘之前完成高斯平滑,在检测到边缘后从结果中移除不必要的边缘之后,还具有非极大值抑制阶段

  • 算法代码如下:

cpp 复制代码
#include <cmath>
#include <iostream>
#include "opencv2/opencv.hpp"
#include<opencv2/cudaimgproc.hpp>

using namespace std;
using namespace cv;
using namespace cv::cuda;

int main()
{
    Mat h_image = imread("images/drawing.JPG", 0);
    if (h_image.empty())
    {
        cout << "can not open image" << endl;
        return -1;
    }
    GpuMat d_edge, d_image;
    Mat h_edge;
    d_image.upload(h_image);
    cv::Ptr<cv::cuda::CannyEdgeDetector> canny_edge = cv::cuda::createCannyEdgeDetector(2.0, 100.0, 3, false);
    canny_edge->detect(d_image, d_edge);
    d_edge.download(h_edge);
    imshow("source", h_image);
    imshow("detected edges", h_edge);
    waitKey(0);

    return 0;
}

2. 使用 Hough 变换进行直线检测

  • hough变换常用于直线检测、圆检测
  • 直线检测函数解析:
cpp 复制代码
/*
cv::cuda::createCannyEdgeDetector 函数参数:
第一个r表示在Hough变换中参数的分辨率,通常为1像素
第二个参数是theta在弧度中的分辨率,取1弧度或者pi/180
第三个参数是形成一条线所需点的最小数量
第四个参数是两点之间的最大间隙被视为同一条直线

*/
 Ptr<cuda::HoughSegmentDetector> hough = 
 cuda::createHoughSegmentDetector(1.0f, (float)(CV_PI / 180.0f), 50, 5);
  • 实现代码如下:
cpp 复制代码
#include <cmath>
#include <iostream>
#include "opencv2/opencv.hpp"
#include<opencv2/cudaimgproc.hpp>

using namespace std;
using namespace cv;
using namespace cv::cuda;


int main()
{
    Mat h_image = imread("images/drawing.JPG", 0);
    resize(h_image, h_image, h_image.size());
    if (h_image.empty())
    {
        cout << "can not open image" << endl;
        return -1;
    }

    Mat h_edge;
    cv::Canny(h_image, h_edge, 100, 200, 3);

    Mat h_imagec;
    cv::cvtColor(h_edge, h_imagec, COLOR_GRAY2BGR);

    Mat h_imageg = h_imagec.clone();
    vector<Vec4i> h_lines;
    {
        const int64 start = getTickCount();
        HoughLinesP(h_edge, h_lines, 1, CV_PI / 180, 50, 60, 5);
        const double time_elapsed = (getTickCount() - start) / getTickFrequency();
        cout << "CPU Time : " << time_elapsed * 1000 << " ms" << endl;
        cout << "CPU FPS : " << (1 / time_elapsed) << endl;
    }

    for (size_t i = 0; i < h_lines.size(); ++i)
    {
        Vec4i line_point = h_lines[i];
        line(h_imagec, Point(line_point[0], line_point[1]), Point(line_point[2], line_point[3]), Scalar(0, 0, 255), 2, LINE_AA);
    }

    GpuMat d_edge, d_lines;
    d_edge.upload(h_edge);
    {
        const int64 start = getTickCount();
        Ptr<cuda::HoughSegmentDetector> hough = cuda::createHoughSegmentDetector(1.0f, (float)(CV_PI / 180.0f), 50, 5);
        hough->detect(d_edge, d_lines);

        const double time_elapsed = (getTickCount() - start) / getTickFrequency();
        cout << "GPU Time : " << time_elapsed * 1000 << " ms" << endl;
        cout << "GPU FPS : " << (1 / time_elapsed) << endl;
    }
    //取出直线两个点
    vector<Vec4i> lines_g;
    if (!d_lines.empty())
    {
        lines_g.resize(d_lines.cols);
        Mat h_lines(1, d_lines.cols, CV_32SC4, &lines_g[0]);
        d_lines.download(h_lines);
    }
    for (size_t i = 0; i < lines_g.size(); ++i)
    {
        Vec4i line_point = lines_g[i];
        line(h_imageg, Point(line_point[0], line_point[1]), Point(line_point[2], line_point[3]), Scalar(0, 0, 255), 2, LINE_AA);
    }

    imshow("source", h_image);
    imshow("detected lines [CPU]", h_imagec);
    imshow("detected lines [GPU]", h_imageg);
    imwrite("hough_source.png", h_image);
    imwrite("hough_cpu_line.png", h_imagec);
    imwrite("hough_gpu_line.png", h_imageg);

    waitKey(0);

    return 0;
}

3. 对圆形进行检测

  • 球检测或者硬币检测
  • 圆检测函数解析:
cpp 复制代码
/*
cv::cuda::createHoughCirclesDetector 参数
第一个参数是dp,表示累加器分辨率与图像分辨率的反比
第二个参数是检测到的圆中心之间的最小距离,调小会检测出其他错误圆,调大则可能丢失圆
第三个参数是Canny 阈值
第四个参数是累加器阈值
第五个和第六个参数是要检测的圆的最小和最大半径,不确定可以取0
*/
cv::Ptr<cv::cuda::HoughCirclesDetector> detector = 
cv::cuda::createHoughCirclesDetector(1, 100, 122, 50, 1, max(h_image.size().width, h_image.size().height));
  • 算法实现如下:
cpp 复制代码
#include <iostream>
#include "opencv2/opencv.hpp"
#include<opencv2/cudaimgproc.hpp>

using namespace cv;
using namespace std;


int main(int argc, char** argv)
{
    Mat h_image = imread("images/eight.tif", IMREAD_COLOR);
    Mat h_gray;
    cvtColor(h_image, h_gray, COLOR_BGR2GRAY);
    cuda::GpuMat d_gray, d_result;
    std::vector<cv::Vec3f> d_Circles;
    medianBlur(h_gray, h_gray, 5);
    cv::Ptr<cv::cuda::HoughCirclesDetector> detector = cv::cuda::createHoughCirclesDetector(1, 100, 122, 50, 1, max(h_image.size().width, h_image.size().height));
    d_gray.upload(h_gray);
    detector->detect(d_gray, d_result);
    d_Circles.resize(d_result.size().width);
    if (!d_Circles.empty())
        d_result.row(0).download(cv::Mat(d_Circles).reshape(3, 1));

    cout << "No of circles: " << d_Circles.size() << endl;
    for (size_t i = 0; i < d_Circles.size(); i++)
    {
        Vec3i cir = d_Circles[i];
        circle(h_image, Point(cir[0], cir[1]), cir[2], Scalar(255, 0, 0), 2, LINE_AA);
    }
    imshow("detected circles", h_image);
    waitKey(0);

    return 0;
}
相关推荐
李加号pluuuus1 小时前
【扩散模型】LCM LoRA:一个通用的Stable Diffusion加速模块
人工智能·stable diffusion
Alkali!2 小时前
2-5 softmax 回归的简洁实现
人工智能·数据挖掘·回归
LabVIEW开发3 小时前
LabVIEW图像分段线性映射
计算机视觉·labview·labview开发
哥廷根数学学派4 小时前
基于Maximin的异常检测方法(MATLAB)
开发语言·人工智能·深度学习·机器学习
xrgs_shz4 小时前
人工智能、机器学习、神经网络、深度学习和卷积神经网络的概念和关系
人工智能·深度学习·神经网络·机器学习·卷积神经网络
FutureUniant4 小时前
GitHub每日最火火火项目(7.7)
python·计算机视觉·ai·github·视频
zzyincsdn5 小时前
从FasterTransformer源码解读开始了解大模型(2.1)代码通读03
人工智能·llm·fastertransform
dc爱傲雪和技术5 小时前
相机参数与图像处理技术解析
图像处理·人工智能·数码相机
QQ21696368816 小时前
Hi6602 恒压恒流SSR电源方案
人工智能·硬件架构·硬件工程·信息与通信·智能硬件
wodertianna6 小时前
机器学习原理之 -- 神经网络:由来及原理详解
人工智能·神经网络·机器学习