经过一些简单的预处理后,我收到了分段图像的布尔掩码.
我想"增强"面具的边框,使它们更光滑.为此我使用具有相当大的圆内核的OPEN形态滤波器,它非常有效,直到分段对象之间的距离足够.但在很多样本中,物体粘在一起.是否存在一些或多或少的简单方法来平滑这种图像而不改变其形态?
如果不首先应用形态滤镜,您可以尝试检测图像的外部轮廓.现在,您可以将这些外部轮廓绘制为填充轮廓,然后应用形态滤镜.这是有效的,因为现在你没有任何填充孔.这很简单.
另一种方法:
找到外部轮廓
取轮廓点的坐标x,y.您可以将它们视为1-D信号,并对这些信号应用平滑滤波器
在下面的代码中,我将第二种方法应用于样本图像.
输入图像
外部轮廓没有任何平滑
在对x和y 1-D信号应用高斯滤波器之后
C++代码
Mat im = imread("4.png", 0); Mat cont = im.clone(); Mat original = Mat::zeros(im.rows, im.cols, CV_8UC3); Mat smoothed = Mat::zeros(im.rows, im.cols, CV_8UC3); // contour smoothing parameters for gaussian filter int filterRadius = 5; int filterSize = 2 * filterRadius + 1; double sigma = 10; vector> contours; vector hierarchy; // find external contours and store all contour points findContours(cont, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(0, 0)); for(size_t j = 0; j < contours.size(); j++) { // draw the initial contour shape drawContours(original, contours, j, Scalar(0, 255, 0), 1); // extract x and y coordinates of points. we'll consider these as 1-D signals // add circular padding to 1-D signals size_t len = contours[j].size() + 2 * filterRadius; size_t idx = (contours[j].size() - filterRadius); vector x, y; for (size_t i = 0; i < len; i++) { x.push_back(contours[j][(idx + i) % contours[j].size()].x); y.push_back(contours[j][(idx + i) % contours[j].size()].y); } // filter 1-D signals vector xFilt, yFilt; GaussianBlur(x, xFilt, Size(filterSize, filterSize), sigma, sigma); GaussianBlur(y, yFilt, Size(filterSize, filterSize), sigma, sigma); // build smoothed contour vector > smoothContours; vector smooth; for (size_t i = filterRadius; i < contours[j].size() + filterRadius; i++) { smooth.push_back(Point(xFilt[i], yFilt[i])); } smoothContours.push_back(smooth); drawContours(smoothed, smoothContours, 0, Scalar(255, 0, 0), 1); cout << "debug contour " << j << " : " << contours[j].size() << ", " << smooth.size() << endl; }