Moja praca oparta jest na obrazach z tablicą kropek (ryc. 1), a efekt końcowy pokazano na ryc. 4. Wyjaśnię moją pracę krok po kroku.Opencv: wykrywanie krawędzi, dylatacja i rysunek cala
Rys 1 oryginalny obraz
Krok 1:. Wykrywanie krawędzi każdego obiektu, łącznie z kropek i "pierścień", który chcę usunąć dla lepszej wydajności. Wynik wykrycia krawędzi pokazano na rys. 2. Użyłem detektora krawędzi Canny'ego, ale nie działało dobrze z niektórymi jasnoszarymi kropkami. Moje pierwsze pytanie brzmi: jak zamknąć kontury kropek i jak najdokładniej zredukować hałas?
fig wykrywania dwóch krawędzi
Etap 2. Jednokładność każdy obiekt. Nie znalazłem dobrego sposobu na wypełnienie dziur, więc rozszerzam je bezpośrednio. Jak pokazano na rys. 3, dziury wydają się zbyt duże, podobnie jak inne szumy. Moje drugie pytanie brzmi: jak wypełnić lub rozszerzyć otwory, aby były wypełnione kółkami w tym samym/podobnym rozmiarze?
Fig.3 Rozszerzenie
Etap 3. Znajdź i wyciągnąć środka ciężkości każdego punktu. Jak pokazano na rys. 4, ze względu na przetwarzanie zgrubnego obrazu, istnieje znaczek "pierścienia", a niektóre kropki są pokazane w dwóch białych pikselach. Poszukiwany wynik powinien pokazywać tylko kropki i jeden biały piksel dla jednej kropki.
Rys. 4: Masowe centra
Oto mój kod dla tych 3 etapów. Czy ktoś może pomóc w poprawie mojej pracy?
#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);
}
Czy próbowałeś już czegoś z [tutaj] (http://stackoverflow.com/questions/1716274/fill-the-holes-in-opencv) jeszcze? – William