我想在 python 中仅提取该图像中的图形部分,我该怎么做?

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

我想将右侧的两个图表一起提取或单独提取,两者都可以提取为一个(https://i.stack.imgur.com/RqwkB.jpg

我不知道该尝试什么,我对此很陌生。我正在使用 python,我从图像中提取文本并将其保存在 csv 中

            import cv2
            import numpy as np

            # Load the image
            image_path = r'C:\Prarthana\PROJECTS\GitHub\MajorProject\Images\1.jpg'
            image = cv2.imread(image_path)

            # Convert the image to grayscale
            gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

            # Apply Gaussian blur to reduce noise
            blurred = cv2.GaussianBlur(gray, (5, 5), 0)

            # Apply Canny edge detection
            edges = cv2.Canny(blurred, 50, 150)

            # Find contours in the edge-detected image
            contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

            # Filter contours based on area to find the largest contour (assuming the graph is the largest area)
            contours = sorted(contours, key=cv2.contourArea, reverse=True)[:1]

            # Create a mask to extract the graph region
            mask = np.zeros_like(gray)
            cv2.drawContours(mask, contours, -1, (255, 255, 255), thickness=cv2.FILLED)

            # Apply the mask to the original image to extract the graph
            graph = cv2.bitwise_and(image, image, mask=mask)

            # Save the extracted graph image
            cv2.imwrite(r'C:\Prarthana\PROJECTS\GitHub\MajorProject\Images\output\extracted_graph.jpg', graph)
python machine-learning data-science image-extraction
1个回答
0
投票

我对图像进行了预处理并使用 LineSegmentDetector 来查找线段。后来使用一些逻辑约束来找到图。尝试下面的代码,我为每个步骤的解释添加了注释。希望这有帮助。

import cv2
import numpy as np
import math

#Def to Calculate distance between 2 points
def distanceCalculate(p1, p2):
    """p1 and p2 in format (x1,y1) and (x2,y2) tuples"""
    dis = ((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2) ** 0.5
    return dis


# Load the image
image_path = 'graphs.jpg'
image = cv2.imread(image_path)

# Convert the image to grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

#Threshold the image to obtain only the black parts
ret, thresholded_image = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
#Invert the image
thresholded_image = 255 - thresholded_image

#Do an erosion operation using cross structure kernal to remove parts the are not horizontal or vertical
kernel =  cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
thresholded_image = cv2.erode(thresholded_image,kernel,iterations = 1)

#Use LineSegmentDetector in CV2 to dinf the line segments in the image
lsd = cv2.createLineSegmentDetector(0)
dlines = lsd.detect(thresholded_image)

#Get the line segments in the image
#Find the distance and angle of the found line segments.
#I select the line segment if the distance is > 25 and angle between 0 to 5 for horizontal aned 85 to 90 for vertical lines
line_image = np.zeros_like(thresholded_image)
for dline in dlines[0]:
    x0 = int(round(dline[0][0]))
    y0 = int(round(dline[0][1]))
    x1 = int(round(dline[0][2]))
    y1 = int(round(dline[0][3]))
    dis = distanceCalculate([x0, y0],[x1,y1])
    angle_between = math.degrees(math.atan2(abs(y1-y0), abs(x1-x0)))
    if dis>25 and (0<=angle_between<5 or 85<angle_between<=90):
        cv2.line(line_image, (x0, y0), (x1,y1), 255, 5, cv2.LINE_AA)

#Dilate the the line image to fill gaps in between
kernel =  cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
line_image = cv2.dilate(line_image,kernel,iterations = 1)

#Find fontour and the associated bounding box
#The area of graph bounding boxes will be large compared to other small line contours, this is used to find the graphs
graph_mask = np.zeros_like(thresholded_image)
contours, _ = cv2.findContours(line_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
selected_bounding_rect = []
for ctr in contours:
    bounding_rect = cv2.boundingRect(ctr)
    bounding_rect_area = bounding_rect[2] * bounding_rect[3]
    if bounding_rect_area>15000:# This can be adjusted according to your need.
        contour_image = cv2.rectangle(graph_mask,bounding_rect,255,-1)

#Get the graph from original image from the mask
selected_image = cv2.bitwise_and(image, image, mask=graph_mask)
# Save the extracted graph image
cv2.imwrite('graph_result.jpg', selected_image)

输出图像:

© www.soinside.com 2019 - 2024. All rights reserved.