shrink objects to pixels

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

图1原始图像
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:01a.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:01a_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:01a_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.

链接地址: http://www.djcxy.com/p/89798.html

上一篇: 停止无限循环

下一篇: 将对象缩小到像素