2012-10-09 4 views
6

. Daha sonra bu noktaları eğriyi izleyen kübik bir spline takacağım. boyunca her bir konumda kullanmak için açısını hesaplamak -Bir blobtan dik açıda bir çizgiyi nasıl örneklendiririm? (Python/OpenCV Başka bir şey geçmenizi öneririz sürece) Ben kavisli konfeti parçalarını andıran ikili lekeler merkezinde aşağı noktalar iz tanıyacak bir program üzerinde çalışıyorum

, bir ikili görüntüde boyunca açılı bir çizgi örnekleme 2B vektörü yaratmak -

:

programının bir parçası olarak, gerek konfeti blob. İşte

görüntülerin bazı örnekler ve noktalar gibi görünebilir takip şeyin skeçler:

enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here

dikey bölümün merkezini bulma siyah bir konfeti basittir. Siyah bir pikselde olmanız, sol ve sağdaki beyaz kenarı bulmanız şartıyla, orta, bunların arasındaki mesafenin yarısıdır. Bunu yapmak kolaydır çünkü yukarıdaki hesaplamayı yapmak için kullanılan 2d vektörü görüntünün sadece bir satırıdır.

this is a 10 pixel height segment of one of the confetti pieces

enter image description here

Ama konfeti parçaları hep düz ve dikey olarak hizaya yok! Bazen kavisli veya yatay olarak hizalanırlar. Burada ihtiyaç duyulan şey, bir açıda konfeti boyunca bir bölümü kesen bir 2d vektörüdür. Bu açılı vektörü görüntüden örneklemenin en etkili yolu nedir? Pratik olarak, bu Python PIL veya OpenCV gibi bir görüntü işleme kitaplığında, bir görüntü açıların çizgilerin vektörleri elde operasyonlar var mı? Bir tane yaparsam, verimli olduğundan emin olmak için nasıl yardımcı olabilirim?

vektörü açısını gerekli hesaplamak için en etkili yolu nedir? Uygun açıyı elde etmenin bir yolu, döndürülen 2d vektöründeki minimum genişlikte siyah segmentle sonuçlanan açıyı bulmaktır. Bu etraflıca, 30 derece ile 360 ​​derece arasında, sadece çevrim konfeti parçasının eğrisinin teğet bulmak ve bu dik hat kullanmak olabilir uygun bir açı elde etmek için başka bir şekilde artırır yapmaya gerek yoktur - ama bu daha karmaşık olabilir. Sorunu daha iyi mücadele konusunda

Herhangi bir düşünce çok yararlı olacaktır. Bir görüntü boyunca 2d çizgisinin nasıl alınacağına ve dikey açıyı elde etmenin etkili bir yoluna ilişkin özel öneriler de harika olacaktır.

enter image description here

cevap

1

Bu kontur incelmesine veya iskelet gibi görünüyor. that answer'a bir göz atın. Python paketine bile bir link var. boyunca yöneliminin bir tahmin ile (genellikle o eksenini yeterli herhangi bir noktada eksenin teğet varsa) -

+0

Kontur incelmesi yararlı olabilir - Buna bakacağım. Sanırım iskeletleme, hesaplama yapamayacak kadar pahalı olacak çünkü en sonunda gerçek zamanda olmasa da video üzerinde yapacağım. Yine de güzel bir Python görüntü işleme kütüphanesi! – user391339

4

Size "uydurma medial ekseni" ilgilenen görünür.Eğer vermezse, @remi morfolojik incelme tarafından önerildiği gibi ...

Ama -

Teknik olarak OpenCV ile, sen Voronoi hücreleri kullanılarak, bir mesafe (cv.PointPolygonTest) dönüşümü kullanarak (cv.cvCalcSubdivVoronoi2D) dikkate olabilecek veya scikits-image paketini kullanmak ve sadece OpenCV kullanmak zorunda kaldım - burada bir iskeletleme kodu (based on a quick and easy technique) kullanarak bir başlangıç ​​denemesi.

simple first image skeletonenter image description hereenter image description here

Ardından örnekleri ve teğet çalışmak keşfedilen noktaları boyunca uydurma bazı yiv vasıtasıyla bunu takip edebiliyoruz (ancak bu uçlarını keşfetmek için biraz daha fazla çalışmayı gerektiren ve bir yerime noktalarını kaldırmak için

/Boşluklar ...)

import cv 

# get images 
orig = cv.LoadImage('o1Mlp.png') 

# create storage images 
grey = cv.CreateImage(cv.GetSize(orig), 8, 1) 
skel = cv.CreateImage(cv.GetSize(orig),8, 1) 
temp = cv.CreateImage(cv.GetSize(orig),8,1) 

# convert image to pure binary B&W based on threshold 
cv.CvtColor(orig, grey, cv.CV_RGB2GRAY) 
cv.Threshold(grey,grey,200,255,cv.CV_THRESH_BINARY_INV) 

# Create cross operator - good for skeletonization 
elem = cv.CreateStructuringElementEx(3,3,1,1,cv.CV_SHAPE_CROSS) 

# Loop until we have consumed all the values in the original image 
while True: 
    cv.MorphologyEx(grey,temp,None,elem,cv.CV_MOP_OPEN) # Shrink.. 
    cv.Not(temp,temp) # ...invert... 
    cv.And(grey,temp,temp) # ...intersect with original... 
    cv.Or(skel,temp,skel) # ... add to current skeleton... 
    cv.Erode(grey,grey,elem) # and reduce original ready for next. 

    (minVal,maxVal,minLoc,maxLoc)= cv.MinMaxLoc(grey) 
    if (maxVal==0): # Any pixels left? 
    break 

# show result 
cv.ShowImage("orig", orig) 
cv.ShowImage("skel", skel) 
cv.WaitKey(-1) 
+0

Çok teşekkürler. Bunu çalışıp çalışıp çalışmayacağını inceleyeceğim. Küçük iskeleleri ana iskeletten çıkarmak zorunda kalacağım, ancak izleme konusunda kesinlikle iyi bir iş çıkar. – user391339

2

Sorunun son kısmı ile ilgili olarak, normalleri bulmak: Kendi algoritmamı kullanırım. Çalışıyor gibi görünüyor. Standart bir çözüm bulursanız veya geliştirirseniz, lütfen bize bildirin!

/// <summary> 
    /// Returns absolute angle between points at offset length, or double.MinValue when not found. 
    /// </summary> 
    /// <param name="sequence">Ordered array of points (e.g., from OpenCV Contour)</param> 
    /// <param name="length">Number of points used to calculate angle</param> 
    /// /// <param name="increment">number of points between each angle calculation (e.g., 1 to attempt to determine angles for all points)</param> 
    /// <returns></returns> 
    public static double[] FindAbsoluteAngles(Point[] sequence, int length, int increment) 
    { 
     double[] angles = new double[sequence.Length]; 
     for (int i = 0; i < sequence.Length; i++) 
      angles[i] = double.MinValue; 

     double last = double.MinValue; 
     for (int i = length; i < sequence.Length; i += increment) 
     { 
      int i1 = i - length; 
      int i2 = i - ((int)length/2); 
      int i3 = i; 

      Point p1 = sequence[i1]; 
      Point p2 = sequence[i2]; 
      Point p3 = sequence[i3]; 

      if (p1.X != p3.X & p1.Y != p3.Y)//Is a diagonal 
      { 
       angles[i2] = 180 - Math.Atan(1.0 * (p1.X - p3.X)/(p1.Y - p3.Y)) * 180/Math.PI; 
      } 
      else if (last != double.MinValue) 
      { 
       //USe previous angle to determine non-diagonals (which can be: 0 or 180; 90 or 270) 
       double error; 
       if (p1.X == p3.X)//Is a vertical 
       { 
        error = Math.Abs(last - 180); 
        if (Math.Min(error, 180 - error) == error) 
         angles[i2] = 180; 
        else 
         angles[i2] = 0; 
       } 
       else if (p1.Y == p3.Y)//Is a horizontal 
       { 
        error = Math.Abs(last - 270); 
        if (Math.Min(error, 180 - error) == error) 
         angles[i2] = 270; 
        else 
         angles[i2] = 90; 
       } 
      } 

      last = angles[i2]; 
     } 

     return angles; 
    } 
İlgili konular