I have a large number of images (hundreds of thousands) and, for each one, I need to say whether or not it has a watermark in the top right corner. The watermark is always the same and is in the same position. It takes the form of a ribbon with a symbol and some text. I'm looking for simple and fast way to do this that, ideally, doesn't use SciPy (as it's not available on the server I'm using -- but it can use NumPy)
So far, I've tried using PIL and the crop function to isolate the area of the image where the watermark should be and then compared the histograms with a RMS function (see http://snipplr.com/view/757/compare-two-pil-images-in-python/). That doesn't work very well as there are lots of errors in both directions.
Any ideas would be much appreciated. Thanks
Another possibility is to use machine learning. My background is natural language processing (not computer vision), but I tried creating a training and testing set using the description of your problem and it seems to work (100% accuracy on unseen data).
The training set consisted of the same images with the watermark (positive example), and without the watermark (negative example).
The testing set consists of images that were not in the training set.
If interested, you can try it with the example training and testing images.
Full version available as a gist. Excerpt below:
import glob
from classify import MultinomialNB
from PIL import Image
TRAINING_POSITIVE = 'training-positive/*.jpg'
TRAINING_NEGATIVE = 'training-negative/*.jpg'
TEST_POSITIVE = 'test-positive/*.jpg'
TEST_NEGATIVE = 'test-negative/*.jpg'
# How many pixels to grab from the top-right of image.
CROP_WIDTH, CROP_HEIGHT = 100, 100
RESIZED = (16, 16)
def get_image_data(infile):
image = Image.open(infile)
width, height = image.size
# left upper right lower
box = width - CROP_WIDTH, 0, width, CROP_HEIGHT
region = image.crop(box)
resized = region.resize(RESIZED)
data = resized.getdata()
# Convert RGB to simple averaged value.
data = [sum(pixel) / 3 for pixel in data]
# Combine location and value.
values = []
for location, value in enumerate(data):
values.extend([location] * value)
return values
def main():
watermark = MultinomialNB()
# Training
count = 0
for infile in glob.glob(TRAINING_POSITIVE):
data = get_image_data(infile)
watermark.train((data, 'positive'))
count += 1
print 'Training', count
for infile in glob.glob(TRAINING_NEGATIVE):
data = get_image_data(infile)
watermark.train((data, 'negative'))
count += 1
print 'Training', count
# Testing
correct, total = 0, 0
for infile in glob.glob(TEST_POSITIVE):
data = get_image_data(infile)
prediction = watermark.classify(data)
if prediction.label == 'positive':
correct += 1
total += 1
print 'Testing ({0} / {1})'.format(correct, total)
for infile in glob.glob(TEST_NEGATIVE):
data = get_image_data(infile)
prediction = watermark.classify(data)
if prediction.label == 'negative':
correct += 1
total += 1
print 'Testing ({0} / {1})'.format(correct, total)
print 'Got', correct, 'out of', total, 'correct'
if __name__ == '__main__':
main()
Training 1
Training 2
Training 3
Training 4
Training 5
Training 6
Training 7
Training 8
Training 9
Training 10
Training 11
Training 12
Training 13
Training 14
Testing (1 / 1)
Testing (2 / 2)
Testing (3 / 3)
Testing (4 / 4)
Testing (5 / 5)
Testing (6 / 6)
Testing (7 / 7)
Testing (8 / 8)
Testing (9 / 9)
Testing (10 / 10)
Got 10 out of 10 correct
[Finished in 3.5s]