Color patches can also be segmented using the LAB color space.
Background:
LAB just like other common color spaces has three channels 1 luminance channel and 2 color channels:
- L-channel: indicates the brightness value in the image
- A-channel: indicates the red and green color in the image
- B-channel: indicates the blue and yellow color in the image
Observing the A-channel in the following diagram:
The red color represents a positive value along A-channel, while green represents a negative value along the same channel. This makes it easy for us to segment both of these colors.
Similarly, blue and yellow can also be segmented along the B-channel
Colors such as white, black and shades of gray are represented in the center of the diagram, making it easier to segment bright colors from an image.
Solution:
Convert BGR image to LAB space:
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
a_channel = lab[:,:,1]
The colored patches already appear distinct.
Normalizing the above to make full use of the range [0-255]:
norm_a_channel = cv2.normalize(a_channel, dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
Now we need to cleverly segment both the desired regions. Instead of finding threshold manually we will threshold based on the median value of the image:
median = int(np.median(norm_a_channel))
median = 112, which is approximate central value of the image.
We will now obtain 2 threshold values:
upper_threshold
: median + (33% of median)
lower_threshold
: median - (33% of median)
upper_threshold = int(median * 1.33)
lower_threshold = int(median * 0.66)
Obtain 2 binary images using both these thresholds:
th1 = cv2.threshold(norm_a_channel, upper_threshold, 255 ,cv2.THRESH_BINARY)[1]
th2 = cv2.threshold(norm_a_channel, lower_threshold, 255, cv2.THRESH_BINARY_INV)[1]
th1
:
th2
:
Finally, add both the images using cv2.add()
. Rather than adding it ourselves, cv2.add()
ensures pixel values stay within range [0-255].
result = cv2.add(th1, th2)
Note: in LAB space you do not manually have to set any range to obtain colors unlike in HSV color space. LAB can be used to segment bright/dominant colors. HSV can be used to segment much finer colors, for example, various shades of green, etc.
Code:
img = cv2.imread('color_patch.jpg')
lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
a_channel = lab[:,:,1]
norm_a_channel = cv2.normalize(a_channel, dst=None, alpha=0, beta=255,norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)
median = int(np.median(norm_a_channel))
upper_threshold = int(median * 1.33)
lower_threshold = int(median * 0.66)
th1 = cv2.threshold(norm_a_channel, upper_threshold, 255 ,cv2.THRESH_BINARY)[1]
th2 = cv2.threshold(norm_a_channel, lower_threshold, 255, cv2.THRESH_BINARY_INV)[1]
result = cv2.add(th1, th2)
cv2.imshow('Result', result)