2010-11-27 32 views
28

, açıkgöz operatör için düşük ve yüksek eşikleri zorunludur:otomatik olarak hesaplanması OpenCV

Matlab içinde
cvCanny(input,output,thresh1,thresh2) 

, otomatik olarak bu hesaplamak için bir seçenek var:

edge(input,'canny') 

Matlab'ın kod kenarına baktım ve bu otomatik olarak bunları hesaplamak için gerçekten doğru değil.

Opencv için otomatik eşik hesaplaması ile birlikte kanlı operatörün herhangi bir uygulamasının farkında mısınız?

sayesinde

+0

Bunu yapan Matlab kodunu yükleyebilir misiniz? –

cevap

40

. Bu Canny algoritması için otomatik eşik değerlerini belirlemek için iyi bir yöntem aramak için geliyor herkes yardımcı olur

Umut ...


resminizin farklı ön ve arka plan, ön plan nesne daha sonra kenarına oluşuyorsa

can kullanılarak

  1. hesaplama Otsu eşiği:

    double otsu_thresh_val = cv::threshold(
        orig_img, _img, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU 
    ); 
    
    izleyerek ekstre kullanır

    _img'a ihtiyacımız yok. Sadece otsu_thresh_val ile ilgileniyoruz ama maalesef şu anda OpenCV'de sadece eşik değerini hesaplamanıza imkan veren bir yöntem yok.

  2. Otsu'nun eşik değerini daha yüksek eşik olarak ve Canny algoritması için alt eşik ile aynı olanın yarısı olarak kullanın. Buna ilişkin

    double high_thresh_val = otsu_thresh_val, 
         lower_thresh_val = otsu_thresh_val * 0.5; 
    cv::Canny(orig_img, cannyOP, lower_thresh_val, high_thresh_val); 
    

fazla bilgi this paper: The Study on An Application of Otsu Method in Canny Operator bulunabilir. Otsu uygulamasının bir açıklaması here bulunabilir.

+0

Burada cv nedir? @VP. – TapanHP

+0

OpenCV @TapanHP –

+0

Anladım .. teşekkürler @Dennis – TapanHP

0

Luca Del Tongo'nun önerdiği gibi, gri görüntüden eşikleri hesaplayabilirsiniz, ör. Java'da OpenCV ...

MatOfDouble mu = new MatOfDouble(); 
MatOfDouble stddev = new MatOfDouble(); 
Core.meanStdDev(greyMat, mu, stddev); 
threshold1 = mu.get(0, 0)[0]; 
threshold2 = stddev.get(0, 0)[0]; 
Imgproc.Canny(greyMat, outputMat, threshold1, threshold2); 
+0

Burada biraz matematik eksik değil misiniz? Ortalama genellikle sapmadan daha büyüktür. Yani bence eşik1 = mu - stddev ve 'eşik2 = mu + stddev ' – marsbear

+0

gibi bir şey olmalı Parlak bir masadaki beyaz bir nesne için ortalama ve sapma için 180 ve 67 aldım. Canny, bu değerlerle herhangi bir kenar tespit etmeyecek. Bu görüntü için 14 ve 30 iyi çalışıyor. – marsbear

1

Aynı probleme başka bir yaklaşımım var. Bu çözüm ayrıca kenar algılama için optimal eşiklerin seçimini içerir.

  • İlk hesaplama gri skala görüntü medyan.
  • Gri ​​ölçek görüntüsünün medyanı değerine göre iki değer (alt ve üst eşikler) seçin.

aşağıdaki yalancı kod, yapılan nasıl gösterir:

v = np.median(gray_img) 
sigma = 0.33 

#---- apply optimal Canny edge detection using the computed median---- 
lower_thresh = int(max(0, (1.0 - sigma) * v)) 
upper_thresh = int(min(255, (1.0 + sigma) * v)) 

tedbirli kenar algılama fonksiyonu parametreler olarak, bu eşik sabitleyin.

Şekil: İstatistikte bir Gauss eğrisini gözlemlerseniz, eğrinin her iki tarafındaki 0,33 arasındaki değerler dağıtımda dikkate alınır. Bu noktaların dışındaki herhangi bir değerin aykırı olduğu varsayılır. Görüntüler veri olarak kabul edildiğinden, bu kavram da burada varsayılmaktadır.

+0

Bunu gördünüz mü (http://www.kerrywong.com/2009/05/07/canny-edge-detection-auto-thresholding/), ya da sizin teoriniz mi? – yode

+0

@yode Buna hiç rastlamadım! Bahsettiğin için teşekkürler! –

3

Ben Matlab Canny kenar algılama kaynak koduna baktım ve ben filepath çıkış görüntüleri tutmak için yer OpenCV 3.

private static Mat getpartialedge(Mat image){ 
    double nonEdgeRate = 0.6; 
    double thresholdRate = 0.6; 
    double w = image.cols(); 
    double h = image.rows(); 
    int bins = 256; 
    Mat sobel = new Mat(); 
    Mat sobelx = new Mat(); 
    Mat sobely = new Mat(); 
    Mat sobelxabs = new Mat(); 
    Mat sobelyabs = new Mat(); 
    Size gsz = new Size(5, 5); 
    if(false) { 
     Imgproc.Canny(image, sobel, 41, 71); 
    }else { 

     //Imgproc.GaussianBlur(graycopy,graycopy, gsz, 2); 
     //Imgproc.dilate(image, image, kernel8); 
     Imgproc.GaussianBlur(image, image, gsz, 2); 


     int apertureSize = 3; 
     Imgproc.Sobel(image, sobelx, CvType.CV_16S, 1, 0, apertureSize, 1, 0); 
     Core.convertScaleAbs(sobelx, sobelxabs); 
     Imgproc.Sobel(image, sobely, CvType.CV_16S, 0, 1, apertureSize, 1, 0); 
     Core.convertScaleAbs(sobely, sobelyabs); 
     Core.addWeighted(sobelxabs, 1, sobelyabs, 1, 0, sobel); 
     sobel.convertTo(sobel, CvType.CV_8U); 


     Mat equalized = new Mat(); 
     Imgproc.equalizeHist(sobel, equalized); 
     Imgcodecs.imwrite(filePath + "aftersobel(eq).png", equalized); 
     Imgcodecs.imwrite(filePath + "aftersobel.png", sobel); 


     Mat hist = new Mat(); 
     List<Mat> matList = new ArrayList<Mat>(); 
     matList.add(sobel); 
     Imgproc.calcHist(matList, new MatOfInt(0), new Mat(), hist, new MatOfInt(bins), new MatOfFloat(0f, 256f)); 
     float accu = 0; 
     float t = (float) (nonEdgeRate * w * h); 
     float bon = 0; 
     float[] accutemp = new float[bins]; 
     for (int i = 0; i < bins; i++) { 
      float tf[] = new float[1]; 
      hist.get(i, 0, tf); 
      accu = accu + tf[0]; 
      accutemp[i] = accu; 
      if (accu > t) { 
       bon = (float) i; 
       break; 
      } 
     } 
     Imgproc.threshold(sobel, sobel, bon, 255, Imgproc.THRESH_BINARY); 
     double ut = bon; 
     double lt = thresholdRate * bon; 


     Imgproc.Canny(image, sobel, lt, ut); 
     //Imgproc.dilate(sobel, sobel, kernel2); 
    } 
    return sobel; 
} 

ile Java yazmaya başardı. Ve giriş görüntüsü U8 veri tipi ile gri ölçekli bir görüntü olmalıdır. Temel ilke, parlaklık tarafından nonEdgeRate (% 60) pikselini kenar olmayan piksel olarak dışlamaktır. Parlaklığı sıralamak için bir histogram kullanılır ve üst eşik değeri% 60 pikselin altında olacak şekilde ayarlanır. Alt eşik, üst eşiği eşik (0,6) ile çarparak ayarlanır.

Özel kullanma durumumda, nonEdgeRate = 0.6 ve double thresholdRate = 0.6 çiftlerinin benim tarafımdan ayarlandığını unutmayın. Orijinal değerler matlabda ayrı ayrı 0.7 ve 0.4'dür.

2

ara üzerinden bu bağlantı: http://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/

Bunlar tekin kenar algılama için, düşük ve yüksek eşik seviyesinin belirlenmesi için basit istatistikler kullanılarak benzer bir çözüm uygulanması.

def auto_canny(image, sigma=0.33): 
    # compute the median of the single channel pixel intensities 
    v = np.median(image) 

    # apply automatic Canny edge detection using the computed median 
    lower = int(max(0, (1.0 - sigma) * v)) 
    upper = int(min(255, (1.0 + sigma) * v)) 
    edged = cv2.Canny(image, lower, upper) 

    # return the edged image 
    return edged