2014-10-12 6 views
4

Я много бил вокруг куста, поэтому я объясню свою проблему здесь и надеюсь, что вся картина, у кого-то есть идеи. С этим изображением:Обнаружить графические области в изображении на веб-странице

Model with Regions

мне нужно обнаружить MouseOver на сгустки над ее глаза и рот, и решить эту проблему в общем виде. Модель и капли находятся на двух разных слоях, поэтому я могу создать одно изображение только с блоками, а другое - только с моделью и каким-то образом синхронизировать виртуальный курсор над блоками, пока он действительно нависает над моделью.

Я также могу сделать многоугольники blobs, для тестирования на удар, но я думаю, что тест на удар по цвету будет намного проще. Если я попаду в синий цвет, я нахожусь на ее губах, и я показываю помады; если я нажму розовым, я буду над ее глазами и покажу образы макияжа глаз.

Каковы предложения и беседа ученых здесь?

ответ

2

Простейший способ сделать это - загрузить изображение слоя в холст, а затем получить все его пиксельные данные. Когда мышь наводится на изображение модели, узнайте, какой цвет выбран в данный момент, и если он отличается от предыдущего, активируйте событие, чтобы указать, что выбор изменился.

Вот пример, не стесняйтесь играть с ним; но следует помнить, что он не обрабатывает все случаи:

  • что, если слой и модель изображения не тот же размер
  • , что если слой и модель изображения не то же самое отношение ширина/высота
  • что, если вы хотите использовать какой-то альфа-канал (пример не принимает его во внимание)

$(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's 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's 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>

1

Вы можете использовать графику 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 (переместить курсор Выходов на картинке)

Он по-прежнему работает, если вы сделаете SVG элемент прозрачный (с использованием заливки: прозрачный). Вы можете быстро изменить наложение на цвет или контур для тестирования.

2

Если у вас могут быть оба изображения (одно с блобом и без него), я думаю, вы можете сделать это, используя холст HTML5.

  • нарисовать изображение обычно
  • обратить блоб изображение под мастер изображения таким образом, она невидима
  • скопировать двоичный объект на холсте
  • OnMouseOver, извлекать данные пикселя (R, G, B и альфа) для холста на подходящих координатах
  • прибыль

Twist: возможно, вы сможете сделать это только с одним изображением и его альфа-каналом, если он вам не нужен ни для чего другого - дайте пикселям полную непрозрачность (A = 255) всюду, кроме blobs 1, 2 и 3, которые будут иметь непрозрачность, равную 255- (1,2,3 ...). У вас не может быть слишком много разных blob или прозрачность станет заметной. Не пробовал, но он должен работать. Учитывая вероятную сжимаемость изображения «только blob-only», пара изображений (одна без прозрачности, одна без прозрачности и только с 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 
    } 
}); 
+0

Очень крутая идея. Может ли он использовать альфу? –

+0

Не понимаю почему. Просто убедитесь, что изображения имеют нужный размер, или растяжка может слегка размыть пиксели и их значения. – LSerni

0

Я настоятельно рекомендую проверенное время метод.

Самый простой способ создать капли и определить, находится ли над ними мышь, - использовать графику svg поверх другого изображения. SVG поддерживает события mouseover и позволяет векторные формы, которые будут давать вам гораздо большую точность, чем использование <map> или <area>.

Я нашел этот вопрос, который также мог бы пролить свет на то, откуда я родом: Hover only on non-transparent part of image. Прочитайте второй ответ, потому что он, скорее всего, будет предпочтен в вашей ситуации.

Элементы svg на вашем изображении будут прозрачными (или что бы вы ни хотели), и вы могли бы легко обнаружить мышь над событиями.

Библиотека из этого вопроса называется raphael. Надеюсь, это окажется полезным.

+0

Звучит знакомо;) – Rembunator