opencv_c++学习(二十四)

一、积分图像

在这里插入图片描述
积分图像是对原图像进行积分操作的算法。如上图左所示,不同颜色代表不同区域。当我们想求取一个像素点的积分值时,我们需要求取该点左上方区域的数据之和,如P0的积分值是浅蓝色区域的数据之和。 P1的积分值为蓝色和橙色区域的数值之和。
在这里插入图片描述
上图展示的是倾斜求和积分方式。
积分图像计算函数:

integral(InputArray src, OutputArray sum, OutputArray sqsum, OutputArray tilted, int sdepth = -1, int sqdepth = -1)

src:输入图像,图像数据类型可以是CV_8U、CV_32F或者CV_64F。
sum:输出标准求和积分图像,图像的数据类型可以是CV_32S、CV_32F或者CV_64F。
sqsum:输出平方求和积分图像,图像的数据类型可以是CV_32F或者CV_64F。
tilted:输出倾斜45°的倾斜求和积分图像,其数据类型与sum相同。
sdepth:输出标准求和积分图像和倾斜求和积分图像的数据类型标志,可以选择的参数为CV_32S,CV_32F或者CV_64F,参数默认值为-1,表示满足数据存储的自适应类型。
sqdepth:输出平方求和积分图像的数据类型标志,可以选择的参数为CV_32F或者CV_64F,参数默认值为-1,表示满足数据存储的自适应类型。
本节使用案例如下:

int main() {
	//创建16*16的全1矩阵
	Mat img = Mat::ones(16, 16, CV_32FC1);

	//在图像中加入随机噪声
	RNG rng(10000);

	for (int y = 0; y < img.rows; y++)
	{
		for (int x = 0; x < img.cols; x++)
		{
			float d = rng.uniform(-0.5, 0.5);
			img.at<float>(y, x) = img.at<float>(y, x) + d;
		}
	}

	//计算标准求和积分
	Mat sum;
	integral(img, sum);

	//为了便于显示,转成CV_8U格式
	Mat sum8U = Mat_<uchar>(sum);
	namedWindow("q", WINDOW_NORMAL);
	imshow("q", sum8U);

	//计算平方求和积分
	Mat sqsum;
	integral(img, sum, sqsum);

	//为了便于显示,转成CV_8U格式
	Mat sqsum8U = Mat_<uchar>(sqsum);
	namedWindow("w", WINDOW_NORMAL);
	imshow("w", sqsum8U);

	//计算倾斜求和积分
	Mat tilted;
	integral(img, sum, sqsum, tilted);

	//为了便于显示,转成CV_8U格式
	Mat tilted8U = Mat_<uchar>(tilted);
	namedWindow("e", WINDOW_NORMAL);
	imshow("e", tilted8U);
		 
	waitKey(0);
	return 0;
}

二、图像分割——漫水填充

在这里插入图片描述

floodFill(InputOutputArray image, InputOutputArray mask, Point seedPoint, Scalar newVal, Rect * rect = 0, Scalar loDiff = Scalar(), upDiff =, Scalar scalar(), int flags = 4

image:输入输出图像,图像数据类型可以为CV_8U或者CV_32F的单通道或者三通道图像。
mask:掩码矩阵,尺寸比如输入图像的宽和高各大2的单通道图像,用于标记漫水填充的区域。
seedPoint:种子点。
newVal:归入种子点区域内像素点的新像素值。
rect:种子点漫水填充区域的最小矩形边界,默认值为0,表示不输出边界。loDiff:添加进种子点区域条件的下界差值。
upDiff:添加进种子点区域条件的上界差值。
flags:漫水填充方法的操作标志。
本节应用案例如下:

int main() {

	//读取图片
	Mat src = imread("1.png");
	if (src.empty())
	{
		printf("不能打开空图片");
		return -1;
	}

	//在生成随机像素的随机数
	RNG rng(10000);

	//连同邻域方式
	int connectivity = 4;

	//掩码图像数值
	int maskVal = 255;

	//漫水填充的标志位,不改变种子像素值
	int flags = connectivity | (maskVal << 8) | FLOODFILL_FIXED_RANGE;

	//设置与选中像素点的差值,上下都为20
	Scalar loDiff = Scalar(20, 20, 20);
	Scalar upDiff = Scalar(20, 20, 20);

	//声明掩膜矩阵变量
	Mat mask = Mat::zeros(src.rows + 2, src.cols + 2, CV_8UC1);

	while (true)
	{
		//随机产生图像中某一像素点
		int py = rng.uniform(0, src.rows - 1);
		int px = rng.uniform(0, src.cols - 1);
		Point point = Point(px, py);

		//对彩色图像填充像素值
		Scalar newVal = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));

		//进行漫水填充,返回填充像素数目
		int area = floodFill(src, mask, point, newVal, &Rect(), loDiff, upDiff, flags);

		imshow("q", mask);

		//按ESC键退出程序
		char key = (char)waitKey();
		if (key == 27 || key == 'q' || key == 'Q')
		{
			break;
		}

	}
	waitKey(0);
	return 0;

}

三、图像分割方法——分水岭法

在这里插入图片描述

watershed(InputArray image, InputOutputArray markers)

image:输入图像,数据类型为CV_8U的三通道图像。
markers:输入(种子区域)/输出CV_32S的单通道图像的标记结果,与原图像具有相同的尺寸。
本节样例如下:

int main() {

	//读取要标记的图片
	Mat src = imread("1.png");
	//读取原始图片
	Mat src1 = imread("3.png");
	if (src.empty() || src1.empty())
	{
		printf("不能打开空图片");
		return -1;
	}

	//watershed参数设置
	Mat maskWaterShed;

	//转化为灰度图
	Mat gray;
	cvtColor(src, gray, COLOR_BGR2GRAY);

	Mat imgMask;
	//二值化并开运算
	threshold(gray, imgMask, 254, 255, THRESH_BINARY);
	Mat k = getStructuringElement(0, Size(3, 3));
	morphologyEx(imgMask, imgMask, MORPH_OPEN, k);

	//轮廓提取
	vector<vector<Point>>contours;
	vector<Vec4i> hierarchy;
	findContours(imgMask, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE);

	//在maskWaterShed上绘制轮廓,用于输入分水岭算法
	maskWaterShed = Mat::zeros(imgMask.size(), CV_32S);
	for (int index = 0; index < contours.size(); index++)
	{
		drawContours(maskWaterShed, contours, index, Scalar::all(index + 1), -1, 8, hierarchy, INT_MAX);
	}

	//进行分水岭算法
	watershed(src1, maskWaterShed);

	//随机生成颜色,用于显示分割
	vector<Vec3b> colors;
	for (int i = 0; i < contours.size(); i++)
	{
		int b = theRNG().uniform(0, 255);
		int g = theRNG().uniform(0, 255);
		int r = theRNG().uniform(0, 255);
		colors.push_back(Vec3b((uchar)b, (uchar)g, (uchar)r));
	}

	//显示图像
	Mat resultImg = Mat(src1.size(), CV_8UC3);
	for (int i = 0; i < imgMask.rows; i++)
	{
		for (int j = 0; j < imgMask.cols; j++)
		{
			//绘制不同区域
			int index = maskWaterShed.at<int>(i, j);

			//如果区域边界
			if (index == -1)
			{
				resultImg.at<Vec3b>(i, j) = Vec3b(255, 255, 255);
			}

			//没有被标记的区域置0
			else if (index<=0 || index > contours.size())
			{
				resultImg.at<Vec3b>(i, j) = Vec3b(0, 0, 0);
			}

			//其他区域保持像素不变
			else
			{
				resultImg.at<Vec3b>(i, j) = colors[index - 1];
			}
		}
	}

	imshow("resultImg", resultImg);
	resultImg = resultImg * 0.8 + src1 * 0.2;
	imshow("resultImg1", resultImg);

	//绘制每个区域的图案
	for (int n = 0; n < contours.size(); n++)
	{
		Mat resImage1 = Mat(src.size(), CV_8UC3);
		for (int i = 0; i < imgMask.rows; i++)
		{
			for (int j = 0; j < imgMask.cols; j++)
			{
				//绘制不同区域
				int index = maskWaterShed.at<int>(i, j);

				//如果区域边界
				if (index == n)
				{
					resultImg.at<Vec3b>(i, j) = src1.at<Vec3b>(i, j);
				}

				else
					resultImg.at<Vec3b>(i, j) = Vec3b(0, 0, 0);

			}
		}
		imshow(to_string(n), resImage1);
	}
	waitKey(0);
	return 0;
}

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

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

相关文章

网页JS自动化脚本(八)使用网页专属数据库indexedDB进行数据收集

我们在网页上进行的活动,往往都需要进行收集一些简单的数据,但是因为浏览器的安全原因,浏览器基本上是无法与本地的操作系统直接产生数据交互的,这本来就是一个由于安全问题生产的无解问题,在浏览器里面是内置了几种数据库的,其中一种就是indexedDB,可以用来储存一些非常小的数…

C++进阶 —— 线程库(C++11新特性)

十&#xff0c;线程库 thread类的简单介绍 在C11之前涉及多线程问题&#xff0c;都是和平台相关的&#xff0c;如windows和Linux下各有自己的接口&#xff0c;这使代码的可移植性较差&#xff1b;C11中最重要的特性就是对线程进行支持&#xff0c;使得C在并行编程时不需要依赖…

Axure教程—水平方向多色图(中继器)

本文将教大家如何用AXURE制作动态水平方向多色图 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://l83ucp.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87822666 二、功能介绍 简单填写中继器内容即可生成动态水平多色…

Linux-模拟一个简单的shell

什么是shell外壳&#xff1f;就是操作系统给我们的一个命令行解释器&#xff0c;在Linux系统中&#xff0c;它的shell叫做bash。 那么bash本质是什么呢&#xff1f; 本质就是一个文件&#xff0c;一个进程。 万物皆文件 每个操作系统的shell都是很复杂的&#xff0c;想要…

【Matter】使用chip tool在ESP32-C3上进行matter开发

文章目录 使用chip tool在ESP32-C3上进行matter开发前提准备编译 chip-tool1.激活esp-matter环境2.编译matter所需环境3.构建CHIP TOOL chip-tool client 调试设备说明1.基于 BLE 调试2.通过IP与设备配对3.Trust store4.忘记当前委托的设备 使用chip-tool点灯1.matter环境激活2…

linuxOPS基础_Linux系统的文件目录结构及用途

linux系统文件目录结构 Linux 系统不同于 Windows&#xff0c;没有 C 盘、D 盘、E 盘那么多的盘符&#xff0c;只有一个根目录&#xff08;/&#xff09;&#xff0c;所有的文件&#xff08;资源&#xff09;都存储在以根目录&#xff08;/&#xff09;为树根的树形目录结构中…

【大数据之Hive】四、配置Hive元数据存储到MySQL

需求&#xff1a;   把Hive元数据写道MySQL的metastore数据库中&#xff08;MySQL默认没有metastore数据库&#xff0c;需要提前创建&#xff1a;create database metastore;&#xff09;   连接地址&#xff1a;jdbc:mysql//hadoop102:3306/metastore   驱动&#xff1a…

什么是SOAP

什么是SOAP 什么是SOAP? SOAP (Simple Object Access Protocol) 是一种基于XML的通信协议&#xff0c;用于在网络上交换结构化的信息。它被广泛用于分布式系统中的应用程序间通信。 SOAP定义了一组规范&#xff0c;描述了消息的格式、通信的方式和处理消息的过程。它允许应…

第四章 程序的控制结构

文章目录 第四章 程序的控制结构4.1 程序的三种控制结构4.1.1 程序流程图4.1.2 程序控制结构基础4.1.3 程序控制结构扩展 4.2 程序的多分支结构4.2.1 单分支结构&#xff1a;if4.2.2 二分支结构&#xff1a;if-else4.2.3 多分支结构&#xff1a;if-elif-else4.2.4 判断条件及组…

图及其与图相关的算法

⭐️前言⭐️ 本篇文章主要介绍图及其与图相关的算法 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主将持续更新学习记录收获&#xff0c;友友们有任何问题可以在评论区留言 &#x1f349;博客中涉及源码及博主…

智慧档案馆八防是怎么建设的?都需要注意哪些内容

智慧档案馆八防环境监控系统一体化解决系统方案 智慧档案库房一体化平台通过智慧档案管理&#xff0c;实现智慧档案感知协同处置功能&#xff1b;实现对档案实体的智能化识别、定位、跟踪监控&#xff1b;实现对档案至智能密集架、空气恒湿净化一体设备、安防设备&#xff0c…

Linux守护进程

守护进程 Linux/Unix 会话 会话首进程 进程组 组长进程&#xff1a;第一个启动的进程叫组长进程。 关闭终端&#xff1a;进程组里全部进程关闭。 setsid()创建一个新的会话。&#xff08;必须是组员进程才可以创建一个新的会话&#xff09; 1.先fork()&#xff0c;退出父进程 2…

电力系统的虚假数据注入攻击和MTD系统研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

字符串最后一个单词的长度

描述 计算字符串最后一个单词的长度&#xff0c;单词以空格隔开&#xff0c;字符串长度小于5000。&#xff08;注&#xff1a;字符串末尾不以空格为结尾&#xff09; 输入描述&#xff1a; 输入一行&#xff0c;代表要计算的字符串&#xff0c;非空&#xff0c;长度小于500…

mysql触发器监听数据投递中间件

目前市面上有许多的 CDC&#xff08;Change Data Capture&#xff09; 框架用于监听数据库的数据变动&#xff0c;例如&#xff1a;canal、Debezium、Maxwell等都是用来解析 binlog 日志实现事件的监听。但是有一个情况就是如果公司对 binlog 日志文件的权限管控的很严格&#…

【学习日记2023.6.2】之 管理端报表统计

文章目录 11. 管理端报表统计11.1 Apache ECharts11.1.1 介绍11.1.2 入门案例 11.2 营业额统计11.2.1 需求分析和设计11.2.2 代码开发Controller层Service层接口Service层实现类Mapper层 11.2.3 功能测试11.2.4 提交代码 11.3 用户统计11.3.1 需求分析和设计11.3.2 代码开发Con…

如何编写接口自动化框架系列通过yaml来管理测试用例(四)

本文是接口自动化测试框架系列篇的第四篇 &#xff0c;主要介绍yaml包的使用 。自动化测试的本质是将功能测试用例交给代码去 目录 1. yaml介绍&#xff1f; 2.python中的yaml包 3.项目中使用yaml包 4 项目总结 执行 &#xff0c;测试人员往往是在自动化框架添加对应的测试…

排查Javascript内存泄漏案例(一)

Chrome DevTools里的Performance面板和Memory面板可以用来定位内存问题。 如何判断应用发生内存泄漏&#xff1f; 为了证明螃蟹的听觉在腿上&#xff0c;一个专家捉了只螃蟹并冲它大吼&#xff0c;螃蟹很快就跑了。然后捉回来再冲它吼&#xff0c;螃蟹又跑了。最后专家把螃蟹的…

WPS 借助 ML Kit 无缝翻译 43 种语言,每年净省 6,500 万美元

△ 动画说明: 在笔记本电脑屏幕中&#xff0c;汉字 "文" 将变为字母 "A"&#xff0c;代表文本的横线将逐一出现&#xff0c;就像有人在输入内容一样。 WPS 是一款办公套件软件&#xff0c;可让用户轻松查看和编辑其所有文档、演示文稿、电子表格等。作为一…

RK3568 AP6275S蓝牙驱动程序调度过程

1、前言 今年3月份调度了RK3568驱动程序&#xff0c;当时由于时间的问题&#xff0c;AP6275S蓝牙驱动程序没有调试成功。当时仔细检查的设备树的配置。 wireless_bluetooth: wireless-bluetooth {compatible "bluetooth-platdata";clocks <&rk809 1>;cl…