Удалить черный заголовок раздела изображения, используя Python OpenCV - PullRequest
2 голосов
/ 13 февраля 2020

Мне нужно удалить затемненный участок на нескольких частях изображения, используя Python CV. Я пробовал с шумоподавлением, которое не дает удовлетворительных результатов.

Например. Мне нужно удалить зачерненную часть в заголовке таблицы (изображение ниже) и преобразовать фон заголовка в белый с содержимым черного цвета.

enter image description here

Может кто-нибудь помочь мне с выбором правильной библиотеки или решения, чтобы преодолеть это?

Ответы [ 2 ]

4 голосов
/ 14 февраля 2020

Трудно отфильтровать пунктирный рисунок, как вы можете видеть. Это явно перекрывает текст. Я вижу по крайней мере два варианта: 1) Использовать периодическую c природу паттерна и выполнять частотную фильтрацию . 2) Попробуйте более простой подход, используя морфологическое попадание или промах для целевых пикселей с целью их выделения.

Давайте рассмотрим вариант 2. Шум имеет очень характерную картину. Если вы работаете с двоичным изображением, в котором все капли окрашены в белый цвет, то шаблон, который вы ищете, это белый пиксель (1) , окруженный 8 черными пикселями (0) :

[ 0, 0, 0 ]
[ 0, 1, 0 ]
[ 0, 0, 0 ]

Операция попадания и пропуска может использоваться для определения местоположения и выделения шаблонов пикселей. Вот хороший пост, если вы хотите узнать о нем больше. А сейчас давайте поработаем с кодом:

//Read the input image, as normal:
std::string imagePath = "C://opencvImages//tableTest.png";
cv::Mat testImage = cv::readImage( imagePath );

//Convert the image to grayscale:
cv::Mat grayImage;
cv::cvtColor( testImage, grayImage, cv::COLOR_BGR2GRAY );

//Get the binary image via otsu:
cv::Mat binaryImage;
cv::threshold( grayImage, binaryImage, 0, 255,cv::THRESH_OTSU );

//Invert the image, as we will be working on white blobs:
binaryImage = 255 - binaryImage;

//Prepare the target kernel. This is where you define the pattern of 
//pixels you are looking for
//Keep in mind that -1 -> black and 1 -> white

cv::Mat kernel = ( cv::Mat_<int>(3, 3) <<
    -1, -1, -1,
    -1, 1, -1,
    -1, -1, -1
);

//perform the hit or miss operation:
cv::Mat hitMissMask;
cv::morphologyEx( binaryImage, hitMissMask, cv::MORPH_HITMISS, kernel );

Вот маска, которую вы получите:

enter image description here

Теперь просто вычтите эту маску к исходному (двоичному) изображению, и вы получите:

enter image description here

Как видите, часть заголовка столбца мешает операция. Если вам нужен белый фон и черные пятна, просто инвертируйте изображение:

enter image description here

3 голосов
/ 14 февраля 2020

Вот модифицированная версия подхода @ eldesgraciado для фильтрации точечного рисунка с использованием морфологического удара или промаха по целевым пикселям в Python. Разница в том, что вместо того, чтобы вычитать маску из двоичного изображения, которое снижает качество текста, мы расширяем двоичное изображение, а затем поразрядно - и сохраняем качество текста.

  1. Получить двоичный файл image. Загрузить изображение, оттенки серого, Порог Оцу

  2. Выполнить операцию морфологического удара или промаха. Мы создаем ядро ​​с точечным растром с cv2.getStructuringElement, затем используйте cv2.filter2D для свертки изображения

  3. Удалите точки. Мы cv2.bitwise-xor маска с двоичным изображением

  4. Исправление поврежденных текстовых пикселей. Мы cv2.dilate затем cv2.bitwise_and окончательная маска с входным изображением и цветным фоновым пикселем белого цвета


Двоичное изображение

enter image description here

Маска точек

enter image description here

Удалить точки

enter image description here

Расширить, чтобы исправить поврежденные текстовые пиксели из процесс шолдинга

enter image description here

Результат

enter image description here

Код

import cv2
import numpy as np

# Load image, grayscale, Otsu's threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Perform morphological hit or miss operation
kernel = np.array([[-1,-1,-1], [-1,1,-1], [-1,-1,-1]])
dot_mask = cv2.filter2D(thresh, -1, kernel)

# Bitwise-xor mask with binary image to remove dots
result = cv2.bitwise_xor(thresh, dot_mask)

# Dilate to fix damaged text pixels
# since the text quality has decreased from thresholding
# then bitwise-and with input image
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
dilate = cv2.dilate(result, kernel, iterations=1)
result = cv2.bitwise_and(image, image, mask=dilate)
result[dilate==0] = [255,255,255]

cv2.imshow('dot_mask', dot_mask)
cv2.imshow('thresh', thresh)
cv2.imshow('result', result)
cv2.imshow('dilate', dilate)
cv2.waitKey()
...