jaredrada
jaredrada

Reputation: 1150

python detect colors outside of range

Background

I am building a program which converts a screenshot of a messaging app into text. One step is to use the open CV matchTemplate function to find if any emojis exist in the screenshot. Since I have to iterate over 1600 emoji characters I would like to first check the screenshot to see if it has colors outside of a range (blue and white). If this check is true I will run the time consuming template matching method.

Question

Given a screenshot below how can I find colors outside of blue and white (the background and text color? I was considering using openCV inRange to find colors that match blue and white, count the number of pixels that dont match, and see if that number is less than the total number of pixels of the image.

Problem

The color ranges I define are too broad to handle all the aliasing around the fonts. The edges of the fonts are all sorts of blue colors. If I define to large of a range I potentially miss finding emojis.

enter image description here

Code so far

# load the image and set up variables
image = cv2.imread(args["image"])
iW, iH = image.shape[:2]
pixels = iW * iH
masked = 0

# define the list of color boundaries
boundaries = [
    ([240, 130, 30], [255, 150, 80]), # blue
    ([250, 250, 250], [255, 255, 255]) # white
]

# loop over the boundaries
for (lower, upper) in boundaries:
    # create NumPy arrays from the boundaries
    lower = np.array(lower, dtype="uint8")
    upper = np.array(upper, dtype="uint8")

    # find the colors within the specified boundaries
    mask = cv2.inRange(image, lower, upper)

    for row in mask:
        for px in row:
            if px == 255:
                masked += 1


if masked < pixels:
    # probably has emojis!!!

Upvotes: 1

Views: 4098

Answers (1)

jaredrada
jaredrada

Reputation: 1150

My solution.

# load the image and up some tracking variables  
image = cv2.imread(args["image"])
accumMask = np.zeros(image.shape[:2], dtype="uint8")

# define the list of color boundaries
boundaries = [
    ([255, 140, 71], [255, 200, 200]),
    ([255, 150, 100], [255, 255, 255])
]

# loop over the boundaries
for (lower, upper) in boundaries:
    # create NumPy arrays from the boundaries
    lower = np.array(lower, dtype="uint8")
    upper = np.array(upper, dtype="uint8")

    # find the colors within the specified boundaries
    mask = cv2.inRange(image, lower, upper)

    # merge the mask into the accumulated masks
    accumMask = cv2.bitwise_or(accumMask, mask)

accumMask = cv2.bitwise_not(accumMask)

# show the images
# cv2.imshow("images", np.hstack([accumMask]))
# cv2.waitKey(0)

unmasked = cv2.countNonZero(accumMask)

if unmasked:
    print "has emoji"
else:
    print "none"

Upvotes: 1

Related Questions