OpenCV - 提取图表上的线

标签 opencv computer-vision houghlinesp

我想创建一个能够从图形中提取线条的程序。

例如,如果输入这样的图表,我只想输出红线。 enter image description here

下面我尝试使用霍夫线变换来做到这一点,但是,我没有得到非常有希望的结果。

import cv2
import numpy as np

graph_img = cv2.imread("/Users/2020shatgiskessell/Desktop/Graph1.png")
gray = cv2.cvtColor(graph_img, cv2.COLOR_BGR2GRAY)

kernel_size = 5
#grayscale image
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)

#Canny edge detecion
edges = cv2.Canny(blur_gray, 50, 150)

#Hough Lines Transformation

#distance resoltion of hough grid (pixels)
rho = 1 
#angular resolution of hough grid (radians)
theta = np.pi/180 
#minimum number of votes
threshold = 15 

#play around with these
min_line_length = 25
max_line_gap = 20

#make new image
line_image = np.copy(graph_img)

#returns array of lines
lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]),
                    min_line_length, max_line_gap)

for line in lines:
    for x1,y1,x2,y2 in line:
        cv2.line(line_image,(x1,y1),(x2,y2),(255,0,0),2)


lines_edges = cv2.addWeighted(graph_img, 0.8, line_image, 1, 0)

cv2.imshow("denoised image",edges)


if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

这会产生下面的输出图像,该图像无法准确识别图形线。我该怎么做呢?

注意:目前,我不关心图表标题或任何其他文本。

enter image description here

我还希望代码也适用于其他图形图像,例如: enter image description here enter image description here 等等

最佳答案

如果图形周围没有太多噪声(如您的示例),我建议使用 Otsu 阈值对图像进行阈值处理,而不是寻找边缘。然后,您只需搜索轮廓,选择最大的轮廓(图形)并将其绘制在空白蒙版上。之后,您可以使用蒙版对图像执行按位运算,您将得到带有图形的黑色图像。如果您更喜欢白色背景,则只需将所有黑色像素更改为白色即可。步骤已写在示例中。希望它能有所帮助。干杯!

示例:

import numpy as np
import cv2

# Read the image and create a blank mask
img = cv2.imread('graph.png')
h,w = img.shape[:2]
mask = np.zeros((h,w), np.uint8)

# Transform to gray colorspace and threshold the image
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# Search for contours and select the biggest one and draw it on mask
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
cv2.drawContours(mask, [cnt], 0, 255, -1)

# Perform a bitwise operation
res = cv2.bitwise_and(img, img, mask=mask)

# Convert black pixels back to white
black = np.where(res==0)
res[black[0], black[1], :] = [255, 255, 255]

# Display the image
cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

enter image description here

编辑:

对于嘈杂的图片,您可以尝试此代码。请注意,不同的图具有不同的噪声,并且可能不适用于每个图图像,因为去噪过程在每种情况下都是特定的。对于不同的噪声,您可以使用不同的方法对其进行去噪,例如直方图均衡、腐 eclipse 、模糊等。此代码适用于所有 3 个图。步骤写在评论里了。希望能帮助到你。干杯!

import numpy as np
import cv2


# Read the image and create a blank mask
img = cv2.imread('graph.png')
h,w = img.shape[:2]
mask = np.zeros((h,w), np.uint8)

# Transform to gray colorspace and threshold the image
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# Perform opening on the thresholded image (erosion followed by dilation)
kernel = np.ones((2,2),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

# Search for contours and select the biggest one and draw it on mask
_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
cv2.drawContours(mask, [cnt], 0, 255, -1)

# Perform a bitwise operation
res = cv2.bitwise_and(img, img, mask=mask)

# Threshold the image again
gray = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# Find all non white pixels
non_zero = cv2.findNonZero(thresh)

# Transform all other pixels in non_white to white
for i in range(0, len(non_zero)):
    first_x = non_zero[i][0][0]
    first_y = non_zero[i][0][1]
    first = res[first_y, first_x]
    res[first_y, first_x] = 255

# Display the image
cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

enter image description here

enter image description here

enter image description here

关于OpenCV - 提取图表上的线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52795426/

相关文章:

Python/OpenCV — 细菌图像中的智能质心跟踪?

python - 如何使用 OpenCV 检测物体的边缘

python - OpenCV 概率霍夫线变换使用 C++ 和 Python 给出不同的结果?

python - 如何从图像中删除线条(由 HoughLines 检测到)?

python - opencv while循环,回到第一个循环

c++ - 使用 OpenCV header 编译 C++ 文件时没有此类文件或目录错误

c# - 在 emgu CV 中使用 SURF 进行对象识别

python - OpenCV 无法正确写入输出文件 (Python)

opencv - 了解霍夫变换

opencv - LibTorch C++和Eigen之间的数据传输