问题描述:

I am processing such an image as shown in Fig.1, which is composed of an array of points and required to convert to Fig. 2.

*Fig.1 original image*

*Fig.2 wanted image*

In order to finish the conversion, firstly I detect the `edge`

of every point and then operate `dilation`

. The result is satisfactory after choosing the proper parameters, seen in Fig. 3.

*Fig.3 image after dilation*

I processed the same image before in MATLAB. When it comes to shrink objects (in Fig.3) to pixels, function `bwmorph(Img,'shrink',Inf)`

works and the result is exactly where Fig. 2 comes from. So how to get the same wanted image in opencv? It seems that there is no similar `shrink`

function.

Here is my code of finding edge and dilation operation:

`#include "opencv2/imgproc/imgproc.hpp"`

#include "opencv2/highgui/highgui.hpp"

#include <stdlib.h>

#include <stdio.h>

#include <cv.h>

#include <highgui.h>

using namespace cv;

// Global variables

Mat src, dilation_dst;

int dilation_size = 2;

int main(int argc, char *argv[])

{

IplImage* img = cvLoadImage("c:\\001a.bmp", 0); // 001a.bmp is Fig.1

// Perform canny edge detection

cvCanny(img, img, 33, 100, 3);

// IplImage to Mat

Mat imgMat(img);

src = img;

// Create windows

namedWindow("Dilation Demo", CV_WINDOW_AUTOSIZE);

Mat element = getStructuringElement(2, // dilation_type = MORPH_ELLIPSE

Size(2*dilation_size + 1, 2*dilation_size + 1),

Point(dilation_size, dilation_size));

// Apply the dilation operation

dilate(src, dilation_dst, element);

imwrite("c:\\001a_dilate.bmp", dilation_dst);

imshow("Dilation Demo", dilation_dst);

waitKey(0);

return 0;

}

1- Find all the contours in your image.

2- Using moments find their center of masses. Example:

```
/// Get 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 ); }
```

3- Create zero(black) image and write all the center points on it.

4- Note that you will have extra one or two points coming from border contours. Maybe you can apply some pre-filtering according to the contour areas, since the border is a big connected contour having large area.

It's not very fast, but I implemented the morphological filtering algorithm from *Digital Image Processing, 4th Edition* by William K. Pratt. This should be exactly what you're looking for.

The code is MIT licensed and available on GitHub at cgmb/shrink.

Specifically, I've defined `cv::Mat cgmb::shrink_max(cv::Mat in)`

to shrink a given `cv::Mat`

of `CV_8UC1`

type until no further shrinking can be done.

So, if we compile *Shrink.cxx* with your program and change your code like so:

```
#include "Shrink.h" // add this line
...
dilate(src, dilation_dst, element);
dilation_dst = cgmb::shrink_max(dilation_dst); // and this line
imwrite("c:\\001a_dilate.bmp", dilation_dst);
```

We get this:

By the way, your image revealed a bug in Octave Image's implementation of bwmorph shrink. Figure 2 should not be the result of a shrink operation on Figure 3, as the ring shouldn't be broken by a shrink operation. If that ring disappeared in MATLAB, it presumably also suffers from some sort of similar bug.

At present, Octave and I have slightly different results from MATLAB, but they're pretty close.