Lately I’ve been working on some automated Twitter accounts that provide various services to their followers. For one of them I needed a way to decipher between accounts that belong to real people, and other novelty/company/promotional accounts. More specifically, I only wanted to have my accounts interact with Twitter users who are actual people.

I noticed that over 90% of human Twitter users had a profile picture with their face in it. Other types of accounts we’re mostly logos, text, or random pictures. I know that with this approach I would have trouble identifying people who had cartoon faces, or cats etc.. in their profile pictures but as long as there weren’t many false positives, then I’d be okay.

I ended up writing a small node module using the opencv built in face detection and the Twitter API to verify if a certain user was likely a person or not.

You can see the code here (https://github.com/ksloan/twitter-facial-recognition).

Here’s the main part of the module:

async.waterfall(
  [
    function (done) {
      T.get(
        'users/lookup',
        {
          screen_name: screen_name,
        },
        done
      );
    },
    function (data, res, done) {
      var uri = data[0].profile_image_url.replace('_normal', '_bigger');
      request({ uri: uri, encoding: null }, function (err, res, body) {
        done(err, res, body, data[0]);
      });
    },
    function (res, body, twitter_user, done) {
      app.check(body, function (err, is_person) {
        done(err, is_person, twitter_user);
      });
    },
  ],
  function (err, is_person, twitter_user) {
    done(err, is_person, twitter_user);
  }
);

You can see that first we lookup the Twitter user by screen name, then buffer the profile image (the bigger format gives us better chances of detecting faces) into app.check, which runs the opencv facial detection, and send back both an is_person bool, and the twitter_user object.

To decide whether is_person should be true or false, all we do is see if there is at least one face detected by the built-in facial detection in opencv (using node-opencv)

cv.readImage(img, function (err, im) {
  im.detectObject(cv.FACE_CASCADE, {}, function (err, faces) {
    if (err) done(err);
    else done(null, faces.length > 0);
  });
});

That’s it! Simple! Again, you can see the entire module here. I’m using this module to check if a Twitter user that is interacting with my account is a person or a spam account trying to get attention, and then I respond accordingly.

I’ve noticed it has trouble detecting body shots (with smaller faces), but that’s mostly because of the size of the images we are processing. If you want to be more accurate you can get the original size image from Twitter, although it sometimes takes significantly more time to download/process them.