opencv - 在噪声很大的图像中检测窄线

标签 opencv image-processing detection noise

我已经在嘈杂的声学图像中执行了预处理步骤,现在我需要检测窄黑线。

你能想出更好的方法来检测这些线条吗?

enter image description here

enter image description here

我的目标是检测此图像中红色框中的线。

enter image description here

最佳答案

失败的答案:- 这不是一个完美的解决方案,但需要进一步的工作以使其对各种图像具有鲁棒性。我注意到黑色线条中的噪点非常少,因此 Canny 在该区域内没有发现很多边缘。代码和结果如下:-

import numpy as np
import cv2

gray = cv2.imread('2.png')
edges = cv2.Canny(gray,10,60,apertureSize = 7)
cv2.imwrite('2-1-edges-10-60.jpg',edges)

kernel = np.ones((5,5),np.uint8)
closeEdges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
cv2.imwrite('2-2-edges-10-60-dilated-1.jpg',closeEdges)

invertEdges = 255 - closeEdges
cv2.imwrite('2-3-invertedges-10-60.jpg',invertEdges)

minLineLength=100
lines = cv2.HoughLinesP(image=invertEdges,rho=1,theta=np.pi/180, threshold=200,lines=np.array([]), minLineLength=minLineLength,maxLineGap=80)

a,b,c = lines.shape
for i in range(a):
    cv2.line(gray, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 1, cv2.LINE_AA)

cv2.imwrite('2-4-houghlines.jpg',gray)

Output1

Output2

在输出图像的反转上使用连通分量并找到最大尺寸的元素可能会有所帮助。

解决这个问题的另一种方法是使用梯度图像并直接找到梯度幅度小范围的区域。这种方法会更加灵活,因为它不需要使用固定阈值 - 如上所述的 10 和 60。阈值可以根据图像梯度进行自适应/您可以在使用硬编码阈值之前对图像梯度进行归一化。

更好的答案(准确率 30-40%)

import numpy as np
import cv2
import os

# Store all images in this folder
path='images-1'

def autocrop(image, threshold=0):
    if len(image.shape) == 3:
        flatImage = np.max(image, 2)
    else:
        flatImage = image

    rows = np.where(np.max(flatImage, 0) > threshold)[0]
    if rows.size:
        cols = np.where(np.max(flatImage, 1) > threshold)[0]
        image = image[cols[0]: cols[-1] + 1, rows[0]: rows[-1] + 1]
    else:
        image = image[:1, :1]
    return image

def skeleton(img):
    size = np.size(img)
    skel = np.zeros(img.shape,np.uint8)

    element = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
    done = False

    while( not done):
        eroded = cv2.erode(img,element)
        temp = cv2.dilate(eroded,element)
        temp = cv2.subtract(img,temp)
        skel = cv2.bitwise_or(skel,temp)
        img = eroded.copy()

        zeros = size - cv2.countNonZero(img)
        if zeros==size:
            done = True

    return skel

def gamma_correction(img, correction):
    img = img/255.0
    img = cv2.pow(img, correction)
    return np.uint8(img*255)

def auto_canny(image, sigma=0.33):
    # compute the median of the single channel pixel intensities
    v = np.median(image)
    # apply automatic Canny edge detection using the computed median
    lower = int(max(0, (1.0 - sigma) * v))
    upper = int(min(255, (1.0 + sigma) * v))
    edged = cv2.Canny(image, lower, upper)

    # return the edged image
    return edged

for file in os.listdir(path):
    if file.endswith(".png"):
        current = os.path.join(path, file)
        img = cv2.imread(current, 0)
        print 'processing ' + current
        img = autocrop(img, 0)
        cv2.imwrite(current + '-0-cropped.jpg', img)
        height, width = img.shape[:2]
        img = cv2.resize(img, (width, width))
        cv2.imwrite(current + '-0-resized.jpg', img)

        # cv2.imwrite(current +'-2-auto_canny_default.jpg', auto_canny(img))
        # img = cv2.medianBlur(img,5)
        # cv2.imwrite(current +'-0-medianBlur.jpg',img)
        # th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2)
        # cv2.imwrite(current +'-1-threshold_gaussian.jpg',th3)

        # laplacian = cv2.Laplacian(img,cv2.CV_64F)
        # cv2.imwrite(current + '-3-threshold_gaussian.jpg', laplacian)

        #img = cv2.bilateralFilter(img, 3, 3, 5)
        edges = cv2.Canny(img,10,20,apertureSize = 5)
        cv2.imwrite(current +'-1-edges-10-60.jpg',edges)

        kernel = np.ones((3,3),np.uint8)
        edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
        cv2.imwrite(current +'-1-edgesClosed-10-60.jpg', edges)

        edges = 255-edges
        cv2.imwrite(current +'-2-edgesClosedInverted-10-60.jpg', edges)
        im2, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
        imgColor = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
        maxArea = 0
        for cnt in contours:
            if maxArea < cv2.contourArea(cnt):
                maxArea = cv2.contourArea(cnt)

        for cnt in contours:
            rect = cv2.minAreaRect(cnt)       #I have used min Area rect for better result
            width = rect[1][0]
            height = rect[1][1]
            if cv2.contourArea(cnt) > int(maxArea/2.5) and ( width < height/2 or height < width/2): 
                cv2.drawContours(imgColor, cnt, -1, (0,255,0), 1)
        cv2.imwrite(current+'-5-Contours.jpg',imgColor)


        # edges = skeleton(255-edges)
        # cv2.imwrite(current +'-2-skeleton.jpg', edges)
        # edges = 255-edges
        # minLineLength=int(width/4)
        # threshold = 20
        # maxLineGap = 1
        # rho = 1
        # lines = cv2.HoughLinesP(image=edges,rho=rho,theta=np.pi/180, threshold=threshold,lines=np.array([]), minLineLength=minLineLength,maxLineGap=maxLineGap)

        # if lines is not None:
        #     a,b,c = lines.shape
        #     for i in range(a):
        #         cv2.line(img, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 1, cv2.LINE_AA)
        #         cv2.line(edges, (lines[i][0][0], lines[i][0][1]), (lines[i][0][2], lines[i][0][3]), (0, 0, 255), 1, cv2.LINE_AA)
        #     cv2.imwrite(current+'-5-houghlines.jpg',img)
        #     cv2.imwrite(current+'-6-houghlines.jpg',edges)
        #     print 'cool'
        # else:
        #     cv2.imwrite(current+'-5-houghlines.jpg',img)

此外,请检查以下链接:

  1. Detection of Continuous, Smooth and Thin Edges in Noisy Images Using Constrained Particle Swarm Optimisation
  2. http://www.imagemagick.org/discourse-server/viewtopic.php?t=14491
  3. http://answers.opencv.org/question/3454/detecting-thick-edges/

关于opencv - 在噪声很大的图像中检测窄线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42788536/

相关文章:

c++ - 是否可以使用标准 openCV 校准鱼眼相机?

c++ - C++中的多线程图像处理

python - 如何正确分类图像中正(亮色)圆圈和负(深色)圆圈的数量

c++ - OpenCV imshow() 循环显示图像

c++ - ubuntu命名空间cv错误上的opencv

python - 使用 OpenCV 删除 OCR 文本框

matlab - matlab中两幅彩色图像的直方图匹配

python - 如何在python中对图像进行反规范化?

algorithm - 在段和连接器的集合中检测所有闭合路径的最有效方法是什么?

javascript - 如何根据 HTTP 主机名 header onload 进行 Javascript 重定向?