Qt+Opencv:基于Hough变换的直线检测

news2025/6/7 23:04:54

一、开场引言

在工业机器视觉领域,有很多直线检测和计算角度的应用场景。如下图,需要进行晶圆的粗对位校正:
在这里插入图片描述
此时需要计算出图像中的近似水平切割道的线条与实际水平线的夹角,从而进行晶圆的位置校正。在这个场景下,Hough变换就派上用场了。

二、认识Hough变换

2.1 Hough变换

Hough变换是一种图像处理技术,用于检测图像中的直线、圆或其他形状。它的基本原理是将图像空间中的特定形状映射到参数空间中,并在参数空间中进行累加,以找到图像中的特定形状。
优点:

  • 对噪声具有一定的鲁棒性,能够在一定程度上抵抗图像中的噪声。
  • 可以检测多种形状,包括直线、圆等。
    缺点:
  • 计算复杂度高,特别是对于大型图像和复杂形状的检测。
  • 对参数空间的离散化和累加需要大量的内存和计算资源。

2.2 概率Hough变换

概率Hough变换是对标准Hough变换的改进,通过随机地选择图像中的像素点来进行累加,从而减少计算量。
优点:

  • 计算量相对较小,适用于大型图像和复杂形状的检测。
  • 对于一些特定的应用场景,如检测长直线,概率Hough变换通常比标准Hough变换更有效。
    缺点:
  • 对于某些形状的检测可能不够精确,特别是在图像中存在大量噪声或形状重叠的情况下。
    比较
  • Hough变换适用于对图像中各种形状的检测,但计算复杂度高。
  • 概率Hough变换通过随机采样来减少计算量,适用于大型图像和复杂形状的检测,但可能牺牲一定的精度。

总的来说,选择使用Hough变换还是概率Hough变换取决于具体的应用场景和对计算效率和检测精度的要求。

三、示例

仍以引言中的图像作为示例,我们在这里作为晶圆级的粗对位,采用概率hough变换即可。代码示例如下:

#ifndef HOUGHLINESDEMO_H
#define HOUGHLINESDEMO_H
class HoughLinesDemo
{
public:
    HoughLinesDemo();

    static int run();
};

#endif // HOUGHLINESDEMO_H
#include "houghlinesdemo.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <QDateTime>
#include <vector>
#include <algorithm>

HoughLinesDemo::HoughLinesDemo()
{

}

int HoughLinesDemo::run()
{

    // 读取图像
    cv::Mat image = cv::imread("image/large_field_1.png");
    // cv::Mat image = cv::imread("image/large_field.bmp");

    /// 将图像转为灰度图
    cv::Mat gray;
    cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

    // 使用Canny边缘检测
    cv::Mat edges;
    cv::Canny(gray, edges, 50, 150, 3);

    // 进行Probabilistic Hough Transform直线检测
    std::vector<cv::Vec4i> lines;
    cv::HoughLinesP(edges, lines, 1, CV_PI/180, 50, 50, 5);


    std::vector<double> angles;
    // 计算每条直线的斜率和与水平线的夹角
    for (size_t i = 0; i < lines.size(); i++) {
        cv::Vec4i l = lines[i];
        cv::line(image, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(0, 0, 255), 2);
        double angle = atan2(l[3] - l[1], l[2] - l[0]) * 180.0 / CV_PI;
        if(angle <= 0){
            angles.push_back(angle);
        }
        std::cout << "Angle with horizontal: " << angle << std::endl;
    }

    // 显示结果
    cv::imshow("Probabilistic Hough Transform", image);
    const QString time = QDateTime::currentDateTime().toString("yy-MM-dd hh-mm-ss");
    QString sImge = QString("result/%1.png").arg(time);
    cv::imwrite(sImge.toStdString(),image);

    // 对角度数据进行排序
    std::sort(angles.begin(), angles.end());

    // 计算中值
    double median;
    if (angles.size() % 2 == 0) {
        median = (angles[angles.size() / 2 - 1] + angles[angles.size() / 2]) / 2.0;
    } else {
        median = angles[angles.size() / 2];
    }
    std::cout << "Median angle: " << median << " degrees" << std::endl;


    // cv 旋转原图
    cv::Point2f center(image.cols / 2.0, image.rows / 2.0); // 旋转中心
    cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, median, 1.0); // 旋转矩阵
    cv::Mat rotatedImage;
    cv::warpAffine(image, rotatedImage, rotationMatrix, image.size());

    // 显示原始图像和旋转后的图像
    cv::imshow("Rotated Image", rotatedImage);

    do { }  while (cvWaitKey(30) < 0);
    cv::destroyAllWindows();

    return 0;
}

四、结果展示

在这里插入图片描述
我们在角度数据处理时,采用的中值计算的方式,误差也会比较大。
Median angle: -0.79298 degrees
可以看到原图及计算角度旋转校正之后的图像,图像有明显的校正,但是水平切割道依然不是完美的水平。将种植计算改为计算直方,将概率hough变换换为hough变换,精度定然会有明显提高。不过作为粗对位而言,实际现场基本够用~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1355377.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Go语言中处理HTTPS请求

随着互联网的发展&#xff0c;安全性变得越来越重要。HTTPS作为安全的HTTP协议&#xff0c;已经被广泛使用。在Go语言中&#xff0c;处理HTTPS请求需要一些特定的步骤。本文将详细介绍如何在Go语言中处理HTTPS请求。 首先&#xff0c;确保你已经安装了Go语言的开发环境&#x…

如何删除K8S中的Pod

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

『C++成长记』运算符重载

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;C &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、运算符重载 &#x1f4d2;1.1两个日期大小的比较 &#x1f4d2;1.2运算符重载…

高通guestOS与hostOS通信框架HAB源码分析——概述

1)什么是HAB&#xff0c;他用来干什么&#xff1f; 如果你了解virtIO的话&#xff0c;就很容易明白HAB是用来干什么的。一句话来说&#xff0c;HAB实际作用和virtIO差不多。以高通8155&#xff08;host qnxguest安卓&#xff09;为例&#xff0c;所有硬件外设驱动都在qnx端&am…

公众号文章如何提高阅读量?媒介盒子教你几招

公众号作为微信运营的主要载体&#xff0c;做得好就能让品牌得到大量曝光&#xff0c;公众号文章作为长文案想要写好还需要一定的技术&#xff0c;今天媒介盒子就来和大家聊聊公众号文章怎么写才能提高阅读量&#xff1a; 一、 内容干货满足读者求知欲 只要你的文章实用性强&…

LeetCode(31) 下一个排列

整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&#xf…

多线程基础入门【Linux】——下篇

目录 一&#xff0c;死锁 1. 死锁的必要条件 2&#xff0c;避免死锁 二&#xff0c;条件变量 同步概念与竞态条件 条件变量——初始化 静态初始化 动态初始化 pthread_cond_destroy (销毁) pthread_cond_wait (等待条件满足) pthread_cond_signal (唤醒线程) ph…

【AI】LoFTR图像匹配算法源码解析

0.LoFTR简介 Local Feature Transformers &#xff08;LoFTR&#xff09;是一种Detector-free的局部特征匹配方法&#xff0c;使用了具有自注意层和互注意层的Transformer模块来处理从卷积网络中提取的密集局部特征&#xff1a;首先在低特征分辨率&#xff08;图像维度的1/8&a…

mysql的读写分离

MySQL 读写分离原理 读写分离就是只在主服务器上写&#xff0c;只在从服务器上读。 主数据库处理事务性操作&#xff0c;而从数据库处理 select 查询。 数据库复制被用来把主数据库上事务性操作导致的变更同步到集群中的从数据库。 常见的mysql读写分离分为以下两种 1&…

网络安全—模拟IP代理隐藏身份

文章目录 网络拓扑安装使用代理服务器设置隐藏者设置 使用古老的ccproxy实现代理服务器&#xff0c;仅做实验用途&#xff0c;禁止做违法犯罪的事情&#xff0c;后果自负。 网络拓扑 均使用Windows Server 2003系统 Router 外网IP&#xff1a;使用NAT模式 IP DHCP自动分配或者…

【损失函数】Hinge Loss 合页损失

1、介绍 Hinge Loss&#xff08;合页损失&#xff09;通常用于支持向量机&#xff08;Support Vector Machine&#xff0c;SVM&#xff09;等模型中&#xff0c;特别是在二分类问题中。它的目标是使正确类别的分数与错误类别的最高分之间的差异达到一个固定的边界&#xff0c;从…

【代码随想录】刷题笔记Day45

前言 早上又赖了会床......早睡早起是奢望了现在&#xff0c;新一年不能这样&#xff01;支棱起来&#xff01; 377. 组合总和 Ⅳ - 力扣&#xff08;LeetCode&#xff09; 这一题用的就是完全背包排列数的遍历顺序&#xff1a;先背包再物品&#xff0c;从前往后求的也是有几…

RK3568驱动指南|第九篇 设备模型-第106章 为什么注册总线之前要先注册设备实例分析实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

OpenAI API/Plus会员信用卡绑定付款方式经历

前言 9月25日起ChatGPT风控升级&#xff0c;428813的卡只可以支付Open ai API-key&#xff0c;直接订阅plus会被拒。部分用户将卡绑定美区Google pay使用app store进行订阅可以成功&#xff0c;如果您没有这两种支付方式&#xff0c;请您重新开一张534786的万事达美卡升级订阅…

专题一:递推与递归

递归 例题 递归实现指数型枚举 从 1∼n这 n个整数中随机选取任意多个&#xff0c;输出所有可能的选择方案。 输入格式 输入一个整数 n。 输出格式 每行输出一种方案。 同一行内的数必须升序排列&#xff0c;相邻两个数用恰好 1 个空格隔开。 对于没有选任何数的方案&#xff0c…

【ModelScope】部署一个属于自己的AI服务

前言 技术栈是Fastapi。 FastAPI 是一个现代、快速&#xff08;基于 Starlette 和 Pydantic&#xff09;、易于使用的 Python web 框架&#xff0c;主要用于构建 RESTful API。以下是 FastAPI 的一些优势&#xff1a; 性能卓越&#xff1a; FastAPI 基于 Starlette 框架&…

GC4938 三相无刷直流电机预驱动芯片可替代A4938/allegro,外置MOS,具有低速降噪,宽电压工作的功能

GC4938 是一款三相无刷直流电机预驱 动芯片。芯片可以驱动 N 型功率 MOSFET&#xff0c; 最高电源到 36V。芯片状态切换逻辑受三个 相位差为 120的霍尔输入确定。 芯片集成固定衰减时间的脉冲调制来控 制电流并且抑制励磁涌流&#xff1b;堵转保护时间可 调&#xff1b;过温保护…

AIOps探索 | 基于大模型构建高效的运维知识及智能问答平台(2)案例分享

原作者&#xff1a;擎创科技产品专家 布博士 案例分享 所需要的软件列表 本次案例的实现&#xff0c;全部采用开源或SAAS的产品来提供&#xff0c;并不涉及到私有化部署的软件产品。软件列表如下所示&#xff0c;如何申请apikey请自行研究&#xff0c;在这里不再详细说明&…

Linux第3步_安装Ubuntu操作系统

创建好虚拟机后&#xff0c;就可以安装Ubuntu操作系统了。 1、双击“VMware Workstation Pro”&#xff0c;得到下面的界面。 2、点击“编辑虚拟机设置”&#xff0c;见下图&#xff1a; 3、等几秒钟&#xff0c;得到下面的界面&#xff1a; 4、点击“CD/DVD”&#xff0c;得到…

opencv入门到精通——Canny边缘检测

目录 理论 OpenCV中的Canny Edge检测 附加资源 在本章中&#xff0c;我们将学习 Canny边缘检测的概念 OpenCV函数: cv.Canny() 理论 Canny Edge Detection是一种流行的边缘检测算法。它由John F. Canny发明 1.这是一个多阶段算法&#xff0c;我们将经历每个阶段。 2.降…