Reputation: 1150
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.
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
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