OpenCV如何平滑轮廓,减少噪声

6
我提取了一张图片的轮廓,您可以在这里看到: contour 然而,它有一些噪点。 我放大了一下,以更清楚地表达我的意思。 enter image description here 我使用的原始图像: enter image description here 代码:
rMaskgray = cv2.imread('redmask.jpg', cv2.CV_LOAD_IMAGE_GRAYSCALE)
(thresh, binRed) = cv2.threshold(rMaskgray, 50, 255, cv2.THRESH_BINARY)

Rcontours, hier_r = cv2.findContours(binRed,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
r_areas = [cv2.contourArea(c) for c in Rcontours]
max_rarea = np.max(r_areas)
CntExternalMask = np.ones(binRed.shape[:2], dtype="uint8") * 255

for c in Rcontours:
    if(( cv2.contourArea(c) > max_rarea * 0.70) and (cv2.contourArea(c)< max_rarea)):
        cv2.drawContours(CntExternalMask,[c],-1,0,1)

cv2.imwrite('contour1.jpg', CntExternalMask)

你能发一下你用来创建这个的代码吗? - Martin Evans
@MartinEvans 已编辑! - marco
如果您将cv2.CHAIN_APPROX_SIMPLE替换为cv2.CHAIN_APPROX_NONE会发生什么? - tfv
请告诉我们您正在使用的OpenCV版本,代码似乎过时了。 - tfv
我正在使用3.0版本的OpenCV。我会进行更新! - marco
2个回答

5
尝试升级到OpenCV 3.1.0。根据以下新版本的代码适应,我尝试使用OpenCV 3.1.0版本,并没有看到你描述的任何效果。
import cv2
import numpy as np

print cv2.__version__

rMaskgray = cv2.imread('5evOn.jpg', 0)
(thresh, binRed) = cv2.threshold(rMaskgray, 50, 255, cv2.THRESH_BINARY)

_, Rcontours, hier_r = cv2.findContours(binRed,cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
r_areas = [cv2.contourArea(c) for c in Rcontours]
max_rarea = np.max(r_areas)
CntExternalMask = np.ones(binRed.shape[:2], dtype="uint8") * 255

for c in Rcontours:
    if(( cv2.contourArea(c) > max_rarea * 0.70) and (cv2.contourArea(c)< max_rarea)):
        cv2.drawContours(CntExternalMask,[c],-1,0,1)

cv2.imwrite('contour1.jpg', CntExternalMask)

enter image description here


我仍然有一些问题: https://dl.dropboxusercontent.com/u/710615/externalpcb.jpg - marco
你是否曾经为此找到解决方案?抱歉,这是一个旧问题,我遇到了同样的问题。@Marco - Jonathan Corrin
@Jonathan:如上所述,使用上述的OpenCV版本似乎问题已经解决。如果您仍然遇到问题,请提供一个示例。 - tfv
@tfv 这是我遇到的问题。我找不到锯齿线和圆滑线之间的平衡点。https://dev59.com/aKfja4cB1Zd3GeqPz7d8?noredirect=1#comment82843179_47936474 - Jonathan Corrin
你可以在这里找到解决方案:http://www.morethantechnical.com/2012/12/07/resampling-smoothing-and-interest-points-of-curves-via-css-in-opencv-w-code/。 - abggcv

1

我不确定是否可以提供Java代码 - 但我为openCV轮廓实现了高斯平滑。逻辑和理论来自这里https://www.morethantechnical.com/2012/12/07/resampling-smoothing-and-interest-points-of-curves-via-css-in-opencv-w-code/

package CurveTools;

import org.apache.log4j.Logger;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Point;

import java.util.ArrayList;
import java.util.List;

import static org.opencv.core.CvType.CV_64F;
import static org.opencv.imgproc.Imgproc.getGaussianKernel;

class CurveSmoother {

    private double[] g, dg, d2g, gx, dx, d2x;
    private double gx1, dgx1, d2gx1;

    public double[] kappa, smoothX, smoothY;
    public double[] contourX, contourY;

    /* 1st and 2nd derivative of 1D gaussian  */
    void getGaussianDerivs(double sigma, int M) {

        int L = (M - 1) / 2;
        double sigma_sq = sigma * sigma;
        double sigma_quad = sigma_sq * sigma_sq;

        dg = new double[M];
        d2g = new double[M];
        g = new double[M];

        Mat tmpG = getGaussianKernel(M, sigma, CV_64F);

        for (double i = -L; i < L + 1.0; i += 1.0) {
            int idx = (int) (i + L);

            g[idx] = tmpG.get(idx, 0)[0];

            // from http://www.cedar.buffalo.edu/~srihari/CSE555/Normal2.pdf
            dg[idx] = -i * g[idx] / sigma_sq;
            d2g[idx] = (-sigma_sq + i * i) * g[idx] / sigma_quad;
        }
    }

    /* 1st and 2nd derivative of smoothed curve point */
    void getdX(double[] x, int n, double sigma, boolean isOpen) {

        int L = (g.length - 1) / 2;

        gx1 = dgx1 = d2gx1 = 0.0;
        for (int k = -L; k < L + 1; k++) {
            double x_n_k;
            if (n - k < 0) {
                if (isOpen) {
                    //open curve - mirror values on border
                    x_n_k = x[-(n - k)];
                } else {
                    //closed curve - take values from end of curve
                    x_n_k = x[x.length + (n - k)];
                }
            } else if (n - k > x.length - 1) {
                if (isOpen) {
                    //mirror value on border
                    x_n_k = x[n + k];
                } else {
                    x_n_k = x[(n - k) - x.length];
                }
            } else {
                x_n_k = x[n - k];
            }

            gx1 += x_n_k * g[k + L]; //gaussians go [0 -> M-1]
            dgx1 += x_n_k * dg[k + L];
            d2gx1 += x_n_k * d2g[k + L];
        }
    }

    /* 0th, 1st and 2nd derivatives of whole smoothed curve */
    void getdXcurve(double[] x, double sigma, boolean isOpen) {

        gx = new double[x.length];
        dx = new double[x.length];
        d2x = new double[x.length];

        for (int i = 0; i < x.length; i++) {
            getdX(x, i, sigma, isOpen);
            gx[i] = gx1;
            dx[i] = dgx1;
            d2x[i] = d2gx1;
        }
    }

    /*
        compute curvature of curve after gaussian smoothing
        from "Shape similarity retrieval under affine transforms", Mokhtarian & Abbasi 2002
        curvex - x position of points
        curvey - y position of points
        kappa - curvature coeff for each point
        sigma - gaussian sigma
    */
    void computeCurveCSS(double[] curvex, double[] curvey, double sigma, boolean isOpen) {
        int M = (int) Math.round((10.0 * sigma + 1.0) / 2.0) * 2 - 1;
        assert (M % 2 == 1); //M is an odd number

        getGaussianDerivs(sigma, M);//, g, dg, d2g

        double[] X, XX, Y, YY;

        getdXcurve(curvex, sigma, isOpen);
        smoothX = gx.clone();
        X = dx.clone();
        XX = d2x.clone();

        getdXcurve(curvey, sigma, isOpen);
        smoothY = gx.clone();
        Y = dx.clone();
        YY = d2x.clone();


        kappa = new double[curvex.length];

        for (int i = 0; i < curvex.length; i++) {
            // Mokhtarian 02' eqn (4)
            kappa[i] = (X[i] * YY[i] - XX[i] * Y[i]) / Math.pow(X[i] * X[i] + Y[i] * Y[i], 1.5);
        }
    }

    /* find zero crossings on curvature */
    ArrayList<Integer> findCSSInterestPoints() {

        assert (kappa != null);

        ArrayList<Integer> crossings = new ArrayList<>();

        for (int i = 0; i < kappa.length - 1; i++) {
            if ((kappa[i] < 0.0 && kappa[i + 1] > 0.0) || kappa[i] > 0.0 && kappa[i + 1] < 0.0) {
                crossings.add(i);
            }
        }
        return crossings;
    }

    public void polyLineSplit(MatOfPoint pl) {
        contourX = new double[pl.height()];
        contourY = new double[pl.height()];

        for (int j = 0; j < contourX.length; j++) {
            contourX[j] = pl.get(j, 0)[0];
            contourY[j] = pl.get(j, 0)[1];
        }
    }

    public MatOfPoint polyLineMerge(double[] xContour, double[] yContour) {

        assert (xContour.length == yContour.length);

        MatOfPoint pl = new MatOfPoint();

        List<Point> list = new ArrayList<>();

        for (int j = 0; j < xContour.length; j++)
            list.add(new Point(xContour[j], yContour[j]));

        pl.fromList(list);

        return pl;
    }

    MatOfPoint smoothCurve(MatOfPoint curve, double sigma) {
        int M = (int) Math.round((10.0 * sigma + 1.0) / 2.0) * 2 - 1;
        assert (M % 2 == 1); //M is an odd number

        //create kernels
        getGaussianDerivs(sigma, M);
        polyLineSplit(curve);

        getdXcurve(contourX, sigma, false);
        smoothX = gx.clone();

        getdXcurve(contourY, sigma, false);
        smoothY = gx;

        Logger.getRootLogger().info("Smooth curve len: " + smoothX.length);

        return polyLineMerge(smoothX, smoothY);
    }
}

Sigma的合适值是多少? - Softlion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接