OpenCV边缘提取算法流程的实现(附DEMO)

目录
  • 1. 具体算法流程
  • 2.流程图
  • 3. 涉及到的代码

在传统的计算机视觉领域,经常需要使用一些传统的图像处理算法完成对图像的边缘提取功能,通过对图像的边缘进行提取完成对目标对象的分割,目标分割技术又包括语义分割与实例分割,比较高端的鲁棒性较强的还是需要卷积神经网络算法进行相关的训练,如fcn全连接网络,mask-rcnn实例分割网络。本案例旨在采用传统的图像处理技术完成对图像的边缘检测任务,并通过膨胀腐蚀操作进行连通域的提取,之后通过连通域的填充以及掩膜操作完成目标对象的分割。

具体需要达到的目标如下:

上图所示,可以很好的将河道信息进行提取。

1. 具体算法流程

首先对采集的图片进行灰度化处理(方便进行数据处理),然后对灰度图像进行中值滤波操作去除湖面上的细小杂质,之后通过x方向和y方向上的Sobel梯度算子分别获取梯度图像,并将梯度图像转换成CV_8UC1类型,并对转换后的x,y方向上的梯度图像进行OTSU二值化操作获取二值图像,并对两幅二值图像按对应像素位置进行与运算,目的是为了去除河道上的波纹干扰。(可以继续对与运算之后的结果图进行中值滤波去除湖面上的细小杂质)。最后对二值图进行多次迭代的膨胀腐蚀操作以及小区域块的填充操作(用到findContours与drawContours接口进行轮廓查找与填充)获取河道连通区域。

2.流程图

可以通过如下流程图进行展示。

3. 涉及到的代码

int main() {
	Mat srcImage, srcImage2, srcImage3;
	for (int j = 1; j <= 172; j++)
	{
		//白天总共172张图片。1-172;验证:1,162,146;
		//(挑选最好的效果作为模板。对比108与117进行分析)。
		//if (j == 108 || j == 117)
		//{//对比分析之后选择第108张图片作为模板图片
		char ch[4096] = { 0 };
		sprintf(ch, "..\\findriveredge\\day\\2 (%d).jpg", j);
		srcImage = imread(ch, IMREAD_ANYCOLOR);
		srcImage2 = srcImage.clone();
		srcImage3 = srcImage.clone();
		if (srcImage.empty())
		{
			return -1;
		}
		if (srcImage.channels() == 3)
		{
			cvtColor(srcImage, srcImage, COLOR_BGR2GRAY);
		}

		Mat outImage;
		medianBlur(srcImage, outImage, g_nKrenel);//首先对灰度图进行中值滤波操作,去除一些杂质。

		Mat grad_x, abs_grad_x, grayImage_x;
		Sobel(outImage, grad_x, CV_16S, 1, 0, 3, 1, 1, BORDER_DEFAULT);
		convertScaleAbs(grad_x, abs_grad_x);
		abs_grad_x.convertTo(grayImage_x, CV_8U);

		Mat grad_y, abs_grad_y, grayImage_y;
		Sobel(outImage, grad_y, CV_16S, 0, 1, 3, 1, 1, BORDER_DEFAULT);
		convertScaleAbs(grad_y, abs_grad_y);
		abs_grad_y.convertTo(grayImage_y, CV_8U);

		Mat XBin, YBin;
		int n_thresh_x = myOtsu(grayImage_x);
		threshold(grayImage_x, XBin, n_thresh_x, 255, THRESH_BINARY);

		int n_thresh_y = myOtsu(grayImage_y);
		threshold(grayImage_y, YBin, n_thresh_y, 255, THRESH_BINARY);

		Mat Bin;
		bitwise_and(XBin, YBin, Bin);

		Mat outBin;
		medianBlur(Bin, outBin, 3);//去除一些杂质点。

		Mat outBin2 = outBin.clone();
		int n_iterations = 5;
		Mat element = getStructuringElement(MORPH_ELLIPSE, Size(15, 15));//膨胀变亮形成连通域。
		Mat element2 = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));//腐蚀操作断开一些连通域。
		dilate(outBin2, outBin2, element, Point(-1, -1), n_iterations);
		erode(outBin2, outBin2, element2, Point(-1, -1), 3);//腐蚀操作,断开河流区域内部的连接区域,方便后续的填充处理。

		//将河流ROI区域小块连通域填黑。
		Mat outBin3 = outBin2.clone();
		vector<vector<Point>> contours;
		vector<Vec4i> hie;
		findContours(outBin3, contours, hie, RETR_LIST, CHAIN_APPROX_SIMPLE);
		float f_area = 0.0;
		for (int i = 0; i < contours.size(); i++)
		{
			f_area = contourArea(contours[i]);
			if (f_area < 250000)
			{
				drawContours(outBin3, contours, i, Scalar(0), -1);
			}
		}

		//由于final bin2在腐蚀过程中存在部分背景区域为黑色空洞,需要将其填白。
		Mat outBin4_tmp = ~outBin3;
		Mat outBin4;
		contours.clear();
		hie.clear();
		findContours(outBin4_tmp, contours, hie, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
		for (unsigned int i = 0; i < contours.size(); i++)
		{
			f_area = contourArea(contours[i]);
			if (f_area < 250000)
			{
				drawContours(outBin4_tmp, contours, i, Scalar(0), -1);
			}
		}
		outBin4 = ~outBin4_tmp;

		//迭代腐蚀突出河流边界区域。
		erode(outBin4, outBin4, element, Point(-1, -1), 10);

		//(可以对腐蚀图在进行一次外轮廓填充)。
		Mat outBin5_tmp = ~outBin4.clone();
		Mat outBin5;
		contours.clear();
		hie.clear();
		findContours(outBin5_tmp, contours, hie, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
		for (unsigned int i = 0; i < contours.size(); i++)
		{
			f_area = contourArea(contours[i]);
			if (f_area < 100000)
			{
				drawContours(outBin5_tmp, contours, i, Scalar(0), -1);
			}
		}
		outBin5 = ~outBin5_tmp;

		//根据outBin4,对原rgb图取感兴趣区域(即河流区域)
		for (int i = 0; i < outBin5.rows; i++)
		{
			for (int j = 0; j < outBin5.cols; j++)
			{
				if (outBin5.at<uchar>(i, j) == 255)
				{
					srcImage2.at<Vec3b>(i, j)[0] = 0;
					srcImage2.at<Vec3b>(i, j)[1] = 0;
					srcImage2.at<Vec3b>(i, j)[2] = 0;
				}
			}
		}
		namedWindow("finalImage", 0);
		imshow("finalImage", srcImage2);//这里的srcImage2表示最后所需效果图

		cout << j << endl;
		waitKey(30);
	}
	return 0;
}

到此这篇关于OpenCV边缘提取算法流程的实现(附DEMO)的文章就介绍到这了,更多相关OpenCV 边缘提取内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python OpenCV 基于图像边缘提取的轮廓发现函数

    基础知识铺垫 在图像中,轮廓可以简单的理解为连接具有相同颜色的所有连续点(边界)的曲线,轮廓可用于形状分析和对象检测.识别等领域. 轮廓发现的原理:先通过阈值分割提取目标物体,再通过边缘检测提取目标物体轮廓. 一个轮廓就是一系列的点(像素),这些点构成了一个有序的点集合. 使用 cv2.findContours 函数可以用来检测图像的边缘. 函数原型说明 contours, hierarchy = cv2.findContours(image, mode, method[, contours[,

  • python+opencv边缘提取与各函数参数解析

    前情提要:作为刚入门机器视觉的小伙伴,第一节课学到机器视觉语法时觉得很难理解, 很多人家的经验,我发现都千篇一律,功能函数没解析,参数不讲解,就一个代码,所以在此将搜集的解析和案例拿出来汇总!!! 一.opencv+python环境搭建 其实能写python的就能写opencv,但是工具很总要,代码提示也很重要,你可能会用submit     vs等工具,submit编码个人觉得不够智能,vs的话过完年我学的方向不一致,所以没用 推荐 pycharm ,在项目setting中的项目解释器中安装

  • opencv python Canny边缘提取实现过程解析

    这篇文章主要介绍了opencv python Canny边缘提取实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Canny是边缘提取算法,在1986年提出的是一个很好的边缘检测器Canny算法介绍 非最大信号抑制: 高低阈值连接: example import cv2 as cv import numpy as np # canny运算步骤:5步 # 1. 高斯模糊 - GaussianBlur # 2. 灰度转换 - cvtCol

  • opencv3/C++图像边缘提取方式

    canny算子实现 使用track bar 调整canny算子参数,提取到合适的图像边缘. #include<iostream> #include<opencv2/opencv.hpp> using namespace cv; void trackBar(int, void*); int s1=0,s2=0; Mat src, dst; int main() { src = imread("E:/image/image/daibola.jpg"); if(src

  • OpenCV边缘提取算法流程的实现(附DEMO)

    目录 1. 具体算法流程 2.流程图 3. 涉及到的代码 在传统的计算机视觉领域,经常需要使用一些传统的图像处理算法完成对图像的边缘提取功能,通过对图像的边缘进行提取完成对目标对象的分割,目标分割技术又包括语义分割与实例分割,比较高端的鲁棒性较强的还是需要卷积神经网络算法进行相关的训练,如fcn全连接网络,mask-rcnn实例分割网络.本案例旨在采用传统的图像处理技术完成对图像的边缘检测任务,并通过膨胀腐蚀操作进行连通域的提取,之后通过连通域的填充以及掩膜操作完成目标对象的分割. 具体需要达到

  • 基于opencv和pillow实现人脸识别系统(附demo)

    目录 一.人脸检测和数据收集 二.训练识别器 三.人脸识别和显示 本文不涉及分类器.训练识别器等算法原理,仅包含对其应用(未来我也会写自己对机器学习算法原理的一些观点和了解) 首先我们需要知道的是利用现有框架做一个人脸识别系统并不难,然后就开始我们的系统开发吧. 我们的系统主要分为三个部分,然后我还会提出对补获图片不能添加中文的解决方案.我们需要完成的任务:1.人脸检测和数据收集2.训练识别器3.人脸识别和显示 在读此篇文章之前我相信你已经做了python环境部署和opencv模块的下载安装工作

  • Java基于redis和mysql实现简单的秒杀(附demo)

    一.秒杀业务分析 所谓秒杀,就是网络卖家发布一些超低价格的商品,所有买家在同一时间网上抢购的一种销售方式.秒杀商品通常有两种限制:时间限制,库存限制,其中库存超卖问题是本教程的重点! 秒杀业务的运行流程主要可以分为以下几点: 商家提交秒杀商品申请,录入秒杀商品数据,主要有:商品标题,商品原价,秒杀价格,商品图片,介绍等信息 运营商审核秒杀申请 秒杀频道首页列出秒杀商品,点击秒杀商品图片可以跳转到秒杀商品详细页面 商品详细页面显示秒杀商品信息,点击立即抢购实现秒杀下单,下单时扣减库存,当库存为0或

  • 深入探讨opencv图像矫正算法实战

    摘要 在机器视觉中,对于图像的处理有时候因为放置的原因导致ROI区域倾斜,这个时候我们会想办法把它纠正为正确的角度视角来,方便下一步的布局分析与文字识别,这个时候通过透视变换就可以取得比较好的裁剪效果. 本次实战,对于图像的矫正使用了两种矫正思路: 针对边缘比较明显的图像,使用基于轮廓提取的矫正算法. 针对边缘不明显,但是排列整齐的文本图像,使用了基于霍夫直线探测的矫正算法. 基于轮廓提取的矫正算法 整体思路: 图片灰度化,二值化 检测轮廓,并筛选出目标轮廓(通过横纵比或面积去除干扰轮廓) 获取

  • Flutter手势密码的实现示例(附demo)

    目录 前言 开始 绘制圆点 绘制手势路径 组合9个圆点盘和手势路径 手势密码组件的使用 上传自定义组件到pub仓库 后记 前言 本篇记录的是使用Flutter完成手势密码的功能,大致效果如下图所示: 该手势密码的功能比较简单,下面会详细记录实现的过程,另外还会简单说明如何将该手势密码作为插件发布到pub仓库. 开始 实现上面的手势密码并不难,大致可以拆分成如下几部分来完成: 绘制9个圆点 绘制手指滑动的线路 合并以上两个部分 绘制圆点 我们使用面向对象的方式来处理9个圆点的绘制,每个圆点作为一个

  • python+django+mysql开发实战(附demo)

    开发工具:pycharm 环境:python3.7.4(例子中用的3.6)下载安装pycharm:http://www.jetbrains.com/pycharm/download/#section=windows分为社区版和专业版,一个免费一个收费Pycharm2021破解版下载: https://www.jb51.net/softs/598504.html下载安装python:https://www.python.org/downloads/windows/安装好开发工具和python环境后

  • C#实现语音视频录制-附demo源码

    在很多语音视频软件系统中,经常有将实时的音频或视频录制为文件保存到磁盘的需求,比如,视频监控系统中录制监控到的视频.视频会议系统中录制整个会议的过程.语音通话系统中录制完整的对话内容.等等. MFile组件(Oraycn.MFile.dll)是傲瑞实用组件之一,它可以将原始的语音数据和视频数据按照指定的格式进行编码,并将它们写入到视频文件(如.mp4)中. 一.缘起 最近正在做的一个网络招聘平台的项目,其中有一个模块是这样的,应聘者可以通过该系统的客户端录制自己的视频(自我介绍)上传到服务器,而

  • 微信小程序实现点击按钮修改文字大小功能【附demo源码下载】

    本文实例讲述了微信小程序实现点击按钮修改文字大小功能.分享给大家供大家参考,具体如下: 1.效果展示 2.关键代码 index.wxml文件 <view class="view" style="font-size:{{fontSize}}pt">我是view标签</view> <button class="btn" type="default" bindtap="magnifyFontS

  • 微信小程序实现点击按钮移动view标签的位置功能示例【附demo源码下载】

    本文实例讲述了微信小程序实现点击按钮移动view标签的位置功能.分享给大家供大家参考,具体如下: 1.效果展示 2.关键代码 index.wxml文件 <view class="view" style="left:{{viewLeft}}px;">我是view标签</view> <button class="btn" type="default" bindtap="changeLocat

随机推荐