Finding black stain from gray rectangle

225 Views Asked by At

I'm trying to identify whether the gray rectangle in the image shown below contains black stain.

Stain Image:

Stain Image

Stain Highlighted:

Stain Highlighted

import numpy 
import matplotlib.pyplot as plt
import cv2

path = r'F:\stain.tif'
img = cv2.imread(path)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_bin = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                   cv2.THRESH_BINARY_INV, 131, 15)

plt.imshow(img_bin, cmap='gray')
plt.show()

Using the OpenCV code above, I was able to create a picture that only whitens the black spot I want to locate as shown below.

Binary image:

binary image

However, I'm not sure how to move any further. My final goal is sorting out pictures that only have those black stains on gray rectangles from thousands of images.

Below is an example of a clean, gray rectangle image that should not be sorted.

Clean Rectangle:

Clean Rectangle

I saw on google using 'stats' array of cv2.connectedComponentsWithStats function might help.

Any advice will be deeply appreciated!

2

There are 2 best solutions below

0
Shamshirsaz.Navid On
grayImg[np.where(grayImg > 20)] = 255
cnts, _ = cv2.findContours(~grayImg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in cnts:
    x, y, w, h = cv2.boundingRect(c)
    cv2.circle(grayImg, (x+w//2, y+h//2), max(w, h), 127, 5)
print("Found any: ", len(cnts) > 0)
3
Christoph Rackwitz On

Step 0: find the octagon, so you know what's inside and what's outside, and the edges of the octagon don't bother you.

Step 1: deal with the uneven illumination. Calculate a median of some kernel size (that's clearly larger than any defects/debris), then subtract that (or divide... but that's more advanced).

Step 2: threshold the "flat illumination" picture and find contours (cv.findContours). Filter by size (cv.contourArea), if necessary.

enter image description here