如何使用Python将checkbox按钮和checkbox文本从图像中分离出来?

2024-04-20 13:55:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我有个形象

由5个平行排列的复选框组成。在

Checkbox Image

我需要分开复选框按钮

和复选框文本

分开保存。在

图像中可以有任意数量的复选框以并行方式排列。如何分割复选框按钮和复选框文本并分别保存它们。在

CheckBox Button

CheckBox Text

我是计算机视觉新手。请指导我如何实现它。在


Tags: 图像文本数量计算机方式视觉按钮复选框
3条回答

我已经拆分了平行排列的图像,并像下面的图像一样保存了它们。在

{a1}

enter image description here

这是我的工作代码,它将方形复选框和图片中的文本分开。在

# Import necessary libraries
from matplotlib import pyplot as plt
import cv2

# Read image
image = cv2.imread('data_2/5.png')

# Height and width of the image
height, width = image.shape[:2]
print("Dimensions of the image.")
print("Height:",height)
print("Width:",width)

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5,5), 0)


# Finding Edges
edges = cv2.Canny(gray, 60, 255)


# contours -> an outline representing or bounding the shape.
_,cnts, hierarchy = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(cnts, key=cv2.contourArea, reverse=True)[:10]
count = 1
for contour in contours:
    if(count<=4):
        #print("Count:",count)
        count = count + 1
        area = cv2.contourArea(contour)
        if area > 100000 and area < 1000:
            contours.remove(contour)
        perimeter = cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, 0.01*perimeter, True)
        if len(approx) == 4:


            cv2.circle(image, (720, 360), 5, (255,0,0), 5)
            cv2.drawContours(image, [approx], -1, (0, 255, 0), 2)   
            M = cv2.moments(approx)

            centers = []
            if M["m00"] != 0:
                cX = int(M["m10"] / M["m00"])
                cY = int(M["m01"] / M["m00"])
            else:
                cX, cY = 0, 0

            P1 = approx[0]
            P1x = P1[0][0]
            P1y = P1[0][1]

            P2 = approx[1]
            P2x = P2[0][0]
            P2y = P2[0][1]

            P3 = approx[2]
            P3x = P3[0][0]
            P3y = P3[0][1]

            P4 = approx[3]
            P4x = P4[0][0]
            P4y = P4[0][1]

plt.imshow(image)
plt.title('Detecting Square')
plt.show()

# Cropping the square_image using array slices   it's a NumPy array
cropped_square = image[P1y:P3y, P2x:P3x]

# Cropping the text image
cropped_text = image[P1y:P3y,P3x+5:width]

# Displaying the cropped square and cropped text image.
plt.imshow(cropped_square)
plt.title('Cropped Square')
plt.show()

plt.imshow(cropped_text)
plt.title('Cropped Text')
plt.show()

# Now saving the cropped square and cropped text image
cv2.imwrite('results/square1.png',cropped_square)
cv2.imwrite('results/text1.png',cropped_text)

上述程序的输出:

enter image description here

我的回答有点晚了,不过也许这会给某些人一个自相矛盾的想法。在

首先搜索图像中的轮廓并创建遮罩和最终图像以显示结果。在

对于每一个轮廓,你会找到轮廓的大小,这样可以帮助你从字母中过滤出你的盒子(盒子的尺寸更大)。对于复选标记,我找到了一个解决方案,可以根据大小和距离轮廓左侧和右侧的极端点的距离(您可以找到很多不同的标准来过滤检查点,可能还有更好的标准-我只关注您在问题中发布的图像)。在

要找到感兴趣的区域,可以使用cv2.boundingRect()找到x、y、h、w值

然后您只需在开始时创建的图像上绘制它(请注意,这些输出仅为黑白)。也许这个方法会给你一些想法。干杯!在

代码示例:

import cv2
import numpy as np

img = cv2.imread('checkbox.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, threshold = cv2.threshold(gray,170,255,cv2.THRESH_BINARY_INV)
im, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
final = np.zeros(gray.shape,np.uint8)
mask = np.zeros(gray.shape,np.uint8)
final2 = np.zeros(gray.shape,np.uint8)
list1 = []


for i in range(0, len(contours)):
    cnt = contours[i]
    epsilon = 0.1*cv2.arcLength(cnt,True)
    approx = cv2.approxPolyDP(cnt,epsilon,True)
    size = cv2.contourArea(approx)
    extLeft = tuple(cnt[cnt[:, :, 0].argmin()][0])
    extRight = tuple(cnt[cnt[:, :, 0].argmax()][0])
    distance = np.sqrt((extLeft[0] - extRight[0])**2 + (extLeft[1] - extRight[1])**2)
    x,y,w,h = cv2.boundingRect(cnt)
    mask[x:x+h, y:y+w]=0
    if 700 > size > 220:
        cv2.drawContours(mask,contours,i,255,-1)
        cv2.drawContours(final,contours,i,255,2)
    elif 16 < distance < 17 and size > 60:
        list1.append(cnt)
    elif size < 250:
        cv2.drawContours(final2,contours,i,(255,255,255),1)

for i in list1:        
    cv2.drawContours(final, [i], -1, (255,255,255), -1)

cv2.bitwise_not(final,final)
cv2.bitwise_not(final2,final2)
cv2.imwrite('c_orig.png', img)
cv2.imwrite('c_boxes.png', final)
cv2.imwrite('c_text.png', final2)
cv2.imshow('img', img)
cv2.imshow('img2', final)
cv2.imshow('img3', final2)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出:

{a1}

enter image description here

enter image description here

假设不管复选框的数量如何,您的图像都将遵循类似网格的模式,一个不错的选择就是尝试模板匹配。MSTM就是一个例子。在

您应该尝试使用模板匹配在图像中查找选中或未选中的框,并将区域提取到右侧。因为您已经提到一行最多可以有5个复选框,所以您可以检查图像的宽度,除以5,得到文本区域的大致大小

相关问题 更多 >