Search code examples
pythonnumpyopencvrgbhsv

making a user defined threshold in opencv


I am trying to detect skin using this proposed algorithm.
In order to so, I need to take only the pixels that fall under this category: conditions

I can do so by "manualy" iterating over each of the image's pixel and using an if statement.
Is there a way i can use (preferably) opencv or numpy to do it more efficiently?


Solution

  • You can do it in the following way:

    import cv2
    import numpy as np
    from pathlib import PosixPath
    
    RED_MIN, RED_MAX = 20, 200
    BLUE_MIN, BLUE_MAX = 20, 200
    GREEN_MIN, GREEN_MAX = 20, 200
    
    if __name__ == '__main__':
        # 1) Load the image
        p = PosixPath('../../Pictures/Spring.jpeg')
        img = cv2.imread(str(p))
        cv2.imshow('Spring', img)
    
        # 2) Split the image into Blue, Green and Red channels
        # (remember, in OpenCV the channels' order is BGR and not RGB)
        blue_img = img[:, :, 0]
        green_img = img[:, :, 1]
        red_img = img[:, :, 2]
    
        # 3) Create masks for each color range
        blue_mask = cv2.inRange(blue_img, BLUE_MIN, BLUE_MAX)
        blue_mask[np.where(blue_mask == 255)] = 1
    
        green_mask = cv2.inRange(green_img, GREEN_MIN, GREEN_MAX)
        green_mask[np.where(green_mask == 255)] = 1
    
        red_mask = cv2.inRange(red_img, RED_MIN, RED_MAX)
        red_mask[np.where(red_mask == 255)] = 1
    
        # 4) Combine the relevant image pixels into one final image
        filtered_img = np.zeros_like(img)
        filtered_img[:, :, 0] = blue_img * blue_mask
        filtered_img[:, :, 1] = green_img * green_mask
        filtered_img[:, :, 2] = red_img * red_mask
    
        cv2.imshow('Filtered image', filtered_img)
    
        cv2.waitKey()
        cv2.destroyAllWindows()
    
    

    Cheers.