首页 > 其他分享 >OpenCV ----像素距离与连通域

OpenCV ----像素距离与连通域

时间:2024-07-19 17:58:44浏览次数:9  
标签:img int 距离 像素 ---- OpenCV 图像 cv

文章目录

一. 图像像素距离变换

1.常用距离的三种定义:

(1)欧式距离-----DIST_L2

​ 两像素点的直线距离,利用勾股定理可计算出两点的欧式距离
d = ( x 1 − x 2 ) 2 + ( y 1 − y 2 ) 2 2 d = \sqrt[2]{(x_1-x_2)^2 +(y_1-y_2)^2 } d=2(x1​−x2​)2+(y1​−y2​)2

(2)街区距离-----DIST_L1

​ 两像素点X和Y方向距离之和,计算公式为
d = ∣ x 1 − x 2 ∣ + ∣ y 1 − y 2 ∣ d = |x_1-x_2| +|y_1-y_2| d=∣x1​−x2​∣+∣y1​−y2​∣

(3)棋盘距离------DIST_C

​ 棋盘距离为两像素点移动到同一行或同一列的最大距离,即两点X方向和Y方向上的最大距离

2. distanceTransform() ------ 距离转换函数
(1) 函数原型
void distanceTransform(InputArray src, 
                            OutputArray dst, 
                            int distanceType, 
                            int maskSize, 
                            int dstType=CV_32F )
     
 //distanceTransform()函数有两个原型,此处为较常用的

src:准备作距离变换的原图像。

dst:经过距离变换后的输出图像。

distanceType:距离类型,标志见上

maskSize :计算距离时使用的mask矩阵大小,参数可以为3或5。

dstType: 输出图像(矩阵)的数据类型,可以是CV_8U 或 CV_32F。当选择CV_8U时,distanceType的类型只能为DIST_L1。

distanceTransform()函数计算的是非零像素点到0像素点的距离

(2)运用演示
//计算简易5*5矩阵  1,1,1,1,1
//               1,1,1,1,1
//               1,1,0,1,1
//               1,1,1,1,1
//               1,1,1,1,1  的三种距离


void QuickDemo::distance_demo(Mat& img)
{
	Mat a = (Mat_<uchar>(5, 5) 
		<< 1, 1, 1, 1, 1 ,
		 1, 1, 1, 1, 1,
		 1, 1, 0, 1, 1 ,
		 1, 1, 1, 1, 1 ,
		 1, 1, 1, 1, 1);

	Mat dis_L1, dis_L2, dis_C;


	distanceTransform(a, dis_L1, DIST_L1, 3, CV_8U);
	cout << "街区距离" << endl << dis_L1 << endl;


	distanceTransform(a, dis_L2, DIST_L2, 3, CV_8U);
	cout << "欧式距离" << endl << dis_L2 << endl;


	distanceTransform(a, dis_C, DIST_C, 3, CV_8U);
	cout << "棋盘距离" << endl << dis_L1 << endl;
}

由于distanceTransform()函数计算的是非零像素点到0像素点的距离,得到下列输出

在这里插入图片描述

二. 图像连通域

(1)定义

图像的连通域是指图像中具有相同像素值并且位置相邻的像素组成的区域。提取图像中不同的连通域是图像处理中较为常用的方法,例如在车牌识别、文字识别、目标检测等领域对感兴趣区域分割与识别。一般情况下,一个连通域内只包含一个像素值,因此为了防止像素值波动对提取不同连通域的影响,连通域分析常处理的是二值化后的图像

(2)邻域

​ opencv中有以下两种形式领域:

4-邻域:必须在水平和垂直方向上相邻,相邻的两个像素坐标必须只有一位不同而且只能相差1个像素

8-邻域: 九宫格形式,相邻的两个像素坐标必须只有一位不同而且只能相差1个像素

在这里插入图片描述

(3)标记连通域函数-----connectedComponents()
int connectedComponents(InputArray image, OutputArray labels,
                          int connectivity, int ltype, int ccltype);

image: 输入二值图像

labels: 输出图像

connectivity: 邻域种类,4或8

ltype: 输出图深度,支持CV_32S 和CV_16S

代码演示:


int main()
{
     Mat img,M,dst;
     img = imread("D:/OpenCV/photo/R.png",1);
	 //对图像进行距离变换
	 if (img.empty())
	 {
		 cout << "请确认图像文件名称是否正确" << endl;
		 return -1;
	 }
	 cv::Mat rice, riceBW;

	 //将图像转成二值图像,用于统计连通域
	 cv::cvtColor(img, rice, cv::COLOR_BGR2GRAY);
	 cv::threshold(rice, riceBW, 50, 255, cv::THRESH_BINARY);

	 //生成随机颜色,用于区分不同连通域
	 cv::RNG rng(10086);
	 cv::Mat out;
	 int number = connectedComponents(riceBW, out, 8, CV_16U);  //统计图像中连通域的个数
	 vector<cv::Vec3b> colors;
	 for (int i = 0; i < number; i++)
	 {
		 //使用均匀分布的随机数确定颜色
		 cv::Vec3b vec3 = cv::Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
		 colors.push_back(vec3);
	 }

	 //以不同颜色标记出不同的连通域
	 cv::Mat result = cv::Mat::zeros(rice.size(), img.type());
	 int w = result.cols;
	 int h = result.rows;
	 for (int row = 0; row < h; row++)
	 {
		 for (int col = 0; col < w; col++)
		 {
			 int label = out.at<uint16_t>(row, col);
			 if (label == 0)  //背景的黑色不改变
			 {
				 continue;
			 }
			 result.at<cv::Vec3b>(row, col) = colors[label];
		 }
	 }

	 //显示结果
	 cv::imshow("原图", img);
	 cv::imshow("标记后的图像", result);

	 cv::waitKey(0);
	 return 0;
}

在这里插入图片描述

(3)connectedComponents()函数

connectedComponents()函数除了输出连通区域标签图像外,还会输出每个连通区域的一些统计信息,如像素数目、外接矩形等。该函数的原型如下:

int connectedComponentsWithStats(InputArray image,
                                 OutputArray labels,
                                 OutputArray stats,
                                 OutputArray centroids,
                                 int connectivity = 8,
                                 int ltype = CV_32S);

参数 stats 为输出的统计信息,参数 centroids 为输出的连通区域质心。

代码演示:

void QuickDemo::connectedComponentsWithstats_demo(Mat& img)
{
	if (img.empty())
	{
		cout << "请确认图像文件名称是否正确" << endl;
		return;
	}

	GaussianBlur(img, img, Size(7, 7),3);
	Mat rice, riceBW;
	cout << img.type() << endl;
	cvtColor(img, rice, COLOR_BGR2GRAY);
	threshold(rice, riceBW, 50, 255, THRESH_BINARY);

	RNG rng(10086);
	Mat out;
	Mat satas, cen;
	int number = connectedComponentsWithStats(riceBW, out, satas, cen, 8, CV_16U);
	vector<Vec3b> colors;
	for (int i = 0; i < number; i++)
	{

		cv::Vec3b vec3 = cv::Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
		colors.push_back(vec3);
	}


	cv::Mat result = cv::Mat::zeros(rice.size(), img.type());
	//int w = result.cols;
	//int h = result.rows;

	for (int i = 1; i < number; ++i)
	{
		int center_x = cen.at<double>(i, 0);
		int center_y = cen.at<double>(i, 1);
		int x = satas.at<int>(i, CC_STAT_LEFT);
		int w = satas.at<int>(i, CC_STAT_WIDTH);
		int y = satas.at<int>(i, CC_STAT_TOP);
		int h = satas.at<int>(i, CC_STAT_HEIGHT);
		Rect rect(x, y, w, h);
		rectangle(img, rect, Scalar(255, 255, 255), 1, 8);
	}


	//cv::imshow("原图", img);
	cv::imshow("标记后的图像", img);

}

在这里插入图片描述

标签:img,int,距离,像素,----,OpenCV,图像,cv
From: https://blog.csdn.net/sunny_code_/article/details/140555151

相关文章

  • 【windows11】笔记本电脑使用PE工具重装系统超详细步骤及常见问题
    因为一些原因昨天重装了一次系统,本来以为是一次简单快捷的重装,但是我们在重装系统的过程中遇到了一些问题,导致重装之后很多出现了一系列小毛病,一度以为自己没装成功,多次重装等烦恼。下面为大家附上部分教程及一些注意事项,相信大家参考别的教程配合可以很顺利地完成。第五步之......
  • PHP 快速入门:构建动态网站的基础
    引言PHP,全称HypertextPreprocessor,是一种广泛用于创建动态网站的服务器端脚本语言。它易于学习,功能强大,能够与多种数据库系统(如MySQL)集成,是Web开发者的常用工具之一。本文将带你快速了解PHP的基本概念和用法。基础语法输出PHP中没有专门的输入语句,但可以通过多种......
  • 深入理解淘客返利系统中的异步消息处理与队列技术
    深入理解淘客返利系统中的异步消息处理与队列技术大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!在现代的淘客返利系统中,高并发和复杂的业务需求要求我们采用异步消息处理和队列技术来提高系统的性能和可伸缩性。本文将深入探讨在淘客返利系统中如......
  • 35.综合练习:买飞机票
    //机票价格按照淡季旺季,头等舱经济舱收费//键盘录入机票原价、月份和仓位//旺季(5月到10月):头等舱9折,经济舱8.5折//淡季(11月到下一年的4月):头等舱7折,经济舱6.5折importjava.util.Scanner;publicclass飞机票{publicstaticvoidmain(String[]args){Sc......
  • 算法基础课-第二章复盘
    一、栈(一)单调栈特点:栈内元素以递增或递减的形式排序。应用:求解下一个更大元素、下一个更小元素、最大子数组和等问题。题目示例:代码逻辑:1、采用递增排序的单调栈,栈顶元素是栈内最大元素。2、循环读入列表元素,在单调栈非空的情况下,如果栈顶元素大于当前元素,将栈顶元素弹出栈......
  • 34.拷贝数组
    定义一个方法:copyOfRange(int[]arr,intx,inty)将数组arr中从索引x开始(包含x)到索引y结束(不包含y)中的元素,复制到新数组中,并将新数组返回例:原始数组arr={1,2,3,4,5,6,7,8,9},新数组newArr={4,5,6,7}publicstaticvoidmain(String[]args){//1.静态初始化定......
  • JavaScript 基础知识 Day01
    一、计算机基础知识1、计算机数据存储单位位(Bit):1bit可以保存一个0或者1(最小的存储单位)字节(Byte):1B=8b千字节(KB):1KB=1024B兆字节(MB):1MB=1024KB吉字节(GB):1GB=1024MB太字节(TB):1TB=1024GB2、关于JavaScript 它是在1952年2月由网景开......
  • RocketMQ实现黑马点评优惠卷下单
    背景在现代电商系统中,秒杀活动因其高并发、高负载的特点,对系统的稳定性和性能要求极高。为了有效地处理秒杀活动中的高并发请求,消息队列成为了一个重要的解决方案。本文将介绍如何使用RocketMQ来实现秒杀下单的功能。目标通过RocketMQ来实现一个秒杀订单的处理流程,保证在......
  • 小白新手搭建个人网盘
    小白新手搭建个人网盘序云服务器ECS重置密码远程连接ECS实例安装OwnCloud安装Apache服务PHP运行环境NAS挂载挂载验证操作体验序阿里云文件存储NAS(ApsaraFileStorageNAS)是一个可大规模共享访问,弹性扩展的分布式文件系统。本文主要是介绍基于ECS挂载NAS实现个人网......
  • DataFunTalk | 数据在零售供应链领域的应用
    本文来源公众号“DataFunTalk”,仅用于学术分享,侵权删,干货满满。原文链接:数据在零售供应链领域的应用导读 本次分享题目为数据在零售供应链领域的应用。主要内容包括以下四大部分:1. 供应链数字化面临的挑战2. 供应链数字化转型架构3. 聚沙成塔:供应链控制塔4. 点石成......