Как отделить кнопку-флажок и текст флажка от изображения с помощью Python? - PullRequest
0 голосов
/ 26 июня 2018

У меня есть изображение

, состоящий из 5 флажков, расположенных параллельно.

Checkbox Image

Мне нужно отделить кнопку-флажок

и текст флажка

и сохраняйте их отдельно.

В изображении может быть любое количество флажков, расположенных параллельно, как я могу разделить кнопку флажка и текст флажка и сохранить их отдельно.

CheckBox Button

CheckBox Text

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

Ответы [ 3 ]

0 голосов
/ 27 июня 2018

Я разделил изображения, расположенные параллельно, и сохранил их, как показано ниже.

enter image description here

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

0 голосов
/ 27 июня 2018

Я немного опоздал с ответом, но, тем не менее, возможно, он послужит кому-то альтернативной идеей.

Сначала вы выполняете поиск контуров в своем изображении и создаете маски и окончательные изображения для отображения результата.

Для каждого контура вы найдете размер контура, так что это поможет вам отфильтровать ваши ящики от букв (ящики больше по размеру). Для флажка я нашел решение отфильтровать его по размеру И по расстоянию от крайней точки слева и справа от контура (вы можете найти множество различных критериев для фильтрации контрольных точек и, возможно, намного более качественные - я сосредоточился только на изображении, которое вы разместили в своем вопросе).

Чтобы попасть в интересующую область, вы найдете значения x, y, h, w с помощью cv2.boundingRect ()

Затем вы просто рисуете его на изображениях, созданных в начале (обратите внимание, что эти выходные данные только черно-белые). Может быть, этот подход даст вам некоторое представление. Ура!

Пример в коде:

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()

Выход:

enter image description here

enter image description here

enter image description here

0 голосов
/ 27 июня 2018

Если предположить, что независимо от количества флажков ваши изображения будут следовать шаблону, подобному сетке, хорошим выбором будет попытка сопоставления с шаблоном. MSTM является примером.

Вы должны попытаться найти отмеченные или не отмеченные поля на изображении с помощью сопоставления с шаблоном и извлечь область с правой стороны от нее. Поскольку вы упомянули, что в строке может быть до 5 флажков, вы можете проверить ширину изображения, разделить ее на 5 и получить приблизительный размер области текста

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...