title: Opencv: Edge detection, Dilation and Mass ceter drawing
body: <p>My work is based on images with an array of dots (Fig. 1), and the final result is shown in Fig. 4. I will explain my work step by step.</p>
  
  <p><strong>Fig. 1 Original image</strong></p>
  
  <p><img src="https://i.stack.imgur.com/TG9M1.png" alt="enter image description here"></p>
  
  <p><strong>Step 1:</strong> Detect the edge of every object, including the dots and a "ring" that I want to delete for better performance. And the result of edge detection is shown in Fig.2. I used Canny edge detector but it didn't work well with some light-gray dots. <strong>My first question is how to close the contours of dots and reduce other noise as much as possible?</strong></p>
  
  <p><strong>Fig. 2 Edge detection</strong></p>
  
  <p><img src="https://i.stack.imgur.com/rdAwi.png" alt="enter image description here"></p>
  
  <p><strong>Step 2:</strong> Dilate every object. I didn't find a good way to fill holes, so I dilate them directly. As shown in Fig.3, holes seem to be enlarged too much and so does other noise. <strong>My second question is how to fill or dilate the holes in order to make them be filled circles in the same/similar size?</strong>  </p>
  
  <p><strong>Fig. 3 Dilation</strong></p>
  
  <p><img src="https://i.stack.imgur.com/SkMb9.png" alt="enter image description here"></p>
  
  <p><strong>Step 3:</strong> Find and draw the mass center of every dot. As shown in Fig. 4, due to the coarse image processing, there exist mark of the "ring" and some of dots are shown in two white pixels. <strong>The result wanted should only show the dots and one white pixel for one dot.</strong></p>
  
  <p><strong>Fig. 4: Mass centers</strong></p>
  
  <p><img src="https://i.stack.imgur.com/RPCNx.png" alt="enter image description here"></p>
  
  <p>Here is my code for these 3 steps. Can anyone help to make my work better?  </p>
  
  <pre><code>#include "opencv2/imgproc/imgproc.hpp"
  #include "opencv2/highgui/highgui.hpp"
  #include &lt;stdlib.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;cv.h&gt;
  #include &lt;highgui.h&gt;
  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&lt;vector&lt;Point&gt;&gt; contours;
      vector&lt;Vec4i&gt; hierarchy;
  
      // Find contours
      findContours(dilation, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
  
      // Get the moments
      vector&lt;Moments&gt; mu(contours.size());
      for(int i = 0; i &lt; contours.size(); i++) {
          mu[i] = moments(contours[i], false);
      }
  
      // Get the mass centers
      vector&lt;Point2f&gt; mc(contours.size());
      for(int i = 0; i &lt; 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&lt; 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);
  }
  </code></pre>