c++ - Opencv: Edge detection, Dilation and Mass ceter drawing -


my work based on images array of dots (fig. 1), , final result shown in fig. 4. explain work step step.

fig. 1 original image

enter image description here

step 1: detect edge of every object, including dots , "ring" want delete better performance. , result of edge detection shown in fig.2. used canny edge detector didn't work light-gray dots. my first question how close contours of dots , reduce other noise as possible?

fig. 2 edge detection

enter image description here

step 2: dilate every object. didn't find way fill holes, dilate them directly. shown in fig.3, holes seem enlarged , other noise. my second question how fill or dilate holes in order make them filled circles in same/similar size?

fig. 3 dilation

enter image description here

step 3: find , draw mass center of every dot. shown in fig. 4, due coarse image processing, there exist mark of "ring" , of dots shown in 2 white pixels. the result wanted should show dots , 1 white pixel 1 dot.

fig. 4: mass centers

enter image description here

here code these 3 steps. can make work better?

#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 mat     mat imgmat(img);     src = img;      namedwindow("step 1: edge", cv_window_autosize);     imshow("step 1: edge", src);      // apply 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));      // moments     vector<moments> mu(contours.size());     for(int = 0; < contours.size(); i++) {         mu[i] = moments(contours[i], false);     }      // mass centers     vector<point2f> mc(contours.size());     for(int = 0; < 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 = 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); } 

there few things can improve results. reduce noise in image, can apply median blur before applying canny operator. common de-noising technique. also, try avoid using c api , iplimage.

    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); 

this reduces amount of noise in edge image: canny result

to better retain original sizes of dots, can perform few iterations of morphological closing smaller kernel rather dilation. reduce joining of dots circle:

// replaces call dilate() cv::morphologyex(src, dilation, morph_close, cv::noarray(),cv::point(-1,-1),2); 

this perform 2 iterations 3x3 kernel, indicated using cv::noarray().

the result cleaner, , dots filled:

closing result

leaving rest of pipeline unmodified gives final result. there still few spurious mass centers circle, considerably fewer original method:

mass centers

if wanted attempt removing circle results entirely, try using cv::houghcircles() , adjusting parameters until result. might have difficulties because entire circle not visible in image, segments, recommend experiment it. if did detect innermost circle, use mask filter out external mass centers.


Comments