锐化边缘

时间:2017-04-04 14:18:01

标签: opencv image-processing computer-vision signal-processing image-segmentation

我正在尝试检测最大/最大的矩形形状并将边界框绘制到检测到的区域。 我尝试了不同的方法来检测轮廓检测的完美边缘(没有孔的边缘)。我搜索了stackoverflow并提出了解决方案 OpenCV sharpen the edges (edges with no holes)Segmentation Edges 不能用我的样本图像。

我想在以下两张图片中检测最大/较大的矩形 Original Image 1Original Image 2

下面是我在调用findcontour之前用于预处理图像的代码。

public  Mat processGrayScaleImage(Mat grayImage){
    Mat value = new Mat();
    Mat sobx = new Mat();
    Mat soby = new Mat();
    Mat grad_abs_val_approx = new Mat();

    Imgproc.GaussianBlur(grayImage, value, new Size(9, 9), 2, 2);
    Mat imf = new Mat();
    value.convertTo(imf, CV_32FC1, 0.5f, 0.5f);

    Imgproc.Sobel(imf, sobx, -1, 1, 0);
    Imgproc.Sobel(imf, soby, -1, 0, 1);

    sobx = sobx.mul(sobx);
    soby = soby.mul(soby);

    Mat sumxy = new Mat();
    //Core.add(sobx,soby, sumxy);
    Core.addWeighted(sobx, 0.5, soby, 0.5, 0, sumxy);
    Core.pow(sumxy, 0.5, grad_abs_val_approx);

    sobx.release();
    soby.release();
    sumxy.release();;


    Mat filtered = new Mat();
    Imgproc.GaussianBlur(grad_abs_val_approx, filtered, new Size(9, 9), 2, 2);
    grad_abs_val_approx.release();

    final MatOfDouble mean = new MatOfDouble();
    final MatOfDouble stdev = new MatOfDouble();
    Core.meanStdDev(filtered, mean, stdev);

    Mat thresholded = new Mat();
    Imgproc.threshold(filtered, thresholded, mean.toArray()[0], 1.0, Imgproc.THRESH_TOZERO);


    Mat converted = new Mat();
    thresholded.convertTo(converted, CV_8UC1);

    thresholded.release();
    filtered.release();

    return converted;

}

我也尝试过HSV色彩空间中的饱和度信号来代替灰度图像,但它不起作用。

有人知道为什么它不能与上面发布的代码一起使用吗?

如何处理图像以锐化轮廓检测的边缘?

欢迎使用任何相关信息(使用Java或C ++或Python)。

//更新:05/04/2017

我测试了第一张原始图像上的高斯差异。结果对轮廓检测没有用。生成的图像xhttps://i.stack.imgur.com/ONw9F.jpg 我使用的代码:

public static Mat dog(Mat grayImage){
    Mat blur1 = new Mat();
    Mat blur2 = new Mat();
    Mat dog = new Mat();
    int radius1 = 15;
    int radius2 = radius1 + 6;

    Imgproc.GaussianBlur(grayImage, blur1, new Size(radius1, radius1), 5);
    Imgproc.GaussianBlur(grayImage, blur2, new Size(radius2, radius2), 5);
    Core.absdiff(blur1, blur2, dog);


    Core.multiply(dog, new Scalar(100), dog);
    Imgproc.threshold(dog, dog, 55, 255, Imgproc.THRESH_BINARY_INV);

    return dog;

}

我还尝试在高斯差异之前应用CLAHE,这里是结果[高斯和克拉的差异的图像结果] xhttps://i.stack.imgur.com/DDbqg.jpg

更新#2

我已按照下面的建议尝试了houghline,但它不起作用。 这是我的代码应用于灰度图像

 public static void houghLines(Mat greyImg, Context ctx){
    Mat lines = new Mat();
    Mat binary = new Mat();
    Mat original = greyImg.clone();
    int threshold = 35;
    int minLineSize = 20;
    int lineGap = 30;

    Imgproc.Canny(greyImg, greyImg, 20, 30, 3, false);

    Imgproc.HoughLinesP(greyImg, lines, 1, Math.PI/70, threshold, minLineSize, lineGap);
    for (int x = 0; x < lines.rows(); x++)
    {
        double[] vec = lines.get(x, 0);
        double x1 = vec[0],
                y1 = vec[1],
                x2 = vec[2],
                y2 = vec[3];
        Point start = new Point(x1, y1);
        Point end = new Point(x2, y2);
        double dx = x1 - x2;
        double dy = y1 - y2;

        double dist = Math.sqrt (dx*dx + dy*dy);

        if(dist>300.d)  
            Imgproc.line(original, start, end, new Scalar(0,255, 0, 255),5);

    }
}

我申请后的结果图片canny xhttps://i.stack.imgur.com/VtGNl.jpg 和最终结果xhttps://i.stack.imgur.com/KIUan.jpg

更新#3 :06/04/2017

我试过Houghlines而不是HoughlinesP。这是行不通的。以下是代码

 public static void houghLines(Mat Original, Context ctx){
    Mat lines = new Mat();
    Mat binary = new Mat();
    Mat greyImg = new Mat();
    Mat im = Original.clone();

    Imgproc.cvtColor(im, greyImg, Imgproc.COLOR_RGB2GRAY);

    Imgproc.Canny(greyImg, binary, 20, 30, 3, true);

    Imgproc.HoughLines(binary, lines, 1, Math.PI/70, 35);

    for (int i = 0; i < lines.cols(); i++){
        double data[] = lines.get(0, i);
        double rho = data[0];
        double theta = data[1];
        double cosTheta = Math.cos(theta);
        double sinTheta = Math.sin(theta);
        double x0 = cosTheta * rho;
        double y0 = sinTheta * rho;
        Point pt1 = new Point(x0 + 10000 * (-sinTheta), y0 + 10000 * cosTheta);
        Point pt2 = new Point(x0 - 10000 * (-sinTheta), y0 - 10000 * cosTheta);
        Imgproc.line(im, pt1, pt2, new Scalar(0, 0, 200), 3);
    }

}

上面代码生成的canny图像:_https://i.stack.imgur.com/6k8sF.jpg 生成的图像带有行_https://i.stack.imgur.com/3e9CB.jpg

在撰写本文时,我还没有找到可行的解决方案。 有没有人对工作解决方案有所了解?

1 个答案:

答案 0 :(得分:0)

我尝试快速检查您分享的图片。在我调整了canny和hough线的参数后,我得到了这个结果。不确定你需要什么样的概括,但试一试。

这是我的代码:

import cv2 as cv2
import numpy as np

# fn = '2PeyG.jpg'
fn = 'qEFMj.jpg'
r_scale = 0.1
# OpenCV reads image with BGR format
img = cv2.imread(fn)
img = cv2.resize(img, (0, 0), fx=r_scale, fy=r_scale)
img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(img, 20, 30, apertureSize=3)


lines = cv2.HoughLines(edges, 1, np.pi/70, 35)

for rho, theta in lines[0]:
    if (np.pi/70 <= theta <= np.pi/7) or (2.056 < theta < 4.970) or (1.570 <= theta <= 1.600):

        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 1000*(-b))
        y1 = int(y0 + 1000*(a))

        x2 = int(x0 - 1000*(-b))
        y2 = int(y0 - 1000*(a))

        cv2.line(img,(x1,y1),(x2,y2),(0,0,255),1)


cv2.imshow('edges', edges)
cv2.imshow('overlay', img)

# cv2.imwrite('lines_overlay.png', img)
cv2.waitKey(3000)

我得到的结果是

enter image description here

我同意这不是你所期待的,但可能是一个很好的起点。希望这有帮助:)