opencv 从噪声图像中检测直线

ukxgm1gy  于 2023-11-22  发布在  其他
关注(0)|答案(1)|浏览(146)

我试图从嘈杂的图像中检测线条,这些是我遵循的步骤:

img= cv2.imread('/content/spec_un45_3900000.jpg',cv2.IMREAD_GRAYSCALE)

字符串
x1c 0d1x的数据

img = 255 - cv2.medianBlur(img, 3) #Invert and blur


#Remove white spots from background
kernel = np.ones((1, 2), np.uint8)  
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel,iterations=2)


edges = cv2.Canny(opening,0,100,apertureSize = 3)
cv2_imshow(edges)


#Hough Line detection
lines = cv2.HoughLinesP(image=edges,
                        rho=1,
                        theta=np.pi/180,
                        threshold=100,
                        lines=np.array([]),
                        minLineLength=5,
                        maxLineGap=200)
for i in range(lines.shape[0]):
                cv2.line(out,
             (lines[i][0][0],
              lines[i][0][1]),
             (lines[i][0][2],
              lines[i][0][3]),
             (0,255, 255), 1, cv2.LINE_AA)


x1c4d 1x的
我尝试了How to detect lines in noisy line images?中提到的方法
有人能帮我调试这个/提供解决方案吗?

8aqjt8rx

8aqjt8rx1#

这不是一个非常有效的答案,但它对严重的噪声具有鲁棒性,并且内核过滤思想对于单尺度匹配(它不处理尺度变化)任务很有用。
使用原始图像(ksize = 201,thresh = 150)
x1c 0d1x的数据
最后一张图像(ksize = 51,thresh = 200)



基本的想法是创建一个与你想要的图像/形状匹配的内核。然后你可以在图像上卷积它并寻找热点。最后我对蒙版进行去重化以去除粗线(在蒙版上运行hough-lines希望只得到一条线而不是一堆线)。

import cv2
import math
import numpy as np

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

# WARNING: be aware of the direction of the zero (positive vs negative)
def zero_catch(value):
    zeroish = 0.00001
    if value <= zeroish:
        return zeroish
    return value

# get line endpoints
def get_coords(x, y, angle, imwidth, imheight):
    x1_length = (x-imwidth) / zero_catch(math.cos(math.radians(angle)));
    y1_length = (y-imheight) / zero_catch(math.sin(math.radians(angle)));
    length = max(abs(x1_length), abs(y1_length));
    endx1 = x + length * math.cos(math.radians(angle));
    endy1 = y + length * math.sin(math.radians(angle));

    x2_length = (x-imwidth) / zero_catch(math.cos(math.radians(angle+180)));
    y2_length = (y-imheight) / zero_catch(math.sin(math.radians(angle+180)));
    length = max(abs(x2_length), abs(y2_length));
    endx2 = x + length * math.cos(math.radians(angle+180));
    endy2 = y + length * math.sin(math.radians(angle+180));

    return int(endx1), int(endy1), int(endx2), int(endy2);

# skinny up the image
def skeletonize(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;

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

# load image
filepath = "noisy_lines.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);

# super brute force solution
ksize = 51; # tweakable scale setting
center = int(ksize / 2);
kernel = np.zeros((ksize, ksize), np.uint8);

# draw line
start_angle = -60;
angle = start_angle; # start offset so that we can see the 0 degree get drawn
while angle < start_angle + 180:
    kernel = np.zeros((ksize,ksize), np.float32);
    sx, sy, ex, ey = get_coords(center, center, angle, ksize, ksize);
    kernel = cv2.line(kernel, (sx,sy), (ex,ey), 1.0 / ksize, 1);
    angle += 1;

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

    # paint onto canvas
    _, linemask = cv2.threshold(conv, 200, 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;

# show image
cv2.destroyAllWindows();
display_canvas = unpad(canvas, pad);
display_canvas = skeletonize(display_canvas);
orig_img = cv2.imread(filepath);
cv2.imshow("Image", orig_img);
cv2.imshow("Canvas", display_canvas);
cv2.waitKey(0);

字符串

相关问题