我正在为学校做一个文本分割项目。我需要对二进制图像进行水平图像投影。我想要的结果是这样的:
。
我正在Python中使用OpenCV。根据问题horizontal and vertical projection of an image和问题Horizontal Histogram in OpenCV的建议,我使用了x_sum = cv2.reduce(img, 0, cv2.REDUCE_SUM, dtype=cv2.CV_32S)
来获取总和的数组。
我尝试使用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示例一样。
答案 0 :(得分:1)
在计算投影时,您基本上要对图像每一行的像素求和。但是,您的文本是黑色的,其编码为零,因此您将在连续的文本很多的地方得到小数字,而在连续的文本很少的地方得到大数字-这与您想要的相反-因此您需要反转:
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像素,如下所示:
有很多方法可以进行可视化。这是一个:
#!/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)
答案 1 :(得分:0)
尝试此简单代码
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()