Detecting graphic areas in an image on a web page

I beat a lot around the bush, so I will explain my problem here and hope for the whole picture, someone has some ideas. With the following image:

Model with Regions

I need to detect a drop in her eyes and mouth and solve this problem in a general way. The model and blobs are on two different layers, so I can create one image only with blocks and with only one model, and somehow synchronize the virtual cursor over the blocks while it really hover over the model.

I can also make blobs polygons for impact testing, but I think the hit color test will be a lot easier. If I fall in blue, I am on her lips and I show lipstick; if I click pink, I will be above her eyes and show images of eye makeup.

What are the suggestions and conversation of scientists here?

+4
source share
4 answers

An easier way to do this is to load the image of the layer into the canvas and then get all its pixel data. When the mouse hovers over the model’s image, find out what color is currently selected and if it differs from the previous one, activate the event to indicate that the selection has changed.

Here is an example, feel free to play with him; but keep in mind that it does not handle all cases:

  • what if the layer and image of the model do not have the same size
  • what if the layer and image of the model do not match the width / height ratio.
  • what to do if you want to use some kind of alpha channel (the example does not take it into account)

$(function() {

  /* we load all the image data first */
  var imageData = null;
  var layerImage = new Image();
  layerImage.onload = function() {
    var canvas = document.createElement("canvas");
    canvas.width = this.width;
    canvas.height = this.height;
    context = canvas.getContext('2d');
    context.drawImage(this, 0, 0, canvas.width, canvas.height);
    imageData = context.getImageData(0, 0, canvas.width, canvas.height).data;
  };

  /* it easier to set the image data for example as base64 data */
  layerImage.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTFH80I3AAAA5klEQVR4Xu3WMQ7CMAwF0IxcgCtw/xsGdWApItWHKorLQ8qESe2HbWjNiwABAgQIECBAgAABAgQIECBAgMAUgd4e/ehMSeTMh4wK2j/nqPjt/TNzm3IXgEFb64CdgBG44hKcsmg8pKDAvbf+7SlY7nvK3xb/+lx5BAA/jMCGpwOqC/z9CFT/ApfP/9Z6T87yBaUJJsVvsen9y8cDMAJ2gCWY7IHll1qaYFL84a9AelnF+CFwxYLSnAGMBFLNivE6QAcMBCq2dJqzETACRuCzQDpPFePTv9riCRAgQIAAAQIECBC4nsATagY67TVyuhAAAAAASUVORK5CYII=";

  var pColor = null;

  /* on mouse over the model image */
  $("#model").mousemove(function(event) {
    /* we correct the offset */
    var offset = $(this).offset();
    var relX = event.pageX - offset.left;
    var relY = event.pageY - Math.round(offset.top);

    /* and get the pixel values at this place (note we are not keeping the alpha channel; it your decision whether or not it is valuable */
    var pixelIndex = relY * layerImage.width + relX;
    var dataIndex = pixelIndex * 4;
    var color = [imageData[dataIndex], imageData[dataIndex + 1], imageData[dataIndex + 2]];

    if (pColor == null) {
      /* we trigger when first entering the image */
      $(this).trigger("newColor", {
        message: "Initial layer color",
        data: color
      });
    } else if (pColor[0] != color[0] || pColor[1] != color[1] || pColor[2] != color[2]) {
      /* we trigger if the new position is a new color in the layer image */
      $(this).trigger("newColor", {
        message: "Changed layer color",
        data: color
      });
    }
    pColor = color;
  });

  /* some small help to convert rgb to css colors */
  function rgb2hex(red, green, blue) {
    var rgb = blue | (green << 8) | (red << 16);
    return '#' + (0x1000000 + rgb).toString(16).slice(1)
  }

  /* there you have the new layer color event management; for the example sake we change the color of some text */
  $("#model").on("newColor", function(event, eventData) {
    $("#selector").css("color", rgb2hex(eventData.data[0], eventData.data[1], eventData.data[2]));
  });
});
img {
  border: 1px solid silver
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

<body>
  <h4>Model image</h4>

  <img id="model" src="data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAAtdJREFUaEPtmS2PwkAQhhGQEASEBIECFAJBgoCAxpDgsWBxSP4lPwGJRCLv5m4uk6Xt7s5He9dLFst2+z7vfG3bxsc//zX+uf6PBPDXEUwRSBEwOpBSyGig+fIUAbOFxg3KjMD1em3EfqvV6vl8GkW7l5cJsF6vY/p//i8RQwbwer22221U5W63K/T4fr93u1263LdMFB8ZAEc96BsOhwER5WIIAMB+NO92u4lMKlw8m80oFJaMEgCg/ZADdvW0A2GMRiPdtgKAEu13tUJG4c667sQFoBap8yl8FdiPDIqyZgFQ9oerU83mlrV0ExaAJfshdKfTiSMLg8BZKR5k4ewPS4TpNplMOLKqAqD88YngSwxjVAVgyR+O8bSmKoCKumeerVoAkZe6xQnA45vCGH7rfGuIFbVRBUDgvO2bCefzWXEj4I8PDtyXOYzQ0cVi4WMonAmWSR8HIDWbzUZ33grXNKifTqcA3Ov1FNUfB3AdhdOv4h6+S0D6fr/HWLVaLd1jBgsAFNChV5RLAVpKelDfbrd16lk1QCLczLZjoPEW6SiMG4FAdUphXO/tCSkD8GEwi9uVDvZLny6gZg6HQ8YvDYBr23g8DnR9319S6XjH5XIJGw4Gg7fxZwwiFDfsyGfQSQeRvnci1ghE+XXz1d3W7bb5WVF3ABpzvpZVdwDM+8CYqyOAmzPRx6l6ARyPx3w/CNd9jQDgNEHq+RO6LgCgvt/vA8Dlcol2tjLnQPRmhW00n+W4rNPpPB6P6J5cAHofqnhlSffIAIDT8/k8n+jNZhO8l6qPHOYKPxlJ3+Wj1swpqJRzKPc06n6JIOf4GBmz1U778kpWxJmvQ9EjEOQergEX1KegcEnIAHAvPgaIRgDpMwO/jjUA/N1hJT3Hia7iL64c4KtRfP/4mkQrq9r3rVUngEBMUgQYCZtqIGRSSqGUQgwHUgoZTSrrQ3KhjN8oYiN/+PJPqpb83Htu7qcAAAAASUVORK5CYII="
  />

  <p>You are pointing at some <strong><span id="selector">color</span></strong>
  </p>

  <hr/>
  <h4>Layer image (reference only, not displayed in page)</h4>

  <img id="layer" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwgAADsIBFShKgAAAABp0RVh0U29mdHdhcmUAUGFpbnQuTkVUIHYzLjUuMTFH80I3AAAA5klEQVR4Xu3WMQ7CMAwF0IxcgCtw/xsGdWApItWHKorLQ8qESe2HbWjNiwABAgQIECBAgAABAgQIECBAgMAUgd4e/ehMSeTMh4wK2j/nqPjt/TNzm3IXgEFb64CdgBG44hKcsmg8pKDAvbf+7SlY7nvK3xb/+lx5BAA/jMCGpwOqC/z9CFT/ApfP/9Z6T87yBaUJJsVvsen9y8cDMAJ2gCWY7IHll1qaYFL84a9AelnF+CFwxYLSnAGMBFLNivE6QAcMBCq2dJqzETACRuCzQDpPFePTv9riCRAgQIAAAQIECBC4nsATagY67TVyuhAAAAAASUVORK5CYII="
  />
</body>
Run codeHide result
+2
source

( ), , , HTML5.

  • , .
  • blob
  • onMouseOver, (R, G, B )

Twist: -, - (A = 255) , 1, 2 3, , 255- (1,2,3...). blob . , . " ", ( , N + 1 , PNG) .

--- , jQuery ( ):

var image  = document.getElementById('mainImage')
var blobs  = document.getElementById('blobImage');

// Create a canvas
canvas = $('<canvas/>')[0];
canvas.width = image.width;
canvas.height = image.height;
// IMPORTANT: for this to work, this script and blobImage.src must be both
// in the same security domain, or you'll get "this operation is insecure"
canvas.getContext('2d').drawImage(blobs, 0, 0, image.width, image.height);

// Now wait for it.
$('#mainImage').mouseover(function(event) {
    // TO DO: offset clientX, clientY by margin on mainImage
    var ctx = canvas.getContext('2d');
    // Get one pixel
    var pix = ctx.getImageData(event.clientX, event.clientY, 1, 1);
    // Retrieve the red component
    var red = pix.data[0];
    if (red > 128) {
        // ... do something for red
    }
});
+2

SVG . , . , , svg. onclick, .

js:

function svg_clicked(objSVG)
{
    alert(objSVG.style.fill);
    alert(objSVG.getAttribute('data-category'));
}

svg:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <ellipse cx="110" cy="80" rx="100" ry="50" style="fill:red;" onclick="svg_clicked(this);" data-category="lipstick" />
</svg>

fiddle ( O )

- , svg ( fill: transparent). .

+1

.

, , - svg . SVG mouseover , , <map> <area>.

I found this question that could also shed light on where I come from: Move your mouse over only the opaque part of the image . Read the second answer because it is likely to be preferred in your situation.

The svg elements in your image will be transparent (or whatever you want), and you could easily spot the mouse over events.

The library from this question is called raphael . Hope this is helpful.

0
source

All Articles