I have an image which contains a table in it. I need to extract the text from it. I tried to remove horizontal and vertical lines first, but it doesn't seems to work. Below is the code which I used.
import cv2
import numpy as np
img = cv2.imread(r'A13205.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 175, 255, cv2.THRESH_BINARY)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4, 4))
morph_img = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
#inverse the image, so that lines are black for masking
morph_img_inv = cv2.bitwise_not(morph_img)
#perform bitwise_and to mask the lines with provided mask
masked_img = cv2.bitwise_xor(thresh, thresh, mask = morph_img)
Input from which text must be extracted
Related
iam a beginner at python and opencv. Iam interested about image processing and iam about to binarize this image.
[This is the image]
(https://i.stack.imgur.com/nKNKt.png)
[The final processed image]
(https://i.stack.imgur.com/R6La9.png)
this is what i try and the step that i implemented. Iam reading about image segmenting and grid removing. The thing that i understand is:
grayscaling image
blur the image
binarize the image
morphological operation
Here's the code
import cv2
import numpy as np
#load an image
img = cv2.imread('src.png')
#grayscaling image
gray0 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#blur image-1
blurred0 = cv2.GaussianBlur(gray0, (3,3), 0)
#thresholding an image-1
t, thresh4 = cv2.threshold(blurred0, 158, 255, cv2.THRESH_BINARY_INV)
#creating kernel
kernel = np.ones((3,3), np.uint8)
#morphological operations
opening1 = cv2.morphologyEx(thresh4, cv2.MORPH_CLOSE, kernel)
#repeat blur-2
close = cv2.GaussianBlur(opening1, (3,3), 0)
#repeat thresholding-2
t, threshz = cv2.threshold(close, 127, 255, cv2.THRESH_BINARY)
#repeat blur-3
layer0 = cv2.GaussianBlur(threshz, (5,5), 0)
#repeat thresholding-3
t, threshz = cv2.threshold(layer0, 90, 255, cv2.THRESH_BINARY)
#morph close
threshzx = cv2.morphologyEx(threshz, cv2.MORPH_CLOSE, kernel)
i felt there's simple way than repeating this code to obtain the binarized image that we want. Thank you for your help.
I'm working on computer vision and I have an image as shown below:
I want to identify the black line on the tissue. I have tried the following code
import cv2
img = cv2.imread('image.png')
# convert img to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# do morphology gradient
kernel = cv2.getStructuringElement(cv2.MORPH_RECT , (3,3))
morph = cv2.morphologyEx(gray, cv2.MORPH_GRADIENT, kernel)
# apply gain
morph = cv2.multiply(morph, 10)
morph=cv2.resize(morph, (1000, 552))
imgStack = stackImages(0.5, ([img ], [morph]))
cv2.imshow('Stacked Images', imgStack)
cv2.waitKey(0)
the above line of code gives:
As we can see, the existing pattern prevails and it is difficult to identify the line. How to discard the true pattern and identify the anamolies.
I did try the other answers in stackoverflow, but nothing seem to work
In reference to the comments, I was suggesting to apply global threshold cv2.threshold():
Code:
img = cv2.imread(r'C:\Users\524316\Desktop\Stack\tissue.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
threshold_value = 20
th = cv2.threshold(gray, threshold_value, 255, cv2.THRESH_BINARY_INV)[1]
cv2.imshow(cv2.hconcat([gray, th]))
cv2.waitKey(0)
Result:
Notice the black line highlighted while no other patterns are affected.
import cv2
import numpy as np
# Load image, grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (7,7), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Create rectangular structuring element and dilate
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
dilate = cv2.dilate(thresh, kernel, iterations=4)
cv2.imshow('dilate', dilate)
cv2.waitKey()
I am trying to mask the text elements in an image and return an image with just the remaining portions. I have applied thresholding and dilating, but how can I retain the background.
Image after thresholding and dilating
Original image:
Here is a simple approach:
Using the inverted dilated image cv2.bitwise_not(dilate), create a mask over the original image.
res = cv2.bitwise_and(image, image, mask=cv2.bitwise_not(dilate))
In the above image you have all text regions and its boundaries masked out.
Now replace those masked out regions with the background of your original image. To do that, first I noted down the coordinates where of the text regoins in mask_ind. Then replaced the pixel values in those regions with the background of the original image image[0,0]
mask_ind = (dilate == 255)
res[mask_ind] = image[0,0]
cv2.imshow(res)
I am trying to remove text from images that has a black border with white fill. Take the image below as an example.
I have tried a few options utilizing opencv and skimage inpaint
import cv2
from skimage.restoration import inpaint
img = cv2.imread('Documents/test_image.png')
mask = cv2.threshold(img, 210, 255, cv2.THRESH_BINARY)[1][:,:,0]
dst = cv2.inpaint(img, mask, 7, cv2.INPAINT_TELEA)
image_result = inpaint.inpaint_biharmonic(img, mask,
multichannel=True)
cv2.imshow('image',img)
cv2.imshow('mask',mask)
cv2.imshow('dst',dst)
cv2.imshow('image_result',image_result)
cv2.waitKey(0)
It seems like the inpainting is just trying to fill with black as that is what it is identifying as being around the areas of interest. What I would like to do is remove the white text and black borders completely, or secondarily try to fill the white with more information from surrounding colors than just the black.
Here is the best solution I could come up with, still open to others with more experience showing me a better way if anyone has an idea.
mask = cv2.threshold(img, 245, 255, cv2.THRESH_BINARY)[1][:,:,0]
new_mask = cv2.dilate(mask, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10,10)))
dst = cv2.inpaint(img, new_mask, 7, cv2.INPAINT_TELEA)
Here are two inpainting methods in Python/OpenCV. Note that I use the saturation channel to create the threshold, since white and black have zero saturation, in principle.
Input:
import cv2
import numpy as np
# read input
img = cv2.imread('white_black_text.png')
# convert to hsv and extract saturation
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
sat = hsv[:,:,1]
# threshold and invert
thresh = cv2.threshold(sat, 10, 255, cv2.THRESH_BINARY)[1]
thresh = 255 - thresh
# apply morphology dilate
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15,15))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_DILATE, kernel)
# do inpainting
result1 = cv2.inpaint(img,thresh,11,cv2.INPAINT_TELEA)
result2 = cv2.inpaint(img,thresh,11,cv2.INPAINT_NS)
# save results
cv2.imwrite('white_black_text_threshold.png', thresh)
cv2.imwrite('white_black_text_inpainted1.png', result1)
cv2.imwrite('white_black_text_inpainted2.png', result1)
# show results
cv2.imshow('thresh',thresh)
cv2.imshow('result1',result1)
cv2.imshow('result2',result2)
cv2.waitKey(0)
cv2.destroyAllWindows()
Threshold and morphology cleaned result:
Result 1 (Telea):
Result 2 (Navier Stokes):
I am trying to remove the background of the image (the background can be any other color or contain noise, dust, etc)
This is the image:
And this is my code:
import cv2
img = cv2.imread('image.jpg', 0)
norm_img = np.zeros(img.shape)
normim = cv2.normalize(img, norm_img, 0, 255, cv2.NORM_MINMAX)
_, thresh1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(thresh1, cv2.MORPH_OPEN, kernel)
mask_inv = cv2.bitwise_not(opening)
seg = cv2.add(mask_inv, normim)
Output:
The code is about to normalize the original image then add with the image that applied morphological which is a binary image.
Result of normalizing the original image and applying morphological the original image:
So what happens with my code, how can I remove the background?
You can do that using Numpy and Python/OpenCV as follows:
Input:
Mask:
import cv2
import numpy as np
# read image
img = cv2.imread('fingerprint.jpg')
# read mask as grayscale
mask = cv2.imread('mask.jpg', cv2.IMREAD_GRAYSCALE)
# threshold mask
thresh = cv2.threshold(mask, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
# apply mask to image
result = img.copy()
result[thresh==0] = (255,255,255)
# save results
cv2.imwrite('fingerprint_masked.jpg', result)
cv2.imshow('masked image', result)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result:
You can try use percentile for normalization.
import cv2
from numpy import percentile
img = cv2.imread('mSEsr.jpg', cv2.IMREAD_GRAYSCALE)
cv2.normalize(img, img, 0, 255, cv2.NORM_MINMAX)
lower=percentile(img, 5)
upper=percentile(img,50)
cv2.normalize(img, img, -lower, 255+255-upper, cv2.NORM_MINMAX) # tune parameters
cv2.imwrite('finger_norm.png', img)
Result: