如何找到文本字段的边线

时间:2016-08-15 16:13:03

标签: opencv image-processing computer-vision

我有一个带有文本的已处理图像,我想要找到会触及文本字段边缘的线条坐标,但是不会穿过它并且会遍历文本的整个边缘。下图显示了我需要的内容(我绘制的红线显示了我想在原始图像上找到的坐标的示例): enter image description here

这不是那么简单,我无法找到处理过的文本字段的边缘(左上角,右上角等),因为它可能是,f.e。段落的开头(这只是可能场景的一个例子):

enter image description here

文本的两边形成一条直线,顶部和底部边缘可能是弯曲的,这样可以使事情变得更容易。

这样做的最佳方式是什么?

我能想到的任何方法要么不实用,要么不合理,或者通常会给出错误的结果。

原始图像以防有人需要处理:

enter image description here

2 个答案:

答案 0 :(得分:2)

想法是找到所有文本的凸包。在我们找到凸包后,我们找到了它的两侧。如果边的y坐标有很大的变化,x坐标变化很小(即线的斜率很大),我们会将其视为边线。

结果图片:

enter image description here

代码:

import cv2
import numpy as np

def getConvexCoord(convexH, ind):
    yLines = []
    xLine = []
    for index in range(len(ind[0])):
        convexIndex = ind[0][index]

        # Get point
        if convexIndex == len(convexH) - 1:
            p0 = convexH[0]
            p1 = convexH[convexIndex]
        else:
            p0 = convexH[convexIndex]
            p1 = convexH[convexIndex + 1]

        # Add y corrdinate
        yLines.append(p0[0, 1])
        yLines.append(p1[0, 1])
        xLine.append(p0[0, 0])
        xLine.append(p1[0, 0])
    return yLines,xLine

def filterLine(line):
    sortX = sorted(line)
    # Find the median
    xMedian = np.median(sortX)
    while ((sortX[-1] - sortX[0]) > I.shape[0]):

        # Find out which is farther from the median and discard
        lastValueDistance = np.abs(xMedian - sortX[-1])
        firstValueDistance = np.abs(xMedian - sortX[0])
        if lastValueDistance > firstValueDistance:

            # Discard last
            del sortX[-1]
        else:
            # Discard first
            del sortX[0]

    # Now return mixX and maxX
    return max(sortX),min(sortX)


# Read image
Irgb = cv2.imread('text.jpg')
I = Irgb[:,:,0]

# Threshold
ret, Ithresh = cv2.threshold(I,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# Find the convex hull of the text
textPixels = np.nonzero(Ithresh)
textPixels = zip(textPixels[1],textPixels[0])
convexH = cv2.convexHull(np.asarray(textPixels))

# Find the side edges in the convex hull
m = []
for index in range((len(convexH))-1):

    # Calculate the angle of the line
    point0 = convexH[index]
    point1 = convexH[index+1]
    if(point1[0,0]-point0[0,0]) == 0:
        m.append(90)
    else:
        m.append(float((point1[0,1]-point0[0,1]))/float((point1[0,0]-point0[0,0])))

# Final line
point0 = convexH[index+1]
point1 = convexH[0]
if(point1[0,0]-point0[0,0]) == 0:
    m.append(90)
else:
    m.append(np.abs(float((point1[0,1]-point0[0,1]))/float((point1[0,0]-point0[0,0]))))

# Take all the lines with the big m
ind1 = np.where(np.asarray(m)>1)
ind2 = np.where(np.asarray(m)<-1)

# For both lines find min Y an max Y
yLines1,xLine1 = getConvexCoord(convexH,ind1)
yLines2,xLine2 = getConvexCoord(convexH,ind2)
yLines = yLines1 + yLines2

# Filter xLines. If we the difference between the min and the max are more than 1/2 the size of the image we filter it out
minY = np.min(np.asarray(yLines))
maxY = np.max(np.asarray(yLines))

maxX1,minX1 = filterLine(xLine1)
maxX2,minX2 = filterLine(xLine2)

# Change final lines to have minY and maxY
line1 = ((minX1,minY),(maxX1,maxY))
line2 = ((maxX2,minY),(minX2,maxY))

# Plot lines
IrgbWithLines = Irgb
cv2.line(IrgbWithLines,line1[0],line1[1],(0, 0, 255),2)
cv2.line(IrgbWithLines,line2[0],line2[1],(0, 0, 255),2)

<强>说明: 该算法假设y坐标变化大于x坐标变化。对于非常高的透视扭曲(45度),情况并非如此。在这种情况下,您可以在斜坡上使用k-means,并将具有较高斜率的组作为垂直线。

答案 1 :(得分:0)

可以使用图像关闭操作找到两侧标记为红色的线条。 使用方形和大小为4的结构元素进行imclose操作后,请在下面找到matlab输出。&#39; the result of code segment

matlab代码如下:

I = rgb2gray(imread(&#39; image.jpg&#39;)); imshow(I);标题(&#39;图像&#39);

Ibinary = im2bw(I); 图中,imshow(Ibinary);

se = strel(&#39; square&#39;,4);

Iclose = imclose(Ibinary,se); 图中,imshow(I关闭);标题(&#39;边线&#39;);