Process image using opencv - python

I have a number of microscopic images and I want to apply detection algorithms on those images using OpenCV. For that, I need to apply some image processing methods. But I am not sure which will be the best method for this one.
I applied exposure and contrast from Shotwell (ubuntu software) which works perfectly fine with my case. How I can do the same in OpenCV or any image processing library in python?
I have attached a link to the input and the required image.
Input image: https://drive.google.com/file/d/1XoY8u5yk0X4620alR61GhoJrd9pJBYji/view?usp=sharing
Required image: https://drive.google.com/file/d/13DpbDYdNsOAh1k_ZLHpYV99ddlIF47vB/view?usp=sharing

For example
img=cv2.imread('points.jpg')
hsv_image = cv2.cvtColor(img ,cv2.COLOR_BGR2HSV)
gray = cv2.cvtColor(hsv_image,cv2.COLOR_BGR2GRAY)
_,mask = cv2.threshold(gray, 75, 255, cv2.THRESH_BINARY)
I get
But I'm not sure if I lost some points or added new ones.

Related

Color Space conversion problem on black image with OpenCV

I am using python-opencv for simple conveniences like binarizing images and counting pixels.
There is a series of images captured from a camera, and some of them are completely black, and some have more information. For example:
The following code is loading the images:
for img in file_list:
image = cv2.imread(img)
plt.imshow(image)
plt.show()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
plt.imshow(gray, cmap='gray')
plt.show()
I need to convert them to grayscale because I'm applying binarization and Otsu's thresholding.
The result of the previous code yields the following images (the first one corresponds to the left side of the example, and the other corresponds to the right side):
So, if the problem was only with displaying the image, I would have no problems. But for pixel counting and binarization this is imposing a hurdle to my work. I tried other color spaces, but the same thing is happening. Any suggestions?
Btw, I'm developing this with jupyter-notebook and using py-opencv-3.4.2 and python 3.7.3 on conda 4.6.10. It does not seem to be a version problem since I also tried using Google Colab, and the same problem appears.

Image Registration of Scanned Text Forms

We print 500 bubble surveys, get them back, and scan them in a giant batch giving us 500 PNG images.
Each image has a slight variations in alignment, but identical size and resolution. We need to register the images so they're all perfectly aligned. (With the next step being semi-automated scoring of the bubbles).
If these were 3D-MRI images, I could accomplish this with a single command line utility; But I'm not seeing any such tool for aligning scanned text documents.
I've played around with opencv as described in Image Alignment (Feature Based) using OpenCV, and it produces dynamite results when it works, but it often fails spectacularly. That approach is looking for documents hidden within natural scenes, a much harder problem than our case where the images are just rotated and translated in 2D, not 3.
I've also explored imreg_dft, which runs consistently but does a very poor job -- presumably the dft approach is better on photographs than text documents.
Does a solution for Image Registration of Scanned Forms already exist? If not, what's the correct approach? Opencv, imreg_dft, or something else?
Similar prior question: How to find blank field on scanned document image
What you can try is using the red outline of the answer boxes to create a mask where you can select the outline. I create a sample below. You can also remove the blue letters by creating a mask for the letters, inverting it, then apply it as a mask. I didn't do that, because he image of the publisher is low-res, and it caused issues. I expect your scans to perform better.
When you have the contours of the boxes you can transform/compare them individually (as the boxes have different sizes). Or you can use the biggest contour to create a transform for the entire document.
You can then use minAreaRect to find the cornerpoints of the contours. Threshold the contourArea to exclude noise / non answer area's.
import cv2
import numpy as np
# load image
img = cv2.imread('Untitled.png')
# convert to hsv colorspace
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# define range of image bachground in HSV
lower_val = np.array([0,0,0])
upper_val = np.array([179,255,237])
# Threshold the HSV image
mask = cv2.inRange(hsv, lower_val, upper_val)
# find external contours in the mask
contours, hier = cv2.findContours(mask, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
# draw contours
for cnt in contours:
cv2.drawContours(img,[cnt],0,(0,255,0),3)
# display image
cv2.imshow('Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

How to make shadowed part of background count as background (picture below) with OpenCV in Python?

I am very new to OpenCV(and to StackOverflow). I'm writing a program with OpenCV which takes a picture with an object (i.e. pen(rice, phone) put on paper) and calculates what percent does the object make of the picture.
Problem I'm facing with is when I threshold image (tried adaptive and otsu) photo is a little bit shadow around edges:
Original image
Resulted picture
And here's my code:
import cv2
img = cv2.imread("image.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
b,g,r = cv2.split(img)
th, thresh = cv2.threshold(b, 100, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
cv2.imwrite("image_bl_wh.png", thresh)
Tried to blur and morphology, but couldn't do it.
How can I make my program count that black parts around the picture as background and is there more better and easier way to do it?
P.S. Sorry for my English grammar mistakes.
This is not a programmatic solution but when you do automatic visual inspection it is the first thing you should try: Improve your set-up. The image is simply darker around the edges so increasing the brightness when recording the images should help.
If that's not an option you could consider having an empty image for comparison. What you are trying to do is background segmentation and there are better ways than simple color thresholding they do however usually require at least one image of the background or multiple images.
If you want a software only solution you should try an edge detector combined with morphological operators.

Python OCR: ignore signatures in documents

I'm trying to do OCR of a scanned document which has handwritten signatures in it. See the image below.
My question is simple, is there a way to still extract the names of the people using OCR while ignoring the signatures? When I run Tesseract OCR it fails to retrieve the names. I tried grayscaling/blurring/thresholding, using the code below, but without luck. Any suggestions?
image = cv2.imread(file_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = cv2.GaussianBlur(image, (5, 5), 0)
image = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
You can use scikit-image's Gaussian filter to blur thin lines first (with an appropriate sigma), followed by binarization of image (e.g., with some thresholding function), then by morphological operations (such as remove_small_objects or opening with some appropriate structure), to remove the signatures mostly and then try classification of the digits with sliding window (assuming that one is already trained with some blurred characters as in the test image). The following shows an example.
from skimage.morphology import binary_opening, square
from skimage.filters import threshold_minimum
from skimage.io import imread
from skimage.color import rgb2gray
from skimage.filters import gaussian
im = gaussian(rgb2gray(imread('lettersig.jpg')), sigma=2)
thresh = threshold_minimum(im)
im = im > thresh
im = im.astype(np.bool)
plt.figure(figsize=(20,20))
im1 = binary_opening(im, square(3))
plt.imshow(im1)
plt.axis('off')
plt.show()
[EDIT]: Use Deep Learning Models
Another option is to pose the problem as an object detection problem where the alphabets are objects. We can use deep learning: CNN/RNN/Fast RNN models (with tensorflow/keras) for object detection or Yolo model (refer to the this article for car detection with yolo model).
I suppose the input pictures are grayscale, otherwise maybe the different color of the ink could have a distinctive power.
The problem here is that, your training set - I guess - contains almost only 'normal' letters, without the disturbance of the signature - so naturally the classifier won't work on letters with the ink of signature on them. One way to go could be to extend the training set with letters of this type. Of course it is quite a job to extract and label these letters one-by-one.
You can use real letters with different signatures on them, but it might be also possible to artificially generate similar letters. You just need different letters with different snippets of signatures moved above them. This process might be automated.
You may try to preprocess the image with morphologic operations.
You can try opening to remove the thin lines of the signature. The problem is that it may remove the punctuation as well.
image = cv2.imread(file_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
image = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
You may have to alter the kernel size or shape. Just try different sets.
You can try other OCR providers for the same task. For example, https://cloud.google.com/vision/ try this. You can upload an image and check for free.
You will get a response from API from where you can extract the text which you need. Documentation for extracting that text is also given on the same webpage.
Check out this. this will help you in fetching that text. this is my own answer when I faced the same problem. Convert Google Vision API response to JSON

How to detect change in colours in the image below?

I need to identify the pixels where there is a change in colour. I googled for edge detection and line detection techniques but am not sure how or in what way can these be applied.
Here are my very naive attempts:
Applying Canny Edge Detection
edges = cv2.Canny(img,0,10)
with various parameters but it didn't work
Applying Hough Line Transform to detect lines in the document
The intent behind this exercise is that I have an ill-formed table of values in a pdf document with the background I have attached. If I am able to identify the row boundaries using colour matching as in this question, my problem will be reduced to identifying columns in the data.
Welcome to image processing. What you're trying to do here is basically trying to find the places where the change in color between neighboring pixels is big, thus where the derivative of pixel intensities in the y direction is substantial. In signal processing, those are called high frequencies. The most common detector for high frequencies in images is called Canny Edge Detector and you can find a very nice tutorial here, on the OpenCV website.
The algorithm is very easy to implement and requires just a few simple steps:
import cv2
# load the image
img = cv2.imread("sample.png")
# convert to grayscale
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# resize for the visualization purposes
img = cv2.resize(img, None, img, fx=0.4, fy=0.4)
# find edges with Canny
edges = cv2.Canny(img, 10, 20, apertureSize=3)
# show and save the result
cv2.imshow("edges", edges)
cv2.waitKey(0)
cv2.imwrite("result.png", edges)
Since your case is very straightforward you don't have to worry about the parameters in the Canny() function call. But if you choose to find out what they do, I recommend checking out how to implement a trackbar and use it for experimenting. The result:
Good luck.

Categories

Resources