Sharpen the edges

半世苍凉 提交于 2019-12-08 04:00:53

问题


I am trying to detect the biggest/larger rectangular shape and draw bounding box to the detected area. I have tried different way to detect perfect edge ( Edges with no holes) for contour detection. I searched on stackoverflow and the solution proposed OpenCV sharpen the edges (edges with no holes) and Segmentation Edges did not work with my sample image.

I would like to detect biggest/larger rectangular shape on the following two images Original Image 1 and Original Image 2

Below is the code that i use to preprocess the image before calling 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;

}

I have also tried the saturation Channel in HSV color space in place of gray image but it does not work.

Does anybody have an idea why it does not works with the code posted above ?

How can I process image in order to sharpen the edges for contour detection ?

Any relevant information(either in Java or C++ or Python ) is welcomed.

//UPDATE : 05/04/2017

I have tested difference of gaussian on the first original image. The result is not useful for contour detection. The resulting image xhttps://i.stack.imgur.com/ONw9F.jpg The code i used :

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;

}

I have also tried to apply CLAHE before difference of gaussian and here is the result [Image result of difference of gaussian and clahe] xhttps://i.stack.imgur.com/DDbqg.jpg

Update #2

I have tried the houghline as suggested below but it does not work. here is my code applied to grayscale image

 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);

    }
}

The result image after i applied canny xhttps://i.stack.imgur.com/VtGNl.jpg and the final result xhttps://i.stack.imgur.com/KIUan.jpg

Update #3 : 06/04/2017

I tried Houghlines and not HoughlinesP. It does not work. Below is the code

 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);
    }

}

The resulting canny image for the code above : _https://i.stack.imgur.com/6k8sF.jpg The resulting image with lines _https://i.stack.imgur.com/3e9CB.jpg

At this time of writing, i have not found a working solution. Does anybody have an idea for a working solution ?


回答1:


I tried a quick check on the image you shared. And I got this result after I tweaked parameters of canny and hough lines a little. Not sure what kind of generalisation you need, but give it a try.

Here is my code:

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)

The result I got was

I agree this is not what you are looking exactly, but probably a good starting point. Hope this helps :)



来源:https://stackoverflow.com/questions/43209866/sharpen-the-edges

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!