Как считать предметы в зависимости от их количества лунок - PullRequest
3 голосов
/ 01 апреля 2019

Я обрабатываю изображение с фигурами, и я пытаюсь подсчитать объекты, которые имеют 1 отверстие, и те, у которых есть 2.

Imgur

Я нашел информацию об этом, но она была в MATLAB Сегментируйте те объекты, в которых есть дыры Они использовали характеристику Эйлера, я знаю, что в Python есть библиотека skimage, но я не могу ее использовать.

Я тоже нашел какой-то код, но не могу его понять. http://www.cis.rit.edu/class/simg782/homework/hw3/hw3solutions.pdf Стр. 16.

PRO hw3 4,A,LA,LC,count
;Find all the holes
Ac=A EQ 0
LC=label region(Ac,/ALL)
;Construct an array with the holes filled in
Afill=(A GT 0) OR (LC GT 1)
;Display the arrays
sa=size(A,/dim)
window,/free,xsize=sa[0],ysize=sa[1]
tvlct,rr,gg,bb,/get
tek color
TV,Afill
window,/free,xsize=sa[0],ysize=sa[1]
TV,LC
;Count the objects with holes. First we
;find all the objects and then match up
;the object labels and the hole labels.
LA=label region(Afill)
window,/free,xsize=sa[0],ysize=sa[1]
TV,LA
ha=histogram(LA)
ia=where(ha ge 0)
print,format=’("Objects",3x,"Count",/,(i2,5x,i7))’,$
[transpose(ia),transpose(ha[ia])]
;Each element of ia corresponds to a filled
;object. Object k is labeled ia[k]. For each
;object that is not background,
;determine whether it has holes.
c=0
print
print,"k ia[k] N C"
For k=1,n elements(ia)-1 DO BEGIN
B=bytarr(sa[0],sa[1]); Make an array with one object
ik=Where(LA eq ia[k]); ;Fill in the object
IF MIN(ik) GE 0 THEN B[ik]=1
;Now see if any of the object pixels match the
;hole image LC. Counts if one or more holes.
IF MAX(B AND (LC GT 0)) GT 0 THEN c++
print,[k,ia[k],n elements(ik),c],format=’(I2,1x,I2,3x,I5,2x,I1)’
END
Print,’Number of objects with one or more holes=’,count
tvlct,rr,gg,bb
END
IDL> hw3 4,A,LA,LC,count

Идея состоит в том, чтобы подсчитать объекты с 1 отверстием и объекты с 2 отверстиями и выделить их края.

"Количество объектов с одним отверстием: 2"

"Количество объектов с двумя отверстиями: 4"

Вот что у меня есть, я сделал это простым cv2.HoughCircles:

Imgur

Ответы [ 2 ]

1 голос
/ 05 апреля 2019

Иерархия контуров может использоваться для подсчета объектов в зависимости от их количества отверстий. Представьте, что у вас есть 100 пустых коробок разных размеров, от большой холодильной коробки до маленькой шкатулки для драгоценностей. Вы хотите хранить все 100 коробок, поэтому вы помещаете некоторые из них в другие большие коробки. Вы также хотите иметь возможность позже найти ящики, поэтому сохраняете список того, какой ящик находится внутри какого ящика. Контуры работают так же, и этот список называется иерархией.

Чтобы найти контуры и иерархию:

img = cv2.imread('/home/stephen/Desktop/test.png', 0)
_, contours, hierarchy = cv2.findContours(img,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)

Далее, итерация по каждому контуру, чтобы найти, есть ли внутри него какие-либо контуры

max_num = np.amax(hierarchy) +1
for c, h in zip(contours, hierarchy[0]):
    # If there is at least one interior contour, find out how many there are
    if h[2] != -1:
        # Make sure it's not the 'zero' contour
        if h[0] == -1:
            num_interior_contours = max_num - h[2]
        else: num_interior_contours = h[0]-h[2]
    else: num_interior_contours = 0

Нарисуйте или посчитайте количество контуров, внутри которых есть другой контур:

if num_interior_contours == 1:
    cv2.drawContours(img_color, [c], -1, (255,0,255), 2)
# Outline the contour in green if there are two holes.
if num_interior_contours == 2:
    cv2.drawContours(img_color, [c], -1, (0,255,0), 2)

shapes with one hole in pink, with two in green

1 голос
/ 05 апреля 2019

Ну, вы всегда можете реализовать характеристику Эйлера самостоятельно. Об этом Стив Эддинс написал в своем блоге MathWorks . Там он цитирует Robot Vision, Бертольд К.П. Хорн, MIT Press, 1989. , где оригинальный автор (очевидно, не может получить доступ к источнику) демонстрирует O (n) способ вычисления (4- связано) Эйлерова характеристика. Затем Eddins демонстрирует, как вы можете выполнить ту же операцию с изображениями с несколькими метками, а также пример кода MATLAB.

Вот мое преобразование Numpy его кода вместе с некоторыми OpenCV для реализации желаемого подсчета дырок:

import numpy as np
import cv2

def EulerNumbers(L):
    '''
    For a label matrix L containing nonnegative integers, returns a vector e
    such that e[k-1] is the 4-connected Euler number of the binary image (L ==
    k), from k = 1 to max(L).

    Adapted from:
    https://blogs.mathworks.com/steve/2014/10/02/lots-and-lots-of-euler-numbers/
    Accessed on 5.4.2019.
    '''

    Lp = np.pad(L, ((1,0), (1,0)), 'constant')

    I_NW = Lp[ :-1,  :-1];
    I_N  = Lp[ :-1, 1:  ];
    I_W  = Lp[1:  ,  :-1];

    is_upstream_convexity = np.logical_and(L,(L != I_N));
    is_upstream_convexity = np.logical_and(is_upstream_convexity, (L != I_NW));
    is_upstream_convexity = np.logical_and(is_upstream_convexity,  (L != I_W));

    is_upstream_concavity = np.logical_and(L,(L != I_NW));
    is_upstream_concavity = np.logical_and(is_upstream_concavity, (L == I_N));
    is_upstream_concavity = np.logical_and(is_upstream_concavity, (L == I_W));

    upstream_convexity_labels = L[is_upstream_convexity];
    upstream_concavity_labels = L[is_upstream_concavity];

    total_upstream_convexities = np.bincount(upstream_convexity_labels)[1:] #Discard the zero bin, which is the background.
    total_upstream_concavities = np.bincount(upstream_concavity_labels)[1:]

    return total_upstream_convexities - total_upstream_concavities;


#Load the image
BwI = cv2.imread('BwI.png', cv2.IMREAD_GRAYSCALE)

#Label all the connected components
_, L = cv2.connectedComponents(BwI)

#Compute all the Euler numbers
e = EulerNumbers(L)

# All the regions with no holes will have an Euler number of 1. Regions with one hole
# will have an Euler number of 0. Two holes -> -1 etc. 

num_no_holes = np.sum(e==1)
num_single_hole = np.sum(e==0)
num_two_holes = np.sum(e==-1)
num_three_holes = np.sum(e==-2)
num_more_holes = np.sum(e<-2)

print('Number of objects without holes : %d'%num_no_holes)
print('Number of objects with single hole : %d'%num_single_hole)
print('Number of objects with two holes : %d'%num_two_holes)
print('Number of objects with three holes : %d'%num_three_holes)
print('Number of objects with more than three holes: %d'%num_more_holes)

## Example, colourcode all objects by their amount of holes

Euler2Numholes = lambda e : abs(e-1)

#Label each region by the number of holes it has + 1.
# +1 so the holeless ones won't dissappear.
L_holecounts = np.zeros(L.shape, dtype=np.int32)
for i in range(1, np.max(L)):
    L_holecounts[L == i] = Euler2Numholes(e[i-1])+1

#Spread the small range to [0,255]
plot_L = cv2.normalize(L_holecounts, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8UC1) 
#Note that this will break when there are more than 255 labels. The colormap only works with uint8.

#Colormap it
plot_L = cv2.applyColorMap(plot_L, cv2.COLORMAP_JET)

cv2.imshow('The objects colourcoded by their number of holes', plot_L)
cv2.waitKey(0)

Выходы:

Количество объектов без отверстий: 21
Количество объектов с одним отверстием: 2
Количество объектов с двумя отверстиями: 4
Количество объектов с тремя отверстиями: 0
Количество объектов с более чем тремя отверстиями: 0

Colour_coded_labels

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...