Как удалить самый большой контур в изображении скелета в Python?

Я хотел бы удалить окружность (крайний периметр знака) этого знака каркаса колеса, кроме того, что находится внутри. Я думаю о функции findcontours () и удаляю самый большой контур, который я нашел

Это входное изображение:

Исходное изображение

Скелетонизированный:

изображение скелета

но, к сожалению, это мое выходное изображение:

изображение скелета без наибольшего контура

Почему не остается только 2 скрещенных сегмента, а сегмент состоит из множества точек

from __future__ import division
import mahotas as mh
import pymorph as pm
import numpy as np

import os
import math

import cv2
from skimage import io
import scipy
from skimage import morphology

complete_path = 'DUPLInuova/ruote 7/e (11).jpg'

fork = mh.imread(complete_path)  
fork = fork[:,:,0]# extract one component, ex R 

#structuring elements
disk7 = pm.sedisk(3)#size 7x7: 7=3+1+3
disk5 = pm.sedisk(2)

#Just a simple thresholding with white background
bfork = fork < 150
bfork = mh.morph.dilate(bfork, disk7)

gray = cv2.imread(complete_path,0)
originale = gray
print("gray")
print(gray.shape)
cv2.imshow('graybin',gray)
cv2.waitKey()

ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV) 
imgbnbin = thresh
print("shape imgbnbin")
print(imgbnbin.shape)
cv2.imshow('binaria',imgbnbin)
cv2.waitKey()
shape = list(gray.shape)
w = int( (shape[0]/100 )*5)
h = int((shape[1]/100)*5)
print(w)
print(h)
element = cv2.getStructuringElement(cv2.MORPH_CROSS,(w,h)) #con 4,4 si vede tutta la stella e riconosce piccoli oggetti
from skimage.morphology import square

graydilate = np.array(imgbnbin, dtype=np.float64)
graydilate = morphology.binary_dilation(graydilate, square(w))
graydilate = morphology.binary_dilation(graydilate, square(w))

out = morphology.skeletonize(graydilate>0)
img = out.astype(float)
cv2.imshow('scikitimage',img)
cv2.waitKey()
img = img.astype(np.uint8)
cv2.imshow('scikitconvert',img)
cv2.waitKey()

contours, hierarchy = cv2.findContours(img,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))

# calculating area for deleting little signs
Areacontours = list()
calcarea = 0.0
unicocnt = 0.0
for i in range (0, len(contours)):
    area = cv2.contourArea(contours[i])
    #print("area")
    print(area)
    if (area > 90 ): 
        if (calcarea<area):
            calcarea = area
            unicocnt = contours[i]

cnt = unicocnt
ara = cv2.contourArea(cnt)
print("cnt")
print(ara)

#delete largest contour
cv2.drawContours(img,[cnt],0,(0,255,0),1)
cv2.imshow('img del contour',img)
cv2.waitKey()

ОБНОВЛЕНИЕ РЕШЕНИЯ (и новый вопрос):

если я сделаю глубокую копию скелетонизированного img после этой строки кода: img = img.astype (np.uint8) # после процедуры скелетонизации

Я могу использовать find_contour со скопированным изображением и применить draw_contour к исходному изображению, и все!

Мои вопросы:

Зачем находить контурное редактирование моего изображения, и я вынужден использовать временное изображение? Почему matplotlib показывает мне правильный результат, а cv2 imshow - нет (он показывает мне черное изображение)?

Новая часть кода:

import copy
imgcontour = copy.copy(img)

imgcnt = img
contours, hierarchy = cv2.findContours(imgcontour,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE )
print(len(contours))

cnt = contours[0]

cv2.drawContours(img,[cnt],0,(0,0,0),1)

cv2.imshow('imgcv2black',img)
cv2.waitKey()

plt.gray()
plt.subplot(121)
plt.imshow(img)
plt.show()

правильный результат в matplotlib

ОБНОВЛЕНИЕ FLOODFILE + DILATE:

Это правильная процедура заливки-расширения? Где это неправильно?

a = np.ones((212,205), dtype=np.uint8)
#myMask = zeros(a.shape[0:2], dtype = uint8)

maskr = np.zeros(a.shape,np.uint8)
print(maskr.shape)
print(img[0])

cv2.floodFill(img,mask =maskr, seedPoint = (0,0), newVal = 1)
element = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3)) 
img = cv2.dilate(img, element)

cv2.imshow('flood',img)
cv2.waitKey()
plt.gray()
plt.subplot(121)
plt.imshow(img)
plt.show()

и я, к сожалению, получаю это:

floodfil + dilate


person improc    schedule 02.05.2013    source источник


Ответы (3)


Другой способ добиться желаемого результата - это заливка скелетонизированного изображения заливкой. Поскольку внешняя граница закрыта, будут выделены все пиксели за пределами объекта. Затем можно применить простое растяжение, чтобы расширить заполненную область, чтобы включить внешнее кольцо. Примените это как маску и удалите все пиксели, которые были заполнены заливкой + растяжением. Это оставит только центр колеса.

person denver    schedule 03.05.2013

Очень простым решением было бы пометить компоненты контуров на изображении. В таком случае вы можете выделить контуры, которые вас интересуют. А поскольку разметка начинается снаружи топологически, если отображаются все метки контура, кроме первой, у вас должен быть результат. В случае, когда контуры уже замкнуты, каркас не понадобится! Также можно использовать дальнейшее прореживание для получения тонких контуров, если те, с которых мы начинаем, толстые.

Ввод: I

введите описание изображения здесь

Обозначенные контуры: L = bwlabel (~ I);

введите описание изображения здесь

Удаление самого большого внешнего контура: рисунок, imshow (L> 1)

введите описание изображения здесь

Это должно быть возможно воспроизвести в scikits настройка маркировки подключенных компонентов.

Вы также можете рассчитать размер этих компонентов и получить их длину (сумма (сумма (L == 1)) и т. Д.)

person beedot    schedule 04.11.2013

Вы также можете использовать круговое преобразование Хафа, чтобы попытаться найти обод колеса, а затем работать оттуда.

person Stefan van der Walt    schedule 06.05.2013