Код: Выделить всё
import cv2
import os
from tqdm import tqdm
def segment_lines(image_path):
# Load the image
img = cv2.imread(image_path)
if img is None:
print(f"Error: Unable to load image at {image_path}")
return []
# Create base output folder
base_output_folder = 'segmented_lines'
os.makedirs(base_output_folder, exist_ok=True)
# Create image-specific output folder inside the base folder
base_name = os.path.splitext(os.path.basename(image_path))[0]
image_output_folder = os.path.join(base_output_folder, base_name)
os.makedirs(image_output_folder, exist_ok=True)
# Convert the image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply binary inverse thresholding
ret, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)
# Define the structuring element for dilation
dilate_kernel = cv2.getStructuringElement(cv2.MORPH_RECT,
(50, 1)) # Wider but shorter kernel to connect words horizontally
mask = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, dilate_kernel)
# Apply erosion to reduce noise and separate lines
erode_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 5))
mask = cv2.morphologyEx(mask, cv2.MORPH_ERODE, erode_kernel)
# Apply a second dilation to rejoin any broken parts of lines
mask = cv2.morphologyEx(mask, cv2.MORPH_DILATE, dilate_kernel)
# Find contours and filter using hierarchy
bboxes = []
bboxes_img = img.copy()
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cntr in contours:
x, y, w, h = cv2.boundingRect(cntr)
if w > 50 and h > 10: # Filter out small contours that are likely noise
cv2.rectangle(bboxes_img, (x, y), (x + w, y + h), (0, 0, 255), 1)
bboxes.append((x, y, w, h))
# Save each segmented line as an individual image with a progress bar
for j, (x, y, w, h) in enumerate(tqdm(bboxes, desc="Saving segmented lines")):
# Ensure the bounding box is within image dimensions
x1 = max(x - 10, 0)
y1 = max(y - 10, 0)
x2 = min(x + w + 10, img.shape[1])
y2 = min(y + h + 10, img.shape[0])
crop = img[y1:y2, x1:x2]
if crop.size > 0:
cv2.imwrite(f'{image_output_folder}/line_{j}.jpg', crop)
# Save the final image with bounding boxes
cv2.imwrite(f'{image_output_folder}/segmented_lines_with_boxes.jpg', bboxes_img)
print(f"Segmented lines saved in the folder '{image_output_folder}'")
if __name__ == '__main__':
image_path = 'img/2.png'
segment_lines(image_path)
Подробнее здесь: https://stackoverflow.com/questions/786 ... gmentation