2

I have two types of images, and they were both contrasted.

Type 1: (white and clean background)

Type 1

Type 2: (some gray texture in background)

enter image description here

I could apply Gaussian blur and Thresholding to process the type 2 image to adjust it to the white background like type 1 as follow code:

type2_img = cv2.imread(type2.png)
# convert to grayscale
gray = cv2.cvtColor(type2_img , cv2.COLOR_BGR2GRAY)
# threshold the image using Otsu's thresholding
thresh = cv2.threshold(gray.copy(), 0, 255, cv2.THRESH_OTSU)[1]
# convert back to RGB
type2_img = cv2.cvtColor(thresh,cv2.COLOR_GRAY2RGB)

And, I could get the following result enter image description here:

However, I do not wish to apply the same method for type 1 images, since it is already satisfied condition.

So, are there any image processing methods within OpenCV that can differentiate type 2 images from type 1?

NguyenHai
  • 57
  • 1
  • 8
  • Does this answer your question? [How to verify if the image contains noise in background before ‘OCR’ing](https://stackoverflow.com/questions/70604177/how-to-verify-if-the-image-contains-noise-in-background-before-ocr-ing) –  Jan 11 '22 at 15:46
  • Hi Yves Daoust, this question covers a smaller scope than the other post. I need to check a bit more on the available options here, then I will update the other post's answer too. Thank you for keep following up. – NguyenHai Jan 12 '22 at 02:43

2 Answers2

2

The type 1 image you provided is grayscale and not completely black & white image. Yet the last threshold output image is black and white.

Based on your question my understanding is both of these should as classified as type 1 and the type 2 image example should classified as type 2.

If it was the case that type 1 was always black and white you could count the number of 0's and 1's in image and check if their sum equaled to total pixel count of image.

An option here is to classify two types of image without modifying images is to use the percentage of black and white pixels of image histogram.

Code

import cv2
import numpy as np
from matplotlib import pyplot as plt
from skimage import exposure

#img_path = r'hist_imgs/1.png'
#img_path = r'hist_imgs/2.png'
img_path = r'hist_imgs/3.png'

img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)
cv2.imshow('Image', img)

img_pixel_count = img.shape[0] * img.shape[1]
print(img.shape)
print(img_pixel_count)

h = np.array(exposure.histogram(img, nbins=256))

bw_count = h[0][0] + h[0][255]
other_count = img_pixel_count - bw_count

print('BW PIXEL COUNT: ',  bw_count)
print('OTHER PIXEL COUNT: ',  other_count)

bw_percentage = (bw_count * 100.0) / img_pixel_count
other_percentage = (other_count * 100.0) / img_pixel_count

print('BW PIXEL PERCENTAGE: ',  bw_percentage)
print('OTHER PIXEL PERCENTAGE: ',  other_percentage)

differentiate_threshold = 3.0
if other_percentage > differentiate_threshold:
    print('TYPE 2: GRAYSCALE')
else:
    print('TYPE 1: BLACK AND WHITE')

plt.hist(img.ravel(), 256, [0, 256])
plt.title('Histogram')
plt.show()

Input Images

Image 1:

enter image description here

Image 2:

enter image description here

Image 3:

enter image description here

Code Output

Image 1:

(154, 74)
11396
BW PIXEL COUNT:  11079
OTHER PIXEL COUNT:  317
BW PIXEL PERCENTAGE:  97.21832221832221
OTHER PIXEL PERCENTAGE:  2.781677781677782
TYPE 1: BLACK AND WHITE

Image 2:

(38, 79)
3002
BW PIXEL COUNT:  1543
OTHER PIXEL COUNT:  1459
BW PIXEL PERCENTAGE:  51.39906728847435
OTHER PIXEL PERCENTAGE:  48.60093271152565
TYPE 2: GRAYSCALE

Image 3:

(38, 79)
3002
BW PIXEL COUNT:  3002
OTHER PIXEL COUNT:  0
BW PIXEL PERCENTAGE:  100.0
OTHER PIXEL PERCENTAGE:  0.0
TYPE 1: BLACK AND WHITE
B200011011
  • 3,798
  • 22
  • 33
  • Hi @B200011011, Thank you very much for your answer. Your solution is by far the closest approach that I am looking for. It does help me to make a very clear threshold to differentiate these images. I will try out a larger set of images, and let you know the result as soon as possible. May I ask if you could explain more on the 'nbins=256' parameter? I notice that in some images that did not have black color, the NumPy array length won't be 256, and the h[0][255] leads to IndexError: index 255 is out of bounds. Is there any setting to make the hist array has a fixed length of 256? – NguyenHai Jan 12 '22 at 02:53
  • 1
    You can try exception handling for `h[0][255]` or `h[0][0]` to see if these values exists before summing. If not then adjust the condition based on that. You can also skip `bw_count` completely and just sum all values from `h[0][1]` to `h[0][254]`, then use `other_percentage` for classification. – B200011011 Jan 12 '22 at 07:26
  • Hi @B200011011, Thank you for your suggestion. I added the exception handling error. So far, your solution gave me the threshold that I wanted, and I am doing more tests with the rest of my data. Again, thank you very much. – NguyenHai Jan 12 '22 at 08:26
  • Hi @B200011011, Thank you very much for your answer last time. I have implemented your solution, but unfortunately, It could not solve completely all the cases which I post in this original question [here](https://stackoverflow.com/questions/70604177/how-to-verify-if-the-image-contains-noise-in-background-before-ocr-ing). Do you have any other suggestions for which I should try? – NguyenHai Jan 21 '22 at 04:53
  • 1
    Sure, I will have a look if I can give any ideas. – B200011011 Jan 21 '22 at 12:52
0

To know if an image is blurried I would use the variance of the Laplacian.

import cv2

im1 = cv2.imread("s1.png")
im2 = cv2.imread("s2.png")

print(f"Im1: {cv2.Laplacian(im1, cv2.CV_64F).var()}")
print(f"Im2: {cv2.Laplacian(im2, cv2.CV_64F).var()}")

Output:

Im1: 10493.1934011934
Im2: 17803.672073381236

I would set a threshold in the middle of each class looking through some train set or examples.

Hope it works!

David Serrano
  • 295
  • 1
  • 5
  • 14
  • 2
    Thank you very much for the help. That seems like the answer that I was looking for. I will try your answer with my data and let you know the result as soon as I can. – NguyenHai Jan 11 '22 at 09:09
  • 2
    Perfect! Let me know how it works and if you need more help. – David Serrano Jan 11 '22 at 09:24
  • Thank you for your last reply. Your solution works on the samples that I provided, but it did not work with my other data. On one class of the images, I found that the std value of Laplacian variance is quite big. I think it was because of a large number of images having numerous sizes. This makes it was difficult to find a threshold based on the variance of the Laplacian. – NguyenHai Jan 12 '22 at 01:58
  • Hi @TsunamiSerra, I have updated the original question [here](https://stackoverflow.com/questions/70604177/how-to-verify-if-the-image-contains-noise-in-background-before-ocr-ing). If you have time, any other suggestions are very welcome. Thanks in advance. – NguyenHai Jan 21 '22 at 04:55
  • 2
    Hi mate, @NguyenHai, if a have time I will take a look for sure. – David Serrano Jan 21 '22 at 07:37