DS图—图非0面积

这篇博客介绍了一种计算二维数组中由1围成的区域面积的方法,通过将非区域内的0变为1,然后使用深度优先搜索策略遍历图形,最终统计0的数量得到面积。作者提到了在边界处理上的技巧,即在原图周围添加一圈0,确保可以从任意围墙外的点开始遍历。示例代码展示了如何实现这个算法。

题目描述

编程计算由"1"围成的下列图形的面积。面积计算方法是统计"1"所围成的闭合曲线中"0"点的数目。如图所示,在10*10的二维数组中,"1"围住了15个点,因此面积为15。

提示:queue

输入

测试次数t

每组测试数据格式为:

数组大小m,n

一个由0和1组成的m*n的二维数组

输出

对每个二维数组,输出符号"1"围住的"0"的个数,即围成的面积。假设一定有1组成的闭合曲线,但不唯一。

输入样例1

2
10 10
0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 1 0 0 0
0 0 0 0 1 0 0 1 0 0
0 0 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 1 0
0 1 0 1 0 1 0 0 1 0
0 1 0 0 1 1 0 1 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 0 0 0 0 0 0
5 8
0 1 1 0 0 1 1 0
1 0 1 0 1 0 0 1
0 1 0 1 0 0 1 0
0 1 0 0 1 1 1 0
0 0 0 0 0 0 0 0

输出样例1

15
5

NOTICE:这道题题目读起来很好懂,算法的实现也很简单,难的是你要知道算法,我采用的算法也是借鉴csdn的大佬的;这题的思路是:将除了1围起来的0之外的所有0变成1,也就是除了面积部分之外其余全为1,这样子计算面积只需要遍历整个图数有多少个0就可以;具体实现的话,就是在原来的图的最外层加上一圈0,然后从最左上角的点开始,以类似走迷宫的方法走完围墙外的所有的0并将他们改为1,最后数多少个0得出结果;为什么要加一圈0呢:样例输入中的第二组测试数据给出答案,因为原来的图中围墙可能在最边上,这样子的话我们就不能够从左上角开始,将所有围墙外的点改为1,加一圈0的话,围墙外的任意两个点之间都可以到达。 

#include <iostream>
using namespace std;

class Graph
{
private:
	int** map;
	int m, n;
public:
	Graph()
	{
		cin >> m >> n;
		map = new int* [m + 2];
		for (int i = 0; i < m + 2; i++)
			map[i] = new int[n + 2];
		for (int i = 0; i < m + 2; i++)
			for (int j = 0; j < n + 2; j++)
				map[i][j] = 0;
		for (int i = 1; i < m + 1; i++)
			for (int j = 1; j < n + 1; j++)
				cin >> map[i][j];
	}
	~Graph()
	{
		for (int i = 0; i < m + 2; i++)
			delete[]map[i];
		delete[]map;
	}
	void walk_map(int i, int j)
	{
		map[i][j] = 1;

		if (j + 1 < n + 2 && map[i][j + 1] == 0)//j+1的判断一定要放前面!
			walk_map(i, j + 1);

		if (i + 1 < m + 2 && map[i + 1][j] == 0)
			walk_map(i + 1, j);

		if (j - 1 >= 0 && map[i][j - 1] == 0)
			walk_map(i, j - 1);

		if (i - 1 >= 0 && map[i - 1][j] == 0)
			walk_map(i - 1, j);
	}
	
	void GetArea()
	{
		walk_map(0, 0);
		int cnt = 0;
		for (int i = 1; i < m + 1; i++)
			for (int j = 1; j < n + 1; j++)
				if (map[i][j] == 0)
					cnt++;
		cout << cnt << endl;
	}
};

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		Graph g;
		g.GetArea();
	}
	return 0;
}

<think>嗯,用户想用Python从片中提取不规则形状,用OpenCV和PIL。首先,我得想想这两个库的功能。OpenCV处理像更强大,特别是计算机视觉方面,而PIL更多是基础的像处理。可能用户需要的是边缘检测、轮廓提取或者颜色分割之类的。 用户提到的是不规则形,所以可能需要找轮廓的方法。OpenCV里findContours函数可以找到轮廓,但需要先预处理像,比如转灰度、二值化。可能步骤是:读取片,转灰度,阈值处理或边缘检测,然后找轮廓。然后根据轮廓提取区域。 还要考虑颜色空间转换,比如如果形和背景颜色差异大,可以用HSV颜色空间来分割。比如inRange函数提取特定颜色范围。或者用自适应阈值处理,因为如果光照不均,普通阈值可能效果不好。 另外,用户可能不知道如何将提取的区域保存或显示,所以代码里可能需要包括显示和保存的部分。比如用matplotlib或OpenCV的imshow。 还要注意,OpenCV的片是BGR格式,而PIL是RGB,转换的时候可能会出问题,需要转换颜色空间。比如用cv2.cvtColor。 可能的问题包括预处理参数设置,比如高斯模糊的核大小,阈值的数值,这些可能需要根据具体片调整。此外,轮廓可能有很多,需要筛选,比如面积大小,或者轮廓近似方法。 然后,根据引用里的资料,引用[4]提到用轮廓和颜色提取的方法,可能需要参考那个。比如用adaptiveThreshold处理,然后找轮廓,创建ROI区域。 所以步骤大概是: 1. 读取片,转成灰度。 2. 预处理(去噪,二值化)。 3. 找轮廓。 4. 筛选需要的轮廓(面积、形状)。 5. 创建掩膜提取区域。 6. 显示或保存结果。 可能还要处理颜色,比如如果物体是某种颜色,用inRange提取颜色掩膜,再结合轮廓。 需要给出代码示例,比如用OpenCV的findContours,然后绘制轮廓或填充掩膜。同时,提醒用户可能需要调整参数,比如阈值、颜色范围等。 此外,用户可能需要知道如何处理不同的片情况,比如复杂背景,或者多个不规则物体。可能需要形态学操作来优化掩膜,比如膨胀、腐蚀。 最后,生成相关问题,比如如何调整参数,处理复杂背景,或者提取特定颜色物体等。</think>### 使用Python提取像中不规则形状的方法(OpenCV+PIL) #### 一、基本步骤与原理 1. **像预处理**:转换为灰度,使用高斯模糊降噪$G(x,y)=\frac{1}{2\pi\sigma^2}e^{-\frac{x^2+y^2}{2\sigma^2}}$,应用自适应阈值处理[^4] 2. **轮廓检测**:通过OpenCV的`findContours`函数获取所有轮廓$$C = \arg\max_{c} \oint_{c} \nabla I \cdot ds$$ 3. **形状筛选**:根据轮廓面积、周长或凸包特性过滤目标区域 4. **掩膜生成**:创建二值掩膜提取目标区域,结合PIL的`Image.fromarray`转换数据格式[^3] #### 二、具体实现代码 ```python import cv2 import numpy as np from PIL import Image def extract_irregular_shape(img_path): # 读取像并转换 img = cv2.imread(img_path) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 预处理(高斯模糊+自适应阈值) blurred = cv2.GaussianBlur(gray, (7,7), 0) thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 查找轮廓 contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 创建掩膜 mask = np.zeros_like(gray) for cnt in contours: area = cv2.contourArea(cnt) if area > 1000: # 过滤小面积噪声 cv2.drawContours(mask, [cnt], -1, 255, -1) # 提取目标区域 result = cv2.bitwise_and(img, img, mask=mask) # 格式转换(PIL显示需要RGB格式) result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB) pil_img = Image.fromarray(result_rgb) return pil_img ``` #### 三、关键参数说明 1. **高斯模糊核大小**:`(7,7)`控制降噪强度,噪声严重时可增大 2. **自适应阈值参数**:块大小`11`和常数`2`需根据像对比度调整 3. **轮廓面积阈值**:`1000`像素过滤噪声,需根据目标尺寸调整 #### 四、进阶优化方向 1. **颜色空间分割**:转换到HSV空间使用`inRange`提取特定颜色区域[^4] $$H \in [20,30], S \in [100,255], V \in [100,255]$$ 2. **边缘增强**:使用Canny边缘检测提升轮廓精度 $$\text{Canny}(img, \text{threshold1}=50, \text{threshold2}=150)$$ 3. **形态学操作**:通过闭运算填充空洞 $$kernel = np.ones((5,5),np.uint8)$$ $$closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)$$
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值