how to segment text/handwritten lines using horizontal profile projection?

Question:

I have managed to get the horizontal profile projection of a handwritten image(the code of which in python is mentioned below). I wish to segment the individual lines and save them. I know this can be done using other methods but I wish to implement it by the horizontal profile projection that I have obtained. Point/Pixel of interest is the starting point from where the projection profile initiates or it is greater than zero till again the projection profile reaches to zero.
Horizontal Profile Projection of handwritten image
The peaks in the image depicts where it detects the text in the image, now I wish to segment and save those sections/individual lines of text of the original image.

    def getHorizontalProjectionProfile(image):
      # Convert black spots to ones
      image[image == 0] = 1
      # Convert white spots to zeros
      image[image == 255] = 0
      horizontal_projection = np.sum(image, axis=1)
      return (horizontal_projection, image)
    #Calling the horizontal projection function
    horizontal_projection = getHorizontalProjectionProfile(binary.copy())

    m = np.max(horizontal_projection[0])
    w = 500
    result = np.zeros((horizontal_projection[0].shape[0],500))
    for row in range(image.shape[0]):
       cv2.line(result, (0,row), (int(horizontal_projection[0]   [row]*w/m),row), (255,255,255), 1)
       cv2.imshow('Result', result)
       cv2.waitKey()

So the result variable displays the image of the horizontal profile projection. Also the variable binary.copy() holds the binary image of the input handwritten image.
Kindly let me know if the post requires any further changes.

Asked By: TheNeanderthal

||

Answers:

Is this what you are looking for?

import cv2
import numpy as np


def getHorizontalProjectionProfile(image):
    # convert black spots to ones and others to zeros
    binary = np.where(image == 0, 1, 0)
    # add up rows
    horizontal_projection = np.sum(binary, axis=1)
    return horizontal_projection


# read image and get threshold
img = cv2.imread("img.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 127, 255, 0)

# call the horizontal projection function
horizontal_projection = getHorizontalProjectionProfile(thresh)

start_of_line = 0
count = 0

for row in range(len(horizontal_projection)):
    if horizontal_projection[row] == 0:
        if start_of_line > 0:
            count += 1
            print(f"Line {count} found from row {start_of_line} to {row}")
            start_of_line = 0
    else:
        if start_of_line == 0:
            start_of_line = row

Output something like:

Line 1 found from row 15 to 43
Line 2 found from row 109 to 143
Line 3 found from row 156 to 190
Line 4 found from row 203 to 237
...
Answered By: Markus