Home > Blockchain >  Given two or more colors, how can I find the maximum and minimum color values?
Given two or more colors, how can I find the maximum and minimum color values?

Time:11-25

I'm processing images using opencv and part of my problem requires that I iterate over the image by its colors and only display colors which match certain ranges of colors. How can I find the maximum and minimum bgr values?

CodePudding user response:

Here is one way to do that in Python/OpenCV/Numpy. Threshold on the color you want. Then use Numpy to get the min and max colors of each channel.

Input:

enter image description here

import cv2
import numpy as np

# load image 
img = cv2.imread('mandril3.jpg')

# create mask for red
lower=np.array((20,40,215))
upper=np.array((100,120,255))
mask = cv2.inRange(img, lower, upper)

# mask the image for viewing
result = img.copy()
result[mask!=255] = (0,0,0)

# separate channels
b,g,r = cv2.split(img)

# compute min and max ranges of red
bmin = np.amin(b[np.where(mask == 255)])
bmax = np.amax(b[np.where(mask == 255)])
gmin = np.amin(g[np.where(mask == 255)])
gmax = np.amax(g[np.where(mask == 255)])
rmin = np.amin(r[np.where(mask == 255)])
rmax = np.amax(r[np.where(mask == 255)])
print("min red:", bmin, gmin, rmin)
print("max red:", bmax, gmax, rmax)

# save results
cv2.imwrite("mandril3_nose_mask.jpg", mask)
cv2.imwrite("mandril3_nose.jpg", result)

cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

Min and Max Colors of the Red Nose:

min red: 20 53 215
max red: 100 120 255

Mask:

enter image description here

Masked Image:

enter image description here

CodePudding user response:

Here is a more proper way to do that in Python/OpenCV. We basically find the color where the average of R,G,B channels after masking for red is the smallest and the color where the average of R,G,B after masking for red is largest.

 - Read the input
 - Select color -- in this case red
 - Threshold the image for the color as a mask
 - Separate channels
 - Get the average image of the 3 channels
 - Find the min and max values in the average image
 - Create a mask for the min values
 - Create a mask for the max values
 - Combine the original mask with the min mask
 - combine the original mask with the max mask
 - Get the coordinates for all pixels where the combined mask and min mask is white.
 - Find the color corresponding to the first coordinate found if more than one
 - Get the coordinates for all pixels where the combined mask and max mask is white.
 - Find the color corresponding to the first coordinate found if more than one

Input:

enter image description here

import cv2
import numpy as np

# load image 
img = cv2.imread('mandril3.jpg')

# create mask for red
lower=np.array((20,40,215))
upper=np.array((100,120,255))
mask = cv2.inRange(img, lower, upper)

# mask the image for viewing
result = img.copy()
result[mask!=255] = (0,0,0)

# separate channels
b,g,r = cv2.split(img)

# get average of channels
ave = cv2.add(b,g,r)/3
ave = ave.astype(np.uint8)

# get min and max for ave
ave_min = np.amin(ave[np.where(mask==255)])
ave_max = np.amax(ave[np.where(mask==255)])

# form min and max masks from ave
mask_min = ave.copy()
mask_min[ave==ave_min] = 255
mask_min[ave!=ave_min] = 0

mask_max = ave.copy()
mask_max[ave==ave_max] = 255
mask_max[ave!=ave_max] = 0

# combine min mask with red mask
red_mask_min = cv2.bitwise_and(mask, mask_min)

# combine max mask with red mask
red_mask_max = cv2.bitwise_and(mask, mask_max)

# get coordinates where masks are white and corresponding color - take first one
min_list = np.argwhere(red_mask_min==255)
min_count = len(min_list)
if min_count != 0:
    min_coord = min_list[0]
    y=min_coord[0]
    x=min_coord[1]
    min_color = img[y:y 1, x:x 1][0][0]
    print("min_red:", min_color)

max_list = np.argwhere(red_mask_max==255)
max_count = len(max_list)
if max_count != 0:
    max_coord = max_list[0]
    y=max_coord[0]
    x=max_coord[1]
    max_color = img[y:y 1, x:x 1][0][0]
    print("max_red:", max_color)


# save results
cv2.imwrite("mandril3_nose_mask.jpg", mask)
cv2.imwrite("mandril3_nose.jpg", result)

# show images
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.imshow("ave", ave)
cv2.imshow("red_mask_min", red_mask_min)
cv2.imshow("red_mask_max", red_mask_max)
cv2.waitKey(0)
cv2.destroyAllWindows()

Red Mask:

enter image description here

Masked Image:

enter image description here

Results:

min_red: [ 22  57 244]
max_red: [ 99 120 242]
  • Related