在二值图像中寻找漏洞
Finding holes in a binary image
假设我们有以下二值图像
0010
0101
0101
0010
0100
1010
0100
0000
0 代表背景像素,1 代表图像 pixels.As 你可以看到这张图有两个洞 image.Is 有没有办法用算法得到这张图的洞数?(Java 或 Python 但不是 Matlab)
这里是一些以代码形式呈现的想法(可能不是您需要的)。
问题是,我不明白你的例子。根据邻域定义,可能会有不同的结果。
- 如果你有一个 8 邻域,所有的零都以某种方式连接(这对周围的 1 意味着什么?)。
- 如果你有一个 4 邻域,每个被 4 个 1 包围的邻域代表一个新洞
- 当然你可以对此进行后处理,但问题仍然不清楚
代码
import numpy as np
from skimage.measure import label
img = np.array([[0,0,1,0],
[0,1,0,1],
[0,1,0,1],
[0,0,1,0],
[0,1,0,0],
[1,0,1,0],
[0,1,0,0],
[0,0,0,0]])
labels = label(img, connectivity=1, background=-1) # conn=1 -> 4 neighbors
label_vals = np.unique(labels) # conn=2 -> 8 neighbors
counter = 0
for i in label_vals:
indices = np.where(labels == i)
if indices:
if img[indices][0] == 0:
print('hole: ', indices)
counter += 1
print(img)
print(labels)
print(counter)
输出
('hole: ', (array([0, 0, 1, 2, 3, 3, 4]), array([0, 1, 0, 0, 0, 1, 0])))
('hole: ', (array([0]), array([3])))
('hole: ', (array([1, 2]), array([2, 2])))
('hole: ', (array([3, 4, 4, 5, 6, 6, 6, 7, 7, 7, 7]), array([3, 2, 3, 3, 0, 2, 3, 0, 1, 2, 3])))
('hole: ', (array([5]), array([1])))
[[0 0 1 0]
[0 1 0 1]
[0 1 0 1]
[0 0 1 0]
[0 1 0 0]
[1 0 1 0]
[0 1 0 0]
[0 0 0 0]]
[[ 1 1 2 3]
[ 1 4 5 6]
[ 1 4 5 6]
[ 1 1 7 8]
[ 1 9 8 8]
[10 11 12 8]
[ 8 13 8 8]
[ 8 8 8 8]]
5
尝试使用 OpenCV connectedComponents 函数。
a=np.full((3,3), 1)
a[1,1]=0
print(a) >> [[1,1,1],[1,0,1],[1,1,1]]
n,comp=cv2.connectedComponents(1-a) # 1-a, because components are considered white (non zero)
print(n-1) # number of holes
我在 С# 上有一个程序可以计算欧拉数
我们可以根据这个公式计算出欧拉数:Eu = (Q3 - Q1)/4;
Q1 - 00 or 00 or 01 or 10
01 10 00 00
Q3 - 01 or 11 or 10 or 11
11 10 11 10.
所以我们遍历矩阵,每一步选择 4 个像素。
我写的算法通过这个公式计算欧拉数。
对不起我的英语不好。
这是我的 github 完整项目的存储库:https://github.com/zeComedian/image-processing
public void BWEuler(int[,] image)
{
int Q1 = 0;
int Q3 = 0;
int rows = image.GetUpperBound(0) + 1;
int columns = image.Length / rows;
for (int i = 1; i < columns - 1; i++)
{
for (int j = 1; j < rows - 1; j++)
{
if (image[i, j] == 0)
{
if ((image[i, j - 1] != 0) && (image[i - 1, j] != 0))
{
Q3++;
}
if ((image[i - 1, j] != 0) && (image[i, j + 1] != 0))
{
Q3++;
}
if ((image[i, j + 1] != 0) && (image[i + 1, j] != 0))
{
Q3++;
}
if ((image[i + 1, j] != 0) && (image[i, j - 1] != 0))
{
Q3++;
}
}
else
{
if ((image[i, j - 1] != 1) && (image[i - 1, j] !=
1))
{
Q1++;
}
if ((image[i - 1, j] != 1) && (image[i, j + 1] !=
1))
{
Q1++;
}
if ((image[i, j + 1] != 1) && (image[i + 1, j] !=
1))
{
Q1++;
}
if ((image[i + 1, j] != 1) && (image[i, j - 1] !=
1))
{
Q1++;
}
}
}
}
int Eu = ((Q3 - Q1) / 4);
textBox3.Text = Eu.ToString();
Console.WriteLine(Eu);
}
假设我们有以下二值图像
0010
0101
0101
0010
0100
1010
0100
0000
0 代表背景像素,1 代表图像 pixels.As 你可以看到这张图有两个洞 image.Is 有没有办法用算法得到这张图的洞数?(Java 或 Python 但不是 Matlab)
这里是一些以代码形式呈现的想法(可能不是您需要的)。
问题是,我不明白你的例子。根据邻域定义,可能会有不同的结果。
- 如果你有一个 8 邻域,所有的零都以某种方式连接(这对周围的 1 意味着什么?)。
- 如果你有一个 4 邻域,每个被 4 个 1 包围的邻域代表一个新洞
- 当然你可以对此进行后处理,但问题仍然不清楚
代码
import numpy as np
from skimage.measure import label
img = np.array([[0,0,1,0],
[0,1,0,1],
[0,1,0,1],
[0,0,1,0],
[0,1,0,0],
[1,0,1,0],
[0,1,0,0],
[0,0,0,0]])
labels = label(img, connectivity=1, background=-1) # conn=1 -> 4 neighbors
label_vals = np.unique(labels) # conn=2 -> 8 neighbors
counter = 0
for i in label_vals:
indices = np.where(labels == i)
if indices:
if img[indices][0] == 0:
print('hole: ', indices)
counter += 1
print(img)
print(labels)
print(counter)
输出
('hole: ', (array([0, 0, 1, 2, 3, 3, 4]), array([0, 1, 0, 0, 0, 1, 0])))
('hole: ', (array([0]), array([3])))
('hole: ', (array([1, 2]), array([2, 2])))
('hole: ', (array([3, 4, 4, 5, 6, 6, 6, 7, 7, 7, 7]), array([3, 2, 3, 3, 0, 2, 3, 0, 1, 2, 3])))
('hole: ', (array([5]), array([1])))
[[0 0 1 0]
[0 1 0 1]
[0 1 0 1]
[0 0 1 0]
[0 1 0 0]
[1 0 1 0]
[0 1 0 0]
[0 0 0 0]]
[[ 1 1 2 3]
[ 1 4 5 6]
[ 1 4 5 6]
[ 1 1 7 8]
[ 1 9 8 8]
[10 11 12 8]
[ 8 13 8 8]
[ 8 8 8 8]]
5
尝试使用 OpenCV connectedComponents 函数。
a=np.full((3,3), 1)
a[1,1]=0
print(a) >> [[1,1,1],[1,0,1],[1,1,1]]
n,comp=cv2.connectedComponents(1-a) # 1-a, because components are considered white (non zero)
print(n-1) # number of holes
我在 С# 上有一个程序可以计算欧拉数
我们可以根据这个公式计算出欧拉数:Eu = (Q3 - Q1)/4;
Q1 - 00 or 00 or 01 or 10 01 10 00 00所以我们遍历矩阵,每一步选择 4 个像素。 我写的算法通过这个公式计算欧拉数。 对不起我的英语不好。 这是我的 github 完整项目的存储库:https://github.com/zeComedian/image-processingQ3 - 01 or 11 or 10 or 11 11 10 11 10.
public void BWEuler(int[,] image)
{
int Q1 = 0;
int Q3 = 0;
int rows = image.GetUpperBound(0) + 1;
int columns = image.Length / rows;
for (int i = 1; i < columns - 1; i++)
{
for (int j = 1; j < rows - 1; j++)
{
if (image[i, j] == 0)
{
if ((image[i, j - 1] != 0) && (image[i - 1, j] != 0))
{
Q3++;
}
if ((image[i - 1, j] != 0) && (image[i, j + 1] != 0))
{
Q3++;
}
if ((image[i, j + 1] != 0) && (image[i + 1, j] != 0))
{
Q3++;
}
if ((image[i + 1, j] != 0) && (image[i, j - 1] != 0))
{
Q3++;
}
}
else
{
if ((image[i, j - 1] != 1) && (image[i - 1, j] !=
1))
{
Q1++;
}
if ((image[i - 1, j] != 1) && (image[i, j + 1] !=
1))
{
Q1++;
}
if ((image[i, j + 1] != 1) && (image[i + 1, j] !=
1))
{
Q1++;
}
if ((image[i + 1, j] != 1) && (image[i, j - 1] !=
1))
{
Q1++;
}
}
}
}
int Eu = ((Q3 - Q1) / 4);
textBox3.Text = Eu.ToString();
Console.WriteLine(Eu);
}