2013-07-19 18 views
7

My çalışma görüntüleri dayanmaktadır çizimi (. Şekil 1) ve nihai sonuç, Şekil 4'de gösterilmiştir I adım çalışmalarım adım açıklayacaktır.opencv. Kenar algılama, Genleşme ve Kütle ceter noktalar dizisi ile

Şekil 1 Orijinal görüntü

enter image description here

Aşama 1:. daha iyi performans için silmek isteyen noktalar ve bir "halka" da dahil olmak üzere, her nesnenin kenarını, algılar. Ve kenar tespitinin sonucu Şekil 2'de gösterilmektedir. Canny kenar dedektörü kullandım ama bazı açık gri noktalar ile iyi çalışmadı. ilk sorum nokta hatlarını kapatıp mümkün olduğunca diğer gürültüyü azaltmak için nasıl?

Şekil 2, kenar algılama

enter image description here

Adım 2:. Dilate her nesne. Delikleri doldurmanın iyi bir yolunu bulamadım, bu yüzden onları doğrudan dilate ediyorum. Şekil 3'te görüldüğü gibi, delikler çok fazla büyütülmüş gibi görünmektedir ve diğer sesler de artmaktadır. İkinci sorum doldurmak ya da onları aynı/benzer boyutta çevreleri doldurulacak yapmak için delikler dilate nasıl?

Şekil 3 Dilatasyon

enter image description here

Adım 3:. bulun ve her noktanın kütlesi merkezini çizin. Şekil 4'te gösterildiği gibi, kaba görüntü işlemeden dolayı, "halkanın" işareti vardır ve bazı noktalar iki beyaz pikselde gösterilmiştir. İstenilen sonuç sadece bir nokta için noktaları ve bir beyaz pikseli göstermelidir.

Şekil 4:. Kütle merkezleri

enter image description here

İşte bu 3 adım için benim kodudur. Herkes işimi daha iyi hale getirebilir mi?

#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 
#include <stdlib.h> 
#include <stdio.h> 
#include <cv.h> 
#include <highgui.h> 
using namespace std; 
using namespace cv; 

// Global variables 
Mat src, edge, dilation; 
int dilation_size = 2; 

// Function header 
void thresh_callback(int, void*); 

int main(int argc, char* argv) 
{ 
    IplImage* img = cvLoadImage("c:\\dot1.bmp", 0);   // dot1.bmp = Fig. 1 

    // Perform canny edge detection 
    cvCanny(img, img, 33, 100, 3); 

    // IplImage to Mat 
    Mat imgMat(img); 
    src = img; 

    namedWindow("Step 1: Edge", CV_WINDOW_AUTOSIZE); 
    imshow("Step 1: Edge", src); 

    // Apply the dilation operation 
    Mat element = getStructuringElement(2, Size(2 * dilation_size + 1, 2 * dilation_size + 1), 
        Point(dilation_size, dilation_size));  // dilation_type = MORPH_ELLIPSE 
    dilate(src, dilation, element); 
    // imwrite("c:\\dot1_dilate.bmp", dilation);    

    namedWindow("Step 2: Dilation", CV_WINDOW_AUTOSIZE); 
    imshow("Step 2: Dilation", dilation); 

    thresh_callback(0, 0); 

    waitKey(0); 
    return 0; 
} 

/* function thresh_callback */ 
void thresh_callback(int, void*) 
{ 
    vector<vector<Point>> contours; 
    vector<Vec4i> hierarchy; 

    // Find contours 
    findContours(dilation, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 

    // Get the moments 
    vector<Moments> mu(contours.size()); 
    for(int i = 0; i < contours.size(); i++) { 
     mu[i] = moments(contours[i], false); 
    } 

    // Get the mass centers 
    vector<Point2f> mc(contours.size()); 
    for(int i = 0; i < contours.size(); i++) { 
     mc[i] = Point2f(mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00); 
    } 

    // Draw mass centers 
    Mat drawing = Mat::zeros(dilation.size(), CV_8UC1); 
    for(int i = 0; i< contours.size(); i++) { 
     Scalar color = Scalar(255, 255, 255); 
     line(drawing, mc[i], mc[i], color, 1, 8, 0); 
    } 

    namedWindow("Step 3: Mass Centers", CV_WINDOW_AUTOSIZE); 
    imshow("Step 3: Mass Centers", drawing); 
} 
+0

Eğer [burada] (http://stackoverflow.com/questions/1716274/fill-the-holes-in-opencv) henüz bir şey denediniz mi? – William

cevap

9

Sonuçlarınızı iyileştirmek için yapabileceğiniz birkaç şey vardır. Görüntüdeki paraziti azaltmak için Canny operatörünü uygulamadan önce medyan bir bulanıklık uygulayabilirsiniz. Bu yaygın bir de-noising tekniği. Ayrıca C API'sini ve IplImage'u kullanmayı denemeye çalışın. Canny result

daha iyi noktaların orijinal boyutlarını korumak için, daha küçük bir çekirdekte ziyade ile morfolojik kapanış birkaç tekrarlamadan gerçekleştirebilir:

cv::Mat img = cv::imread("c:\\dot1.bmp", 0);   // dot1.bmp = Fig. 1 

    cv::medianBlur(img, img, 7); 

    // Perform canny edge detection 
    cv::Canny(img, img, 33, 100); 

Bu önemli ölçüde kenar görüntüdeki gürültüyü de azaltarak dilatasyon. Bu aynı zamanda, bir daire ile noktaların birleştirilmesi azaltır: Bu cv::noArray() kullanılarak belirtilir 3x3 çekirdek, iki yineleme gerçekleştirecek

// This replaces the call to dilate() 
cv::morphologyEx(src, dilation, MORPH_CLOSE, cv::noArray(),cv::Point(-1,-1),2); 

.

sonuç daha temizdir, noktalar tamamen doldurulur:

Closing result

değiştirilmemiş nihai sonucu verir senin boru hattının geri kalanını terk etmek. Orijinal yönteminden önemli ölçüde daha az bulunmaktadır daireden birkaç sahte kitle merkezleri hala vardır, ancak: tamamen sonuçlardan daireyi kaldırarak girişimi istiyorsa

Mass centers

, sen cv::HoughCircles() kullanarak ve ayar deneyebilirsiniz iyi bir sonuç elde edene kadar parametreler. Bu bazı zorluklara neden olabilir, çünkü tüm daire görüntüde görünmez, yalnızca segmentler, ancak bunu denemenizi öneririm. En içteki daireyi tespit ettiyseniz, bunu harici kütle merkezlerini filtrelemek için maske olarak kullanabilirsiniz.

+0

Teşekkürler, işimi geliştirdin. Başka bir soru: cv :: Canny ve cvCanny arasında küçük bir fark fark ettim. Neden iki benzer işlevler yarattılar ve hangisini (cv :: 've' cv' öneki ile fermiyonlar daha sık kullanmalıyım? – WangYudong

+0

Bu ikisi arasında fark olmamalıdır - aynı uygulamayı dahili olarak kullanırlar. 'cv :: Canny()', tercih etmeniz gereken C++ API'da 'cv :: Mat' ile kullanılır. 'cvCanny()', 'IplImage' kullanan C API'sinden olup, kullanımdan kaldırılmıştır. – Aurelius

5

nasıl nokta hatlarını kapatmak için? kullanımı doldurulmuş bir çizim seçeneği ile drawContours yöntemi (CV_FILLED veya kalınlık = -1)

gürültüyü azaltmak?blurring (düşük geçiş filtreleme) yöntemlerinden birini kullanın.

benzer boyut? dilatasyondan sonra erozyon = morphological closing kullanın.

bir dış halka olmadan bir daire, çıkışı için nokta? tüm contour areas ortalama bul. Bu değere göre büyük bir fark olan erase contours. Kalan merkezleri çıkış.

Aurelius zaten bunların çoğu söz, ancak bu sorun ilginç sessiz olduğundan, muhtemelen çalışacağız ve yeterince zamanınız olduğunda eksiksiz bir çözüm sonrası. İyi şanslar.

İlgili konular