Treehouse

nude.js: Nudity Detection with JavaScript

By on  
nude.js

When I first heard about nude.js, the client side nudity detection software, I was very skeptical for a number of reasons:

  1. Ideally, nudity detection should be done on the server side so that adult materials don't make it to the client at all.
  2. I don't have faith in automated nudity detection as a whole (which, as a programmer, may seem stupid)
  3. Would nudity in greyscale imagery be detected?  How accurate can the detection be?
  4. If you did detect nudity in an image, what would you do?  What's a practical usage?

I've spent some time with the nude.js software and wanted to show you how to use it and let you know if my skepticisms were answered.

About nude.js

From a technical standpoint, nude.js uses Canvas and WebWorker technology to set the image up for analyzation.  The image is loaded into canvas and compared against this nudity algorithm, which consists of the following steps:

  • Detect skin-colored pixels in the image.
  • Locate or form skin regions based on the detected skin pixels.
  • Analyze the skin regions for clues of nudity or non-nudity.
  • Classify the image as nude or not.

nude.js supports IE9+ (with excanvas), Firefox 3.6+, WebKit-based browsers (Chrome, Safari, Mobile Safari), and Opera.  nude.js also recently added support for video image analyzation.  There's an extra JavaScript file included with nude.js for clients that do not support the WebWorker API.

Using nude.js

Start by adding nude.js adding your images to the page as usual:

<!-- No canvas for IE, so download it and include it for IE -->
<!--[if IE]>
<script type="text/javascript" src="excanvas_r3/excanvas.compiled.js"></script>	
<![endif]-->
<script src="nude.js/compressed/nude.min.js"></script>

<!-- images to check -->
<img src="dvt1.jpg" alt="Dita Von Tease" id="image1" onclick="onImageClick('image1');" />
<img src="dvt2.jpg" alt="Dita Von Tease" id="image2" onclick="onImageClick('image2');" />
<img src="dvt3.jpg" alt="Dita Von Tease" id="image3" onclick="onImageClick('image3');" />
<img src="dvt4.jpg" alt="Dita Von Tease" id="image4" onclick="onImageClick('image4');" />

Using nude.js is simple because there are only two methods to use:  <code>load</code> and <code>scan</code>.  The <code>load</code> method takes the element <code>id</code> or element itself and draws a canvas image based on the original image.  The <code>scan</code> method runs the algorithm on the canvas image data, returning <code>true</code> or <code>false</code>.

function onImageClick(node) {
	nude.load(node);
	// Scan it
	nude.scan(function(result){ 
		alert(result ? "Nudity found in " + node.id + "!" : "Not nude");
	});
}

As you can imagine, the process can be taxing on your browser so don't expect an immediate result.  The size of the image is an obvious consideration.  If you rely heavily on nude.js, be aware that your large images could be problematic.

Thoughts After Using nude.js

This library did remarkably well in detecting nudity in quality JPEG images of females but had a bit of trouble with darker skin tones.  In my tests, nude.js failed in finding nudity in greyscale images and movie screencaps (probably from lack of image quality).  I had difficulty in implementing a decent video test.

In the end, I'm impressed with what nude.js but I can't help but feel that it's not ready for prime time.  Image scanning can take a few seconds to return a result and, in some cases, bricks the browser until analyzation is complete.  Since nude.js (well, the algorithm it uses) has issues detecting nudity in greyscale images, images of lessor quality, and dark skin tones, I can't highly recommend it for sites that consider nudity-block critical.  I have to believe that nudity detection has a bigger place on the server side, preventing questionable imagery from hitting the client at all.  Great work by Patrick Wied though -- nude.js is unique and fairly reliable.

I do have a demo available here.  Please note!  This demo is NSFW.  The nudity is covered by black DIVs but the images themselves do contain nudity.  We're all grownups, right?  Look at your own risk.

ydkjs-5.png

Recent Features

Incredible Demos

  • External Site Link Favorite Icons Using MooTools and&nbsp;CSS

    I recently came upon an interesting jQuery article about how you can retrieve all external links within a page, build the address of the site's favorite icon, and place the favorite icon along side the link. I've chosen a different approach which...

  • CSS&nbsp;pointer-events

    The responsibilities taken on by CSS seems to be increasingly blurring with JavaScript. Consider the -webkit-touch-callout CSS property, which prevents iOS's link dialog menu when you tap and hold a clickable element. The pointer-events property is even more JavaScript-like, preventing: click actions from doing...

Discussion

  1. As a heads up (NOT A PUN), the demo all but crashed my browser. It was incredibly resource intensive. Beyond a proof of concept or tech showcase, I really fail to see the application of this script. I would think that any site which is that concerned with what is being fed back to the client should just police all content instead of relying on ANY program, be it client or server side.

    • It’s definitely resource intensive but never crashed my browser. I do see application of this type of script — think of Facebook. Facebook can’t police every image that gets uploaded. That said, and as I said in my post, I think a server-side application of the script would be me optimal.

      Of course, images can be loaded dynamically from another server so this script does have some application.

    • The computer I’m using is a 2.6GHz Dual Core with 2GB RAM and Win XP. It happens to be very slow. But then I think the kind of people this script is aimed at tend to not have the best technology.

    • grant

      I have very similar specs and it came incredibly close to crashing mine too. I held on for about 5 minutes and let it ride out.

  2. Did you find any cases where it was not porn, but was labeling it as so? Or did you only test on legit porn?

    • I actually mean “nudity” not “porn”. Not all nudity is porn.

    • No, actually. I didn’t get any false positives, but I wasn’t trying too hard to trick it either.

  3. It is in fact pretty darn heavy on the browser, but totally awesome!

    Practical uses may include a photo submission social site where nudity is restricted.

    Good idea, David, thanks for sharing.

  4. adom

    i got : not nude,nude,not nude,nude

    in the example doesnt seem right :/

    • He put one up that he knew would fail, saying it was non-nude when it was nude to prove a point.

  5. Wow jS can do anything……… thanx david

  6. Rolf

    Well, I think the algorithm is actually doing most of the work. It’s a nice script but I think it’s not really usefull for reasons already mentioned.. this should be done server side if at all (but that’s another discussion).
    Did you check male nudes with big pumped up chests like old arnie pics? haha

  7. Sam Foster

    I think we’re just not being creative here. The script and algorithm attempts to find photos containing nudity, it says nothing about how you use that info. Perhaps a bookmarklet that finds all nude pics on the page and populates a lightbox with them? Maybe mine streetview for good people-watching spots. Maybe something to monitor and switch off webcams unfortunately left on :)

    • While I like your creativity, I think all but the first of these applications would be better served with a server-side program.

      Ok, I’m done with all the nay-saying. It’s still and impressive bit of code.

  8. This is the power of JS…..

  9. Wouter De Ryck

    What are you working on? Seem to notice 2 adult content related posts in a row…

  10. Number 1 & 3 are not nude for my Firefox 4…

  11. It is amazing sir… really nice thing.

  12. guydrupal

    Thanks for sharing david,

    great work.

  13. Does this work on the principle of recognizing skin tone and if it finds an excess of them, it points out the same as nudity? I am sure that my son will find this script useful. I’l let him know about this site.

  14. Learner

    Hi,
    I am new to HTML5 and its new features. So, I just wanted to know if the following topics are new features of HTML5:
    – web socket.
    – web workers
    Can anyone please guide me on this!! Thanks!!

  15. atbyrd

    I have a new hero…you

  16. David, very nice js example… shows power of js.
    Thanks for sharing this one.

  17. bob

    Analyzation.

    Haha.

    • Jefph

      Totally! I remember, once upon a time, there was a word ‘analysis’..

      hey ho..

  18. Honestly, I only read davidwalsh.name for the articles :P

  19. bob

    link to the algo is dead- can you relink or at least provide the name?

  20. Hey man, what the heck, putting black divs on images? Luckily I have Firebug! Right click > Inspect Element > Delete Element.

    Just kidding, awesome tutorial!

  21. Rob Grainger

    Shurely that should be prude.js

  22. brian

    The check software needs to be able to detect anatomical parts, in different orientations (and state!) and perhaps even the context of such items – rather than simple ‘dumb’ colour pixel checking. You don’t want to block a picture of Aunty Agatha’s new baby or the swimming gala, or even that holiday beach advert (or maybe you do!). This is one very difficult task to get 100% right and JavaScript and even most PC’s are not going to be up to the job.

  23. Jordi Steffen

    This is a Joke – isn’it? If NOT: What gives you the right to censor what I might see?
    Ok to play around with js, but not more.

  24. Lenin Strawskim

    Can anyone tell me why one would need nudity detection?? If I want to find nudity, I just google it and as soon as I have found it, I can detect it with my own eyes. No need for javascript.
    And when, on any occasion I would not know how to google nudity, I can always aks my kids. Because kids always know where to find such stuff.
    Is there some American cultural thing that I am missing, as a European?

  25. James

    On my machine it was actually quite snappy. Only took about 5 seconds per image, but only #2 came back correctly. Still it’s an interesting bit of code and it shows that things like face detection is probably possible in JS on the client.

  26. Chris Chiesa

    Personally I find there to be nothing wrong with nudity and all of this attempt at technological solution to a collective psychological hangup to be a waste of time trying to solve the WRONG PROBLEM. Just sayin’.

    • Jeremy Thomson

      Right on!

      I’ve got to wonder how successful this would be in detecting Manga, or folks in gimp suits.
      Block the harmless nudity, let the extreme stuff through.

  27. JavaScript can also be used to create a nerd AI mind and even a Russian nerd AI Mind.

  28. Jeff

    Wouldn’t a violence detector be better for society than a nudity detector? Everyone has a nude body and more than likely enjoys nude bodies of one form or another. Put in another light, I’d rather my children see pictures of nude bodies than see pictures someone shooting someone else in the head. The USA has this concept so backwards.

    Interesting problem set though :)

  29. WOW! thats awosome!

  30. Mommy

    Come on, kids! How about developing some .js to detect gratuitous violence, instead? I’d much rather my children see nudity than shooting, blood, and gore. We’re pretty fucked up, eh?
    Love, Mom

  31. Wow I had no idea that JS could detect nudity!

  32. Exotic Hadron

    Interestingly, simply scrolling the test page shows that algorithm (or possibly it’s a nude script’s implementation flaw?) changes its result for some of test images. Eventually, your samples all result in “Not nude” in my tests.

  33. Nice work man , Js algorithm is cool , Hiding the nudity , well we can play games with visitors :p

  34. David

    Hello David Walsh, I have download your zip file and export them already. I try to use index.html in tests folder but no effect when click “scan Image”. no matter IE, firefox. Any files I have lost ?

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!