[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;
}
相关推荐
liruiqiang05几秒前
机器学习 - 衡量模型的特性
人工智能·机器学习
thinkMoreAndDoMore10 分钟前
深度学习(3)-TensorFlow入门(梯度带)
人工智能·深度学习·tensorflow
Dream251216 分钟前
【Transformer架构】
人工智能·深度学习·transformer
黎智程17 分钟前
AI助力小微企业技术开发规范化管理 | 杂谈
人工智能
web1508541593540 分钟前
超级详细Spring AI运用Ollama大模型
人工智能·windows·spring
啊哈哈哈哈哈啊哈哈42 分钟前
J4打卡—— ResNet 和 DenseNet结合实现鸟类分类
人工智能·pytorch·分类
alden_ygq1 小时前
Ollama API 交互
人工智能·交互
小刘私坊1 小时前
机器梦境:AI如何在创意的狂野边疆上重塑艺术
人工智能
香橙薄荷心1 小时前
人工智能之自动驾驶技术体系
人工智能·机器学习·自动驾驶
孤寂大仙v1 小时前
深度学习入门:从零开始理解神经网络
人工智能·深度学习·神经网络