Как построить горизонтальную проекцию бинарного изображения в OpenCV - PullRequest
0 голосов
/ 21 января 2019

Я делаю проект сегментации текста для школы.Мне нужно сделать горизонтальную проекцию изображения двоичного изображения.Результаты, которые я хочу, выглядят так:

Example from quora[1].

Я использую OpenCV в Python.Я использовал x_sum = cv2.reduce(img, 0, cv2.REDUCE_SUM, dtype=cv2.CV_32S), чтобы получить массив сумм, как советовал этот вопрос: горизонтальная и вертикальная проекция изображения и этот вопрос: Горизонтальная гистограмма в OpenCV .

Я пытался получить изображение горизонтальной проекции, используя cv2.calcHist, но я получил только одну горизонтальную линию.Мой код ниже:

image = cv2.imread(file_name)
x_sum = cv2.reduce(image, 0, cv2.REDUCE_SUM, dtype=cv2.CV_32S)
horizontal_projection=cv2.calcHist(x_sum,[0],None,[256],[0,256])
cv2.imwrite("image2.png", horizontal_projection) 

Пожалуйста, помогите и скажите мне, что я делаю неправильно.Мне нужно, чтобы результаты моей горизонтальной проекции были такими же, как в примере с Quora.

Ответы [ 2 ]

0 голосов
/ 29 марта 2019

Попробуйте этот простой код

 import cv2
 import numpy as np
 from matplotlib import pyplot as plt
 img = cv2.imread('text.png', cv2.IMREAD_GRAYSCALE)
 height, width = img.shape[:2]
 med = cv2.medianBlur(img,3)
 cv2.namedWindow("med", cv2.WINDOW_NORMAL)
 cv2.imshow("med",med)
 cv2.waitKey(0)
 sum_x = cv2.reduce(cv2.bitwise_not(med), 1, cv2.REDUCE_SUM, dtype=cv2.CV_32S)
 plt.plot(sum_x)
 plt.xlim([0, height])
 plt.show()
0 голосов
/ 21 января 2019

При расчете проекции вы, как правило, хотите суммировать пиксели вдоль каждой строки изображения. Тем не менее, ваш текст черный, который закодирован как ноль, так что вы получите маленькие числа, где много текста в строке и большие числа, где мало текста - что противоположно тому, что вы хотите - так вам нужно инвертировать:

import cv2
import numpy as np

# Load as greyscale
im = cv2.imread('text.png', cv2.IMREAD_GRAYSCALE)

# Invert
im = 255 - im

# Calculate horizontal projection
proj = np.sum(im,1)

Массив proj теперь имеет высоту 141 строку, каждая соответствует количеству текста в этой строке изображения:

array([    0,     0,     0,     0,    40,    44,   144,   182,   264,
         326,   425,  1193,  2718,  5396,  9272, 11880, 13266, 13597,
       12906, 11962, 10791,  9647,  8554, 20469, 45426, 65714, 81397,
       81675, 66590, 58714, 58046, 60516, 66136, 71794, 77552, 78555,
       74868, 72083, 70139, 70160, 72174, 76409, 82854, 88962, 94721,
       88105, 69126, 47753, 23966, 13845, 17406, 19145, 19079, 16548,
       11524,  8511,  7465,  7042,  7197,  6577,  5022,  3476,  1797,
         809,   450,   309,   348,   351,   250,   232,   271,   279,
         251,   628,  1419,  3259,  6187,  8272,  9551,  9825,  9119,
        7984,  6444,  5305,  4596, 13385, 31647, 46330, 57459, 56139,
       42402, 34928, 33729, 35055, 38874, 41649, 43394, 43265, 41291,
       40126, 39767, 40515, 42390, 44478, 46793, 47881, 47743, 43983,
       36644, 28054, 18242, 15583, 20047, 22038, 21569, 17751, 10571,
        6830,  6580,  6231,  5681,  4595,  2879,  1642,   771,   365,
         320,   282,   105,    88,    76,    76,    28,    28,    28,
          28,     0,     0,     0,     0,     0], dtype=uint64)

Я обрезал ваше изображение до 819x141 пикселей следующим образом:

enter image description here


Есть много способов сделать визуализацию. Вот один из них:

#!/usr/bin/env python3

import cv2
import numpy as np

# Load as greyscale
im = cv2.imread('text.png', cv2.IMREAD_GRAYSCALE)

# Invert
im = 255 - im

# Calculate horizontal projection
proj = np.sum(im,1)

# Create output image same height as text, 500 px wide
m = np.max(proj)
w = 500
result = np.zeros((proj.shape[0],500))

# Draw a line for each row
for row in range(im.shape[0]):
   cv2.line(result, (0,row), (int(proj[row]*w/m),row), (255,255,255), 1)

# Save result
cv2.imwrite('result.png', result)

enter image description here

...