Моя цель - реализовать функцию skimage measure.label из первых принципов. Я хотел бы сделать это для получения помеченного изображения.
Есть три функции. Первый «ccl» выполняет итерацию по каждому пикселю, проверяя, посещался ли ранее пиксель или нет, и устанавливая соответствующее значение маркировки. Вторая функция, check_neighbours, просматривает все окружающие пиксели, чтобы сравнить, являются ли они частью одной и той же метки на изображении. Он также определяет, какие значения связаны. Последняя функция, join_neighbours, используется для соединения разделов, которые связаны между собой.
import cv2
import numpy as np
from skimage import measure
from skimage.filters import threshold_otsu
bgr_image=cv2.imread('filename')
gray_image = np.dot(bgr_image[..., :3], [0.114, 0.587, 0.299])
threshold = threshold_otsu(gray_image)
binary_image = gray_image > threshold
def check_neighbours(i, j, label,label_image,image,row,col):
label_image[i,j] = label
positions=[[i+1, j], [i-1, j],[i-1, j-1], [i + 1, j + 1],[i-1, j +1], [i + 1, j-1],[i, j+1], [i, j-1]]
for pos in positions:
if pos[0]>=0 and pos[0]<row and pos[1]>=0 and pos[1]<col and label_image[pos[0],pos[1]]>0 and image[pos[0],pos[1]] == 1:
if label_image[pos[0],pos[1]] != label_image[i,j]:
neighbours=sorted([label_image[pos[0],pos[1]],label_image[i,j]])
if not neighbours in dup and not neighbours[::-1] in dup:
dup.append(neighbours)
if pos[0]>=0 and pos[0]<row and pos[1]>=0 and pos[1]<col and image[pos[0],pos[1]] == 1:
label_image[pos[0],pos[1]]=label
return label_image
def ccl(image):
row, col = image.shape
count=0
label_image=np.asarray(np.zeros((row,col)), np.uint8)
for i in range(row):
for j in range(col):
if image[i,j] == 1:
if label_image[i,j]>0:
label = label_image[i,j]
else:
label=count+1
count=label
label_image=check_neighbours(i, j, label, label_image,image, row, col)
return label_image
def join_neighbours(image):
row, col = image.shape
for q in dup:
for i in range(row):
for j in range(col):
if image[i,j]==q[1]:
image[i,j]=q[0]
return image
#labelling image
dup=[]
print("Theirs")
print(measure.label(binary_image))
print()
print("Mine")
print(join_neighbours(ccl(binary_image)))
test_image=np.asarray([[True,True,True,True,False],[True,False,False,False,False],[False,False,False,True,True],[False,False,False,True,False],[True,False,False,True,True],[True,False,False,True,True],[True,False,False,True,False],[True,False,False,True,False],[True,False,False,True,False],[True,False,False,False,False],[True,False,True,False,True],[True,False,True,True,True]])
#labelling test data
dup=[]
print("Theirs")
print(measure.label(test_image))
print()
print("Mine")
print(join_neighbours(ccl(test_image)))
Когда я тестирую функции с небольшими наборами данных, выходные данные такие же, как и для функции measure.label, однако, когда я тестирую изображение, я не получаю такие же выходные данные.
Image:
measure.label output:
[[ 0 0 0 ... 7 7 7]
[ 0 0 0 ... 7 7 7]
[ 0 0 0 ... 7 7 7]
...
[ 0 0 0 ... 107 107 107]
[ 0 0 0 ... 107 107 107]
[ 0 0 0 ... 107 107 107]]
My output:
[[ 0 0 0 ... 8 8 8]
[ 0 0 0 ... 8 8 8]
[ 0 0 0 ... 8 8 8]
...
[ 0 0 0 ... 36 36 36]
[ 0 0 0 ... 36 36 36]
[ 0 0 0 ... 36 36 36]]
Test data:
test_image=[[True,True,True,True,False],[True,False,False,False,False],[False,False,False,True,True],[False,False,False,True,False],[True,False,False,True,True],[True,False,False,True,True],[True,False,False,True,False],[True,False,False,True,False],[True,False,False,True,False],[True,False,False,False,False],[True,False,True,False,True],[True,False,True,True,True]]
measure.label output:
[[1 1 1 1 0]
[1 0 0 0 0]
[0 0 0 2 2]
[0 0 0 2 0]
[3 0 0 2 2]
[3 0 0 2 2]
[3 0 0 2 0]
[3 0 0 2 0]
[3 0 0 2 0]
[3 0 0 0 0]
[3 0 4 0 4]
[3 0 4 4 4]]
My output:
[[1 1 1 1 0]
[1 0 0 0 0]
[0 0 0 2 2]
[0 0 0 2 0]
[3 0 0 2 2]
[3 0 0 2 2]
[3 0 0 2 0]
[3 0 0 2 0]
[3 0 0 2 0]
[3 0 0 0 0]
[3 0 4 0 4]
[3 0 4 4 4]]
Таким образом, если кто-то может указать мне правильное направление относительно того, что я делаю неправильно, это будет очень цениться.