【计算机视觉系列实战教程 (实战03)】:提取两点之间的边缘点

1、目的

图像中任意两点(起点到终点)之间,提取由深色到浅色(或由浅色到深色)的第一个边缘点。这样有利于精确地提取指定区域内的图像边缘。

经实践证明:本算法能够有效地定位两点之间的边缘信息,在实际工程中只需修改候选边缘点的筛选即可。

2、实践步骤

(1)拟合直线

将两点之间的连续坐标提取出来存储在vector容器中

/* 向量之间的直线点拟合,获取起点到终点所在直线的所有坐标点(有序:从起点到终点) */
int GetLinePntsByVec(const cv::Point &PStart,
					const cv::Point &PEnd, 
					std::vector<cv::Point> &vPtsLine)
{
	//vPtsLine用于存放从起点到终点的连续坐标
	vPtsLine.push_back(PStart);
	double dDis = 
		cv::sqrt(cv::pow(PStart.x-PEnd.x,2) + cv::pow(PStart.y-PEnd.y, 2) );//向量的长度
	if(dDis = 0 )
	{
		return -1;
	}
	int iN = std::max(std::abs(PStart.x-PEnd.x),std::abs(PStart.y-PEnd.y));
	vPtsLine.reserve(iN); //直线点的数量
	double dDeta = dDis / iN; //取样步长
	cv::Vec2d v0 = cv::Vec2d(PEnd.x-PStart.x, PEnd.y-PStart.y) / dDis; //两点之间的单位向量
	for(int i = 1; i<iN; ++i)
	{
		vPtsLine.push_back(
			cv::Point(
				cvRound(double(vPtsLine[0].x)+i*dDeta*v0[0]),
				cvRound(double(vPtsLine[0].y)+i*dDeta*v0[1])
			)
		);
	}
	return 1;
}

(2)求直线所在像素点的梯度

计算直线上每一个像素点的梯度值

int GetGradFrmLine(const cv::Mat &imGrayBorder, 
				const std::vector<cv::Point> &vPtsLine,
				std::vector<double>& vGradLine)
{	
	//遍历直线上的像素,并得到每个像素的梯度(方向梯度)
	cv::Mat kernel_x = (cv::Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
	 cv::Mat kernel_y = (cv::Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
	 int iResX = 0;
	 int iResY = 0;
	 for (auto& pt : vPtsLine)
	 {
	     iResX = filter2D_Signal(imGrayBorder, pt, kernel_x);
	     iResY = filter2D_Signal(imGrayBorder, pt, kernel_y);
	     double dRes = cv::Vec2d(iResX, iResY).dot(v0); //得到直线上当前点方向梯度值
	     vGradLine.push_back(abs(dRes));
	 }
	 if(vGradLine.empty())
	 {
	 	return -1;
	 }
	 return 1;
}

(3)根据直线上的方向梯度值得到边缘点

筛选最佳的点作为直线经过的边缘点

本函数将梯度最大的值作为提取的结果,用户可根据自己的实际需求修改:


inline bool myCompareSec(const std::pair<int, double>& a, const std::pair<int, double>& b)
{
    return a.second > b.second;
}

inline bool myCompareFir(const std::pair<int, double>& a, const std::pair<int, double>& b)
{
    return a.first < b.first;
}

int GetEdgPntFrmLine(
	const cv::Mat &imGrayBorder, 
	cv::Point &PStart, 
	cv::Point &PEnd,
	cv::Point &Edg,
	bool bWhtToBlk)
{
	std::vector<cv::Point> vPntsLine;
	//直线拟合得到点集合vPntsLine
	GetLinePntsByVec(PStart, PEnd, vPntsLine);
	//计算直线上每一个像素点的梯度
	std::vector<double> vGradLine;
	GetGradFrmLine(imGrayBorder, vPtsLine,vGradLine);
	//对梯度值进行排序,并跟踪索引
	std::vector<std::pair<int, double>> vIdxGrad;
	for (int i = 0; i < vSobel.size(); ++i)
	{
	    vIdxGrad.push_back(std::pair<int, double>(i, vSobel[i]));
	}
	std::sort(vIdxGrad.begin(), vIdxGrad.end(), myCompareSec);
	//对梯度最大的诺干个点进行筛选(作为候选边缘点)
    std::vector<int> vIdxMax;
    for (int i = 0; i < std::max(int(vIdxSobel.size() / 15), 30); ++i)
    {
        if (i == 0) vIdxMax.push_back(vIdxGrad[0].first);
        else
        {
            int iCnt = 0;
            for (const int& idx : vIdxMax)
            {
                if (abs(idx - vIdxGrad[i].first) > 10) 
                    iCnt++;
            }
            if (iCnt == vIdxMax.size()) {
                if (vIdxGrad[i].second > 40.0)
                {
                    vIdxMax.push_back(vIdxGrad[i].first);
                }
            }
        }
    }
    std::sort(vIdxMax.begin(), vIdxMax.end());
	//这里的实例将梯度最大的点作为边缘点(可更具实际需求处理这些候选点)
	PEdg = vPtsLine[vIdxMax[vIdxMax.size()-1]];
	return 1;

	
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智能文档革新:合合信息智能文档处理平台上线基金合同抽取模型!

一、什么是基金合同&#xff1f; 基金合同是指具有平等地位主体的基金当事人在基金活动中&#xff0c;为规范其间的权利、义务&#xff0c;依意思表示一致而形成的契约或协议。《证券投资基金法》第五十二条规定&#xff0c;公开募集基金的基金合同应当包括下列内容: &#x…

软件游戏d3dcompiler_43.dll丢失怎么办,总结几种有效的方法

在使用电脑时&#xff0c;可能会碰到找不到d3dcompiler_43.dll的问题。即在使用过程中&#xff0c;突然弹出一个提示“d3dcompiler_43.dll丢失”&#xff0c;由于此文件的缺失&#xff0c;部分程序将无法启动。为恢复正常使用&#xff0c;我们需要修复此文件。接下来&#xff0…

【C++】 解决 C++ 语言报错:Undefined Reference

文章目录 引言 未定义引用&#xff08;Undefined Reference&#xff09;是 C 编程中常见的错误之一&#xff0c;通常在链接阶段出现。当编译器无法找到函数或变量的定义时&#xff0c;就会引发未定义引用错误。这种错误会阻止生成可执行文件&#xff0c;影响程序的正常构建。本…

Java项目:基于SSM框架实现的中小企业人力资源管理系统【ssm+B/S架构+源码+数据库+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的中小企业人力资源管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简…

matlab 绘制高等数学中的二维函数示例

matlab 绘制高等数学中的二维函数示例 绘制高等数学中的二维函数示例绘制结果 绘制高等数学中的二维函数示例 clc,clear,close all; % 定义方程 eqn (x, y) (x.^2 y.^2).^3 - y.^4;% 绘制方程曲线和坐标轴 ezplot(eqn, [-2, 2, -2, 2]) hold on % 在同一图形中保持绘图% 绘…

国际上备考所有云计算/IT证书的五大优质免费课程网站

最近越来越多的小伙伴来问小李哥&#xff0c;小李哥亚马逊云科技AWS认证大满贯是在哪里上课复习的呢&#xff1f;全部上付费课程那不是一笔巨款吗&#xff1f;小李哥这次来盘点备考国际上IT证书的5大优质免费课程网站(不只是亚马逊云科技AWS的课程&#xff0c;其他课程同样可以…

满足GMSL静电防护要求的方案

什么是GMSL&#xff1f;它是做什么用的&#xff1f;它有什么优点&#xff1f;设计GMSL防静电有啥难度&#xff1f; 带着这些疑问我们先了解下什么是GMSL。 一&#xff0e;简述 GMSL GMSL&#xff08;Gigabit Multimedia Serial Link&#xff09;即千兆多媒体串行链路&#xf…

odoo 物联网 设备数据采集方案

图一 架构手稿(许老师专属) 图二 架构简图 部署 方案一&#xff1a; odoo业务数据库与设备采集数据库使用一个instance。 缺点&#xff1a;重启pg服务相互影响。 方案二&#xff1a; odoo业务数据库与设备采集数据库独立部署&#xff0c;使用两个instance。 优点&#xff1a;…

一个使用率超高的大数据实验室是如何练成的?

厦门大学嘉庚学院“大数据应用实训中心”&#xff08;以下简称“实训中心”&#xff09;自2022年建成以来&#xff0c;已经成为支撑“大数据专业”复合型人才培养的重要支撑&#xff0c;目前实训中心在专业课程实验教学、项目实训、数据分析类双创比赛、毕业设计等方面都有深入…

CVPR2024自动驾驶轨迹预测方向的论文整理

2024年自动驾驶轨迹预测方向的论文汇总 1、Producing and Leveraging Online Map Uncertainty in Trajectory Prediction 论文地址&#xff1a;https://arxiv.org/pdf/2403.16439 提出针对在线地图不确定性带给轨迹预测的影响对应的解决方案。 在轨迹预测中&#xff0c;利用在…

vscode连接SSH——连接学校服务器,使用conda配置个人环境并使用

服务器的连接 在vscode远程资源管理中配置配置文件&#xff0c;如下图&#xff1a; 然后点击左下角进行连接&#xff1a; 点击需要连接的服务器&#xff0c;输入对应密码即可登录成功。 服务器上创建自己的环境 确保服务器上已安装anaconda。 先查看服务器上的conda信息&…

Linux_共享内存通信

目录 1、共享内存原理 2、申请共享内存 2.1 ftok 2.2 测试shmget、ftok 2.3 查看系统下的共享内存 3、关联共享内存 3.1 测试shmat 4、释放共享内存 4.1 测试shmctl 5、实现共享内存通信 6、共享内存的特性 结语 前言&#xff1a; 在Linux下&#xff0c;有一…

jenkins在使用pipeline时,为何没有方块形视图

项目场景&#xff1a; 安装完Jenkins时后&#xff0c;通过pipeline创建的项目任务。 问题描述 在立即构建后&#xff0c;没有显示每个阶段的视图。 原因分析&#xff1a; 原因是&#xff0c;刚安装的Jenkins&#xff0c;这个视图不是Jenkins自带的功能&#xff0c;而必须安装…

Cannot resolve symbol ‘log`

idea里的代码log变红色&#xff0c;是因为缺少Lombok插件。 安装lombok插件即可。安装完应用&#xff0c;重启软件就好了。 依次点击菜单栏中的 File → Settings&#xff08;Windows/Linux&#xff09; 或 IntelliJ IDEA → Preferences&#xff08;macOS&#xff09;。在设置…

设计模式探索:单例模式

1. 什么是单例模式? 定义: 单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一种全局访问点以访问该实例。常见的场景包括身份证号码、政府等需要唯一实例的情况。 单例模式通常用于那些需要在应用程序中仅存在一个实例的情况,例如配置管理器、线程池、数据…

ret2syscall简单总结

主要是自己的简单的学习总结。 知识点 关于系统调用如何传递参数问题&#xff0c;即系统调用约定&#xff08;syscall&#xff0c;int 80h&#xff0c;svc&#xff09;_int 80h intel汇编用法-CSDN博客 ret2syscall的做题思路&#xff08;以32位程序为例&#xff09; - ZikH…

2024年【山东省安全员A证】考试试卷及山东省安全员A证考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 山东省安全员A证考试试卷根据新山东省安全员A证考试大纲要求&#xff0c;安全生产模拟考试一点通将山东省安全员A证模拟考试试题进行汇编&#xff0c;组成一套山东省安全员A证全真模拟考试试题&#xff0c;学员可通过…

react 项目中预防xss攻击的插件 dompurify

一、安装 $ yarn add dompurify $ yarn add --dev types/dompurify 二、使用 import DOMPurify from dompurify;// 1、处理&#xff1a; DOMPurify.sanitize(htmlContent)// 2、之后放进 dangerouslySetInnerHTML dangerouslySetInnerHTML{{ __html: cleanHTML }} 如&#…

Django自动生成Swagger接口文档 —— Python

1. 前言 当接口开发完成&#xff0c;紧接着需要编写接口文档。传统的接口文档通常都是使用Word或者一些接口文档管理平台进行编写&#xff0c;但此类接口文档维护更新比较麻烦&#xff0c;每次接口有变更&#xff0c;需要手动修改接口文档。在实际的工作中&#xff0c;经常会遇…