Here is an approach that accumulates arrays for columns and rows. Then one can search for maxima in such accumulations (above a certain threshold) and deduce in which row or column there is a vertical or horizontal line.
If you want to quickly test the code, use the following Google Colab Notebook.
Google Colab Notebook
import numpy as np import cv2 import scipy from scipy.signal import find_peaks from matplotlib import pyplot as plt url = "https://i.sstatic.net/S00ap.png" !wget $url -q -O input.jpg fileName = 'input.jpg' img = cv2.imread(fileName) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) tmp = img.copy() gray = cv2.cvtColor(tmp, cv2.COLOR_BGR2GRAY) blurred = cv2.bilateralFilter(gray, 11, 61, 39) edges = cv2.Canny(blurred, 0, 255) v_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,3)) h_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,1)) v_morphed = cv2.morphologyEx(edges, cv2.MORPH_OPEN, v_kernel, iterations=2) v_morphed = cv2.dilate(v_morphed, None) h_morphed = cv2.morphologyEx(edges, cv2.MORPH_OPEN, h_kernel, iterations=2) h_morphed = cv2.dilate(h_morphed, None) v_acc = cv2.reduce(v_morphed, 0, cv2.REDUCE_SUM, dtype=cv2.CV_32S) h_acc = cv2.reduce(h_morphed, 1, cv2.REDUCE_SUM, dtype=cv2.CV_32S) def smooth(y, box_pts): box = np.ones(box_pts)/box_pts y_smooth = np.convolve(y, box, mode='same') return y_smooth s_v_acc = smooth(v_acc[0,:],9) s_h_acc = smooth(h_acc[:,0],9) v_peaks, v_props = find_peaks(s_v_acc, 0.70*np.max(np.max(s_v_acc))) h_peaks, h_props = find_peaks(s_h_acc, 0.70*np.max(np.max(s_h_acc))) for peak_index in v_peaks: cv2.line(tmp, (peak_index, 0), (peak_index, img.shape[0]), (255, 0, 0),2) for peak_index in h_peaks: cv2.line(tmp, (0, peak_index), (img.shape[1], peak_index), (0, 0, 255),2) v_height = v_props['peak_heights'] #list of the heights of the peaks h_height = h_props['peak_heights'] #list of the heights of the peaks def align_axis_x(ax, ax_target): """Make x-axis of `ax` aligned with `ax_target` in figure""" posn_old, posn_target = ax.get_position(), ax_target.get_position() ax.set_position([posn_target.x0, posn_old.y0, posn_target.width, posn_old.height]) def align_axis_y(ax, ax_target): """Make y-axis of `ax` aligned with `ax_target` in figure""" posn_old, posn_target = ax.get_position(), ax_target.get_position() ax.set_position([posn_old.x0, posn_target.y0, posn_old.width, posn_target.height]) fig = plt.figure(constrained_layout=False, figsize=(24,16)) spec = fig.add_gridspec(ncols=4, nrows=2, height_ratios=[1, 1]) ax1 = fig.add_subplot(spec[0,0]) ax1.imshow(tmp) ax2 = fig.add_subplot(spec[0, 1]) ax2.imshow(v_morphed) ax3 = fig.add_subplot(spec[0, 2]) ax3.imshow(h_morphed) ax4 = fig.add_subplot(spec[0, 3], sharey=ax3) ax4.plot(h_acc[:,0], np.arange(len(h_acc[:,0])), 'y', marker="o", ms=1, mfc="k", mec="k") ax4.plot(s_h_acc, np.arange(len(s_h_acc)), 'r', lw=1) ax4.plot(h_height, h_peaks, "x", lw="5") ax5 = fig.add_subplot(spec[1, 1], sharex=ax2) ax5.plot(np.arange(len(v_acc[0,:])), v_acc[0,:], 'y', marker="o", ms=1, mfc="k", mec="k") ax5.plot(np.arange(len(s_v_acc)), s_v_acc, 'r', lw=2) ax5.plot(v_peaks, v_height, "x", lw="5") plt.tight_layout() align_axis_y(ax4,ax3) align_axis_x(ax5,ax2)
