Q:

Color identification in an image using opencv in python

![enter image description here][1]
Able to identify and get blue colour but culdnt identify the red colour range unable to fix colour range for red/purple stripes.I have used contour and created range for red,green,blue colour .That stripes colour range is not correct I tried settig maximum range for red/purple
import numpy as np
import cv2 
img = cv2.imread(r'/home/pavithra/Downloads/pic.jpeg')

hsvFrame = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 

# Set range for red color and  
red_lower = np.array([136, 86, 86], np.uint8) 
red_upper = np.array([239, 12, 50], np.uint8) 
red_mask = cv2.inRange(hsvFrame, red_lower, red_upper) 

green_lower = np.array([25, 52, 72], np.uint8) 
green_upper = np.array([102, 255, 255], np.uint8) 
green_mask = cv2.inRange(hsvFrame, green_lower, green_upper) 

blue_lower = np.array([94, 80, 2], np.uint8) 
blue_upper = np.array([120, 255, 255], np.uint8) 
blue_mask = cv2.inRange(hsvFrame, blue_lower, blue_upper) 
    
kernal = np.ones((5, 5), "uint8") 
red_mask = cv2.dilate(red_mask, kernal) 
res_red = cv2.bitwise_and(img, img,  
                            mask = red_mask) 
    
# For green color 
green_mask = cv2.dilate(green_mask, kernal) 
res_green = cv2.bitwise_and(img, img, 
                            mask = green_mask) 
    
# For blue color 
blue_mask = cv2.dilate(blue_mask, kernal) 
res_blue = cv2.bitwise_and(img, img, 
                            mask = blue_mask) 

# Creating contour to track red color 
contours, hierarchy = cv2.findContours(red_mask, 
                                        cv2.RETR_TREE, 
                                        cv2.CHAIN_APPROX_SIMPLE) 
      
for pic, contour in enumerate(contours): 
    area = cv2.contourArea(contour) 
    if(area > 300): 
        x, y, w, h = cv2.boundingRect(contour) 
        img = cv2.rectangle(img, (x, y),  
                                    (x + w, y + h),  
                                    (0, 255, 0), 2) 
            
        cv2.putText(img, "Red", (x, y), 
                    cv2.FONT_HERSHEY_SIMPLEX, 1.0, 
                    (0, 255, 0),2)     

contours, hierarchy = cv2.findContours(green_mask, 
                                        cv2.RETR_TREE, 
                                        cv2.CHAIN_APPROX_SIMPLE) 
    
for pic, contour in enumerate(contours): 
    area = cv2.contourArea(contour) 
    if(area > 300): 
        x, y, w, h = cv2.boundingRect(contour) 
        img = cv2.rectangle(img, (x, y),  
                                    (x + w, y + h), 
                                    (0, 255, 0), 2) 
            
        cv2.putText(img, "Green", (x, y), 
                    cv2.FONT_HERSHEY_SIMPLEX,  
                    1.0, (0, 255, 0),2) 

contours, hierarchy = cv2.findContours(blue_mask, 
                                        cv2.RETR_TREE, 
                                        cv2.CHAIN_APPROX_SIMPLE) 
for pic, contour in enumerate(contours): 
    area = cv2.contourArea(contour) 
    if(area > 300): 
        x, y, w, h = cv2.boundingRect(contour) 
        img = cv2.rectangle(img, (x, y), 
                                    (x + w, y + h), 
                                    (255, 0, 0), 2) 
            
        cv2.putText(img, "Blue", (x, y), 
                    cv2.FONT_HERSHEY_SIMPLEX, 
                    1.0, (255, 0, 0),2) 
            
resize = cv2.resize(img, (800, 480))
cv2.imshow("All clg", resize) 
cv2.waitKey(0)

A:

I split the image into half just to avoid unnecessary noise reductions. Then rotated the image to make the text horizontal. Binarized the image and obtained the three big blue-colored covid19 labels. Sorted them according to their y-coordinate (top to bottom). Performed some operations to obtain the region of interest (ROI, the two stripes which I named labels). Binarized each label to obtain the two contours of the colored stripes. Adjusted the gamma of the labels so that the colors become a little darker. Obtained the red-component of each stripe. Sorted them according to their x-coordinate (left to right). Assigned the stripe with the highest red value the red color, the other as purple.
Code:
    def adjust_gamma(image, gamma=1.0):
        # build a lookup table mapping the pixel values [0, 255] to
        # their adjusted gamma values
        invGamma = 1.0 / gamma
        table = np.array([((i / 255.0) ** invGamma) * 255
            for i in np.arange(0, 256)]).astype("uint8")
        # apply gamma correction using the lookup table
        return cv2.LUT(image, table)

    def rotate(image: np.ndarray,angle, background_color): 
        old_width, old_height = image.shape[:2]
        angle_radian = math.radians(angle)
        width = abs(np.sin(angle_radian) * old_height) + abs(np.cos(angle_radian) * old_width)
        height = abs(np.sin(angle_radian) * old_width) + abs(np.cos(angle_radian) * old_height)
        image_center = tuple(np.array(image.shape[1::-1]) / 2)
        rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)  
        rot_mat[1, 2] += (width - old_width) / 2
        rot_mat[0, 2] += (height - old_height) / 2
        return cv2.warpAffine(image, rot_mat, (int(round(height)), int(round(width))), borderValue=background_color)

    img = cv2.imread("covid.jpg")
    rows,cols = img.shape[:2]
    img = img[:,:cols//2]
    rot = rotate(img,90,(255,255,255))
    gray = cv2.cvtColor(rot,cv2.COLOR_BGR2GRAY)
    otsu = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
    opening = cv2.morphologyEx(otsu,cv2.MORPH_OPEN,np.ones((3,3),np.uint8),iterations=3)
    dilate = cv2.dilate(opening,np.ones((1,5),np.uint8),iterations=5)
    dilate2 = cv2.dilate(dilate,np.ones((3,3),np.uint8),iterations=3)
    contours,_ = cv2.findContours(dilate2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

    lables = [] # the three covid19 
    y_coords = [] # to sort the lables from top to bottom (the one with single color comes 1st)
    for cnt in contours:
        x,y,w,h = cv2.boundingRect(cnt)
        x = x + 10
        w = w - 20
        y_coords.append(y)
        lables.append(rot[y+h//3:y+h-h//3,x+w//2:x+int(w*0.70)])
    y_coords,lables = zip(*sorted(zip(y_coords,lables))) # sorting the lables from top to bottom
    y_coords = list(y_coords)
    lables = list(lables)

    otsus = []
    grays = []
    for image in lables:
        gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
        grays.append(gray)
        mean = np.mean(gray)
        median = np.median(gray)
        otsus.append(cv2.threshold(gray,median-10,255,cv2.THRESH_BINARY)[1])
    s = [] # just a list to store all the red and purple stripes
    for i in range(len(otsus)):
        otsus[i] = ~otsus[i]
        rows,cols = otsus[i].shape[:2]
        M = np.float32([[1,0,5],[0,1,5]])
        lables[i] = cv2.warpAffine(lables[i],M,(cols+5,rows+10)) # giving some padding
        
        # adjusting the gamma to make the colors more dark
        lables[i] = adjust_gamma(lables[i],gamma=0.40)
        
        otsus[i] = cv2.warpAffine(otsus[i],M,(cols+5,rows+10)) # same padding
        strips,_ = cv2.findContours(otsus[i],cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
        x_coords = [] # to sort the red and purple stripes from left to right
        color = ["red","red"] # setting inital colors both to red 
        red_components = []
        for j in range(len(strips)):
            x,y,w,h = cv2.boundingRect(strips[j])
            x_coords.append(x)
            # strip = lables[i][y:y+h,x:x+w,:]
            # strip = lables[i][y+h//4:y+h-h//4,x+w//4:x+w-w//4,:]
            strip = lables[i][y:y+h,x+w//5:x+w-w//5,:]
            s.append(strip)
            try:
                strip_color_b = int(np.mean(strip[0]))
                strip_color_g = int(np.mean(strip[1]))
                strip_color_r = int(np.mean(strip[2]))
                # strip_color = (strip_color_b,strip_color_g,strip_color_r)
                red = strip_color_r
                red_components.append(red)
            except IndexError:
                print("Lable number ",i,"has only a single color.")

        x_coords,red_components = zip(*sorted(zip(x_coords,red_components))) # simultaneously sorting the red and purple stripes from left to right 
        
        try:
            if red_components[0] < red_components[1]:
                color[0] = "purple"
            else:
                color[1] = "purple"
            # print("red components = ",red_components)
            print("Lable = ",i,"strip = ",0,"color = ",color[0])
            print("Lable = ",i,"strip = ",1,"color = ",color[1]) # LEFT to RIGHT
        except IndexError:
            print("Lable number ",i,"is excluded. Continuing with further labels.")

    print("TOTAL NUMBER OF LABLES = ",len(lables))   
        
    # reading the text
    custom_oem_psm_config = r'--oem 3 --psm 3'
    print(pytesseract.image_to_string(otsu,config=custom_oem_psm_config))

    cv2.imshow("Lable 0",lables[0])
    cv2.imshow("Lable 1",lables[1])
    cv2.imshow("Lable 2",lables[2])
    cv2.imshow("rotated",rot)
    cv2.waitKey(0)

OUTPUT:
Lable number  0 has only a single color.
Lable number  0 is excluded. Continuing with further labels.
Lable =  1 strip =  0 color =  purple
Lable =  1 strip =  1 color =  red
Lable =  2 strip =  0 color =  purple
Lable =  2 strip =  1 color =  red
TOTAL NUMBER OF LABLES =  3
COVID-19Aq
COVID-19Ag

Please correct me if I am wrong.

