【QtOpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContoursdrawContours】

本文主要是介绍【QtOpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContoursdrawContours】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、函数介绍
    • 1、HoughLinesP
    • 2、HoughCircles
    • 3、findContours
    • 4、 drawContours
  • 二、演示
    • 1、GUI
    • 2、代码实现
  • 总结


前言

越来越多的开发人员选择基于开源的Qt框架与OpenCV来实现界面和算法,其原因不单单是无版权问题,更多是两个社区的发展蓬勃,可用来学习的资料与例程特别丰富。以下是关于利用Qt构建GUI并使用OpenCV中的HoughLinesP/HoughCircles/findContours&drawContours函数进行图像检测。
软件版本:Qt-5.12.0/OpenCV-4.5.3
平台:Windows10/11–64


一、函数介绍

1、HoughLinesP

函数原型
cv::HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )

参数解释
image:输入图像,即源图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后,再填在这里;
Iines:经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是是每个检测到的线段的结束点;
rho:以像素为单位的距离精度。另一种形容方式是直线搜索时的进步尺寸的单位半径;
theta:以弧度为单位的角度精度。另一种形容方式是直线搜索时的进步尺寸的单位角度;
threshold:累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中;
minLineLength:有默认值0,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来;
maxLineGap:有默认值0,允许将同一行点与点之间连接起来的最大的距离;

2、HoughCircles

函数原型
cv::HoughCircles(InputArray image,OutputArray circles, int method, double dp, double minDist, double param1=100,double param2=100, int minRadius=0, int maxRadius=0 )

参数解释
image输入图像,即源图像,需为8位的灰度单通道图像;
circles:经过调用HoughCircles函数后此参数存储了检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x, y, radius)表示;
method:即使用的检测方法,目前OpenCV中就霍夫梯度法一种可以使用,它的标识符为CV_HOUGH_GRADIENT,在此参数处填这个标识符即可;
dp:用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。上述文字不好理解的话,来看例子吧。例如,如果dp= 1时,累加器和输入图像具有相同的分辨率。如果dp=2,累加器便有输入图像一半那么大的宽度和高度;
minDist:为霍夫变换检测到的圆的圆心之间的最小距离,即让我们的算法能明显区分的两个不同圆之间的最小距离。这个参数如果太小的话,多个相邻的圆可能被错误地检测成了一个重合的圆。反之,这个参数设置太大的话,某些圆就不能被检测出来了;
param1:有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半;
param2:也有默认值100。它是第三个参数method设置的检测方法的对应的参数。对当前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在检测阶段圆心的累加器阈值。它越小的话,就可以检测到更多根本不存在的圆,而它越大的话,能通过检测的圆就更加接近完美的圆形了;
minRadius:有默认值0,表示圆半径的最小值;
maxRadius:也有默认值0,表示圆半径的最大值;

3、findContours

函数原型:
cv::findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy,
int mode, int method, Point offset = Point());

参数解释
image:单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;
contours:contours定义为“vector contours”,是一个双重向量(向量内每个元素保存了一组由连续的Point构成的点的集合的向量),每一组点集就是一个轮廓,有多少轮廓,contours就有多少元素;
hierarchy:hierarchy定义为“vector hierarchy”,Vec4i的定义:typedef Vec<int, 4> Vec4i;(向量内每个元素都包含了4个int型变量),所以从定义上看,hierarchy是一个向量,向量内每个元素都是一个包含4个int型的数组。向量hierarchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。hierarchy内每个元素的4个int型变量是hierarchy[i][0] ~ hierarchy[i][3],分别表示当前轮廓 i 的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓的编号索引。如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓,则相应的hierarchy[i][*]被置为-1。
mode:定义轮廓的检索模式,取值如下:

CV_RETR_EXTERNAL:只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略;
CV_RETR_LIST:检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到;
CV_RETR_CCOMP: 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层;
CV_RETR_TREE: 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。

method:定义轮廓的近似方法,取值如下:

CV_CHAIN_APPROX_NONE:保存物体边界上所有连续的轮廓点到contours向量内;
CV_CHAIN_APPROX_SIMPLE:仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留;
CV_CHAIN_APPROX_TC89_L1:使用teh-Chinl chain 近似算法;
CV_CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain 近似算法。

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

4、 drawContours

函数原型
cv::drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar & color, int thickness = 1, int lineType = LINE_8, InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point())

参数解释
image:目标图像
contours:输入的所有轮廓(每个轮廓以点集的方式存储)
contoursIdx:指定绘制轮廓的下标(若为负数,则绘制所有轮廓)
color:绘制轮廓的颜色
thickness:绘制轮廓的线的宽度(若为负数,则填充轮廓内部)
lineType:绘制轮廓的线型(4连通、8连通或者反锯齿)
hierarchy:关于层级的可选信息,仅用于当你想要绘制部分轮廓的时候
maxLevel:绘制轮廓的最大层级,若为0,则仅仅绘制指定的轮廓;若为1,则绘制该轮廓及其内嵌轮廓,若为2,则绘制该轮廓、其内嵌轮廓以及内嵌轮廓的内嵌轮廓,依次类推。该参数只有在有层级信息输入时才被考虑。
offset:可选的轮廓偏移参数,所有的轮廓将会进行指定的偏移

当thickness = FILLED,即使没有提供层级信息也可以正确处理带孔洞的连通域情况(分析轮廓时采用奇偶规则),但如果是单独检索的轮廓合并则可能会出现错误的情况,该情况下则需要分开处理。

二、演示

1、GUI

在这里插入图片描述
如上图创建Operator的QComboBox控件进行函数选择,Action的功能按钮QPushButton,对当前窗口进行检测,并输出状态信息。

2、代码实现

HoughLinesP/HoughCircles/findContours&drawContours实现代码:
geometryBtn的clicked()槽函数

void MainWindow::on_geometryBtn_clicked()
{std::size_t numView = ui->tabWidget->currentIndex() % 3;if (dispMat[numView]->empty()){outputInfo(2, tr("Please make sure the Mat exist!"));return;}if (dispMat[numView]->channels() == 3){cv::cvtColor(*dispMat[numView], *dispMat[numView], cv::COLOR_RGB2GRAY);}tmpMat->zeros(dispMat[numView]->size(), \dispMat[numView]->type());cv::GaussianBlur(*dispMat[numView], *dispMat[numView], cv::Size(3, 3), \0, 0, cv::BORDER_DEFAULT);int operatorType = ui->geometryCombo->currentIndex();	// 0: line, 1: circle, 2: contoursswitch (operatorType){case 0:{int cannyThresh = ui->cannyThreshSlider->value();int lineThresh = ui->lineThreshSlider->value();std::vector<cv::Vec4i> lines;cv::Canny(*dispMat[numView], *tmpMat, cannyThresh, \cannyThresh * 2, 3);cv::HoughLinesP(*tmpMat, lines, 1, CV_PI/180, lineThresh, 50, 10);for (size_t i = 0; i < lines.size(); i++){cv::Vec4i l = lines[i];cv::line(*tmpMat, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), \cv::Scalar(0, 0, 255), 1, 1, 1);}outputInfo(1, tr("Lines done."));break;}case 1:{int circleThresh = ui->circleThreshSlider->value();std::vector<cv::Vec3f> circles;double startTime = static_cast<double>(cv::getTickCount());cv::HoughCircles(*dispMat[numView], circles, cv::HOUGH_GRADIENT, \1, dispMat[numView]->rows / 16, \circleThresh, circleThresh/2, \0, 0);double timeCost = (static_cast<double>(cv::getTickCount()) - \startTime) / cv::getTickFrequency();QString costTime = "Cost time: " + QString::number(timeCost);outputInfo(1, costTime);for (size_t i = 0; i < circles.size(); i++){cv::Point center(cvRound(circles[i][0]), \cvRound(circles[i][1]));int radius = cvRound(circles[i][2]);cv::circle(*tmpMat, center, 3, \cv::Scalar(0, 255, 0), -1, 8, 0);cv::circle(*tmpMat, center, radius, \cv::Scalar(0, 0, 255), 3, 8, 0);}outputInfo(1, tr("Circles done."));break;}case 2:{cv::RNG rng(12345);int cannyThresh = ui->cannyThreshSlider->value();cv::Canny(*dispMat[numView], *tmpMat, cannyThresh, \cannyThresh * 2, 3);std::vector<std::vector<cv::Point>> contours;std::vector<cv::Vec4i> hierarchy;cv::findContours(*tmpMat, contours, hierarchy, \cv::RETR_TREE, \cv::CHAIN_APPROX_SIMPLE, \cv::Point(0, 0));std::vector<std::vector<cv::Point>> contoursPoly(contours.size());std::vector<cv::Rect> boundRect(contours.size());std::vector<cv::Point2f> center(contours.size());std::vector<float> radius(contours.size());for (size_t i = 0; i < contours.size(); i++){cv::approxPolyDP(cv::Mat(contours[i]), contoursPoly[i], 3, true);boundRect[i] = cv::boundingRect(cv::Mat(contoursPoly[i]));minEnclosingCircle(contoursPoly[i], center[i], radius[i]);}for (size_t i = 0; i < contours.size(); i++){cv::Scalar color = cv::Scalar(rng.uniform(0, 255), \rng.uniform(0, 255), \rng.uniform(0, 255));cv::drawContours(*tmpMat, contoursPoly, static_cast<int>(i), \color, 1, 8, \std::vector<cv::Vec4i>(), 0, \cv::Point());cv::rectangle(*tmpMat, boundRect[i].tl(), \boundRect[i].br(), \color, 2, 8, 0);cv::circle(*tmpMat, center[i], static_cast<int>(radius[i]), \color, 2, 8, 0);}outputInfo(1, tr("Contours done."));break;}}if (ui->geometryChkBox->isChecked()){*dispMat[numView] = tmpMat->clone();cvtMatPixmap(dispMat, dispPixmap, numView);}else{if (tmpMat->channels() == 3){QImage tmpImage = QImage(tmpMat->data, tmpMat->cols,tmpMat->rows, \static_cast<int>(tmpMat->step), \QImage::Format_RGB888);dispPixmap[numView]->setPixmap(QPixmap::fromImage(tmpImage.rgbSwapped()));}else{QImage tmpImage = QImage(tmpMat->data, tmpMat->cols,tmpMat->rows, \static_cast<int>(tmpMat->step), \QImage::Format_Grayscale8);dispPixmap[numView]->setPixmap(QPixmap::fromImage(tmpImage.rgbSwapped()));}}
}

总结

以上是关于利用Qt进行GUI构建并使用OpenCV中的 HoughLinesP/HoughCircles/findContours&drawContours函数进行图像检测。
参考:
链接:前期https://blog.csdn.net/richard_yuu/article/details/128037970
其中疑问或错误,欢迎联系交流,

这篇关于【QtOpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContoursdrawContours】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/richard_yuu/article/details/128093291
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/179075

相关文章

C++ 检测文件大小和文件传输的方法示例详解

《C++检测文件大小和文件传输的方法示例详解》文章介绍了在C/C++中获取文件大小的三种方法,推荐使用stat()函数,并详细说明了如何设计一次性发送压缩包的结构体及传输流程,包含CRC校验和自动解... 目录检测文件的大小✅ 方法一:使用 stat() 函数(推荐)✅ 用法示例:✅ 方法二:使用 fsee

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)

《使用Python和Matplotlib实现可视化字体轮廓(从路径数据到矢量图形)》字体设计和矢量图形处理是编程中一个有趣且实用的领域,通过Python的matplotlib库,我们可以轻松将字体轮廓... 目录背景知识字体轮廓的表示实现步骤1. 安装依赖库2. 准备数据3. 解析路径指令4. 绘制图形关键

Python中OpenCV与Matplotlib的图像操作入门指南

《Python中OpenCV与Matplotlib的图像操作入门指南》:本文主要介绍Python中OpenCV与Matplotlib的图像操作指南,本文通过实例代码给大家介绍的非常详细,对大家的学... 目录一、环境准备二、图像的基本操作1. 图像读取、显示与保存 使用OpenCV操作2. 像素级操作3.

C/C++的OpenCV 进行图像梯度提取的几种实现

《C/C++的OpenCV进行图像梯度提取的几种实现》本文主要介绍了C/C++的OpenCV进行图像梯度提取的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录预www.chinasem.cn备知识1. 图像加载与预处理2. Sobel 算子计算 X 和 Y

c/c++的opencv图像金字塔缩放实现

《c/c++的opencv图像金字塔缩放实现》本文主要介绍了c/c++的opencv图像金字塔缩放实现,通过对原始图像进行连续的下采样或上采样操作,生成一系列不同分辨率的图像,具有一定的参考价值,感兴... 目录图像金字塔简介图像下采样 (cv::pyrDown)图像上采样 (cv::pyrUp)C++ O

Python+wxPython构建图像编辑器

《Python+wxPython构建图像编辑器》图像编辑应用是学习GUI编程和图像处理的绝佳项目,本教程中,我们将使用wxPython,一个跨平台的PythonGUI工具包,构建一个简单的... 目录引言环境设置创建主窗口加载和显示图像实现绘制工具矩形绘制箭头绘制文字绘制临时绘制处理缩放和旋转缩放旋转保存编

python+OpenCV反投影图像的实现示例详解

《python+OpenCV反投影图像的实现示例详解》:本文主要介绍python+OpenCV反投影图像的实现示例详解,本文通过实例代码图文并茂的形式给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录一、前言二、什么是反投影图像三、反投影图像的概念四、反向投影的工作原理一、利用反向投影backproj

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

使用Python实现图像LBP特征提取的操作方法

《使用Python实现图像LBP特征提取的操作方法》LBP特征叫做局部二值模式,常用于纹理特征提取,并在纹理分类中具有较强的区分能力,本文给大家介绍了如何使用Python实现图像LBP特征提取的操作方... 目录一、LBP特征介绍二、LBP特征描述三、一些改进版本的LBP1.圆形LBP算子2.旋转不变的LB