如何在使用Otsu二值化时,使用OpenCV Python对图像进行分割

3
我对计算机视觉概念很陌生,但正在努力学习。我有一张包含字母的图片,并对其执行了大津二值化,使图像中的所有实际内容都更改为相同的颜色(在我的情况下为白色255)。现在我想将图像分割成字母。例如,enter image description here 现在我想循环遍历这个图像,以获取其中每个字符的单独numpy数组或单独图像,以便将其传递给我构建的模型。请问如何实现这一点或是否有任何算法可用?
我考虑过使用循环,但这似乎会耗费太多时间。

你所说的“获取每个单独字符”具体指什么?是获取包含每个字符的子图像,还是获取表示实际字符的字符本身?这些任务截然不同,需要澄清。 - David
获取包含每个字符的子图像。 - Srihari Mohan
1个回答

3
在以下解决方案中,您可以针对每个句子单独获取单词。在逐个获取单词后,它将按字符输出。
这是完整的代码:
import cv2
import numpy as np
image = cv2.imread("stach.png",0)
cv2.imshow('orig',image)
# image = cv2.resize(image_original,None,fx=4, fy=4, interpolation = cv2.INTER_CUBIC)



#dilation
kernel = np.ones((5,100), np.uint8)
img_dilation = cv2.dilate(image, kernel, iterations=1)
# original_resized = cv2.resize(img_dilation, (0,0), fx=.2, fy=.2)
cv2.imshow('dilated',img_dilation)
cv2.waitKey(0)
#find contours
im2,ctrs, hier = cv2.findContours(img_dilation.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

#sort contours
sorted_ctrs = sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[1])

for i, ctr in enumerate(sorted_ctrs):

    # Get bounding box
    x, y, w, h = cv2.boundingRect(ctr)

    # Getting ROI
    roi = image[y:y+h, x:x+w]

# #   show ROI
    cv2.imshow('segment no:' +str(i),roi)
    cv2.waitKey(0)



    im = cv2.resize(roi,None,fx=4, fy=4, interpolation = cv2.INTER_CUBIC)
    ret_1,thresh_1 = cv2.threshold(im,127,255,cv2.THRESH_BINARY_INV)
    # original_resized = cv2.resize(thresh, (0,0), fx=.2, fy=.2)
    cv2.imshow('Threshold_1',thresh_1)
    cv2.waitKey(0)
    cv2.bitwise_not(thresh_1, thresh_1)
    kernel = np.ones((5, 30), np.uint8)
    words = cv2.dilate(thresh_1, kernel, iterations=1)
    cv2.imshow('words', words)
    cv2.waitKey(0)


    #words=cv2.cvtColor(words, cv2.COLOR_BGR2GRAY);

    #find contours
    im,ctrs_1, hier = cv2.findContours(words, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    #sort contours
    sorted_ctrs_1 = sorted(ctrs_1, key=lambda ctr: cv2.boundingRect(ctr)[0])

    for j, ctr_1 in enumerate(sorted_ctrs_1):

        # Get bounding box
        x_1, y_1, w_1, h_1 = cv2.boundingRect(ctr_1)

        # Getting ROI
        roi_1 = thresh_1[y_1:y_1+h_1, x_1:x_1+w_1]

        # #   show ROI
        cv2.imshow('Line no: ' + str(i) + " word no : " +str(j),roi_1)
        cv2.waitKey(0)

        #chars = cv2.cvtColor(roi_1, cv2.COLOR_BGR2GRAY);

        # dilation
        kernel = np.ones((10, 1), np.uint8)
        joined = cv2.dilate(roi_1, kernel, iterations=1)
        # original_resized = cv2.resize(img_dilation, (0,0), fx=.2, fy=.2)
        cv2.imshow('joined', joined)
        cv2.waitKey(0)

        # find contours
        im, ctrs_2, hier = cv2.findContours(joined, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        # sort contours
        sorted_ctrs_2 = sorted(ctrs_2, key=lambda ctr: cv2.boundingRect(ctr)[0])



        for k, ctr_2 in enumerate(sorted_ctrs_2):
            # Get bounding box
            x_2, y_2, w_2, h_2 = cv2.boundingRect(ctr_2)

            # Getting ROI
            roi_2 = roi_1[y_2:y_2 + h_2, x_2:x_2 + w_2]

            # #   show ROI
            cv2.imshow('Line no: ' + str(i) + ' word no : ' + str(j) + ' char no: ' + str(k), roi_2)
            cv2.waitKey(0)

首先需要进行文本分割。使用以下代码:

kernel = np.ones((5,100), np.uint8)
img_dilation = cv2.dilate(image, kernel, iterations=1)

使用5x100的核来分离图像中的行。

结果如下:

之后从上述图像中提取轮廓并将该轮廓坐标应用于原始图像。然后提取图像的线条。示例线如下:

然后对每个这些行应用另一个核,使用与提取行相同的方法提取单词。

kernel = np.ones((5, 30), np.uint8)
words = cv2.dilate(thresh_1, kernel, iterations=1)

在逐个提取单词后,可以使用以下代码逐个提取字符:

for k, ctr_2 in enumerate(sorted_ctrs_2):
    # Get bounding box
    x_2, y_2, w_2, h_2 = cv2.boundingRect(ctr_2)

    # Getting ROI
    roi_2 = roi_1[y_2:y_2 + h_2, x_2:x_2 + w_2]

希望您能理解我提供的方法。您可以根据您的要求对完整代码进行修改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接