Получить белый текст на черном фоне - PullRequest
1 голос
/ 15 января 2020

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

enter image description here

Я использовал пороговое значение отсу для бинаризации изображения

enter image description here

После идентификации контура и удаления нетекстовых областей я определил необходимую текстовую область.

enter image description here

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

Ожидаемый результат:

enter image description here

import cv2
import numpy as np


def process(img):
 # read image
 img_no = str(img)
 rgb = cv2.imread(img_no + '.jpg')
 # cv2.imshow('original', rgb)

 # convert image to grayscale
 gray = cv2.cvtColor(rgb, cv2.COLOR_BGR2GRAY)

 _, bw_copy = cv2.threshold(gray, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

 # bilateral filter
 blur = cv2.bilateralFilter(gray, 5, 75, 75)
 # cv2.imshow('blur', blur)

 # morphological gradient calculation
 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
 grad = cv2.morphologyEx(blur, cv2.MORPH_GRADIENT, kernel)
 # cv2.imshow('gradient', grad)

 # binarization
 _, bw = cv2.threshold(grad, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
 # cv2.imshow('otsu', bw)

 # closing
 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 1))
 closed = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel)
 # cv2.imshow('closed', closed)

 # finding contours
 contours, hierarchy = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

 mask = np.zeros(closed.shape, dtype=np.uint8)
 mask1 = np.zeros(bw_copy.shape, dtype=np.uint8)

 for idx in range(len(contours)):
    x, y, w, h = cv2.boundingRect(contours[idx])
    mask[y:y + h, x:x + w] = 0
    area = cv2.contourArea(contours[idx])
    aspect_ratio = float(w) / h
    cv2.drawContours(mask, contours, idx, (255, 255, 255), -1)
    r = float(cv2.countNonZero(mask[y:y + h, x:x + w])) / (w * h)

    # identify region of interest
    if r > 0.34 and 0.52 < aspect_ratio < 13 and area > 145.0:
        cv2.drawContours(mask1, [contours[idx]], -1, (255, 255, 255), -1)

 result = cv2.bitwise_and(bw_copy, mask1)
 cv2.imshow('result', result)

 print(img_no + " Done")
 cv2.waitKey()

Новый Изображение

Принятый ответ не работает с этой картинкой.

enter image description here

1 Ответ

3 голосов
/ 15 января 2020

На первый взгляд это выглядит как простой вопрос, но решить его довольно сложно. Однако у вас уже есть все ингредиенты, необходимые для решения проблемы, и вам требуется лишь небольшая настройка вашего алгоритма.

Вот суть:

Вам нужно перевернутое изображение (wb_copy) вашего порогового изображения (bw_copy).

enter image description here

enter image description here

Вы проделали большую работу создание маски

enter image description here

Запустите операцию bitwise_and как для bw_copy, так и для wb_copy с маской выше. Вы должны получить результат, показанный ниже.

enter image description here

enter image description here

Как видите, ваш Ответ abit от обоих изображений. Все, что вам нужно сделать, это для каждого шарика шрифта, отсчитать ненулевой пиксель из обоих изображений и выбрать тот, который имеет большее количество. Это даст желаемый результат.

enter image description here

Вот изменения, которые я внес в код

  # finding contours
    _,contours,_ = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

    mask = np.zeros(closed.shape, dtype=np.uint8)
    mask1 = np.zeros(bw_copy.shape, dtype=np.uint8)
    wb_copy = cv2.bitwise_not(bw_copy)
    new_bw = np.zeros(bw_copy.shape, dtype=np.uint8)

    for idx in range(len(contours)):
        x, y, w, h = cv2.boundingRect(contours[idx])
        mask[y:y + h, x:x + w] = 0
        area = cv2.contourArea(contours[idx])
        aspect_ratio = float(w) / h
        cv2.drawContours(mask, contours, idx, (255, 255, 255), -1)
        r = float(cv2.countNonZero(mask[y:y + h, x:x + w])) / (w * h)


        # identify region of interest
        if r > 0.34 and 0.52 < aspect_ratio < 13 and area > 145.0:

            cv2.drawContours(mask1, [contours[idx]], -1, (255, 255, 255), -1)

            bw_temp = cv2.bitwise_and(mask1[y:y + h, x:x + w],bw_copy[y:y + h, x:x + w])
            wb_temp = cv2.bitwise_and(mask1[y:y + h, x:x + w],wb_copy[y:y + h, x:x + w])

            bw_count = cv2.countNonZero(bw_temp)
            wb_count = cv2.countNonZero(wb_temp)

            if bw_count > wb_count:
                new_bw[y:y + h, x:x + w]=np.copy(bw_copy[y:y + h, x:x + w])
            else:
                new_bw[y:y + h, x:x + w]=np.copy(wb_copy[y:y + h, x:x + w])

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