OpenCV 中的轮廓/物体检测

问题描述 投票:0回答:1

我有一些 OpenCV 经验,但在检测下图中的轮廓时确实遇到问题。 我能够检测到显示的一些黑色圆圈,但这些是传感器上的污垢,我真的想检测图像中的轨迹,如第二张图像中的红色轮廓所示。

Image

Image with tracks required to be detected outlined in red

我正在尝试使用 Canny 边缘检测和

cv.ADAPTIVE_THRESH_GAUSSIAN_C
,它给出了最好的结果,但很难获得正确的参数,并且结果因图像而异。 我还尝试过使用
cv.fastNlMeansDenoising
去噪,以及 Canny 边缘检测之前的高斯模糊,但结果并没有太大改善。

检测跌落相对容易,但检测轨迹则不然。

我可能必须写一些东西来尝试通过逐行扫描图像来检测轨道,但这看起来很笨拙,而且我不知道如何开始。 我正在使用 OpenCV 和 Python。

有人有什么建议吗?

python opencv computer-vision object-detection semantic-segmentation
1个回答
0
投票

我不确定是否应该将此作为答案发布。这很大程度上是从我的答案中复制的(从噪声图像中检测线)。基本思想与在图像上卷积线核以突出显示线相同。如果重复太多,我可以删除这个答案,只留下链接回另一个答案的评论。

有三个可调整的参数:

  • klength -> 要检测的线的最小长度(较低 =更敏感)
  • kwidth -> 您想要检测的线条的最小宽度(较低=更敏感)
  • 阈值 -> 最小响应 标记为阳性的水平(较低 = 更敏感)

当前设置在图像中获得两个额外的小点,如果需要,可以按大小(opencv 轮廓区域)过滤掉这些点。

enter image description here

enter image description here

import cv2
import math
import numpy as np

# returns integer point positions with 0.5 ties-to-even rule
def intify(point):
    point[0] = round(point[0]);
    point[1] = round(point[1]);
    return point

# translate 2d point in-place
def translate2D(point, shift, sign=1):
    x = point[0] + (shift[0] * sign)
    y = point[1] + (shift[1] * sign)
    point[0] = x
    point[1] = y

# rotate a 2d point in-place
def rotate2D(point, angle_deg, anchor=[0,0]):
    rads = math.radians(angle_deg);
    translate2D(point, anchor, sign=-1)
    x,y = point
    rx = x * math.cos(rads) - y * math.sin(rads)
    ry = x * math.sin(rads) + y * math.cos(rads)
    point[0] = rx
    point[1] = ry
    translate2D(point, anchor, sign=1)

# moves a point to a new origin frame
def pointToFrame(point, pos, angle, no_round=False):
    rotate2D(point, angle)
    translate2D(point, pos)
    if not no_round:
        intify(point)

# rescale image
def scale(img, scale_factor):
    h,w = img.shape[:2];
    h = int(h*scale_factor);
    w = int(w*scale_factor);
    return cv2.resize(img, (w,h));

# chops padding
def unpad(img, padsize):
    h,w = img.shape[:2];
    img = img[padsize:h-padsize, padsize:w-padsize];
    return img;

def build_kernel(angle, ksize, width):
    kernel = np.zeros((ksize,ksize), np.float32)

    # get line endpoints
    middle = int(ksize / 2)
    center = [middle, middle]
    start = [-ksize, 0]
    end = [ksize, 0]
    pointToFrame(start, center, angle)
    pointToFrame(end, center, angle)

    # draw the masking line
    kernel = cv2.line(kernel, start, end, 1, width)
    kernel /= np.sum(kernel) # normalize
    return kernel

# load image
filepath = "deleteme_noisy_img.png";
img = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
orig_height, orig_width = img.shape[:2]

# pad to avoid edge dropoff
pad = int(orig_width/2)
img = cv2.copyMakeBorder(img, pad, pad, pad, pad, cv2.BORDER_REFLECT, None)

# get mask
_, mask = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
height,width = mask.shape

# background canvas
canvas = np.zeros_like(mask)

# tweakable settings
klength = 71
kwidth = 5
threshold = 180

# draw line
angle = 0
filenum = 0
while angle < 180:
    # create a line kernel
    kernel = build_kernel(angle, klength, kwidth)
    angle += 1;

    # convolve
    conv = cv2.filter2D(mask, -1, kernel, borderType=cv2.BORDER_CONSTANT)

    # paint onto canvas
    _, linemask = cv2.threshold(conv, threshold, 255, cv2.THRESH_BINARY) # tweakable sensitivity setting
    canvas = cv2.bitwise_or(canvas, linemask)

    # chop off padding
    display_canvas = unpad(canvas, pad)
    display_conv = unpad(conv, pad)

    # stack the images
    sbs = np.hstack((display_canvas, display_conv))
    sbs = scale(sbs, 0.5)

    # show
    cv2.imshow("side-by-side", sbs)
    key = cv2.waitKey(1)
    if key == ord('q'):
        break

    # save to folder for gif
    # filename = "images/" + str(filenum).zfill(5) + ".png"
    # cv2.imwrite(filename, sbs)
    # filenum += 1
cv2.destroyAllWindows()

# draw on image
display_canvas = unpad(canvas, pad)
orig_img = cv2.imread(filepath)
orig_img[display_canvas == 255] = (0,0,200)

# show image
cv2.imshow("Image", orig_img)
cv2.imshow("Canvas", display_canvas)
# cv2.imwrite("red.png", orig_img)
cv2.waitKey(0)
© www.soinside.com 2019 - 2024. All rights reserved.