2016-05-04 36 views
6

Python kullanarak resimlerdeki delikleri doldurmalıyım. Bu, almayı başarabildiğim nesnelerle görüntüdür - onlar gerçekten istediğim nesnelerin kenarlarıdır, bu yüzden onları doldurmam gerekir. enter image description hereBir resimde zor doldurma delikleri

O ndimage.binary_fill_holes(A) kullanarak çok basit görünüyordu, ama sorun o (el kırmızı renk ile doldurulur) bu üretmesidir:

enter image description here

Ama bu gerekir:

enter image description here

Bu, herhangi bir şekilde çözülebilir mi? enter image description here

+0

Güzel sorun. Burada açıklandığı gibi OpenCV'den kontur hiyerarşisi ile çözebileceğinizi düşündünüz. Http://docs.opencv.org/3.1.0/d9/d8b/tutorial_py_contours_hierarchy.html#gsc.tab=0 ama bu kritik kontur olduğundan bu işe yaramaz. gerçek çocuk yok. Bunun, örnek dosyayı kullanarak çalışmadığını hızlıca görebilirsiniz. Https://github.com/Itseez/opencv/blob/master/samples/python/contours.py – tfv

+0

Teşekkürler, @tfv! Olumsuz sonuç da bir sonuçtur ... – Phlya

+0

Verdiğiniz resmin, aradığınız kararı vermesine izin vermediğini söyleyebilirim. Bir sınır var (eğer algoritma sizin istediğinizi alması bekleniyorsa), bir kesişme noktasını geçtikten sonra bir diğerini geçtiğinizde, hala bir deliğin içindeydiniz. normal durumlar. – roadrunner66

cevap

2

ben bir çözüm buldum düşünüyorum: Eğer bir deneyin isterseniz

Bu eksenler olmadan ilk görüntüdür. Zamanım tükendiğinden beri biraz uzun, ama belki yardımcı olur. Sadece bu sorun için kodlanmıştım, ancak birçok görüntü için genelleştirmesi kolay olmalı. İlk

Bazı adlandırma kurallarına:

  • I fon ışıması çevrelediği kompakt bölgeler olarak "ilk seviye bölgeleri" tanımlar. Bu birinci seviye bölgeler farklı alt bölgelerden oluşabilir. Birden fazla alt bölgeden oluşan birinci düzey bölgeye kritik bölge adı verilir.

Temel düşüncem kritik bölgelerin parçası olan iki alt bölgedeki konturların uzunluklarını karşılaştırmaktır. Ancak, Ben onların tam kontür uzunluğunu karşılaştırmak değil, sadece arka plan yakın olan segment. Arka tarafa yakın olan kısa kontur segmenti olan bir delik olarak kabul edilir.

İlk olarak sonuç görüntüleriyle başlayacağım.

biz bahsediyoruz yukarıdaki adlandırma kurallarına vizualizing şeyin Bazı bakış: kritik bölgenin

enter image description here

iki alt bölgeler. Arka plana yakın olan bölgelerin her birinin iki kenarlık bölümü farklı renklerde (çok ince, mavi ve koyu kırmızı, ancak görünür) işaretlenmiştir. Bu segmentler ("ince" alanlar hatalara neden) elbette mükemmel değil, ama yeterli uzunluğunu karşılaştırmak için:

enter image description here

nihai sonuç. "Kapalı" deliğe sahip olmak istediğinizde bana bildirin, sadece orijinal siyah konturları arka plan yerine bölgelere atamanız gerekir ([DÜZENLE] Sınırları atayan üç işaretli kod satırı dahil ettim siz istediniz bölgelerde) için:

enter image description here

Kod burada takılır. Oldukça sağlam ve açık bir şekilde OpenCV kontur fonksiyonunu kullandım ve bazı maskeleme teknikleri.Kod, görselleştirilmeleri nedeniyle okunaklı, okunaklılığı nedeniyle özür diler, ancak bu soruna iki çizgi çözümü görünmemektedir.

Bazı son sözler: İlk olarak, döngülerden kaçınan ve arka plana yakın iki kontur parçasını belirlemek için set.intersection kullanılmasına izin veren nokta kümelerini kullanarak konturları eşleştirmeyi denedim, ancak siyah çizgilerinizden oldukça kalın, kontürler birbiriyle uyuşmuyor. Konturların iskeletlenmesini denedim, fakat bu başka bir solucan konservesi açmıştı, bu yüzden kontur noktaları arasında bir döngü ve hesaplama mesafesi yapan bir döküm yaklaşımıyla çalıştım. Bu kısmı yapmanın daha güzel bir yolu olabilir, ama işe yarıyor.

Ayrıca Shapely modülünü kullanmayı düşündüm, ondan bazı avantajlar elde etmenin yolları olabilir, ama bulamadım, bu yüzden tekrar düşürdüm.

import numpy as np 
import scipy.ndimage as ndimage 
from matplotlib import pyplot as plt 
import cv2 


img= ndimage.imread('image.png') 

# Label digfferentz original regions 
labels, n_regions = ndimage.label(img) 
print "Original number of regions found: ", n_regions 
# count the number of pixels in each region 
ulabels, sizes = np.unique(labels, return_counts=True) 
print sizes 

# Delete all regions with size < 2 and relabel 
mask_size = sizes < 2 
remove_pixel = mask_size[labels] 
labels[remove_pixel] = 0 
labels, n_regions = ndimage.label(labels) #,s) 
print "Number of regions found (region size >1): ", n_regions 
# count the number of pixels in each region 
ulabels, sizes = np.unique(labels, return_counts=True) 
print ulabels 
print sizes 


# Determine large "first level" regions 
first_level_regions=np.where(labels ==1, 0, 1) 
labeled_first_level_regions, n_fl_regions = ndimage.label(first_level_regions) 
print "Number of first level regions found: ", n_fl_regions 


# Plot regions and first level regions 
fig = plt.figure() 
a=fig.add_subplot(2,3,1) 
a.set_title('All regions') 
plt.imshow(labels, cmap='Paired', vmin=0, vmax=n_regions) 
plt.xticks([]), plt.yticks([]), plt.colorbar() 
a=fig.add_subplot(2,3,2) 
a.set_title('First level regions') 
plt.imshow(labeled_first_level_regions, cmap='Paired', vmin=0, vmax=n_fl_regions) 
plt.xticks([]), plt.yticks([]), plt.colorbar() 


for region_label in range(1,n_fl_regions): 
    mask= labeled_first_level_regions!=region_label 
    result = np.copy(labels) 
    result[mask]=0  
    subregions = np.unique(result).tolist()[1:] 
    print region_label, ": ", subregions 

    if len(subregions) >1: 
     print " Element 4 is a critical element: ", region_label 
     print " Subregions: ", subregions 

     #Critical first level region 
     crit_first_level_region=np.ones(labels.shape) 
     crit_first_level_region[mask]=0 

     a=fig.add_subplot(2,3,4) 
     a.set_title('Crit. first level region') 
     plt.imshow(crit_first_level_region, cmap='Paired', vmin=0, vmax=n_regions) 
     plt.xticks([]), plt.yticks([]) 

     #Critical Region Contour 
     im = np.array(crit_first_level_region * 255, dtype = np.uint8) 
     _, contours0, hierarchy = cv2.findContours(im.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) 
     crit_reg_contour = [contours0[0].flatten().tolist()[i:i+2] for i in range(0, len(contours0[0].flatten().tolist()), 2)] 
     print crit_reg_contour 
     print len(crit_reg_contour) 



     #First Subregion 
     mask2= labels!=subregions[1] 
     first_subreg=np.ones(labels.shape) 
     first_subreg[mask2]=0 

     a=fig.add_subplot(2,3,5) 
     a.set_title('First subregion: '+str(subregions[0])) 
     plt.imshow(first_subreg, cmap='Paired', vmin=0, vmax=n_regions) 
     plt.xticks([]), plt.yticks([])   

     #First Subregion Contour 
     im = np.array(first_subreg * 255, dtype = np.uint8) 
     _, contours0, hierarchy = cv2.findContours(im.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) 
     first_sub_contour = [contours0[0].flatten().tolist()[i:i+2] for i in range(0, len(contours0[0].flatten().tolist()), 2)] 
     print first_sub_contour 
     print len(first_sub_contour) 




     #Second Subregion 
     mask3= labels!=subregions[0] 
     second_subreg=np.ones(labels.shape) 
     second_subreg[mask3]=0 

     a=fig.add_subplot(2,3,6) 
     a.set_title('Second subregion: '+str(subregions[1])) 
     plt.imshow(second_subreg, cmap='Paired', vmin=0, vmax=n_regions) 
     plt.xticks([]), plt.yticks([])  

     #Second Subregion Contour 
     im = np.array(second_subreg * 255, dtype = np.uint8) 
     _, contours0, hierarchy = cv2.findContours(im.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) 
     second_sub_contour = [contours0[0].flatten().tolist()[i:i+2] for i in range(0, len(contours0[0].flatten().tolist()), 2)] 
     print second_sub_contour 
     print len(second_sub_contour) 


     maxdist=6 
     print "Points in first subregion close to first level contour:" 
     close_1=[] 
     for p1 in first_sub_contour: 
      for p2 in crit_reg_contour: 
       if (abs(p1[0]-p2[0])+abs(p1[1]-p2[1]))<maxdist: 
        close_1.append(p1) 
        break 

     print close_1 
     print len(close_1) 

     print "Points in second subregion close to first level contour:" 
     close_2=[] 
     for p1 in second_sub_contour: 
      for p2 in crit_reg_contour: 
       if (abs(p1[0]-p2[0])+abs(p1[1]-p2[1]))<maxdist: 
        close_2.append(p1) 
        break 

     print close_2 
     print len(close_2)  


     for p in close_1: 
      result[p[1],p[0]]=1 

     for p in close_2: 
      result[p[1],p[0]]=2 


     if len(close_1)>len(close_2): 
      print "first subregion is considered a hole:", subregions[0] 
      hole=subregions[0] 
     else:    
      print "second subregion is considered a hole:", subregions[1] 
      hole=subregions[1] 


     #Plot Critical region with subregions 
     a=fig.add_subplot(2,3,3) 
     a.set_title('Critical first level region with subregions') 
     plt.imshow(result, cmap='Paired', vmin=0, vmax=n_regions) 
     plt.xticks([]), plt.yticks([]) 

     result2=result.copy() 


#Plot result 
fig2 = plt.figure() 
a=fig2.add_subplot(1,1,1) 
a.set_title('Critical first level region with subregions and bordering contour segments') 
plt.imshow(result2, cmap='flag', vmin=0, vmax=n_regions) 
plt.xticks([]), plt.yticks([]) 


#Plot result 
mask_hole=np.where(labels ==hole, True, False) 
labels[mask_hole]=1 
labels=np.where(labels > 1, 2, 1) 

# [Edit] Next two lines include black borders into final result 
mask_borders=np.where(img ==0, True, False) 
labels[mask_borders]=2 


fig3 = plt.figure() 
a=fig3.add_subplot(1,1,1) 
a.set_title('Final result') 
plt.imshow(labels, cmap='flag', vmin=0, vmax=n_regions) 
plt.xticks([]), plt.yticks([]) 


plt.show() 
+0

teşekkür ederim! Tam olarak ihtiyacım olan şeyi yapmayı başarmış gibisin! (Sadece konturların bölgelerin bir parçası olması gerekir, bu 'oldukça önemlidir) Daha sonra daha ayrıntılı olarak kontrol edeceğim ve muhtemelen cevabınızı kabul edeceğim. – Phlya

+1

Bunu yapmak için üç işaretli çizgi ekledim ve son resmi buna göre değiştirdim. – tfv