Isolating for multiple dark regions in an image

I have multiple images with darks bands and I want to draw a rectangle over all of the darker bands. I have tried using HSV color detection, it works reasonably well but it picks up darker regions Current output of the code, code below.

import cv2
import numpy as np
import matplotlib.pyplot as plt
stretch = frames.copy() #Frame is the imported image
#Increasing the contrast of the image
# CLAHE (Contrast Limited Adaptive Histogram Equalization)
clahe = cv2.createCLAHE(clipLimit=2., tileGridSize=(8,8))
lab = cv2.cvtColor(stretch, cv2.COLOR_BGR2LAB)  # convert from BGR to LAB color space
l, a, b = cv2.split(lab)  # split on 3 different channels

l2 = clahe.apply(l)  # apply CLAHE to the L-channel

lab = cv2.merge((l2,a,b))  # merge channels
img2 = cv2.cvtColor(lab, cv2.COLOR_LAB2BGR)  # convert from LAB to BG

# convert to gray
gray = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
# blur
smooth = cv2.GaussianBlur(gray, (11,11), 0)

img2 = cv2.cvtColor(smooth,cv2.COLOR_GRAY2BGR)

frame_HSV = cv2.cvtColor(img2, cv2.COLOR_BGR2HSV)
frame_threshold = cv2.inRange(frame_HSV, (0, 0, 10), (180, 255, 80))
contours,hierarchy, = cv2.findContours(frame_threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

areas = [cv2.contourArea(c) for c in contours]
sorted_areas = np.sort(areas)
#cnt=contours[areas.index(sorted_areas[-1])] #the biggest contour
largestContourArea = sorted_areas[-1]*0.1
largestContour = 0
for cnt in contours:
    contourArea = cv2.contourArea(cnt)
    if( contourArea > largestContourArea):
        #cv2.drawContours(frames, cnt, -1, (255,0,132), thickness=4) 
        x,y,w,h = cv2.boundingRect(cnt)
        cv2.rectangle(frames, (x, y), (x+w, y+h), (255,0,0), 4)
        ROI = frames[y:y+h,x:x+w]     
cv2.drawContours(frames, contours, -1, (0,150,132), thickness=4) 

Output I want

I have tried Canny detection but I couldn’t get it to work, I do have limited experience with it. Is there another way to draw a box around the dark bands?


Otsu thresholding does a pretty good job of that image. IMHO, there’s little point converting a near-grey to HSL as there is no colour, so I load it as greyscale:

import cv2

# Load as greyscale - no colour anyway
im = cv2.imread('9uu2H.jpg', cv2.IMREAD_GRAYSCALE)

# Otsu threshold
_, thr = cv2.threshold(im,127,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)

Note: I cropped off your black border because I didn’t want to confuse Otsu thresholding with an additional, third class of grey, i.e. black.

Note: I added a red border artificially so you can see the extent on Stack Overflow’s background.

Note: You can add blurring, or filtering, or morphology to fill holes to taste.

enter image description here