0

我正在尝试检测最大/较大的矩形形状,并将边界框绘制到检测区域。 我尝试了不同的方法来检测轮廓检测的完美边缘(没有孔的边缘)。我在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)。

//更新:2017年5月4日

我已经测试第一原始图像上高斯差。结果对轮廓检测无用。所得到的图像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和下面是结果[图像结果差的高斯和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); 

    } 
} 

结果图像后,我申请精明xhttps我的代码://i.stack.imgur.com/VtGNl.jpg 而最终的结果xhttps://i.stack .imgur.com/KIUan.jpg

更新#3:2017年6月4日

我试过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); 
    } 

} 

为上述代码将所得精明图像:_HTTPS://i.stack.imgur.com/6k8sF.jpg 用线_HTTPS所得图像://i.stack.imgur .com/3e9CB.jpg

在这个时候,我还没有找到一个工作解决方案。 有没有人有一个工作解决方案的想法?

+0

对于这样的图像,请尝试**高斯差异** –

+1

此外,请考虑使用[直方图均衡](https://en.wikipedia.org/wiki/Histogram_equalization)以获得更好的对比度图片。 –

+0

感谢您的建议。我试过了,并没有工作。我已更新我的帖子 – Kheuch

回答

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

我同意这是不是你正在寻找究竟是什么,但可能是一个很好的起点。希望这有助于:)

+0

谢谢尝试。我试过你的解决方案,但我没有得到相同的结果。请检查我的帖子,我更新了你的建议 – Kheuch

+0

你可以试试HoughLines而不是HoughLinesP一次吗?我很想知道为什么你不能得到相同的结果。这也是我的Canny边缘检测器结果。你是否也一样? https://i.stack.imgur.com/AAcis.png – harshkn

+0

我按照你的建议尝试了HoughLines,并且我更新了我的帖子。由此产生的canny是https://i.stack.imgur.com/6k8sF.jpg和最终结果:https://i.stack.imgur.com/3e9CB.jpg。你可以注意到,它不起作用。它很奇怪。 – Kheuch