Identify lines/dots on white image discarding the patterns - python

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.

Related

Image Enhancing in Python

So, I have been trying to enhance images so I can use text recognition, but since the images are extremely low quality and I am a beginner I haven't been able to perform a great job.
Below is the original image:
Original Image:
First I resized the image
img = cv2.imread('test.jpg')
cv2.imshow('Original',img)
cv2.waitKey(0)
img = cv2.resize(img,(500,500),interpolation = cv2.INTER_AREA)
cv2.imshow('Resized',img)
cv2.waitKey(0)
then I changed the background color to gray
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('GRAY',img_gray)
cv2.waitKey(0)
I did some thresholding
ret, img_threshold = cv2.threshold(img_gray, 70, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('THRESHOLD', img_threshold)
cv2.waitKey(0)
and I used morphology to get a better image
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(6,6))
opening = cv2.morphologyEx(img_threshold, cv2.MORPH_OPEN, kernel, iterations = 2)
kernel = np.ones((9,9),np.uint8)
open_img = cv2.morphologyEx(opening, cv2.MORPH_OPEN, kernel, iterations = 3)
cv2.imshow('OPENING',open_img)
cv2.waitKey(0)
My final product is below:
Final Image 2
My question is how can I remove the white chunks and the line crossing the numbers

Using pytesseract to get text from an image

I'm trying to use pytesseract to convert some images into text. The images are very basic and I tried using some preprocessing:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.bitwise_not(gray)
gray = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
The original image looks like this:
The resulting image looks like this:
I do this for a bunch of numbers with the same font in the same location here are the results:
It still gives no text in the output. For a few of the images, it does, but not for all and the images look nearly identical.
Here is a snippet of the code I'm using:
def checkCurrentState():
"""image = pyautogui.screenshot()
image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
cv2.imwrite("screenshot.png", image)"""
image = cv2.imread("screenshot.png")
checkNumbers(image)
def checkNumbers(image):
numbers = []
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.bitwise_not(gray)
gray = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
for i in storeLocations:
cropped = gray[i[1]:i[1]+storeHeight, i[0]:i[0]+storeWidth]
number = pytesseract.image_to_string(cropped)
numbers.append(number)
print(number)
cv2.imshow("Screenshot", cropped)
cv2.waitKey(0)
To perform OCR on an image, its important to preprocess the image. The idea is to obtain a processed image where the text to extract is in black with the background in white. Here's a simple approach using OpenCV and Pytesseract OCR.
To do this, we convert to grayscale, apply a slight Gaussian blur, then Otsu's threshold to obtain a binary image. From here, we can apply morphological operations to remove noise. We perform text extraction using the --psm 6 configuration option to assume a single uniform block of text. Take a look here for more options.
Here's a visualization of each step:
Input image
Convert to grayscale -> Gaussian blur
Otsu's threshold -> Morph open to remove noise
Result from Pytesseract OCR
1100
Code
import cv2
import pytesseract
pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
# Grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
# Morph open to remove noise
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
# Perform text extraction
data = pytesseract.image_to_string(opening, lang='eng', config='--psm 6')
print(data)
cv2.imshow('blur', blur)
cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.waitKey()

How to reference an image without writing in Python

This is the code that I currently have. I want to avoid writing an image then loading it again and then copying it. Why isn't my code in the second part working?
import cv2
load_imaged = cv2.imread("image.png", 0)
# Apply GaussianBlur to reduce image noise if it is required
otsu_threshold, otsu_result = cv2.threshold(
load_imaged, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU, )
# Optimal threshold value is determined automatically.
# Visualize the image after the Otsu's method application
cv2.imwrite("otsu.png", otsu_result)
hole_image = cv2.imread("otsu.png")
# copy image
img = hole_image.copy()
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("Image", imgray)
cv2.waitKey()
cv2.destroyAllWindows()
and I'm trying to reference the image like this (in line 9) but it's returning an error.
Invalid number of channels in input image:
'VScn::contains(scn)'
where
'scn' is 1
import cv2
load_imaged = cv2.imread("image.png", 0)
# Apply GaussianBlur to reduce image noise if it is required
otsu_threshold, otsu_result = cv2.threshold(
load_imaged, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU, )
# copy image
img = otsu_result.copy()
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("Image", imgray)
cv2.waitKey()
cv2.destroyAllWindows()
Any help is appreciated
You are trying to convert an gray-scale image into gray image.
Remove imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) line and you will get the result.

Removing White Text with Black Borders From Image

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

Extract text from image containing a table

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

Categories

Resources