Remove black header section of image using Python OpenCV

*爱你&永不变心* 提交于 2020-02-22 07:45:08

问题


I need to remove the blackened section in multiple parts of image using Python CV. I tried with denoising which doesn't give satisfactory results.

Eg. I need to remove the blackened part in Table Header (below image) and convert the header background to white with contents as black.

Can anyone help me with choosing the correct library or solution to overcome this?


回答1:


Here's a modified version of @eldesgraciado's approach to filter the dotted pattern using a morphological hit or miss operation on the target pixels in Python. The difference is that instead of subtracting the mask with the binary image which decreases text quality, we dilate the binary image then bitwise-and to retain the text quality.

  1. Obtain binary image. Load image, grayscale, Otsu's threshold

  2. Perform morphological hit or miss operation. We create a dot pattern kernel with cv2.getStructuringElement then use cv2.filter2D to convolve the image

  3. Remove dots. We cv2.bitwise-xor the mask with the binary image

  4. Fix damaged text pixels. We cv2.dilate then cv2.bitwise_and the finalized mask with the input image and color background pixels white


Binary image

Dot mask

Remove dots

Dilate to fix damaged text pixels from the thresholding process

Result

Code

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



回答2:


It is difficult to filter the dotted pattern, as you can see. It is clearly overlapping the text. I see at least two options: 1) Exploit the periodic nature of the pattern and carry out frequency filtering. 2) Try a simpler approach using a morphological hit or miss operation on the target pixels, aiming to isolate them.

Let's check out option 2. The noise has a very distinctive pattern. If you work with the binary image where all the blobs are colored in white, the pattern you are looking for is a white pixel (1) surrounded by 8 black pixels (0):

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

The hit and miss operation can be used to locate and isolate pixel patterns. Here's a good post if you want to learn more about it. For now, let’s work on the code:

//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 );

This is the mask you get:

Now, just subtract this mask to the original (binary) image and you get this:

As you can see, part of the column header gets in the way of the operation. If you want a white background and black blobs, just invert the image:



来源:https://stackoverflow.com/questions/60200291/remove-black-header-section-of-image-using-python-opencv

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!